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