How devices in device tree and platform drivers were connected
Solution 1
The canonical answer to your question can be found at LWN: Platform Devices and Device Trees. What you need is the proper guidance on using it. A Tutorial on the Device Tree is a reasonable instruction guide. For background, you should read about Linux and the Device Tree. Also, elinux.org has a few wikis that should help, like Device Tree Linux and Device Tree Usage and Device Tree Reference.
Solution 2
in the probe function of the driver there has to be/must be this line :
probe(struct bus_client *client,
const struct bus_device_id *id)
{
const struct of_device_id *match;
match = of_match_device(omap_gpio_match);
if (!match)
return -ENODEV;
else
//write the driver stuff for Probe
This is how the device tree is linked with your driver. omap_gpio_match you have already linked with the "compatible id" which you have defined in the device tree and thats how driver has been linked with the device tree.
Related videos on Youtube
jianing
Updated on June 04, 2022Comments
-
jianing almost 2 years
I read some articles about this topic. but none of them describes the details.
What I know is:
declare "compatible" property in Device tree:
gpio0: gpio@44e07000 { compatible = "ti,omap4-gpio"; ... };
and make the connection to platform driver by
static const struct of_device_id omap_gpio_match[] = { { .compatible = "ti,omap4-gpio", }, { }, }; ... 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), }, };
and as a result, of_match_table will be used to match the compatible property declared in Device Tree.
and the match action performed in platform_match (
drivers/base/platform.c
) function. I doubt this because the I greped reference of of_match_table and the only probable result located in of_device_get_match_data (drivers/of/device.c
) function.~/wk/linux$ find . -name '*.c' | xargs grep '\<of_match_table\>' | grep -v -E 'of_match_table\s+=' ./drivers/dma/sirf-dma.c: (of_match_device(op->dev.driver->of_match_table, ./drivers/macintosh/macio_asic.c: const struct of_device_id * matches = drv->of_match_table; ./drivers/macintosh/macio_asic.c: match = of_match_device(drv->driver.of_match_table, dev); ./drivers/nvmem/mxs-ocotp.c: match = of_match_device(dev->driver->of_match_table, dev); ./drivers/reset/sti/reset-syscfg.c: match = of_match_device(dev->driver->of_match_table, dev); ./drivers/mtd/devices/m25p80.c: * matching for .of_match_table ./drivers/soc/rockchip/pm_domains.c: match = of_match_device(dev->driver->of_match_table, dev); ./drivers/phy/phy-rockchip-usb.c: match = of_match_device(dev->driver->of_match_table, dev); ./drivers/acpi/bus.c: * @of_match_table: List of device IDs to match against. ./drivers/acpi/bus.c: const struct of_device_id *of_match_table) ./drivers/acpi/bus.c: if (!of_match_table || !of_compatible) ./drivers/acpi/bus.c: for (id = of_match_table; id->compatible[0]; id++) ./drivers/acpi/bus.c: drv->of_match_table); ./drivers/acpi/bus.c: drv->acpi_match_table, drv->of_match_table); ./drivers/pci/host/pcie-hisi.c: match = of_match_device(driver->of_match_table, &pdev->dev); ./drivers/pinctrl/stm32/pinctrl-stm32.c: match = of_match_device(dev->driver->of_match_table, dev); ./drivers/of/device.c: match = of_match_device(dev->driver->of_match_table, dev); ./drivers/mfd/axp20x.c: of_id = of_match_device(dev->driver->of_match_table, dev); ./drivers/gpu/drm/armada/armada_crtc.c: match = of_match_device(dev->driver->of_match_table, dev); ./arch/powerpc/kernel/ibmebus.c: ibmebus_create_devices(drv->driver.of_match_table); ./arch/powerpc/kernel/ibmebus.c: const struct of_device_id *matches = drv->of_match_table; ./sound/soc/qcom/lpass-cpu.c: match = of_match_device(dev->driver->of_match_table, dev);
But this function is not used in some common modules.
~/wk/linux$ find . -name '*.c' | xargs grep of_device_get_match_data ./drivers/dma/sh/shdmac.c: pdata = of_device_get_match_data(&pdev->dev); ./drivers/dma/tegra210-adma.c: cdata = of_device_get_match_data(&pdev->dev); ./drivers/dma/tegra20-apb-dma.c: cdata = of_device_get_match_data(&pdev->dev); ./drivers/usb/host/xhci-tegra.c: tegra->soc = of_device_get_match_data(&pdev->dev); ./drivers/usb/phy/phy-msm-usb.c: pdata->phy_type = (enum msm_usb_phy_type)of_device_get_match_data(&pdev->dev); ./drivers/mtd/spi-nor/fsl-quadspi.c: q->devtype_data = of_device_get_match_data(dev); ./drivers/mtd/nand/qcom_nandc.c: dev_data = of_device_get_match_data(dev); ./drivers/mtd/nand/atmel_nand.c: of_device_get_match_data(host->dev); ./drivers/rtc/rtc-sunxi.c: chip->data_year = of_device_get_match_data(&pdev->dev); ./drivers/spi/spi-mpc512x-psc.c: mps->type = (int)of_device_get_match_data(dev); ./drivers/watchdog/mpc8xxx_wdt.c: wdt_type = of_device_get_match_data(&ofdev->dev); ./drivers/phy/phy-exynos-mipi-video.c: phy_dev = of_device_get_match_data(dev); ./drivers/phy/phy-sun4i-usb.c: data->cfg = of_device_get_match_data(dev); ./drivers/pci/host/pci-imx6.c: (enum imx6_pcie_variants)of_device_get_match_data(&pdev->dev); ./drivers/pci/host/pcie-qcom.c: pcie->ops = (struct qcom_pcie_ops *)of_device_get_match_data(dev); ./drivers/i2c/busses/i2c-rcar.c: priv->devtype = (enum rcar_i2c_type)of_device_get_match_data(dev); ./drivers/i2c/busses/i2c-tegra.c: i2c_dev->hw = of_device_get_match_data(&pdev->dev); ./drivers/tty/serial/imx.c: sport->devdata = of_device_get_match_data(&pdev->dev); ./drivers/gpio/gpio-mpc8xxx.c: of_device_get_match_data(&pdev->dev); ./drivers/gpio/gpio-tegra.c: config = of_device_get_match_data(&pdev->dev); ./drivers/clk/clk-palmas.c: match_data = of_device_get_match_data(&pdev->dev); ./drivers/input/misc/pmic8xxx-pwrkey.c: pwrkey->shutdown_fn = of_device_get_match_data(&pdev->dev); ./drivers/input/touchscreen/edt-ft5x06.c: chip_data = of_device_get_match_data(&client->dev); ./drivers/pinctrl/sh-pfc/core.c: info = of_device_get_match_data(&pdev->dev); ./drivers/thermal/rcar_thermal.c: unsigned long of_data = (unsigned long)of_device_get_match_data(dev); ./drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c: data = of_device_get_match_data(&pdev->dev); ./drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c: data = of_device_get_match_data(&pdev->dev); ./drivers/net/ethernet/renesas/sh_eth.c: mdp->cd = (struct sh_eth_cpu_data *)of_device_get_match_data(&pdev->dev); ./drivers/net/ethernet/renesas/ravb_main.c: chip_id = (enum ravb_chip_id)of_device_get_match_data(&pdev->dev); ./drivers/of/device.c:const void *of_device_get_match_data(const struct device *dev) ./drivers/of/device.c:EXPORT_SYMBOL(of_device_get_match_data); ./drivers/gpu/drm/nouveau/nouveau_platform.c: func = of_device_get_match_data(&pdev->dev); ./drivers/gpu/drm/exynos/exynos_drm_rotator.c: of_device_get_match_data(dev); ./drivers/gpu/drm/exynos/exynos_mixer.c: drv = of_device_get_match_data(dev); ./drivers/gpu/drm/exynos/exynos5433_drm_decon.c: ctx->out_type = (unsigned long)of_device_get_match_data(dev); ./drivers/gpu/drm/exynos/exynos_drm_fimd.c: ctx->driver_data = of_device_get_match_data(dev); ./drivers/gpu/drm/exynos/exynos_hdmi.c: hdata->drv_data = of_device_get_match_data(dev); ./drivers/gpu/drm/exynos/exynos_drm_dsi.c: dsi->driver_data = of_device_get_match_data(dev); ./drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c: dc_ops = (struct kirin_dc_ops *)of_device_get_match_data(dev); ./drivers/gpu/drm/msm/hdmi/hdmi_phy.c: phy->cfg = (struct hdmi_phy_cfg *)of_device_get_match_data(dev); ./drivers/gpu/drm/msm/hdmi/hdmi.c: of_device_get_match_data(dev); ./drivers/gpu/drm/msm/msm_drv.c: return (int) (unsigned long) of_device_get_match_data(dev); ./drivers/gpu/drm/rockchip/rockchip_drm_vop.c: vop_data = of_device_get_match_data(dev); ./sound/soc/sh/rcar/core.c: priv->flags = (unsigned long)of_device_get_match_data(dev); ./sound/soc/sh/rcar/rsrc-card.c: of_data = of_device_get_match_data(dev); ./sound/soc/sh/rcar/rsrc-card.c: const struct rsrc_card_of_data *of_data = of_device_get_match_data(dev);
anyone can give some useful information?
-
0andriy over 7 yearsAll ID tables (in your case OF tables) are packed in the special section in the kernel binary (and thus in the memory when loaded and unpacked). The OF core during intialization takes on input the DT blob and matches each compatible string from the DT with the list of registered (made duting compilation of kernel) drivers. Besides that the depmod database and device helper (udev, for example) help with resolving dependencies.
-
0andriy over 7 yearsAnd for the future a hint: use
git grep
instead of what you did with shell.git grep -n -w of_device_get_match_data
. -
jianing over 7 yearsthank you Andy, this
git grep
is great useful.
-
-
0andriy over 7 yearsNo, this is wrong since core takes care about it. See my comment above