[RFC] early init and DT platform devices allocation/registration
Hiroshi Doyu
hdoyu at nvidia.com
Wed Jun 26 02:36:28 EST 2013
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.
>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