clinux-kernellinux-device-driverkernel-module

How do I properly probe a platform device?


I am trying to create a platform driver I have the following code

Module

// SPDX-License-Identifier: GPL-2.0

#include <linux/module.h>
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/of_device.h>
#include <linux/fb.h>

static int simple_probe(struct platform_device *pdev)
{
    printk(KERN_ERR "SIMPLE: %s\n", "Probing");
    return 0;
}

const struct of_device_id simple_of_match[] = {
    {
        .compatible = "example,simple",
    },
    { /*End of List*/ },
};

struct platform_driver simple_driver = { 
    .probe = simple_probe,
    .driver = { 
        .name = "simple",
        .owner = THIS_MODULE,
        .of_match_table = simple_of_match 
    }
};

static int __init init(void)
{
    if (platform_driver_register(&simple_driver)) {
        printk(KERN_ERR "SIMPLE: %s\n", "Registerered");
    } else {
        printk(KERN_ERR "SIMPLE: %s\n", "Failed");
    }
    return 0;
}

static void __exit deinit(void)
{
    platform_driver_unregister(&simple_driver);
}

module_init(init);
module_exit(deinit);

MODULE_DESCRIPTION("Simple Platform driver");
MODULE_AUTHOR("Bret Joseph Antonio <[email protected]>");
MODULE_LICENSE("GPL");

My device tree doesn't seem to be running an overlay so the devices status is ok. It is still not running the probe callback.

DEVICE TREE

/dts-v1/;

/ {
    simple@0 {
        compatible = "example,simple";
        pinctrl-names = "lcm_rst_out1_gpio", "lcm_rst_out0_gpio";
        pinctrl-0 = <&PHANDLE1>;
        pinctrl-1 = <&PHANDLE2>;
        status = "okay";
    };
};

I am expecting the kernel to register my driver and then run the probe function but the code

    if (platform_driver_register(&simple_driver) == 0) {
        printk(KERN_ERR "SIMPLE: %s\n", "Registered");
    } else {
        printk(KERN_ERR "SIMPLE: %s\n", "Failed");
    }

returns [ 0.178889] SIMPLE: Registered but the probe function remains silent. What does the probe function depend on? Shouldn't it run probe as soon as it finds the node in the device tree?


Solution

  • You need to export your struct of_device_id simple_of_match[] to the of (Open Firmware) subsystem with a MODULE_DEVICE_TABLE(of, simple_of_match); statement. This will create the required alias entry for the module during build time.

    Consolation is that other kernel drivers in mainline have been patched for this very same omission, e.g. [PATCH] mtd: nand: tango: Export OF device ID table as module aliases and [PATCH] pwm: samsung: Use MODULE_DEVICE_TABLE() to include OF modalias.
    That latter patch mentions:

    If the ... driver is built as a module, modalias information is not filled so the module is not autoloaded. Use the MODULE_DEVICE_TABLE() macro to export the OF device ID so the module contains that information.

    That implies that if your driver was always a built-in module rather than a loadable module, then you would not need to have a MODULE_DEVICE_TABLE(of, simple_of_match); statement.


    Convention for kernel code is to declare all symbols as static whenever possible. Your code is inconsistent in that regard, i.e. struct of_device_id simple_of_match[] and struct platform_driver simple_driver are global.

    Suggested edits in patch form:

    - const struct of_device_id simple_of_match[] = {
    + static struct of_device_id simple_of_match[] = {
        {
            .compatible = "example,simple",
        },
        { /*End of List*/ },
      };
    
    + MODULE_DEVICE_TABLE(of, simple_of_match);
    
    
    - struct platform_driver simple_driver = { 
    + static struct platform_driver simple_driver = { 
         .probe = simple_probe,
         .driver = { 
             .name = "simple",
             .owner = THIS_MODULE,
             .of_match_table = simple_of_match 
         }
      };