2016-07-21 2 views
2

Я прочитал несколько статей по этой теме. но ни одна из них не описывает детали.Как подключались устройства в дереве устройств и драйверах платформы

То, что я знаю:

объявить "совместимый" свойство в дереве устройств:

gpio0: [email protected] { 
    compatible = "ti,omap4-gpio"; 
    ... 
}; 

и сделать связь с водителем платформы по

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), 
    }, 
}; 

и в результате , of_match_table будет использоваться для соответствия ible, объявленное в дереве устройств.

и действие по итогам матча, выполненное в platform_match (drivers/base/platform.c) функция. Я сомневаюсь в этом, потому что я скопировал ссылку of_match_table и единственный вероятный результат, расположенный в of_device_get_match_data (drivers/of/device.c).

~/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); 

Но эта функция не используется в некоторых распространенных модулях.

~/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); 

Любой может предоставить полезную информацию?

+0

Все идентификационные таблицы (в вашем случае таблицы OF) упакованы в специальный раздел в двоичном формате ядра (и, следовательно, в памяти при загрузке и распаковке). Ядро OF во время intialization берет на вход DT blob и сопоставляет каждую совместимую строку с DT со списком ** зарегистрированных ** (сделанных компиляцией ядра ядра) драйверов. Кроме того, база данных depmod и помощник устройства (например, udev) помогают в разрешении зависимостей. – 0andriy

+0

И для будущего намек: используйте 'git grep' вместо того, что вы сделали с оболочкой. 'git grep -n -w of_device_get_match_data'. – 0andriy

+0

спасибо Энди, этот «git grep» очень полезен. – jianing

ответ

1

в пробной функции водителя там должно быть/должна быть эта строка:

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 

Это как дерево устройство связано с драйвером. omap_gpio_match, вы уже связаны с «совместимым идентификатором», который вы определили в дереве устройств, и каким образом драйвер был связан с деревом устройств.

+0

Нет, это неправильно, поскольку ядро ​​заботится об этом. Смотрите мой комментарий выше – 0andriy

1

Канонический ответ на ваш вопрос можно найти на LWN: Platform Devices and Device Trees. Что вам нужно, это правильное руководство по его использованию. A Tutorial on the Device Tree - разумное руководство по эксплуатации. Для фона, вы должны прочитать о Linux and the Device Tree. Кроме того, у elinux.org есть несколько вики, которые должны помочь, например Device Tree Linux и Device Tree Usage и Device Tree Reference.

Смежные вопросы