Jump to content

Interaction DTS <> LKM, some questions


Recommended Posts

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 by Zeiss
versions added
Link to comment
Share on other sites

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 by zador.blood.stained
Didn't see the target device in the end.
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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#

 

Link to comment
Share on other sites

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);

 

Link to comment
Share on other sites

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!

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

Terms of Use - Privacy Policy - Guidelines