Question

I am reading about the Linux Device model which is built around buses,devices and drivers .I am able to understand a bit about how devices and driver matches happen but not clear about the role of buses here,how buses matches with device.

One more doubt I have regarding where platform device gets it name from.

"The platform bus,simply compares the name of each device against the name of each driver; if they are the same, the device matches the driver."

Now I could n't really understand above point .I believe device name is first defined in dts file and then corresponding Driver name is defined in platform driver code .

if these two name matches ,probe is called from driver code which will confirm device is really in existence.

Could anybody let me know the whole process specially from Bus point of view.

Was it helpful?

Solution

To add to @Federico's answer, which describes very well the general case, platform devices can be matched to platform drivers using four things (that are prioritized). Here is the match function of the platform "bus":

static int platform_match(struct device *dev, struct device_driver *drv)
{
        struct platform_device *pdev = to_platform_device(dev);
        struct platform_driver *pdrv = to_platform_driver(drv);

        /* Attempt an OF style match first */
        if (of_driver_match_device(dev, drv))
                return 1;

        /* Then try ACPI style match */
        if (acpi_driver_match_device(dev, drv))
                return 1;

        /* Then try to match against the id table */
        if (pdrv->id_table)
                return platform_match_id(pdrv->id_table, pdev) != NULL;

        /* fall-back to driver name match */
        return (strcmp(pdev->name, drv->name) == 0);
}

Here are two important ones.

OF style match

Match using the device tree (of_driver_match_device). If you don't know the device tree concept yet, go read about it. In this data structure, each device has its own node within a tree representing the system. Each device also has a compatible property which is a list of strings. If any platform driver declares one of the compatible strings as being supported, there will be a match and the driver's probe will be called.

Here's an example of a node:

gpio0: gpio@44e07000 {
    compatible = "ti,omap4-gpio";
    ti,hwmods = "gpio1";
    gpio-controller;
    #gpio-cells = <2>;
    interrupt-controller;
    #interrupt-cells = <1>;
    reg = <0x44e07000 0x1000>;
    interrupts = <96>;
};

This describes a GPIO controller. It only has one compatible string which is ti,omap4-gpio. Any registered platform driver declaring this same compatible string will be probed. Here's its driver:

static const struct of_device_id omap_gpio_match[] = {
    {
        .compatible = "ti,omap4-gpio",
        .data = &omap4_pdata,
    },
    {
        .compatible = "ti,omap3-gpio",
        .data = &omap3_pdata,
    },
    {
        .compatible = "ti,omap2-gpio",
        .data = &omap2_pdata,
    },
    { },
};
MODULE_DEVICE_TABLE(of, omap_gpio_match);

static struct platform_driver omap_gpio_driver = {
    .probe      = omap_gpio_probe,
    .driver     = {
        .name   = "omap_gpio",
        .pm = &gpio_pm_ops,
        .of_match_table = of_match_ptr(omap_gpio_match),
    },
};

The driver is able to drive three types of GPIOs, including the one mentioned before.

Please note that platform devices are not magically added to the platform bus. The architecture/board initialization will call platform_device_add or platform_add_devices, in this case with the help of OF functions to scan the tree.

Name matching

If you look at platform_match, you will see that the match falls back to name matching. A simple string comparison is done between the driver name and the device name. This is how older platform driver worked. Some of them still do, like this one here:

static struct platform_driver imx_ssi_driver = {
    .probe = imx_ssi_probe,
    .remove = imx_ssi_remove,

    .driver = {
        .name = "imx-ssi",
        .owner = THIS_MODULE,
    },
};

module_platform_driver(imx_ssi_driver);

Again, the board specific initialization will have to call platform_device_add or platform_add_devices to add platform devices, which in the case of name matching ones are entirely created statically in C (name is given in C, resources like IRQs and base addresses, etc.).

OTHER TIPS

In the Linux kernel there are different buses (SPI, I2C, PCI, USB, ...).

Each bus has the list of drivers and devices that are registered on the bus.

Each time you connect a new device or a new driver to a bus, it starts the matching loop.

Suppose that you register a new SPI device. The SPI bus start a matching loop where it invokes the SPI match function to verify if your device match with a driver already registered in on the bus. If it does not match, there is nothing to do.

Now, suppose that you register a new SPI driver. The bus start again the matching loop in order to verify if any of the registered device match with this new driver. If it match, the driver probe() function is invoked.

Each bus has it own method to match a driver with a device. In order to implement a bus you have to write the matching function. So, you can implement a bus that match by name, by integer value, or anything you want.

You start the bus mechanism each time you register a driver or a device.

Here how I implemented the ZIO bus. Here you can find the SPI bus Here the core of the bus system

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top