[RFC] early init and DT platform devices allocation/registration

Grant Likely grant.likely at secretlab.ca
Wed Jun 26 03:52:33 EST 2013


On Tue, Jun 25, 2013 at 5:36 PM, Hiroshi Doyu <hdoyu at nvidia.com> wrote:
> Stephen Warren <swarren at wwwdotorg.org> wrote @ Tue, 25 Jun 2013 16:56:22 +0200:
>
>> >> How this problem is supposed to be solved in the kernel ?
>> >>
>> >> 1- drivers that are to be up and running at early_initcall time must not
>> >>    rely on the device/driver model (but then they cannot use any API that
>> >>    requires a struct device to function (eg regmap))
>> >> 2- the driver should allocate a platform device at early initcall from
>> >>    a DT compatible node. Do not know how to deal with platform device
>> >>    duplication though, since of_platform_populate() will create another
>> >>    platform device when the node is parsed
>> >
>> > While I've resisted it in the past, I would be okay with adding struct
>> > device pointer in the device_node structure. I've resisted because I
>> > don't want drivers following the device_node pointer and making an
>> > assumption about what /kind/ of device is pointed to by it. However,
>> > this is an important use case and it makes it feasible to use an early
>> > platform device with of_platform_populate.
>>
>> Hiroshi (who I have CC'd here) has also been asking about this same
>> issue downstream. The issue for us is that we need to initialize an SMMU
>> driver before any devices that are translated by the SMMU. One option is
>> to force the register/probe of the SMMU driver explicitly, early in the
>> machine's .init_machine() callback, before of_platform_populate(), to
>> ensure the ordering. Then, we run into the same duplicate device issue,
>> and the change Grant mentions above would help solve this.
>
> Here's my workaround. I need to call of_detach_node() with OF_DYNAMIC
> to avoid duplicated device registration.

Gah! my eyes!

Don't do that. It is incredibly problematic. Look at inhibiting
duplicate device creation instead.

g.

>
> From f4d88b8521c278b41b72028d326c03cfd2e90af8 Mon Sep 17 00:00:00 2001
> From: Hiroshi Doyu <hdoyu at nvidia.com>
> Date: Fri, 14 Jun 2013 15:22:02 +0300
> Subject: [PATCH 1/1] ARM: tegra: Populate AHB/IOMMU earlier than others
>
> Populate AHB/IOMMU earlier than others. IOMMU depends on AHB. IOMMU
> needs to be instanciated earlier than others so that IOMMU can
> register other platform devices as IOMMU'able. Once IOMMU is
> populated, IOMMU/AHB nodes are detached to prevent another
> registeration.
>
> Signed-off-by: Hiroshi Doyu <hdoyu at nvidia.com>
> ---
>  arch/arm/mach-tegra/Kconfig |  1 +
>  arch/arm/mach-tegra/tegra.c | 24 ++++++++++++++++++++++++
>  drivers/iommu/tegra-smmu.c  |  3 +++
>  3 files changed, 28 insertions(+)
>
> diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
> index ef3a8da..79905fe 100644
> --- a/arch/arm/mach-tegra/Kconfig
> +++ b/arch/arm/mach-tegra/Kconfig
> @@ -15,6 +15,7 @@ config ARCH_TEGRA
>         select SOC_BUS
>         select SPARSE_IRQ
>         select USE_OF
> +       select OF_DYNAMIC
>         help
>           This enables support for NVIDIA Tegra based systems.
>
> diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
> index 0d1e412..0c494b5 100644
> --- a/arch/arm/mach-tegra/tegra.c
> +++ b/arch/arm/mach-tegra/tegra.c
> @@ -80,6 +80,28 @@ static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
>         {}
>  };
>
> +static void tegra_of_platform_populate_iommu(void)
> +{
> +       int i;
> +       struct platform_device *pdev;
> +       const char * const dname[] = {"ahb", "iommu", };
> +
> +       for (i = 0; i < ARRAY_SIZE(dname); i++) {
> +               struct device_node *np;
> +               char path[NAME_MAX];
> +
> +               snprintf(path, sizeof(path), "/%s", dname[i]);
> +               np  = of_find_node_by_path(path);
> +               if (!np)
> +                       break;
> +
> +               pdev = of_platform_device_create(np, NULL, NULL);
> +               of_node_put(np);
> +               if (!pdev)
> +                       break;
> +       }
> +}
> +
>  static void __init tegra_dt_init(void)
>  {
>         struct soc_device_attribute *soc_dev_attr;
> @@ -107,6 +129,8 @@ static void __init tegra_dt_init(void)
>
>         parent = soc_device_to_device(soc_dev);
>
> +       tegra_of_platform_populate_iommu();
> +
>         /*
>          * Finished with the static registrations now; fill in the missing
>          * devices
> diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
> index f6f120e..6c9de3f 100644
> --- a/drivers/iommu/tegra-smmu.c
> +++ b/drivers/iommu/tegra-smmu.c
> @@ -1238,6 +1238,9 @@ static int tegra_smmu_probe(struct platform_device *pdev)
>         smmu_debugfs_create(smmu);
>         smmu_handle = smmu;
>         bus_set_iommu(&platform_bus_type, &smmu_iommu_ops);
> +
> +       of_detach_node(dev->of_node);
> +       of_detach_node(smmu->ahb);
>         return 0;
>  }
>
> --
> 1.8.1.5
>


More information about the devicetree-discuss mailing list