MCP23017 I2C Device driver probe function is not called - linux

I am using the following I2C/GPIO Device driver to access the MCP23017 GPIOs. With the insmod command I am able to load the driver and its listed in /proc/modules. I have two MCP23017 chips connected to my Raspberry Pi. Both are detected at addresses 0x20 and 0x21. The initcall to the driver registers the driver. I checked this by printing out a message. But the driver probe function is not called. The devices are not opened/ cannot be located elsewhere.
How is the probe function called?
Should the probe be done manually to locate the devices?
Is the probe call similar to the open call?
I tried this echo mcp23017 0x20 > new_device to manually create a new device with the address. But it didnt work. I got the followin message: Driver 'mcp23s08' is already registered, aborting...
Any help would be appreciated.

probe() function is called when driver is matched with your device description in Device Tree. Matching happens when compatible field of your driver found in Device Tree (for your driver it's "microchip,mcp23017" string).
Apparently you don't have your device (MCP23017) described in Device Tree, that's why probe() is not called. You can load corresponding Device Tree Overlay to overcome this issue. The one you pointed out in your comment seems to be correct. Read more about loading overlays in Raspberry Pi ecosystem here.
You can try to load your overlay like described in that article:
$ sudo dtoverlay mcp23017.dtbo
Or you can try to use Capemgr for this purpose. Personally I didn't try any of those, so you should look which works for you best.
Update
Replying to your questions in comments.
But when I try the i2cdetect command it shows UU.
See man i2cdetect. So "UU" means that i2cdetect skipped probing because device at the address you specified is already used by driver. I guess it what you intended, so it's ok.
With a rmmod mcp23017 command I see the device still under devices but i2cdetect shows 0x20
So you unloaded the driver and now i2cdetect shows you that there is some device on 0x20 address. I guess it's correct behavior. Also if you want to get rid completely of your device -- try to unload DT overlay along with driver.
Also I have connected two MCP23017 chips. But I can see only the device at 0x20 under devices. The I2C chip at 0x21 is still not detected, though the driver says it supports up to 8 chips
I can see two possible causes to this issue.
DT overlay only has description for device with 0x20 address, but missing description for device with 0x21 address. If this is the case, you should find sources for your DT overlay, add description for rest of your devices, compile that modified DT overlay and then load it instead of pre-built one.
All devices may be configured for using 0x20 address. See section 1.4
Hardware Address Decoder in MCP23017 datasheet for details. Check A0, A1, A2 pins on your chips.

Related

hwmon device (lm75) not getting detected

I have a board with TMP75 temp sensor on an i2c bus, which is handled by lm75 driver. It's at the address 0x4a.
I'm loading the driver (linux) and it's getting loaded but it is not detecting the device.
In the /sys/bus/i2c/drivers/lm75/ , I see only following files/folder :
bind module uevent unbind.
I don't see any other entry where possibly the temp_input etc. device attributes are present. Not sure how do I debug this further..
I can see the driver loaded in lsmod
/sys/bus/i2c/devices/ doesn't show the device to be bound.
Update:
I put prints in the probe to see if that's getting called. I don't see those prints.

i2cdetect doesn't find anything on goodix chip

I have a goodix chip for the touchscreen on my tablet PC and even though I compiled the latest kernel module for it, things are not working.
I am using exactly this kernel version with the patched driver:
https://github.com/NimbleX/kernel
For starters, the picture of the said chip is the following:
The DSDT tables contain information regarding the touchscreen.
From what I understand the touchscreen is connected via an I2C serial interface but lshw shows that *-serial is UNCLAIMED.
Nevertheless I can see that the i2c_i801 module for the SMBus controller is loaded.
With the help of Aleksei I was able to determine that the toucscreen is connected to i2c-1 buss and that the controller must use 0x14 or 0x5d address.
Unfortunatelly, i2cdetect doesn't find anything, as it can be seen here.
I created a lengthy gist with the output of the following:
dmesg
DSDT.dsl
lshw
lspci
lsusb
/proc/bus/input/devices
xinput
I know that some of these are redundant and that others are useless but nevertheless it's better to have where to search than to miss something out.
I measured with a multimeter and the chip is powered both when running Windows and Linux so this rules out that I need to somehow tell Linux to power this thing out.
So, what do do next in order to debug this thing?
Hi can you check where pin 5,6 are connected specifically 6 which is reset ic so if that may be reseting the ic. just a posiblity.

UART binding # runtime

When does the console and UART binding happen in Linux,is it possible to unbind the UART from console and bind it to other module(GPS) at runtime.
My board is having a single UART,can i switch between console and GPS at runtime.if yes how do i do it? if no what is the hack which I need to do?
Yes you can. At run time you can unbind/bind any driver. You can find more information here:
https://lwn.net/Articles/143397/
You can find the correct driver for your the UART (and GPS probably, but I'm not sure. Never played with it) here:
cd /sys/class/tty/<your-device>/device/driver/
Then in these directories you have the sysfs files bind and unbind. The device ID to use to unbind the device from the driver is typically show in the driver directory.
The platform_device is not special at all, it behaves like any other driver. Typically the device id of a platform device it's its name (there is not a bus enumeration behind). Here an example with platform_device with my PC:
# ls /sys/bus/platform/devices/
alarmtimer gpio_ich iTCO_wdt platform-framebuffer.0 PNP0800:00 PNP0C14:00
coretemp.0 hp-wmi microcode PNP0003:00 PNP0C04:00 serial8250
Fixed MDIO bus.0 i8042 pcspkr PNP0103:00 PNP0C0C:00
# cd /sys/bus/platform/drivers/serial8250/
# ls
bind serial8250 uevent unbind

I2C Mux on Linux

I am trying to understand how to address devices behind I2C Mux like PCA9548 in linux.
If the topology is something like
CPU->I2C_A Controller->PCA9548->Channel 0->RTC
CPU->I2C_A Controller->PCA9548->Channel 1->Temp Sensor
CPU->I2C_B Controller->PCA9548->Channel 0->Voltage Sensor
CPU->I2C_B Controller->PCA9548->Channel 1->Speed Sensor
I want to know the representation of these devices in user space? What are the associated sysfs entries?
I also want to know if pc9548 is the only driver required in kernel and i2c-dev and i2c-core are already available? Or driver for RTC/sensors is also required?
I have tried to read this, but could not follow it much.
My requirement is to read/write to those devices from user space. Do I have to instantiate devices and assign addresses to it in startup script?
Thanks,
Hemant
You could use i2c-tools for manipulation at user space, if the driver has some problem.
Also you'll need enable the kernel module "i2c-dev" for the char device.
Like /dev/i2c-0
link here.
The necessary driver are i2c-mux, pca954x, I believe you already have i2c-core.
Also you should describe all the I2C devices in device tree or other files.
If the driver is prepared, you may see 8 i2c adapters under /dev, and their salve device is under /sys/bus/i2c.

Linux PCI Driver calls init, but not probe

I'm developing a driver for an FPGA-board connected to my machine via an PCIe expansion slot, and everything works great if the board is powered on prior to the PC. However, if I book up my computer first and then the FPGA board, I get the rather unusual behavior of the device being recognized and loading my module (I see the "init" function called in my syslog), however the "probe" function is never called.
I think this is due to an invalid BAR0. Output from dmesg when I power on the board:
[ 71.287587] pci 0000:3b:00.0: [0ae5:0001] type 00 class 0x000000
[ 71.287613] pci 0000:3b:00.0: reg 0x10: [mem 0x00000000-0x0000ffff]
[ 71.287821] pci 0000:3b:00.0: System wakeup disabled by ACPI
[ 71.328537] my_driver:
[ 71.328537] ****************************************************************
[ 71.328542] my_driver: init debug=2
That first reg should be something like 0xb4000000-0xb400ffff but instead it's coming up as 0. (Like I said, it works perfectly if it's powered on before the computer).
Is there an additional step required to get it to allocate this block? Or somehow to indicate to the kernel that it needs to do this?
The solution wound up being a manual call to pci_assign_resource ( http://lxr.free-electrons.com/source/drivers/pci/setup-res.c#L283 ).
Calling this right before pci_enable_device caused the OS, rather than the BIOS, to allocate the required BAR's and now it all works!
I do still have to manually trigger a PCI bus rescan ( echo 1 > /sys/bus/pci/rescan ).
Your PCI device must be powered up prior to the BIOS PCI enumeration phase.
On enumeration phase, the BIOS tries to read the ID of the PCI devices that might be connected.
If it reads invalid ID (0xfffff) it skips that PCI device.
I don't have a reference, but AFAIK, you have about a second before you must populate the configuration space of the PCI.
Are you sure you register the PCI driver and don't return non-zero from mod_init? Please try to manually bind the device to your driver:
echo -n "0000:3b:00.0" > /sys/bus/pci/drivers/my_driver/bind
Unallocated BAR should not be an issue when loading the driver.
As for the BAR being 0 and HotPlug: find out what is your platform and if and how HotPlug is supported. You need to have the right HotPlug driver in the kernel for this sort of thing to work. BARs are allocated by the kernel (or initially firmware/BIOS) so you can't set them to anything meaningful from the FPGA side - there you can only set the size. Kernel has to do the rescanning and reassignment after device appears. I vaguely recall that there should be some reservation going on during boot, otherwise kernel will not have to space to give to your devices' BAR and it will not reassign the windows on bridges below your device as they can be actively used by other devs. Other option is to just do the BAR programming yourself from the driver. It ain't that hard but you would probably don't want to ship this kind of hacks to customers. Also, even though your device does seem to come up fine, make sure you don't have HP disabled in FW/BIOS.

Resources