Zeiss Posted May 15, 2018 Posted May 15, 2018 (edited) Hello together, I'm developing a device driver for a network interface controller for MOST bus. So, first of all, I've added a node with all the settings for this IC in my DTS, the IC is connected to second I²C-controller: &i2c2 { pinctrl-names = "default"; pinctrl-0 = <&i2c2_pins_a>; status = "okay"; os8104: os8104@41 { compatible = "smsc,os8104"; reg = <0x41>; master = <0>; /* slave mode*/ bypass = <0>; /* /ABY (all bypass mode) im register bXCR */ reset_gpios = <&pio 8 17>; /* PI17 */ int_gpios = <&pio 8 16>; /* PI16 */ aint_gpios = <&pio 8 19>; /* PI19 */ error_gpios = <&pio 8 18>; /* PI18 */ }; }; The has got a couple of pins, which are indicating the status of bus and control the IC (i.e. /reset-pin), so I've connected them to PI16 - PI19. Here is the probe function in my LKM: static int os8104_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device_node *dn; int rc = 0; u8 val; struct os8104 *priv; int irq; priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); if (!priv) { return -ENOMEM; } dn = of_find_node_by_name(NULL, os8104_driver.driver.name); if (dn == NULL) { printk(KERN_ERR "Node not found! \n"); return -ENODEV; } rc = of_property_read_u8(dn, "master", &val); if (rc < 0) { printk(KERN_ERR "Property master not found!\n"); return -ENODEV; } else { priv->master = val; } rc = of_property_read_u8(dn, "bypass", &val); if (rc < 0) { printk(KERN_ERR "Property bypass not found!\n"); return -ENODEV; } else { priv->bypass = val; } priv->adapter = to_i2c_adapter(client->dev.parent); priv->client = client; priv->reset_gpios = devm_gpiod_get (&client->dev, "reset_gpios", GPIOD_OUT_HIGH); priv->int_gpios = devm_gpiod_get (&client->dev, "int_gpios", GPIOD_IN); priv->aint_gpios = devm_gpiod_get (&client->dev, "aint_gpios", GPIOD_IN); priv->error_gpios = devm_gpiod_get (&client->dev, "error_gpios", GPIOD_IN); irq = gpiod_to_irq (priv->int_gpios); return 0; } Ok, my problem is/are the four devm_gpiod_get (....), the functions returning -2, that means not found. Any idea, what is going wrong? Kernel version is 4.14.39 and SBC is a BananaPRO (Allwinner A20). Many thanks Edited May 15, 2018 by Zeiss versions added
zador.blood.stained Posted May 15, 2018 Posted May 15, 2018 (edited) You didn't say which SoC are you developing for. For common sunxi SoCs like A20, H3, ... this reset_gpios = <&pio 8 17>; /* PI17 */ int_gpios = <&pio 8 16>; /* PI16 */ aint_gpios = <&pio 8 19>; /* PI19 */ error_gpios = <&pio 8 18>; /* PI18 */ is wrong since you need 4 cells for a GPIO property: pin controller phandle, pin bank number, pin number in the bank and flags. Flags parameter is mandatory and is usually set to 0. So you most likely need to update your DT to this reset_gpios = <&pio 8 17 0>; /* PI17 */ int_gpios = <&pio 8 16 0>; /* PI16 */ aint_gpios = <&pio 8 19 0>; /* PI19 */ error_gpios = <&pio 8 18 0>; /* PI18 */ Edited May 15, 2018 by zador.blood.stained Didn't see the target device in the end.
zador.blood.stained Posted May 15, 2018 Posted May 15, 2018 Also not relevant to your issue, but if you need interrupts, you could look at this and register your device as an interrupt controller client rather than trying to use the GPIO framework.
Zeiss Posted May 15, 2018 Author Posted May 15, 2018 Many thanks SoC during development is an A20. Okay, I'll change my DT and check this after that. Interrupts: sure, I'll test this too, it's just for "quick and dirty" test.There is just one interrupt, for INT_GPIOS pin, the other pins are just "look and check" pins.
Zeiss Posted May 15, 2018 Author Posted May 15, 2018 So, I've checked them. My DT after change: &i2c2 { pinctrl-names = "default"; pinctrl-0 = <&i2c2_pins_a>; status = "okay"; os8104: os8104@41 { compatible = "smsc,os8104"; reg = <0x41>; master = <0>; bypass = <1>; reset_gpios = <&pio 8 17 0>; /* PI17 */ int_gpios = <&pio 8 16 0>; /* PI16 */ aint_gpios = <&pio 8 19 0>; /* PI19 */ error_gpios = <&pio 8 18 0>; /* PI18 */ }; }; And corresponding code: static int os8104_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device_node *dn; int rc = 0; u32 val; priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); if (!priv) { return -ENOMEM; } dn = of_find_node_by_name(NULL, os8104_driver.driver.name); if (dn == NULL) { printk(KERN_ERR "Node not found! \n"); return -ENODEV; } rc = of_property_read_u32(dn, "master", &val); if (rc < 0) { printk(KERN_ERR "Property master not found!\n"); return -ENODEV; } else { priv->master = val; } printk(KERN_INFO "Value of property master is: %d\n", priv->master); rc = of_property_read_u32(dn, "bypass", &val); if (rc < 0) { printk(KERN_ERR "Property bypass not found!\n"); return -ENODEV; } else { priv->bypass = val; } printk(KERN_INFO "Value of property bypass is: %d\n", priv->bypass); priv->adapter = to_i2c_adapter(client->dev.parent); priv->client = client; priv->reset_gpios = devm_gpiod_get (&client->dev, "reset_gpios", GPIOD_OUT_HIGH); if (IS_ERR(priv->reset_gpios)) { dev_err(&client->dev, "%s ERROR: Can't get RESET GPIO\n",__func__); return PTR_ERR(priv->reset_gpios); } return 0; } After insmod ./os8104.ko dmesg says: Quote root@banana:~/dev/os8104# insmod ./os8104.ko [ 444.827324] os8104: loading out-of-tree module taints kernel. [ 444.833882] os8104 1-0041: os8104_probe ERROR: Can't get RESET GPIO [ 444.840201] os8104: probe of 1-0041 failed with error -2 root@banana:~/dev/os8104# The error is still there. And here some additional debugging: os8104-node is there: root@banana:/sys# find ./ -name os8104* ./firmware/devicetree/base/soc@01c00000/i2c@01c2b400/os8104@41 root@banana:/sys# The gpios defined inside of them too: root@banana:/sys/firmware/devicetree/base/soc@01c00000/i2c@01c2b400/os8104@41# ls -la total 0 drwxr-xr-x 2 root root 0 May 15 17:57 . drwxr-xr-x 3 root root 0 May 15 17:57 .. -r--r--r-- 1 root root 16 May 15 17:59 aint_gpios -r--r--r-- 1 root root 4 May 15 17:59 bypass -r--r--r-- 1 root root 12 May 15 17:59 compatible -r--r--r-- 1 root root 16 May 15 17:59 error_gpios -r--r--r-- 1 root root 16 May 15 17:59 int_gpios -r--r--r-- 1 root root 4 May 15 17:59 master -r--r--r-- 1 root root 7 May 15 17:59 name -r--r--r-- 1 root root 4 May 15 17:59 reg -r--r--r-- 1 root root 16 May 15 17:59 reset_gpios root@banana:/sys/firmware/devicetree/base/soc@01c00000/i2c@01c2b400/os8104@41#
zador.blood.stained Posted May 15, 2018 Posted May 15, 2018 I missed this initially, but you also need to check this: https://www.kernel.org/doc/Documentation/gpio/board.txt Your DT properties should be named <function>-gpios and in devm_gpiod_get you should omit the "-gpios" suffix. I.e. reset-gpios = <&pio 8 17 0>; /* PI17 */ ... priv->reset_gpios = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
Zeiss Posted May 15, 2018 Author Posted May 15, 2018 Oh men.... this was my mistake :( After correction in dmesg: [ 50.087284] os8104: loading out-of-tree module taints kernel. [ 50.093827] Value of property master is: 0 [ 50.097947] Value of property bypass is: 1 [ 50.102223] OS8104 INT mapped to irq 83 [ 50.106131] OS8104 INT interrupt request result is: 0 And cat /proc/interrupts: root@banana:~# cat /proc/interrupts CPU0 CPU1 18: 0 0 GICv2 29 Level arch_timer 19: 2836 1494 GICv2 30 Level arch_timer 22: 0 0 GICv2 54 Level /soc@01c00000/timer@01c20c00 23: 0 0 GICv2 113 Level sun5i_timer0 24: 0 0 GICv2 152 Level arm-pmu 25: 0 0 GICv2 153 Level arm-pmu 26: 0 0 GICv2 59 Level 1c02000.dma-controller 27: 0 0 GICv2 42 Level sun4i-spi 28: 178410 0 GICv2 64 Level sunxi-mmc 29: 7500 0 GICv2 67 Level sunxi-mmc 30: 0 0 GICv2 71 Level ehci_hcd:usb1 31: 0 0 GICv2 96 Level ohci_hcd:usb3 33: 0 0 GICv2 88 Level ahci-sunxi[1c18000.sata] 34: 0 0 GICv2 72 Level ehci_hcd:usb2 35: 0 0 GICv2 97 Level ohci_hcd:usb4 38: 0 0 GICv2 56 Level 1c20d00.rtc 42: 0 0 GICv2 37 Level sunxi-ir 44: 88 0 GICv2 61 Level sun4i-ts 45: 534 0 GICv2 33 Level ttyS0 48: 226 0 GICv2 39 Level mv64xxx_i2c 49: 0 0 GICv2 41 Level mv64xxx_i2c 65: 0 0 sunxi_pio_edge 10 Edge 1c0f000.mmc cd 70: 338 0 sunxi_pio_level 15 Level brcmf_oob_intr 83: 0 0 sunxi_pio_edge 28 Edge os8104_int_irq 87: 0 0 sunxi-nmi 0 Level axp20x_irq_chip 121: 0 0 axp20x_irq_chip 33 Edge axp20x-pek-dbr 122: 0 0 axp20x_irq_chip 34 Edge axp20x-pek-dbf IPI0: 0 0 CPU wakeup interrupts IPI1: 0 0 Timer broadcast interrupts IPI2: 2647 73841 Rescheduling interrupts IPI3: 0 4 Function call interrupts IPI4: 0 0 CPU stop interrupts IPI5: 0 0 IRQ work interrupts IPI6: 0 0 completion interrupts Err: 0 root@banana:~# It's looking pretty good. Thank you very much!
Recommended Posts