# i2c gpio extender https://www.kernel.org/doc/html/latest/i2c/instantiating-devices.html https://bootlin.com/pub/conferences/2018/elc/opdenacker-kernel-programming-device-model-i2c/kernel-programming-device-model-i2c.pdf ## Add dt node parse https://lore.kernel.org/patchwork/patch/384816/ ## Use of multiple gpio controllers ### Get i2c_client from phandle ```C struct device_node *toto = of_parse_phandle(np, "demod", 0); if (!toto) panic("of_parse_phandle"); struct i2c_client *demod = of_find_i2c_device_by_node(toto); if (!demod) panic("of_find_i2c_device_by_node"); printk("\tdemod=%px\n", demod); ``` ### Inspect GPIO chips ```shell $ grep -d skip . /sys/class/gpio/*/* /sys/class/gpio/gpiochip0/base:0 /sys/class/gpio/gpiochip0/label:pinctrl-bcm2835 /sys/class/gpio/gpiochip0/ngpio:54 /sys/class/gpio/gpiochip100/base:100 /sys/class/gpio/gpiochip100/label:brcmvirt-gpio /sys/class/gpio/gpiochip100/ngpio:2 /sys/class/gpio/gpiochip128/base:128 /sys/class/gpio/gpiochip128/label:brcmexp-gpio /sys/class/gpio/gpiochip128/ngpio:8 ``` The grep is just a way of showing file names and contents. Each "chip" has a label, base and ngpio. The file "label" identifies the driver, "base" contains the number of the first gpio, while "ngpio" tells you how many there are, so the output above tells use that the pinctrl-bcm2835 driver gives access to GPIOs 0-53. I expect the MCP23017 driver to appear as "gpio-mcp23xxx", with ngpio set to 16. For your application you can either programmatically search for the directory under /sys/class/gpio with the correct label and read the contents of "base" - this is the "right" way to do it - or you can try it once by hand and hard-code the values. ## i2c bus matching process ``` Call process: i2c_add_driver -->i2c_register_driver -->driver->driver.bus = &i2c_bus_type; -->driver_register -->bus_add_driver -->driver_attach -->bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); // Polling for devices on i2c bus -->__driver_attach -->driver_match_device -->driver_probe_device -->really_probe -->dev->bus->probe(dev); -->i2c_device_probe<i2c_bus_type;Realization in Structures> -->if (!driver->probe || !driver->id_table) -->driver->probe(client, i2c_match_id(driver->id_table, client)); -->xxx_drv_probe<i2c_driver Our driver im ``` Therefore, when registering i2c_driver, the id_table in i2c_driver must be implemented!!! https://programmer.group/note-6-reasons-for-not-executing-i2c-driver-probe-function-after-linux-3.0.html