uCLinux Maxim14830 Driver Not Probing - linux-kernel

I am trying to get a Maxim14830 evaluation board to work with my Emcraft STM32F4 SOM. My SOM is running the Emcraft uClinux kernel 2.0.0 (Forked from Kernel 4.4) on github here (I have plans to attempt this with Kernel version 4.5 as well).
The driver is not registering the 4 ttyMAX[n] devices. Upon further inspection, none of the max310x.c driver code is actually being executed based on the printk's I've added. I would at least expect the probe function to run during boot.
The source code on github for the maxim14830 (protocol?) driver is here max310x.c
The source code on github for the spi (controller?) driver is here spi-stm32.c
I have been able to add an spidev device fine, so my belief is that this is a problem unique to the maxim14830.
I see a spi device here:
/sys/devices/platform/soc/40003800.spi/spi_master/spi1/spi1.0 # cat modalias
spi:maxim14830
I see the max310x driver here:
/sys/bus/spi/drivers/max310x
I see the following devicetree entries:
/sys/firmware/devicetree/base/soc/spi#40003800/max14830#0 # cat compatible
maxim,maxim14830
/sys/firmware/devicetree/base/clocks/osc_max14830
My devicetree looks like so:
&spi_2 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi_2>;
cs-gpios = <&gpiob 9 OUT>;
timeouts = <3>;
max14830: max14830#0 {
status = "okay";
compatible="maxim,maxim14830";
reg = <0>;
gpio-controller;
#gpio-cells = <2>;
spi-max-frequency = <20000000>;
interrupt-parent = <&exti>;
interrupts = <10>;
clocks = <&spi_uart_clk>;
clock-names = "xtal";
};
spidev: spidev#2 {
status = "disabled";
compatible = "linux,spidev";
spi-max-frequency = <20000000>;
reg = <0>;
};
};
I'm able to compile my device tree blob, and uboot the corresponding linux image fine. From my printk's, stm32_spi_probe is being called from the "Controller Driver," but to my knowledge no max310x.c driver code is being called after..
Where should I go to debug this further? This is my first embedded linux project and I could use some pointers..

Related

jedec,spi-nor not executing in linux kernel

I am trying to use a MTD device for storage on a Licheepi Zero. I have been able to add and use i2c and spidev succesfully, however I cannot make jedec,spi-nor execute during kernel bootup.
My dts is (I have tried many variations of this):
&spi0 {
pinctrl-0 = <&spi0_pins>; // tried without these two lines
pinctrl-names = "default";
status = "okay";
/* tried with and without this */
/*cs-gpios = <&pio 2 2 GPIO_ACTIVE_LOW>, <&pio 1 0 GPIO_ACTIVE_LOW>;*/
flash#0 {
compatible = "winbond,w25q64", "jedec,spi-nor"; // I tried deleting winbond,w25q64
status = "okay"; // I added this line on desperation
spi-max-frequency = <50000000>; // I tried lowering this to 10MHz
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
};
};
When I boot the kernel using this dts I cannot see jedec,spi-nor trying to probe for the NOR-FLASH, it is like if "jedec,spi-nor" is simply not executing. I know my changes are working because if I replace flash#0{compatible="jedec,spi-nor";..} with spidev#0{compatible = "spidev";..} I get a spidev device (which is functional) and can also see it on dmesg.
Some other outputs:
cat /proc/mtd
dev: size: erasesize name
ls /sys/class/mtd is empty
# cat /sys/class/spi_master/spi0/spi0.0/uevent
OF_NAME=flash
OF_FULLNAME=/soc/spi#1c68000/flash#0
OF_COMPATIBLE_0=winbond,w25q64
OF_COMPATIBLE_1=jedec,spi-nor
OF_COMPATIBLE_N=2
MODALIAS=spi:w25q64
MTD_SPI_NOR is enabled in menuconfig. I also added it as a module and tried running modprobe -v jedec_probe.ko and modprobe -v spi-nor.ko but I see absolutely no verbose. mtdinfo userspace counts 0 MTD devices.
The linux kernel I am using is 5.3.5. I am compilling it with buildroot. I checked and w25q64 is supported in jdec,spi-nor (linux-5.3.5/drivers/mtd/spi-nor/spi-nor.c)
It seems I was missing CONFIG_MTD_M25P80, now I get:
[ 0.781483] m25p80 spi0.0: found s25fl064k, expected w25q64
[ 0.787181] m25p80 spi0.0: s25fl064k (8192 Kbytes)

How to find dma_request_chan() failure reason details?

In an external kernel module, using DMA Engine, when calling dma_request_chan() returns an error pointer of value -19, i.e. ENODEV or "No such device".
Now, in the active device tree, I do find a dma-names entry with what I'm trying to get a channel for, so my suspicion is that something else deeper in the forest is already not found.
How do I find out what's wrong?
Background:
I have a Zynq MP Ultrascale+ board here, with an FPGA design which uses AXI VDMA block to provide one channel of data to be received on the Cortex A's Linux, where the data is written to DDR4 by the FPGA and to be read from Linux.
I found that there is a Xilinx DMA driver included in the kernel, in the Xilinx source repo anyway, currently kernel version 5.6.0.
And that that driver has no user space interface, such that an intermediate kernel driver is needed.
This is depicted, and they have an example here: Section "4 DMA Proxy Design". I modified the code in the dma-proxy.c of the zip file linked there such that it uses only the RX channel, i.e. also only tries to request it.
The code for that is here, to not make this post huge:
Modified dma-proxy.c at onlinegdb.com
Line 407 has the function create_channel(), which used to use dma_request_slave_channel() which ditches the error code of the function it wraps, so to see the error, I am using that one instead: dma_request_chan().
The function create_channel() is called in function dma_proxy_probe() # line 470 (the occurences before that are deactivated by compile switch).
So by way of this call, dma_request_chan() will be called with the parameters:
create_channel(pdev, &channels[RX_CHANNEL], "dma_proxy_rx", DMA_DEV_TO_MEM);
The Device Tree for my board has an added node for dma-proxy driver as is shown at the top of the dma-proxy.c
dma_proxy {
compatible ="xlnx,dma_proxy";
dmas = <&axi_dma_0 0>;
dma-names = "dma_proxy_rx";
};
The name "axi_dma_0" matches with the name in the axi DMA device tree node:
axi_dma_0: dma#a0000000 {
#dma-cells = <0x1>;
clock-names = "s_axi_lite_aclk", "m_axi_s2mm_aclk";
clocks = <0x3 0x47 0x3 0x47>;
compatible = "xlnx,axi-dma-7.1", "xlnx,axi-dma-1.00.a";
interrupt-names = "s2mm_introut";
interrupt-parent = <0x1d>;
interrupts = <0x0 0x2>;
reg = <0x0 0xa0000000 0x0 0x1000>;
xlnx,addrwidth = <0x28>;
xlnx,sg-length-width = <0x1a>;
phandle = <0x1e>;
dma-channel#a0000030 {
compatible = "xlnx,axi-dma-s2mm-channel";
dma-channels = <0x1>;
interrupts = <0x0 0x2>;
xlnx,datawidth = <0x40>;
xlnx,device-id = <0x0>;
};
If I now look here:
% cat /proc/device-tree/dma_proxy/dma-names
dma_proxy_rx
Looks like my dma_proxy_rx, that I'm trying to request the channel for, is in there.
Edit:
In the boot log, I see this:
xilinx-vdma a0000000.dma: Please ensure that IP supports buffer length > 23 bits
irq: no irq domain found for interrupt-controller#a0010000 !
xilinx-vdma a0000000.dma: unable to request IRQ 0
xilinx-vdma a0000000.dma: WARN: Device release is not defined so it is not safe to unbind this driver while in use
xilinx-vdma a0000000.dma: Xilinx AXI DMA Engine Driver Probed!!
There are warnings - but in the end, the Xilinx AXI DMA Engine got "probed", meaning the lowest level driver loaded and is ready, right?
So it looks to me like there should be my device, but the kernel disagrees.
I've got the same problem with similar configuration. After digging a lot of kernel source code (especially drivers/dma/xilinx/xilinx_dma.c) I've solved this problem by changing channel number in dmas parameter from 0 to 1 in dma-proxy device tree entry like this:
dma_proxy {
compatible ="xlnx,dma_proxy";
dmas = <&axi_dma_0 1>;
dma-names = "dma_proxy_rx";
};
It seems that dma-proxy example is written for AXI DMA block with both mm2s (channel #0) and s2mm (channel #1) channels. And if we remove mm2s channel from AXI DMA block, the s2mm channel stays #1.

Why doesn't device_create return error when a file already exists?

I am writing a PCI driver with a character device for an interface (Linux 4.9.13). Here's the scenario that bothers me:
Run touch /dev/foo0 which creates a normal file in the /dev directory.
Load the driver module. Here's a pseudo code representing what happens there (pretty standard character device registration):
// When the module is initialized:
alloc_chrdev_region(&dev, 0, 256, "foo");
class = class_create(THIS_MODULE, "foo");
// Later, when a suitable PCI device is connected the probe function
// calls the following functions:
cdev_init(dev->md_cdev, &fops);
dev->md_devnum = MKDEV(major, 0 + index);
res = cdev_add(dev->md_cdev, dev->md_devnum, 1);
dev->md_sysfsdev = device_create(class, 0, dev->md_devnum, 0, "foo%d", index);
Details:
index is just another free index
What seems weird to me is nothing raises an error that there is already a /dev/foo0 file which is not a character device. I do check all the errors (I think so) but I omitted related code for the sake of conciseness. Everything works as expected if I do not run touch /dev/foo0. Otherwise, I can neither read nor write to the device.
Why is it so? Shouldn't device_create return an error or at least create /dev/foo1 instead?

touchscreen ft5x06 not responding?

I am using kontron smarc-samx6i board run with nxp imx6q processor. I am currently working with yocto In that I need to interface a touch screen of ft5316 through I2C . For that I edited the device tree as follows:
polytouch: edt_ft5x06#39 {
compatible = "edt","edt_ft5x06","edt-ft5x06";
reg = <0x39>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_smx6_i2c_gpio_1>;
irq_pin=<&gpio3 1 0>;
interrupt-parent = <&gpio3>;
interrupts = <0 70 0x04>;
};
When I am using i2cdump command the touchscreen responds successfully, but when I am working with module it won't respond.
When I am using the below command i am getting following output
root#smarc-samx6i:~# cat /proc/bus/input/devices
I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="gpio-keys.27"
P: Phys=gpio-keys/input0
S: Sysfs=/devices/soc0/gpio-keys.27/input/input0
U: Uniq=
H: Handlers=kbd event0 evbug
B: PROP=0
B: EV=23
B: KEY=4000 100000 0 0 0
B: SW=1
My device did not probe and i am not getting any error while instantiating the device using the command:
echo edt_ft5x06 0x39> /sys/bus/i2c/devices/i2c-1/new_device
Instantiated device edt_ft5x06 at 0x39 device
How can i make it work!!
I assume that by "when working with the module it won't respond" you mean it won't respond to any touch events on the touchscreen. Did the driver module correctly load? Is it built-in or used as a loadable module? Did you check "dmesg" for confirming the driver loaded properly or output of lsmod? If the driver loaded properly, are you getting interrupts?
What is the output of "cat /proc/interrupts"? Do you see the interrupt requests increasing when you press the touchscreen? If not then, then you have a problem with interrupts. If you see the interrupts, can you check with an utility like "evtest" to see if you get touchscreen events?

Configure Linux I2C Speed

I am using I2C on the Snowball board, running at 400KHz by default and would like to reduce this to 100KHz.
I use the api defined in and configure as follows
m_fd = open(m_filename.c_str(), O_RDWR);
if (ioctl(m_fd, I2C_SLAVE_FORCE, m_addr) < 0)
{
throw I2cError(DeviceConfigFail);
}
Does anyone know how I would go about changing the speed to standard mode.
Thanks
You can change the I2C SCL frequency in your driver's 'struct i2c_gpio_platform_data'.
static struct i2c_gpio_platform_data xyz_i2c_gpio_data = {
.sda_pin = GPIO_XYZ_SDA,
.scl_pin = GPIO_XYZ_SCL,
.udelay = 5, //#udelay: signal toggle delay. SCL frequency is (500 / udelay) kHz
....
};
Changing 'udelay' changes your 'xyz' i2c device's clock frequency.
You should change the I2C Frequency in driver source file of the corresponding peripheral (ie: Slave device to which you are communicating through I2C. Example: EEPROM/Camera etc.)
You may find some macro defined in that driver source code... like:
#define EEPROM_I2C_FREQ 400000 //400KHz
Change it to:
#define EEPROM_I2C_FREQ 100000 //100KHz
Only for that corresponding driver, I2C frequency/speed will be changed.

Resources