Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How devices in device tree and platform drivers were connected

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?

like image 447
jianing Avatar asked Jul 21 '16 02:07

jianing


People also ask

What is difference between platform driver and device driver?

Platform driver is for those devices that are on chip. Normal device driver are for those that are interfaced to the processor chip.

How does a device tree work?

A device tree represents the hardware. The information in a device tree comes from sources such as hardware specifications and board schematics. The resolved DTS and DTSI files for a device are represented as an FDT structure. The device tree compiler (DTC) compiles the FDT structure into a DTB file.

How are kernel and device tree linked?

A device tree is a tree data structure that describes the hardware configuration of the system to the Linux operating system. During boot, the Linux kernel will use the information in the device tree to recognize, load appropriate drivers and manage the hardware devices in the system.

What is a platform device driver?

Platform drivers are dedicated to devices not based on conventional buses. I2C devices or SPI devices are platform devices, but respectively rely on I2C or SPI buses not on the platform bus. Everything needs to be done manually with the platform driver.


2 Answers

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.

like image 196
Raulp Avatar answered Oct 07 '22 01:10

Raulp


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.

like image 32
JonS Avatar answered Oct 07 '22 01:10

JonS