Re: [RFC 04/10] memory: Add Tegra124 memory controller support
Thierry Reding writes: > diff --git a/include/dt-bindings/memory/tegra124-mc.h > b/include/dt-bindings/memory/tegra124-mc.h > new file mode 100644 > index ..6b1617ce022f > --- /dev/null > +++ b/include/dt-bindings/memory/tegra124-mc.h > @@ -0,0 +1,30 @@ > +#ifndef DT_BINDINGS_MEMORY_TEGRA124_MC_H > +#define DT_BINDINGS_MEMORY_TEGRA124_MC_H > + > +#define TEGRA_SWGROUP_DC 0 > +#define TEGRA_SWGROUP_DCB 1 > +#define TEGRA_SWGROUP_AFI 2 > +#define TEGRA_SWGROUP_AVPC 3 > +#define TEGRA_SWGROUP_HDA 4 > +#define TEGRA_SWGROUP_HC 5 > +#define TEGRA_SWGROUP_MSENC6 > +#define TEGRA_SWGROUP_PPCS 7 > +#define TEGRA_SWGROUP_SATA 8 > +#define TEGRA_SWGROUP_VDE 9 > +#define TEGRA_SWGROUP_MPCORELP 10 > +#define TEGRA_SWGROUP_MPCORE 11 > +#define TEGRA_SWGROUP_ISP2 12 > +#define TEGRA_SWGROUP_XUSB_HOST13 > +#define TEGRA_SWGROUP_XUSB_DEV 14 > +#define TEGRA_SWGROUP_ISP2B15 > +#define TEGRA_SWGROUP_TSEC 16 > +#define TEGRA_SWGROUP_A9AVP17 > +#define TEGRA_SWGROUP_GPU 18 > +#define TEGRA_SWGROUP_SDMMC1A 19 > +#define TEGRA_SWGROUP_SDMMC2A 20 > +#define TEGRA_SWGROUP_SDMMC3A 21 > +#define TEGRA_SWGROUP_SDMMC4A 22 > +#define TEGRA_SWGROUP_VIC 23 > +#define TEGRA_SWGROUP_VI 24 > + > +#endif In the SMMUv8 patch series, I have assigned unique IDs for all those HWAs among Tegra SoC generations so that DT can provide which HWAs are attached to that SoC. The SMMUv8 driver would be unified among Tegra SoCs, then. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC 04/10] memory: Add Tegra124 memory controller support
Thierry Reding thierry.red...@gmail.com writes: diff --git a/include/dt-bindings/memory/tegra124-mc.h b/include/dt-bindings/memory/tegra124-mc.h new file mode 100644 index ..6b1617ce022f --- /dev/null +++ b/include/dt-bindings/memory/tegra124-mc.h @@ -0,0 +1,30 @@ +#ifndef DT_BINDINGS_MEMORY_TEGRA124_MC_H +#define DT_BINDINGS_MEMORY_TEGRA124_MC_H + +#define TEGRA_SWGROUP_DC 0 +#define TEGRA_SWGROUP_DCB 1 +#define TEGRA_SWGROUP_AFI 2 +#define TEGRA_SWGROUP_AVPC 3 +#define TEGRA_SWGROUP_HDA 4 +#define TEGRA_SWGROUP_HC 5 +#define TEGRA_SWGROUP_MSENC6 +#define TEGRA_SWGROUP_PPCS 7 +#define TEGRA_SWGROUP_SATA 8 +#define TEGRA_SWGROUP_VDE 9 +#define TEGRA_SWGROUP_MPCORELP 10 +#define TEGRA_SWGROUP_MPCORE 11 +#define TEGRA_SWGROUP_ISP2 12 +#define TEGRA_SWGROUP_XUSB_HOST13 +#define TEGRA_SWGROUP_XUSB_DEV 14 +#define TEGRA_SWGROUP_ISP2B15 +#define TEGRA_SWGROUP_TSEC 16 +#define TEGRA_SWGROUP_A9AVP17 +#define TEGRA_SWGROUP_GPU 18 +#define TEGRA_SWGROUP_SDMMC1A 19 +#define TEGRA_SWGROUP_SDMMC2A 20 +#define TEGRA_SWGROUP_SDMMC3A 21 +#define TEGRA_SWGROUP_SDMMC4A 22 +#define TEGRA_SWGROUP_VIC 23 +#define TEGRA_SWGROUP_VI 24 + +#endif In the SMMUv8 patch series, I have assigned unique IDs for all those HWAs among Tegra SoC generations so that DT can provide which HWAs are attached to that SoC. The SMMUv8 driver would be unified among Tegra SoCs, then. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC 04/10] memory: Add Tegra124 memory controller support
Thierry Reding writes: > From: Thierry Reding > > The memory controller on NVIDIA Tegra124 exposes various knobs that can > be used to tune the behaviour of the clients attached to it. > > Currently this driver sets up the latency allowance registers to the HW > defaults. Eventually an API should be exported by this driver (via a > custom API or a generic subsystem) to allow clients to register latency > requirements. > > This driver also registers an IOMMU (SMMU) that's implemented by the > memory controller. > > Signed-off-by: Thierry Reding > --- > drivers/memory/Kconfig |9 + > drivers/memory/Makefile |1 + > drivers/memory/tegra124-mc.c | 1945 > ++ > include/dt-bindings/memory/tegra124-mc.h | 30 + > 4 files changed, 1985 insertions(+) > create mode 100644 drivers/memory/tegra124-mc.c > create mode 100644 include/dt-bindings/memory/tegra124-mc.h I prefer reusing the existing SMMU and having MC and SMMU separated since most of SMMU code are not different from functionality POV, and new MC features are quite independent of SMMU. If it's really convenient to combine MC and SMMU into one driver, we could move "drivers/iomm/tegra-smmu.c" here first, and add MC features on the top of it. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC 09/10] drm/tegra: Add IOMMU support
Thierry Reding writes: > From: Thierry Reding > > When an IOMMU device is available on the platform bus, allocate an IOMMU > domain and attach the display controllers to it. The display controllers > can then scan out non-contiguous buffers by mapping them through the > IOMMU. > > Signed-off-by: Thierry Reding > --- > drivers/gpu/drm/tegra/dc.c | 21 > drivers/gpu/drm/tegra/drm.c | 17 > drivers/gpu/drm/tegra/drm.h | 3 + > drivers/gpu/drm/tegra/fb.c | 16 ++- > drivers/gpu/drm/tegra/gem.c | 236 > +++- > drivers/gpu/drm/tegra/gem.h | 4 + > 6 files changed, 273 insertions(+), 24 deletions(-) > > diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c > index afcca04f5367..0f7452d04811 100644 > --- a/drivers/gpu/drm/tegra/dc.c > +++ b/drivers/gpu/drm/tegra/dc.c > @@ -9,6 +9,7 @@ > > #include > #include > +#include > #include > > #include "dc.h" > @@ -1283,8 +1284,18 @@ static int tegra_dc_init(struct host1x_client *client) > { > struct drm_device *drm = dev_get_drvdata(client->parent); > struct tegra_dc *dc = host1x_client_to_dc(client); > + struct tegra_drm *tegra = drm->dev_private; > int err; > > + if (tegra->domain) { > + err = iommu_attach_device(tegra->domain, dc->dev); I wanted to keep device drivers iommu-free with the following: http://patchwork.ozlabs.org/patch/354074/ > + if (err < 0) { > + dev_err(dc->dev, "failed to attach to IOMMU: %d\n", > + err); > + return err; > + } > + } > + > drm_crtc_init(drm, >base, _crtc_funcs); > drm_mode_crtc_set_gamma_size(>base, 256); > drm_crtc_helper_add(>base, _crtc_helper_funcs); > @@ -1318,7 +1329,9 @@ static int tegra_dc_init(struct host1x_client *client) > > static int tegra_dc_exit(struct host1x_client *client) > { > + struct drm_device *drm = dev_get_drvdata(client->parent); > struct tegra_dc *dc = host1x_client_to_dc(client); > + struct tegra_drm *tegra = drm->dev_private; > int err; > > devm_free_irq(dc->dev, dc->irq, dc); > @@ -1335,6 +1348,8 @@ static int tegra_dc_exit(struct host1x_client *client) > return err; > } > > + iommu_detach_device(tegra->domain, dc->dev); > + > return 0; > } > > @@ -1462,6 +1477,12 @@ static int tegra_dc_probe(struct platform_device *pdev) > return -ENXIO; > } > > + err = iommu_attach(>dev); > + if (err < 0) { > + dev_err(>dev, "failed to attach to IOMMU: %d\n", err); > + return err; > + } > + > INIT_LIST_HEAD(>client.list); > dc->client.ops = _client_ops; > dc->client.dev = >dev; > diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c > index 59736bb810cd..1d2bbafad982 100644 > --- a/drivers/gpu/drm/tegra/drm.c > +++ b/drivers/gpu/drm/tegra/drm.c > @@ -8,6 +8,7 @@ > */ > > #include > +#include > > #include "drm.h" > #include "gem.h" > @@ -33,6 +34,16 @@ static int tegra_drm_load(struct drm_device *drm, unsigned > long flags) > if (!tegra) > return -ENOMEM; > > + if (iommu_present(_bus_type)) { > + tegra->domain = iommu_domain_alloc(_bus_type); Can we use "dma_iommu_mapping" instead of domain? I thought that DMA API is on the top of IOMMU API so that it may be cleaner to use only DMA API. > + if (IS_ERR(tegra->domain)) { > + kfree(tegra); > + return PTR_ERR(tegra->domain); > + } > + > + drm_mm_init(>mm, 0, SZ_2G); > + } > + > mutex_init(>clients_lock); > INIT_LIST_HEAD(>clients); > drm->dev_private = tegra; > @@ -71,6 +82,7 @@ static int tegra_drm_load(struct drm_device *drm, unsigned > long flags) > static int tegra_drm_unload(struct drm_device *drm) > { > struct host1x_device *device = to_host1x_device(drm->dev); > + struct tegra_drm *tegra = drm->dev_private; > int err; > > drm_kms_helper_poll_fini(drm); > @@ -82,6 +94,11 @@ static int tegra_drm_unload(struct drm_device *drm) > if (err < 0) > return err; > > + if (tegra->domain) { > + iommu_domain_free(tegra->domain); > + drm_mm_takedown(>mm); > + } > + > return 0; > } > > diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h > index 96d754e7b3eb..a07c796b7edc 100644 > --- a/drivers/gpu/drm/tegra/drm.h > +++ b/drivers/gpu/drm/tegra/drm.h > @@ -39,6 +39,9 @@ struct tegra_fbdev { > struct tegra_drm { > struct drm_device *drm; > > + struct iommu_domain *domain; > + struct drm_mm mm; > + > struct mutex clients_lock; > struct list_head clients; > > diff --git a/drivers/gpu/drm/tegra/fb.c
Re: [RFC 10/10] mmc: sdhci-tegra: Add IOMMU support
Thierry Reding writes: > From: Thierry Reding > > Attach to the device's master interface of the IOMMU at .probe() time. > IOMMU support becomes available via the DMA mapping API interoperation > code, but this explicit attachment is necessary to ensure proper probe > order. > > Signed-off-by: Thierry Reding > --- > drivers/mmc/host/sdhci-tegra.c | 8 > 1 file changed, 8 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c > index 33100d10d176..b884614fa4e6 100644 > --- a/drivers/mmc/host/sdhci-tegra.c > +++ b/drivers/mmc/host/sdhci-tegra.c > @@ -15,6 +15,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -237,6 +238,11 @@ static int sdhci_tegra_probe(struct platform_device > *pdev) > match = of_match_device(sdhci_tegra_dt_match, >dev); > if (!match) > return -EINVAL; > + > + rc = iommu_attach(>dev); > + if (rc < 0) > + return rc; > + I thought that, if we consider that ->probe() should include minimal H/W probing so that DMA API call in ->probe() could be deferred after ->probe() and till it's in use actually, like opening a device node. For me this decision(minimal h/w probe) seemed logical but it would add a new restriction. One advantage is that we could still keep all drivers wihtout any IOMMU code if it doesn't call DMA API in ->probe(). > soc_data = match->data; > > host = sdhci_pltfm_init(pdev, soc_data->pdata, 0); > @@ -310,6 +316,8 @@ static int sdhci_tegra_remove(struct platform_device > *pdev) > clk_disable_unprepare(pltfm_host->clk); > clk_put(pltfm_host->clk); > > + iommu_detach(>dev); > + > sdhci_pltfm_free(pdev); > > return 0; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC 09/10] drm/tegra: Add IOMMU support
Thierry Reding thierry.red...@gmail.com writes: From: Thierry Reding tred...@nvidia.com When an IOMMU device is available on the platform bus, allocate an IOMMU domain and attach the display controllers to it. The display controllers can then scan out non-contiguous buffers by mapping them through the IOMMU. Signed-off-by: Thierry Reding tred...@nvidia.com --- drivers/gpu/drm/tegra/dc.c | 21 drivers/gpu/drm/tegra/drm.c | 17 drivers/gpu/drm/tegra/drm.h | 3 + drivers/gpu/drm/tegra/fb.c | 16 ++- drivers/gpu/drm/tegra/gem.c | 236 +++- drivers/gpu/drm/tegra/gem.h | 4 + 6 files changed, 273 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index afcca04f5367..0f7452d04811 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -9,6 +9,7 @@ #include linux/clk.h #include linux/debugfs.h +#include linux/iommu.h #include linux/reset.h #include dc.h @@ -1283,8 +1284,18 @@ static int tegra_dc_init(struct host1x_client *client) { struct drm_device *drm = dev_get_drvdata(client-parent); struct tegra_dc *dc = host1x_client_to_dc(client); + struct tegra_drm *tegra = drm-dev_private; int err; + if (tegra-domain) { + err = iommu_attach_device(tegra-domain, dc-dev); I wanted to keep device drivers iommu-free with the following: http://patchwork.ozlabs.org/patch/354074/ + if (err 0) { + dev_err(dc-dev, failed to attach to IOMMU: %d\n, + err); + return err; + } + } + drm_crtc_init(drm, dc-base, tegra_crtc_funcs); drm_mode_crtc_set_gamma_size(dc-base, 256); drm_crtc_helper_add(dc-base, tegra_crtc_helper_funcs); @@ -1318,7 +1329,9 @@ static int tegra_dc_init(struct host1x_client *client) static int tegra_dc_exit(struct host1x_client *client) { + struct drm_device *drm = dev_get_drvdata(client-parent); struct tegra_dc *dc = host1x_client_to_dc(client); + struct tegra_drm *tegra = drm-dev_private; int err; devm_free_irq(dc-dev, dc-irq, dc); @@ -1335,6 +1348,8 @@ static int tegra_dc_exit(struct host1x_client *client) return err; } + iommu_detach_device(tegra-domain, dc-dev); + return 0; } @@ -1462,6 +1477,12 @@ static int tegra_dc_probe(struct platform_device *pdev) return -ENXIO; } + err = iommu_attach(pdev-dev); + if (err 0) { + dev_err(pdev-dev, failed to attach to IOMMU: %d\n, err); + return err; + } + INIT_LIST_HEAD(dc-client.list); dc-client.ops = dc_client_ops; dc-client.dev = pdev-dev; diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 59736bb810cd..1d2bbafad982 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -8,6 +8,7 @@ */ #include linux/host1x.h +#include linux/iommu.h #include drm.h #include gem.h @@ -33,6 +34,16 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) if (!tegra) return -ENOMEM; + if (iommu_present(platform_bus_type)) { + tegra-domain = iommu_domain_alloc(platform_bus_type); Can we use dma_iommu_mapping instead of domain? I thought that DMA API is on the top of IOMMU API so that it may be cleaner to use only DMA API. + if (IS_ERR(tegra-domain)) { + kfree(tegra); + return PTR_ERR(tegra-domain); + } + + drm_mm_init(tegra-mm, 0, SZ_2G); + } + mutex_init(tegra-clients_lock); INIT_LIST_HEAD(tegra-clients); drm-dev_private = tegra; @@ -71,6 +82,7 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) static int tegra_drm_unload(struct drm_device *drm) { struct host1x_device *device = to_host1x_device(drm-dev); + struct tegra_drm *tegra = drm-dev_private; int err; drm_kms_helper_poll_fini(drm); @@ -82,6 +94,11 @@ static int tegra_drm_unload(struct drm_device *drm) if (err 0) return err; + if (tegra-domain) { + iommu_domain_free(tegra-domain); + drm_mm_takedown(tegra-mm); + } + return 0; } diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 96d754e7b3eb..a07c796b7edc 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -39,6 +39,9 @@ struct tegra_fbdev { struct tegra_drm { struct drm_device *drm; + struct iommu_domain *domain; + struct drm_mm mm; + struct mutex clients_lock; struct list_head clients; diff --git
Re: [RFC 10/10] mmc: sdhci-tegra: Add IOMMU support
Thierry Reding thierry.red...@gmail.com writes: From: Thierry Reding tred...@nvidia.com Attach to the device's master interface of the IOMMU at .probe() time. IOMMU support becomes available via the DMA mapping API interoperation code, but this explicit attachment is necessary to ensure proper probe order. Signed-off-by: Thierry Reding tred...@nvidia.com --- drivers/mmc/host/sdhci-tegra.c | 8 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 33100d10d176..b884614fa4e6 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -15,6 +15,7 @@ #include linux/err.h #include linux/module.h #include linux/init.h +#include linux/iommu.h #include linux/platform_device.h #include linux/clk.h #include linux/io.h @@ -237,6 +238,11 @@ static int sdhci_tegra_probe(struct platform_device *pdev) match = of_match_device(sdhci_tegra_dt_match, pdev-dev); if (!match) return -EINVAL; + + rc = iommu_attach(pdev-dev); + if (rc 0) + return rc; + I thought that, if we consider that -probe() should include minimal H/W probing so that DMA API call in -probe() could be deferred after -probe() and till it's in use actually, like opening a device node. For me this decision(minimal h/w probe) seemed logical but it would add a new restriction. One advantage is that we could still keep all drivers wihtout any IOMMU code if it doesn't call DMA API in -probe(). soc_data = match-data; host = sdhci_pltfm_init(pdev, soc_data-pdata, 0); @@ -310,6 +316,8 @@ static int sdhci_tegra_remove(struct platform_device *pdev) clk_disable_unprepare(pltfm_host-clk); clk_put(pltfm_host-clk); + iommu_detach(pdev-dev); + sdhci_pltfm_free(pdev); return 0; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC 04/10] memory: Add Tegra124 memory controller support
Thierry Reding thierry.red...@gmail.com writes: From: Thierry Reding tred...@nvidia.com The memory controller on NVIDIA Tegra124 exposes various knobs that can be used to tune the behaviour of the clients attached to it. Currently this driver sets up the latency allowance registers to the HW defaults. Eventually an API should be exported by this driver (via a custom API or a generic subsystem) to allow clients to register latency requirements. This driver also registers an IOMMU (SMMU) that's implemented by the memory controller. Signed-off-by: Thierry Reding tred...@nvidia.com --- drivers/memory/Kconfig |9 + drivers/memory/Makefile |1 + drivers/memory/tegra124-mc.c | 1945 ++ include/dt-bindings/memory/tegra124-mc.h | 30 + 4 files changed, 1985 insertions(+) create mode 100644 drivers/memory/tegra124-mc.c create mode 100644 include/dt-bindings/memory/tegra124-mc.h I prefer reusing the existing SMMU and having MC and SMMU separated since most of SMMU code are not different from functionality POV, and new MC features are quite independent of SMMU. If it's really convenient to combine MC and SMMU into one driver, we could move drivers/iomm/tegra-smmu.c here first, and add MC features on the top of it. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2] devicetree: Add generic IOMMU device tree bindings
Arnd Bergmann writes: >> > +Multiple-master IOMMU: >> > +-- >> > + >> > + iommu { >> > + /* the specifier represents the ID of the master */ >> > + #address-cells = <1>; >> > + #size-cells = <0>; >> > + }; >> > + >> > + master { >> > + /* device has master ID 42 in the IOMMU */ >> > + iommus = <&/iommu 42>; >> > + }; >> >> Presumably the ID would be the streamID on ARM's SMMU. How would a >> master with 8 streamIDs be described? This is what Calxeda midway has >> for SATA and I would expect that to be somewhat common. Either you >> need some ID masking or you'll have lots of duplication when you have >> windows. > > I don't understand the problem. If you have stream IDs 0 through 7, > you would have > > master@a { > ... > iommus = < 0>; > }; > > master@b { > ... > iommus = < 1; > }; > > ... > > master@12 { > ... > iommus = < 7; > }; > > and you don't need a window at all. Why would you need a mask of > some sort? IIUC the original problem, "a master with 8 streamIDs" means something like below, where some devices have multiple IDs but some have a single. A sinle #address-cells cannot afford those 2 masters at once. iommu { /* the specifier represents the ID of the master */ #address-cells = <1>; #size-cells = <0>; }; master@a { ... iommus = < 1 2 3>; # 3 IDs }; master@b { ... iommus = < 4>; # 1 ID }; Tegra,SMMU has a similar problem and we have used a fixed size bitmap(64 bit) to afford 64 stream IDs so that a single device can hold multiple IDs. If we apply the same bitmap to the above exmaple: iommu { /* the specifier represents the ID of the master */ #address-cells = <1>; #size-cells = <0>; }; master@a { ... iommus = < (BIT(1) | BIT(2) | BIT(3))>; # IDs 1 2 3 }; master@b { ... iommus = < BIT(4)>; # ID 4 }; The disadvantage of this is that this limits the max number of streamIDs to support. If # of streamID is increased later more than 64, this format cannot cover any more. You have to predict the max # of streamIDs in advance if steamID is statically assigned. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2] devicetree: Add generic IOMMU device tree bindings
Arnd Bergmann a...@arndb.de writes: +Multiple-master IOMMU: +-- + + iommu { + /* the specifier represents the ID of the master */ + #address-cells = 1; + #size-cells = 0; + }; + + master { + /* device has master ID 42 in the IOMMU */ + iommus = /iommu 42; + }; Presumably the ID would be the streamID on ARM's SMMU. How would a master with 8 streamIDs be described? This is what Calxeda midway has for SATA and I would expect that to be somewhat common. Either you need some ID masking or you'll have lots of duplication when you have windows. I don't understand the problem. If you have stream IDs 0 through 7, you would have master@a { ... iommus = smmu 0; }; master@b { ... iommus = smmu 1; }; ... master@12 { ... iommus = smmu 7; }; and you don't need a window at all. Why would you need a mask of some sort? IIUC the original problem, a master with 8 streamIDs means something like below, where some devices have multiple IDs but some have a single. A sinle #address-cells cannot afford those 2 masters at once. iommu { /* the specifier represents the ID of the master */ #address-cells = 1; #size-cells = 0; }; master@a { ... iommus = smmu 1 2 3; # 3 IDs }; master@b { ... iommus = smmu 4; # 1 ID }; Tegra,SMMU has a similar problem and we have used a fixed size bitmap(64 bit) to afford 64 stream IDs so that a single device can hold multiple IDs. If we apply the same bitmap to the above exmaple: iommu { /* the specifier represents the ID of the master */ #address-cells = 1; #size-cells = 0; }; master@a { ... iommus = smmu (BIT(1) | BIT(2) | BIT(3)); # IDs 1 2 3 }; master@b { ... iommus = smmu BIT(4); # ID 4 }; The disadvantage of this is that this limits the max number of streamIDs to support. If # of streamID is increased later more than 64, this format cannot cover any more. You have to predict the max # of streamIDs in advance if steamID is statically assigned. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv6+ 01/13] of: introduce of_property_for_earch_phandle_with_args()
Hiroshi Doyu wrote @ Thu, 12 Dec 2013 14:14:04 +0200 (EET): > > > From 8f7c0404aa68f0e8dbe0babc240590f6528ecc1f Mon Sep 17 00:00:00 2001 > > > From: Hiroshi Doyu > > > Date: Fri, 15 Nov 2013 10:52:53 +0200 > > > Subject: [PATCH] of: introduce of_property_for_each_phandle_with_args() > > > > > > Iterating over a property containing a list of phandles with arguments > > > is a common operation for device drivers. This patch adds a new > > > of_property_for_each_phandle_with_args() macro to make the iteration > > > simpler. > > > > > > Signed-off-by: Hiroshi Doyu > > > Cc: Rob Herring > > > --- > > > drivers/of/base.c | 46 ++ > > > include/linux/of.h | 32 > > > 2 files changed, 78 insertions(+) > > > > > > diff --git a/drivers/of/base.c b/drivers/of/base.c > > > index f807d0e..cd4ab05 100644 > > > --- a/drivers/of/base.c > > > +++ b/drivers/of/base.c > > > @@ -1201,6 +1201,52 @@ void of_print_phandle_args(const char *msg, const > > > struct of_phandle_args *args) > > > printk("\n"); > > > } > > > > > > +const __be32 *of_phandle_iter_next(const char *cells_name, int > > > cell_count, > > > +const __be32 *cur, const __be32 *end, > > > +struct of_phandle_args *out_args) > > > > Having to pass in cells_name, cell_count, cur and end each time seems a > > little odd. Can a state structure be used instead? > > > > struct of_phandle_iter_state { > > const char *cells_name; > > int cells_count; > > const __be32 *cur; > > const __be32 *end; > > struct of_phandle_args out_args; > > } > > > > Make the caller provide one of those and fill it in with the init > > function. > > I rewrote this a few times and so now I have a few version of this > implementations :-) The above proposal is similar to the version v6+++ > mentioned in the above patch note: > > > > v6+++: > > > Introduced a new struct "of_phandle_iter" to keep the state when > > > iterating over the list. > > which is: > > [RFC][PATCHv6+++ 01/13] of: introduce > of_property_for_earch_phandle_with_args() > http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007087.html > > Stephen seemed to prefer the version without state struct. I like the > idea to not pass the same arguments repeatly. Instead, wrapping them > in a struct with state may look better. > > So if Stephen agrees, I'll rewrite the version with state struct > again. Stephen, let me know what you think. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv7 04/12] driver/core: populate devices in order for IOMMUs
Thierry Reding wrote @ Sat, 14 Dec 2013 13:24:22 +0100: > * PGP Signed by an unknown key > > On Thu, Dec 12, 2013 at 06:14:02PM -0800, Greg KH wrote: > > On Thu, Dec 12, 2013 at 11:39:20AM +, Grant Likely wrote: > > > On Thu, 12 Dec 2013 09:57:05 +0200, Hiroshi Doyu wrote: > > > > IOMMU devices on the bus need to be poplulated first, then iommu > > > > master devices are done later. > > > > > > > > With CONFIG_OF_IOMMU, "iommus=" DT binding would be used to identify > > > > whether a device can be an iommu msater or not. If a device can, we'll > > > > defer to populate that device till an iommu device is populated. Then, > > > > those deferred iommu master devices are populated and configured with > > > > help of the already populated iommu device. > > > > > > > > Signed-off-by: Hiroshi Doyu > > > > Cc: Greg Kroah-Hartman > > > > --- > > > > This is related to the following discussion: > > > > [RFC PATCH] Documentation: devicetree: add description for generic > > > > bus properties > > > > > > > > http://lists.infradead.org/pipermail/linux-arm-kernel/2013-November/215042.html > > > > > > > > v6: > > > > Spinned off only driver core part from: > > > > [PATCHv5 2/9] driver/core: populate devices in order for IOMMUs > > > > > > > > v5: > > > > Use "iommus=" binding instread of arm,smmu's "#stream-id-cells". > > > > > > > > v4: > > > > This is newly added, and the successor of the following RFC: > > > > [RFC][PATCHv3+ 1/2] driver/core: Add of_iommu_attach() > > > > > > > > http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006914.html > > > > > > > > Signed-off-by: Hiroshi Doyu > > > > --- > > > > drivers/base/dd.c | 5 + > > > > 1 file changed, 5 insertions(+) > > > > > > > > diff --git a/drivers/base/dd.c b/drivers/base/dd.c > > > > index 0605176..0605f52 100644 > > > > --- a/drivers/base/dd.c > > > > +++ b/drivers/base/dd.c > > > > @@ -25,6 +25,7 @@ > > > > #include > > > > #include > > > > #include > > > > +#include > > > > > > > > #include "base.h" > > > > #include "power/power.h" > > > > @@ -273,6 +274,10 @@ static int really_probe(struct device *dev, struct > > > > device_driver *drv) > > > > > > > > dev->driver = drv; > > > > > > > > + ret = of_iommu_attach(dev); > > > > + if (ret) > > > > + goto probe_failed; > > > > + > > > > > > As discussed before, I really don't think hooking in to dd.c is the > > > right thing to do here, and certainly not as a device tree specific > > > function. ACPI or PCI described devices may have the same constraints > > > and those won't have DT descriptions. > > > > I agree, this shouldn't be in the driver core. > > Okay, so what would be an alternative? Grant's objection makes sense and > we could easily just wrap the call to of_iommu_attach() within a generic > iommu_attach() that could decide at runtime which exact implementation > to call, depending on whether the device is DT, ACPI, PCI or whatnot. > > If we don't want something like that in the core either, then the only > other alternative would be to call this from each driver. However given > the desire to handle IOMMUs completely transparently for device drivers > that would be missing the point. What about using "bus_notifier" to send -EPROBE_DEFER? The current bus_notifier framework doesn't have the ability to defer the probe, but I may think that this change is acceptable relatively. The fundamental problem is that IOMMU doesn't follow the exact bus model like "chained IOMMU" cases, but this discussion may take long to be solved. I think that "bus_notifier" with send -EPROBE_DEFER would cover most of the normal cases, like normal IOMMU device probe population order. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv7 04/12] driver/core: populate devices in order for IOMMUs
Thierry Reding thierry.red...@gmail.com wrote @ Sat, 14 Dec 2013 13:24:22 +0100: * PGP Signed by an unknown key On Thu, Dec 12, 2013 at 06:14:02PM -0800, Greg KH wrote: On Thu, Dec 12, 2013 at 11:39:20AM +, Grant Likely wrote: On Thu, 12 Dec 2013 09:57:05 +0200, Hiroshi Doyu hd...@nvidia.com wrote: IOMMU devices on the bus need to be poplulated first, then iommu master devices are done later. With CONFIG_OF_IOMMU, iommus= DT binding would be used to identify whether a device can be an iommu msater or not. If a device can, we'll defer to populate that device till an iommu device is populated. Then, those deferred iommu master devices are populated and configured with help of the already populated iommu device. Signed-off-by: Hiroshi Doyu hd...@nvidia.com Cc: Greg Kroah-Hartman gre...@linuxfoundation.org --- This is related to the following discussion: [RFC PATCH] Documentation: devicetree: add description for generic bus properties http://lists.infradead.org/pipermail/linux-arm-kernel/2013-November/215042.html v6: Spinned off only driver core part from: [PATCHv5 2/9] driver/core: populate devices in order for IOMMUs v5: Use iommus= binding instread of arm,smmu's #stream-id-cells. v4: This is newly added, and the successor of the following RFC: [RFC][PATCHv3+ 1/2] driver/core: Add of_iommu_attach() http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006914.html Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/base/dd.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 0605176..0605f52 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -25,6 +25,7 @@ #include linux/async.h #include linux/pm_runtime.h #include linux/pinctrl/devinfo.h +#include linux/of_iommu.h #include base.h #include power/power.h @@ -273,6 +274,10 @@ static int really_probe(struct device *dev, struct device_driver *drv) dev-driver = drv; + ret = of_iommu_attach(dev); + if (ret) + goto probe_failed; + As discussed before, I really don't think hooking in to dd.c is the right thing to do here, and certainly not as a device tree specific function. ACPI or PCI described devices may have the same constraints and those won't have DT descriptions. I agree, this shouldn't be in the driver core. Okay, so what would be an alternative? Grant's objection makes sense and we could easily just wrap the call to of_iommu_attach() within a generic iommu_attach() that could decide at runtime which exact implementation to call, depending on whether the device is DT, ACPI, PCI or whatnot. If we don't want something like that in the core either, then the only other alternative would be to call this from each driver. However given the desire to handle IOMMUs completely transparently for device drivers that would be missing the point. What about using bus_notifier to send -EPROBE_DEFER? The current bus_notifier framework doesn't have the ability to defer the probe, but I may think that this change is acceptable relatively. The fundamental problem is that IOMMU doesn't follow the exact bus model like chained IOMMU cases, but this discussion may take long to be solved. I think that bus_notifier with send -EPROBE_DEFER would cover most of the normal cases, like normal IOMMU device probe population order. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv6+ 01/13] of: introduce of_property_for_earch_phandle_with_args()
Hiroshi Doyu hd...@nvidia.com wrote @ Thu, 12 Dec 2013 14:14:04 +0200 (EET): From 8f7c0404aa68f0e8dbe0babc240590f6528ecc1f Mon Sep 17 00:00:00 2001 From: Hiroshi Doyu hd...@nvidia.com Date: Fri, 15 Nov 2013 10:52:53 +0200 Subject: [PATCH] of: introduce of_property_for_each_phandle_with_args() Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Signed-off-by: Hiroshi Doyu hd...@nvidia.com Cc: Rob Herring robherri...@gmail.com --- drivers/of/base.c | 46 ++ include/linux/of.h | 32 2 files changed, 78 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0e..cd4ab05 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1201,6 +1201,52 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) printk(\n); } +const __be32 *of_phandle_iter_next(const char *cells_name, int cell_count, +const __be32 *cur, const __be32 *end, +struct of_phandle_args *out_args) Having to pass in cells_name, cell_count, cur and end each time seems a little odd. Can a state structure be used instead? struct of_phandle_iter_state { const char *cells_name; int cells_count; const __be32 *cur; const __be32 *end; struct of_phandle_args out_args; } Make the caller provide one of those and fill it in with the init function. I rewrote this a few times and so now I have a few version of this implementations :-) The above proposal is similar to the version v6+++ mentioned in the above patch note: v6+++: Introduced a new struct of_phandle_iter to keep the state when iterating over the list. which is: [RFC][PATCHv6+++ 01/13] of: introduce of_property_for_earch_phandle_with_args() http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007087.html Stephen seemed to prefer the version without state struct. I like the idea to not pass the same arguments repeatly. Instead, wrapping them in a struct with state may look better. So if Stephen agrees, I'll rewrite the version with state struct again. Stephen, let me know what you think. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv6+ 01/13] of: introduce of_property_for_earch_phandle_with_args()
Grant Likely wrote @ Thu, 12 Dec 2013 12:34:17 +0100: > On Wed, 11 Dec 2013 14:33:38 +0100, Hiroshi Doyu wrote: > > Hi Grant, > > > > Grant Likely wrote @ Wed, 11 Dec 2013 14:28:45 > > +0100: > > > > > On Thu, 21 Nov 2013 11:57:00 -0700, Stephen Warren > > > wrote: > > > > On 11/21/2013 10:17 AM, Hiroshi Doyu wrote: > > > > > Iterating over a property containing a list of phandles with arguments > > > > > is a common operation for device drivers. This patch adds a new > > > > > of_property_for_each_phandle_with_args() macro to make the iteration > > > > > simpler. > > > > > > > > > > Signed-off-by: Hiroshi Doyu > > > > > --- > > > > > v6+: > > > > > Use the description, which Grant Likely proposed, to be full enough > > > > > that a future reader can figure out why a patch was written. > > > > > > > > > > http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007062.html > > ... > > > > > That's right, I forgot I said that. Yes please fix the implementation. > > > > Here's the latest. I'll include this with the next v7 series. > > > > Can I get your Acked-by with this? > > > > --8< > > > > From 8f7c0404aa68f0e8dbe0babc240590f6528ecc1f Mon Sep 17 00:00:00 2001 > > From: Hiroshi Doyu > > Date: Fri, 15 Nov 2013 10:52:53 +0200 > > Subject: [PATCH] of: introduce of_property_for_each_phandle_with_args() > > > > Iterating over a property containing a list of phandles with arguments > > is a common operation for device drivers. This patch adds a new > > of_property_for_each_phandle_with_args() macro to make the iteration > > simpler. > > > > Signed-off-by: Hiroshi Doyu > > Cc: Rob Herring > > --- > > v7: > > Fixed some minors pointed by Rob and Stephen. > > > > v6: > > Iterate without intrducing a new struct. > > > > v6+++: > > Introduced a new struct "of_phandle_iter" to keep the state when > > iterating over the list. > > > > v6++: > > Optimized to avoid O(n^2), suggested by Stephen Warren. > > http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007066.html > > > > I didn't introduce any struct to hold params and state here. > > > > v6+: > > Use the description, which Grant Likely proposed, to be full enough > > that a future reader can figure out why a patch was written. > > > > v5: > > New patch for v5. > > > > Signed-off-by: Hiroshi Doyu > > --- > > drivers/of/base.c | 46 ++ > > include/linux/of.h | 32 > > 2 files changed, 78 insertions(+) > > > > diff --git a/drivers/of/base.c b/drivers/of/base.c > > index f807d0e..cd4ab05 100644 > > --- a/drivers/of/base.c > > +++ b/drivers/of/base.c > > @@ -1201,6 +1201,52 @@ void of_print_phandle_args(const char *msg, const > > struct of_phandle_args *args) > > printk("\n"); > > } > > > > +const __be32 *of_phandle_iter_next(const char *cells_name, int cell_count, > > +const __be32 *cur, const __be32 *end, > > +struct of_phandle_args *out_args) > > Having to pass in cells_name, cell_count, cur and end each time seems a > little odd. Can a state structure be used instead? > > struct of_phandle_iter_state { > const char *cells_name; > int cells_count; > const __be32 *cur; > const __be32 *end; > struct of_phandle_args out_args; > } > > Make the caller provide one of those and fill it in with the init > function. I rewrote this a few times and so now I have a few version of this implementations :-) The above proposal is similar to the version v6+++ mentioned in the above patch note: > > v6+++: > > Introduced a new struct "of_phandle_iter" to keep the state when > > iterating over the list. which is: [RFC][PATCHv6+++ 01/13] of: introduce of_property_for_earch_phandle_with_args() http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007087.html Stephen seemed to prefer the version without state struct. I like the idea to not pass the same arguments repeatly. Instead, wrapping them in a struct with state may look better. So if Stephen agrees, I'll rewrite the version with state struct again. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 05/12] iommu/core: add ops->{bound,unbind}_driver()
ops->{bound,unbind}_driver() functions are called at BUS_NOTIFY_{BOUND,UNBIND}_DRIVER respectively. This is necessary to control the device population order. IOMMU master devices depend on an IOMMU device instanciation. IOMMU master devices can be registered to an IOMMU only after it's successfully populated. This IOMMU registration is done via ops->bound_driver(). Currently this population can be deferred if depending IOMMU device hasn't yet been populated in driver core. This cannot be done via ops->add_device() since after add_device() device's population/instanciation can be still deferred via probe(). Signed-off-by: Hiroshi Doyu --- v6: New for v6. Signed-off-by: Hiroshi Doyu --- drivers/iommu/iommu.c | 13 +++-- include/linux/iommu.h | 4 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index efc..5469d36 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -540,14 +540,23 @@ static int iommu_bus_notifier(struct notifier_block *nb, * ADD/DEL call into iommu driver ops if provided, which may * result in ADD/DEL notifiers to group->notifier */ - if (action == BUS_NOTIFY_ADD_DEVICE) { + switch (action) { + case BUS_NOTIFY_ADD_DEVICE: if (ops->add_device) return ops->add_device(dev); - } else if (action == BUS_NOTIFY_DEL_DEVICE) { + case BUS_NOTIFY_DEL_DEVICE: if (ops->remove_device && dev->iommu_group) { ops->remove_device(dev); return 0; } + case BUS_NOTIFY_BOUND_DRIVER: + if (ops->bound_driver) + ops->bound_driver(dev); + break; + case BUS_NOTIFY_UNBIND_DRIVER: + if (ops->unbind_driver) + ops->unbind_driver(dev); + break; } /* diff --git a/include/linux/iommu.h b/include/linux/iommu.h index a444c79..a0e92be 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -96,6 +96,8 @@ enum iommu_attr { * @domain_has_cap: domain capabilities query * @add_device: add device to iommu grouping * @remove_device: remove device from iommu grouping + * @bound_driver: called at BUS_NOTIFY_BOUND_DRIVER + * @unbind_driver: called at BUS_NOTIFY_UNBIND_DRIVER * @domain_get_attr: Query domain attributes * @domain_set_attr: Change domain attributes * @pgsize_bitmap: bitmap of supported page sizes @@ -114,6 +116,8 @@ struct iommu_ops { unsigned long cap); int (*add_device)(struct device *dev); void (*remove_device)(struct device *dev); + int (*bound_driver)(struct device *dev); + void (*unbind_driver)(struct device *dev); int (*device_group)(struct device *dev, unsigned int *groupid); int (*domain_get_attr)(struct iommu_domain *domain, enum iommu_attr attr, void *data); -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 03/12] iommu/of: check if dependee iommu is ready or not
IOMMU devices on the bus need to be poplulated first, then iommu master devices are done later. With CONFIG_OF_IOMMU, "iommus=" DT binding would be used to identify whether a device can be an iommu msater or not. If a device can, we'll defer to populate that device till an depending iommu device is populated. Signed-off-by: Hiroshi Doyu --- v6: Spinned off only of_iommu part from: [PATCHv5 2/9] driver/core: populate devices in order for IOMMUs v5: Use "iommus=" binding instread of arm,smmu's "#stream-id-cells". v4: This is newly added, and the successor of the following RFC: [RFC][PATCHv3+ 1/2] driver/core: Add of_iommu_attach() http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006914.html Signed-off-by: Hiroshi Doyu --- drivers/iommu/of_iommu.c | 14 ++ include/linux/of_iommu.h | 6 ++ 2 files changed, 20 insertions(+) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 5d1aeb9..557c0c8 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -125,3 +125,17 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index, return 0; } EXPORT_SYMBOL_GPL(of_get_dma_window); + +int of_iommu_attach(struct device *dev) +{ + const __be32 *cur, *end; + struct of_phandle_args args; + + of_property_for_each_phandle_with_args(dev->of_node, "iommus", + "#iommu-cells", 0, args, cur, end) { + if (!of_find_iommu_by_node(args.np)) + return -EPROBE_DEFER; + } + + return 0; +} diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index a0aa9d4..14c9a5c 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -14,6 +14,7 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix, extern void iommu_add(struct iommu *iommu); extern void iommu_del(struct iommu *iommu); +extern int of_iommu_attach(struct device *dev); #else @@ -32,6 +33,11 @@ static inline void iommu_del(struct iommu *iommu) { } +static inline int of_iommu_attach(struct device *dev) +{ + return 0; +} + #endif /* CONFIG_OF_IOMMU */ #endif /* __OF_IOMMU_H */ -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 02/12] iommu/of: introduce a global iommu device list
This enables to find an populated IOMMU device via a device node. This can be used to see if an dependee IOMMU is populated or not to keep correct device population order. Client devices need to wait an IOMMU to be populated. Suggested by Thierry Reding and copied his example code. Signed-off-by: Hiroshi Doyu Cc: Joerg Roedel Cc: Thierry Reding --- v6: New for v6. Signed-off-by: Hiroshi Doyu --- drivers/iommu/of_iommu.c | 37 + include/linux/of_iommu.h | 16 2 files changed, 53 insertions(+) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index ee249bc..5d1aeb9 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -20,6 +20,43 @@ #include #include #include +#include +#include + +static DEFINE_MUTEX(iommus_lock); +static LIST_HEAD(iommus_list); + +void iommu_add(struct iommu *iommu) +{ + INIT_LIST_HEAD(>list); + mutex_lock(_lock); + list_add_tail(>list, _list); + mutex_unlock(_lock); +} + +void iommu_del(struct iommu *iommu) +{ + INIT_LIST_HEAD(>list); + mutex_lock(_lock); + list_del(>list); + mutex_unlock(_lock); +} + +static struct iommu *of_find_iommu_by_node(struct device_node *np) +{ + struct iommu *iommu; + + mutex_lock(_lock); + list_for_each_entry(iommu, _list, list) { + if (iommu->dev->of_node == np) { + mutex_unlock(_lock); + return iommu; + } + } + mutex_unlock(_lock); + + return NULL; +} /** * of_get_dma_window - Parse *dma-window property and returns 0 if found. diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index 51a560f..a0aa9d4 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -3,10 +3,18 @@ #ifdef CONFIG_OF_IOMMU +struct iommu { + struct list_head list; + struct device *dev; +}; + extern int of_get_dma_window(struct device_node *dn, const char *prefix, int index, unsigned long *busno, dma_addr_t *addr, size_t *size); +extern void iommu_add(struct iommu *iommu); +extern void iommu_del(struct iommu *iommu); + #else static inline int of_get_dma_window(struct device_node *dn, const char *prefix, @@ -16,6 +24,14 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix, return -EINVAL; } +static inline void iommu_add(struct iommu *iommu) +{ +} + +static inline void iommu_del(struct iommu *iommu) +{ +} + #endif /* CONFIG_OF_IOMMU */ #endif /* __OF_IOMMU_H */ -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 09/12] iommu/tegra: smmu: get swgroups from DT "iommus="
This provides the info about which swgroups a device belongs to. This info is passed from DT. This is necessary for the unified SMMU driver among Tegra SoCs since each has different H/W accelerators. Signed-off-by: Hiroshi Doyu --- v6: - Explained "#iommu-cells" in the binding document. - Fixed old "nvidia,memory-clients" with 'iommus" in the binding document. - Move smmu_of_get_swgroups() here from the previous patch not to break git bisecting. v5: "iommu=" in a device DT is used instead of "mmu-masters" in an iommu DT. This is "iommu=" version of: [PATCHv4 5/7] iommu/tegra: smmu: Support "mmu-masters" binding Signed-off-by: Hiroshi Doyu --- .../bindings/iommu/nvidia,tegra30-smmu.txt | 30 - drivers/iommu/tegra-smmu.c | 135 ++--- 2 files changed, 145 insertions(+), 20 deletions(-) diff --git a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt index 89fb543..fd53f54 100644 --- a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt +++ b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt @@ -1,6 +1,6 @@ NVIDIA Tegra 30 IOMMU H/W, SMMU (System Memory Management Unit) -Required properties: +Required properties in the IOMMU node: - compatible : "nvidia,tegra30-smmu" - reg : Should contain 3 register banks(address and length) for each of the SMMU register blocks. @@ -8,9 +8,23 @@ Required properties: - nvidia,#asids : # of ASIDs - dma-window : IOVA start address and length. - nvidia,ahb : phandle to the ahb bus connected to SMMU. +- iommus: phandle to an iommu device which a device is + attached to and indicates which swgroups a device belongs to(SWGROUP ID). + SWGROUP ID is from 0 to 63, and a device can belong to multiple SWGROUPS. +- #iommu-cells. Should be 2. In client IOMMU specifiers, the two cells + represent a 64-bit bitmask of SWGROUP IDs under which the device + initiates transactions. The least significant word is first. See + for a list of valid values. + +Required properties in device nodes affected by the IOMMU: +- iommus: A list of phandle plus specifier pairs for each IOMMU that + affects master transactions initiated by the device. The number of + cells in each specifier is defined by the #iommu-cells property in + the IOMMU node referred to by the phandle. The meaning of the + specifier cells is defined by the referenced IOMMU's binding. Example: - smmu { + smmu: iommu { compatible = "nvidia,tegra30-smmu"; reg = <0x7000f010 0x02c 0x7000f1f0 0x010 @@ -18,4 +32,16 @@ Example: nvidia,#asids = <4>;/* # of ASIDs */ dma-window = <0 0x4000>;/* IOVA start & length */ nvidia,ahb = <>; + #iommu-cells = <2>; }; + + host1x { + compatible = "nvidia,tegra30-host1x", "simple-bus"; + iommus = < TEGRA_SWGROUP_CELLS(HC)>; + + gr3d { + compatible = "nvidia,tegra30-gr3d"; + iommus = < TEGRA_SWGROUP_CELLS(NV) + TEGRA_SWGROUP_CELLS(NV2)>; + + }; diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 6ab977a..fd4479a 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -190,6 +190,8 @@ enum { * Per client for address space */ struct smmu_client { + struct device_node *of_node; + struct rb_node node; struct device *dev; struct list_headlist; struct smmu_as *as; @@ -233,6 +235,7 @@ struct smmu_device { spinlock_t lock; char*name; struct device *dev; + struct rb_root clients; struct page *avp_vector_page; /* dummy page shared by all AS's */ /* @@ -310,6 +313,96 @@ static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs) */ #define FLUSH_SMMU_REGS(smmu) smmu_read(smmu, SMMU_CONFIG) +static struct smmu_client *find_smmu_client(struct smmu_device *smmu, + struct device_node *dev_node) +{ + struct rb_node *node = smmu->clients.rb_node; + + while (node) { + struct smmu_client *client; + + client = container_of(node, struct smmu_client, node); + if (dev_node < client->of_node) + node = node->rb_left; + else if (dev_node > client->of_node) + node = node->rb_right; + else + return client; + } + +
[PATCHv7 07/12] iommu/tegra: smmu: register device to iommu dynamically
platform_devices are registered as IOMMU'able dynamically via add_device() and remove_device(). Tegra SMMU can have multiple address spaces(AS). IOMMU'able devices can belong to one of them. Multiple IOVA maps are created at boot-up, which can be attached to devices later. We reserve 2 of them for static assignment, AS[0] for system default, AS[1] for AHB clusters as protected domain from others, where there are many traditional pheripheral devices like USB, SD/MMC. They should be isolated from some smart devices like host1x for system robustness. Even if smart devices behaves wrongly, the traditional devices(SD/MMC, USB) wouldn't be affected, and the system could continue most likely. DMA API(ARM) needs ARM_DMA_USE_IOMMU to be enabled. Signed-off-by: Hiroshi Doyu --- v6: Use smmu_iommu_{bound,unbind}_driver() instead of smmu_iommu_{add,del}_device() to register devices to SMMU. v5: Add check NUM_OF_STATIC_MAPS < #asids. v4: Combined the following from v3. This makes more sense what they do. [PATCHv3 06/19] iommu/tegra: smmu: Select ARM_DMA_USE_IOMMU in Kconfig [PATCHv3 07/19] iommu/tegra: smmu: Create default IOVA maps [PATCHv3 08/19] iommu/tegra: smmu: Register platform_device to IOMMU dynamically [PATCHv3 19/19] iommu/tegra: smmu: Support Multiple ASID Signed-off-by: Hiroshi Doyu --- drivers/iommu/Kconfig | 1 + drivers/iommu/tegra-smmu.c | 70 +- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 3e7fdbb..0a86d63 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -170,6 +170,7 @@ config TEGRA_IOMMU_SMMU bool "Tegra SMMU IOMMU Support" depends on ARCH_TEGRA && TEGRA_AHB select IOMMU_API + select ARM_DMA_USE_IOMMU help Enables support for remapping discontiguous physical memory shared with the operating system into contiguous I/O virtual diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 3c772c9..99b4bd4 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -39,6 +39,9 @@ #include #include +#include + +#include enum smmu_hwgrp { HWGRP_AFI, @@ -319,6 +322,8 @@ struct smmu_device { struct device_node *ahb; + struct dma_iommu_mapping **map; + int num_as; struct smmu_as as[0]; /* Run-time allocated array */ }; @@ -947,6 +952,44 @@ static void smmu_iommu_domain_destroy(struct iommu_domain *domain) dev_dbg(smmu->dev, "smmu_as@%p\n", as); } +/* + * ASID[0] for the system default + * ASID[1] for PPCS("AHB bus children"), which has SDMMC + * ASID[2][3].. open for drivers, first come, first served. + */ +enum { + SYSTEM_DEFAULT, + SYSTEM_PROTECTED, + NUM_OF_STATIC_MAPS, +}; + +static int smmu_iommu_bound_driver(struct device *dev) +{ + int err = -EPROBE_DEFER; + u32 swgroups = dev->platform_data; + struct dma_iommu_mapping *map = NULL; + + if (test_bit(TEGRA_SWGROUP_PPCS, swgroups)) + map = smmu_handle->map[SYSTEM_PROTECTED]; + else + map = smmu_handle->map[SYSTEM_DEFAULT]; + + if (map) + err = arm_iommu_attach_device(dev, map); + else + return -EPROBE_DEFER; + + pr_debug("swgroups=%08lx map=%p err=%d %s\n", +swgroups, map, err, dev_name(dev)); + return err; +} + +static void smmu_iommu_unbind_driver(struct device *dev) +{ + dev_dbg(dev, "Detaching from map %p\n", to_dma_iommu_mapping(dev)); + arm_iommu_detach_device(dev); +} + static struct iommu_ops smmu_iommu_ops = { .domain_init= smmu_iommu_domain_init, .domain_destroy = smmu_iommu_domain_destroy, @@ -956,6 +999,8 @@ static struct iommu_ops smmu_iommu_ops = { .unmap = smmu_iommu_unmap, .iova_to_phys = smmu_iommu_iova_to_phys, .domain_has_cap = smmu_iommu_domain_has_cap, + .bound_driver = smmu_iommu_bound_driver, + .unbind_driver = smmu_iommu_unbind_driver, .pgsize_bitmap = SMMU_IOMMU_PGSIZES, }; @@ -1144,6 +1189,23 @@ static int tegra_smmu_resume(struct device *dev) return err; } +static void tegra_smmu_create_default_map(struct smmu_device *smmu) +{ + int i; + + for (i = 0; i < smmu->num_as; i++) { + dma_addr_t base = smmu->iovmm_base; + size_t size = smmu->page_count << PAGE_SHIFT; + + smmu->map[i] = arm_iommu_create_mapping(_bus_type, + base, size, 0); + if (IS_ERR(smmu->map[i])) + dev_err(smmu->dev, + "Couldn't create: asid=%d map=%p %pa-%pa\n", + i, smmu->ma
[PATCHv7 06/12] ARM: tegra: create a DT header defining SWGROUP ID
Create a header file to define the swgroup IDs used by the IOMMU(SMMU) binding. "swgroup" is a group of H/W clients which a Tegra SoC supports. This unique ID can be used to calculate MC_SMMU__ASID_0 register offset and MC__HOTRESET_*_0 register bit. This will allow the same header to be used by both device tree files, and drivers implementing this binding, which guarantees that the two stay in sync. This also makes device trees more readable by using names instead of magic numbers. For HOTRESET bit shifting we need another conversion table, which will come later. Signed-off-by: Hiroshi Doyu --- v6: Use 0x instead of ~0UL since dtc expand this to ~0ULL. v5: Added new macro TEGRA_SWGROUP_CELLS() and WO_U32_OF_U64(). v4: This is almost same as the previous v3. Just TEGRA_SWGROUP_MAX is added. [PATCHv3 15/19] ARM: tegra: Create a DT header defining SWGROUP ID Signed-off-by: Hiroshi Doyu --- include/dt-bindings/memory/tegra-swgroup.h | 50 ++ 1 file changed, 50 insertions(+) create mode 100644 include/dt-bindings/memory/tegra-swgroup.h diff --git a/include/dt-bindings/memory/tegra-swgroup.h b/include/dt-bindings/memory/tegra-swgroup.h new file mode 100644 index 000..9c279f1 --- /dev/null +++ b/include/dt-bindings/memory/tegra-swgroup.h @@ -0,0 +1,50 @@ +/* + * This header provides constants for binding nvidia,swgroup ID + */ + +#ifndef _DT_BINDINGS_MEMORY_TEGRA_SWGROUP_H +#define _DT_BINDINGS_MEMORY_TEGRA_SWGROUP_H + +#define TEGRA_SWGROUP_AFI 0 /* 0x238 */ +#define TEGRA_SWGROUP_AVPC 1 /* 0x23c */ +#define TEGRA_SWGROUP_DC 2 /* 0x240 */ +#define TEGRA_SWGROUP_DCB 3 /* 0x244 */ +#define TEGRA_SWGROUP_EPP 4 /* 0x248 */ +#define TEGRA_SWGROUP_G2 5 /* 0x24c */ +#define TEGRA_SWGROUP_HC 6 /* 0x250 */ +#define TEGRA_SWGROUP_HDA 7 /* 0x254 */ +#define TEGRA_SWGROUP_ISP 8 /* 0x258 */ +#define TEGRA_SWGROUP_ISP2 SWGROUP_ISP +#define TEGRA_SWGROUP_DC14 9 /* 0x490 *//* Exceptional non-linear */ +#define TEGRA_SWGROUP_DC12 10 /* 0xa88 *//* Exceptional non-linear */ +#define TEGRA_SWGROUP_MPE 11 /* 0x264 */ +#define TEGRA_SWGROUP_MSENCSWGROUP_MPE +#define TEGRA_SWGROUP_NV 12 /* 0x268 */ +#define TEGRA_SWGROUP_NV2 13 /* 0x26c */ +#define TEGRA_SWGROUP_PPCS 14 /* 0x270 */ +#define TEGRA_SWGROUP_SATA215 /* 0x274 */ +#define TEGRA_SWGROUP_SATA 16 /* 0x278 */ +#define TEGRA_SWGROUP_VDE 17 /* 0x27c */ +#define TEGRA_SWGROUP_VI 18 /* 0x280 */ +#define TEGRA_SWGROUP_VIC 19 /* 0x284 */ +#define TEGRA_SWGROUP_XUSB_HOST20 /* 0x288 */ +#define TEGRA_SWGROUP_XUSB_DEV 21 /* 0x28c */ +#define TEGRA_SWGROUP_A9AVP22 /* 0x290 */ +#define TEGRA_SWGROUP_TSEC 23 /* 0x294 */ +#define TEGRA_SWGROUP_PPCS124 /* 0x298 */ +#define TEGRA_SWGROUP_SDMMC1A 25 /* 0xa94 *//* Linear shift again */ +#define TEGRA_SWGROUP_SDMMC2A 26 /* 0xa98 */ +#define TEGRA_SWGROUP_SDMMC3A 27 /* 0xa9c */ +#define TEGRA_SWGROUP_SDMMC4A 28 /* 0xaa0 */ +#define TEGRA_SWGROUP_ISP2B29 /* 0xaa4 */ +#define TEGRA_SWGROUP_GPU 30 /* 0xaa8 */ +#define TEGRA_SWGROUP_GPUB 31 /* 0xaac */ +#define TEGRA_SWGROUP_PPCS232 /* 0xab0 */ + +#define TWO_U32_OF_U64(x) ((x) & 0x) ((x) >> 32) +#define TEGRA_SWGROUP_BIT(x) (1ULL << TEGRA_SWGROUP_##x) +#define TEGRA_SWGROUP_CELLS(x) TWO_U32_OF_U64(TEGRA_SWGROUP_BIT(x)) + +#define TEGRA_SWGROUP_MAX 64 + +#endif /* _DT_BINDINGS_MEMORY_TEGRA_SWGROUP_H */ -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 04/12] driver/core: populate devices in order for IOMMUs
IOMMU devices on the bus need to be poplulated first, then iommu master devices are done later. With CONFIG_OF_IOMMU, "iommus=" DT binding would be used to identify whether a device can be an iommu msater or not. If a device can, we'll defer to populate that device till an iommu device is populated. Then, those deferred iommu master devices are populated and configured with help of the already populated iommu device. Signed-off-by: Hiroshi Doyu Cc: Greg Kroah-Hartman --- This is related to the following discussion: [RFC PATCH] Documentation: devicetree: add description for generic bus properties http://lists.infradead.org/pipermail/linux-arm-kernel/2013-November/215042.html v6: Spinned off only driver core part from: [PATCHv5 2/9] driver/core: populate devices in order for IOMMUs v5: Use "iommus=" binding instread of arm,smmu's "#stream-id-cells". v4: This is newly added, and the successor of the following RFC: [RFC][PATCHv3+ 1/2] driver/core: Add of_iommu_attach() http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006914.html Signed-off-by: Hiroshi Doyu --- drivers/base/dd.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 0605176..0605f52 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "base.h" #include "power/power.h" @@ -273,6 +274,10 @@ static int really_probe(struct device *dev, struct device_driver *drv) dev->driver = drv; + ret = of_iommu_attach(dev); + if (ret) + goto probe_failed; + /* If using pinctrl, bind pins now before probing */ ret = pinctrl_bind_pins(dev); if (ret) -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 12/12] iommu/tegra: smmu: add SMMU to an global iommu list
This allows to inquire if SMMU is populated or not. Suggested by Thierry Reding and copied his example code. Signed-off-by: Hiroshi Doyu Cc: Thierry Reding --- v6: New for v6. Signed-off-by: Hiroshi Doyu --- drivers/iommu/tegra-smmu.c | 55 +- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 2d4b8b6..d0f0ba7 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -225,6 +225,8 @@ struct smmu_debugfs_info { * Per SMMU device - IOMMU device */ struct smmu_device { + struct iommuiommu; + void __iomem*regbase; /* register offset base */ void __iomem**regs; /* register block start address array */ void __iomem**rege; /* register block end address array */ @@ -234,7 +236,6 @@ struct smmu_device { unsigned long page_count; /* total remappable size */ spinlock_t lock; char*name; - struct device *dev; struct rb_root clients; struct page *avp_vector_page; /* dummy page shared by all AS's */ @@ -371,7 +372,7 @@ static int register_smmu_client(struct smmu_device *smmu, return -EBUSY; } - client = devm_kzalloc(smmu->dev, sizeof(*client), GFP_KERNEL); + client = devm_kzalloc(smmu->iommu.dev, sizeof(*client), GFP_KERNEL); if (!client) return -ENOMEM; @@ -388,7 +389,7 @@ static int smmu_of_get_swgroups(struct device *dev, unsigned long *swgroups) of_property_for_each_phandle_with_args(dev->of_node, "iommus", "#iommu-cells", 0, args, cur, end) { - if (args.np != smmu_handle->dev->of_node) + if (args.np != smmu_handle->iommu.dev->of_node) continue; BUG_ON(args.args_count != 2); @@ -527,7 +528,7 @@ static void free_ptbl(struct smmu_as *as, dma_addr_t iova) unsigned long *pdir = (unsigned long *)page_address(as->pdir_page); if (pdir[pdn] != _PDE_VACANT(pdn)) { - dev_dbg(as->smmu->dev, "pdn: %lx\n", pdn); + dev_dbg(as->smmu->iommu.dev, "pdn: %lx\n", pdn); ClearPageReserved(SMMU_EX_PTBL_PAGE(pdir[pdn])); __free_page(SMMU_EX_PTBL_PAGE(pdir[pdn])); @@ -542,7 +543,7 @@ static void free_pdir(struct smmu_as *as) { unsigned addr; int count; - struct device *dev = as->smmu->dev; + struct device *dev = as->smmu->iommu.dev; if (!as->pdir_page) return; @@ -585,11 +586,11 @@ static unsigned long *locate_pte(struct smmu_as *as, unsigned long addr = SMMU_PDN_TO_ADDR(pdn); /* Vacant - allocate a new page table */ - dev_dbg(as->smmu->dev, "New PTBL pdn: %lx\n", pdn); + dev_dbg(as->smmu->iommu.dev, "New PTBL pdn: %lx\n", pdn); *ptbl_page_p = alloc_page(GFP_ATOMIC); if (!*ptbl_page_p) { - dev_err(as->smmu->dev, + dev_err(as->smmu->iommu.dev, "failed to allocate smmu_device page table\n"); return NULL; } @@ -649,7 +650,7 @@ static int alloc_pdir(struct smmu_as *as) /* * do the allocation, then grab as->lock */ - cnt = devm_kzalloc(smmu->dev, + cnt = devm_kzalloc(smmu->iommu.dev, sizeof(cnt[0]) * SMMU_PDIR_COUNT, GFP_KERNEL); page = alloc_page(GFP_KERNEL | __GFP_DMA); @@ -663,7 +664,8 @@ static int alloc_pdir(struct smmu_as *as) } if (!page || !cnt) { - dev_err(smmu->dev, "failed to allocate at %s\n", __func__); + dev_err(smmu->iommu.dev, + "failed to allocate at %s\n", __func__); err = -ENOMEM; goto err_out; } @@ -693,7 +695,7 @@ static int alloc_pdir(struct smmu_as *as) err_out: spin_unlock_irqrestore(>lock, flags); - devm_kfree(smmu->dev, cnt); + devm_kfree(smmu->iommu.dev, cnt); if (page) __free_page(page); return err; @@ -748,7 +750,7 @@ static int smmu_iommu_map(struct iommu_domain *domain, unsigned long iova, unsigned long pfn = __phys_to_pfn(pa); unsigned long flags; - dev_info(as->smmu->dev, "[%d] %08lx:%pa\n", as->asid, iova, ); + dev_info(as->smmu->iommu.dev, "[%d] %08lx:%pa\n", as->asid, iova, ); if (!pfn_valid(pfn)) return -ENOMEM; @@ -765,7 +767,7 @@ static size_t sm
[PATCHv7 11/12] iommu/tegra: smmu: Rename hwgrp -> swgroups
Use the correct term for SWGROUP related variables and macros. The term "swgroup" is the collection of "memory client". A "memory client" usually represents a HardWare Accelerator(HWA) like GPU. Sometimes a strut device can belong to multiple "swgroup" so that "swgroup's'" is used here. This "swgroups" is the term used in Tegra TRM. Rename along with TRM. Signed-off-by: Hiroshi Doyu --- v4: New for v4 Signed-off-by: Hiroshi Doyu --- drivers/iommu/tegra-smmu.c | 36 ++-- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 2b8a302..2d4b8b6 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -179,12 +179,12 @@ enum { #define NUM_SMMU_REG_BANKS 3 -#define smmu_client_enable_hwgrp(c, m) smmu_client_set_hwgrp(c, m, 1) -#define smmu_client_disable_hwgrp(c) smmu_client_set_hwgrp(c, 0, 0) -#define __smmu_client_enable_hwgrp(c, m) __smmu_client_set_hwgrp(c, m, 1) -#define __smmu_client_disable_hwgrp(c) __smmu_client_set_hwgrp(c, 0, 0) +#define smmu_client_enable_swgroups(c, m) smmu_client_set_swgroups(c, m, 1) +#define smmu_client_disable_swgroups(c) smmu_client_set_swgroups(c, 0, 0) +#define __smmu_client_enable_swgroups(c, m) __smmu_client_set_swgroups(c, m, 1) +#define __smmu_client_disable_swgroups(c) __smmu_client_set_swgroups(c, 0, 0) -#define HWGRP_ASID_REG(x) ((x) * sizeof(u32) + SMMU_ASID_BASE) +#define SWGROUPS_ASID_REG(x) ((x) * sizeof(u32) + SMMU_ASID_BASE) /* * Per client for address space @@ -195,7 +195,7 @@ struct smmu_client { struct device *dev; struct list_headlist; struct smmu_as *as; - unsigned long hwgrp[2]; + unsigned long swgroups[2]; }; /* @@ -377,7 +377,7 @@ static int register_smmu_client(struct smmu_device *smmu, client->dev = dev; client->of_node = dev->of_node; - memcpy(client->hwgrp, swgroups, sizeof(u64)); + memcpy(client->swgroups, swgroups, sizeof(u64)); return insert_smmu_client(smmu, client); } @@ -403,7 +403,7 @@ static int smmu_of_get_swgroups(struct device *dev, unsigned long *swgroups) return -ENODEV; } -static int __smmu_client_set_hwgrp(struct smmu_client *c, +static int __smmu_client_set_swgroups(struct smmu_client *c, unsigned long *map, int on) { int i; @@ -412,10 +412,10 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, struct smmu_device *smmu = as->smmu; if (!on) - map = c->hwgrp; + map = c->swgroups; for_each_set_bit(i, map, TEGRA_SWGROUP_MAX) { - offs = HWGRP_ASID_REG(i); + offs = SWGROUPS_ASID_REG(i); val = smmu_read(smmu, offs); if (on) { if (val) { @@ -425,7 +425,7 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, } val = mask; - memcpy(c->hwgrp, map, sizeof(u64)); + memcpy(c->swgroups, map, sizeof(u64)); } else { WARN_ON((val & mask) == mask); val &= ~mask; @@ -438,7 +438,7 @@ skip: return 0; } -static int smmu_client_set_hwgrp(struct smmu_client *c, +static int smmu_client_set_swgroups(struct smmu_client *c, unsigned long *map, int on) { int err; @@ -447,7 +447,7 @@ static int smmu_client_set_hwgrp(struct smmu_client *c, struct smmu_device *smmu = as->smmu; spin_lock_irqsave(>lock, flags); - err = __smmu_client_set_hwgrp(c, map, on); + err = __smmu_client_set_swgroups(c, map, on); spin_unlock_irqrestore(>lock, flags); return err; } @@ -487,7 +487,7 @@ static int smmu_setup_regs(struct smmu_device *smmu) smmu_write(smmu, val, SMMU_PTB_DATA); list_for_each_entry(c, >client, list) - __smmu_client_set_hwgrp(c, c->hwgrp, 1); + __smmu_client_set_swgroups(c, c->swgroups, 1); } smmu_write(smmu, smmu->translation_enable_0, SMMU_TRANSLATION_ENABLE_0); @@ -815,7 +815,7 @@ static int smmu_iommu_attach_dev(struct iommu_domain *domain, return -ENOMEM; client->as = as; - err = smmu_client_enable_hwgrp(client, client->hwgrp); + err = smmu_client_enable_swgroups(client, client->swgroups); if (err) return -EINVAL; @@ -835,7 +835,7 @@ static int smmu_iommu_attach_dev(struct iommu_domain *domain, * Reserve "page zero" for AVP vectors using a common dummy * page. */ - if (test_bit(TEGRA_SWGROUP_AVPC, client->
[PATCHv7 08/12] iommu/tegra: smmu: calculate ASID register offset by ID
ASID register offset is caclulated by SWGROUP ID so that we can get rid of old SoC specific MACROs. This ID conversion is needed for the unified SMMU driver over Tegra SoCs. We use dt-bindings MACRO instead of SoC dependent MACROs. The formula is: MC_SMMU__ASID_0 = MC_SMMU_AFI_ASID_0 + ID * 4; Now SWGROUP ID is the global HardWare Accelerator(HWA) identifier among all Tegra SoC except Tegra2. Signed-off-by: Hiroshi Doyu --- v5: Added SMMU_ASID_BASE(== SMMU_AFI_ASID). Removed unused ASID offset definitions. Use 'unsigned long *' instead of u64 for swgroups bitmap. v4: Combined the following patches from v3: [PATCHv3 09/19] iommu/tegra: smmu: Calculate ASID register offset by ID [PATCHv3 16/19] iommu/tegra: smmu: Use dt-bindings MACRO Signed-off-by: Hiroshi Doyu --- drivers/iommu/tegra-smmu.c | 111 +++-- 1 file changed, 17 insertions(+), 94 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 99b4bd4..6ab977a 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -43,46 +43,6 @@ #include -enum smmu_hwgrp { - HWGRP_AFI, - HWGRP_AVPC, - HWGRP_DC, - HWGRP_DCB, - HWGRP_EPP, - HWGRP_G2, - HWGRP_HC, - HWGRP_HDA, - HWGRP_ISP, - HWGRP_MPE, - HWGRP_NV, - HWGRP_NV2, - HWGRP_PPCS, - HWGRP_SATA, - HWGRP_VDE, - HWGRP_VI, - - HWGRP_COUNT, - - HWGRP_END = ~0, -}; - -#define HWG_AFI(1 << HWGRP_AFI) -#define HWG_AVPC (1 << HWGRP_AVPC) -#define HWG_DC (1 << HWGRP_DC) -#define HWG_DCB(1 << HWGRP_DCB) -#define HWG_EPP(1 << HWGRP_EPP) -#define HWG_G2 (1 << HWGRP_G2) -#define HWG_HC (1 << HWGRP_HC) -#define HWG_HDA(1 << HWGRP_HDA) -#define HWG_ISP(1 << HWGRP_ISP) -#define HWG_MPE(1 << HWGRP_MPE) -#define HWG_NV (1 << HWGRP_NV) -#define HWG_NV2(1 << HWGRP_NV2) -#define HWG_PPCS (1 << HWGRP_PPCS) -#define HWG_SATA (1 << HWGRP_SATA) -#define HWG_VDE(1 << HWGRP_VDE) -#define HWG_VI (1 << HWGRP_VI) - /* bitmap of the page sizes currently supported */ #define SMMU_IOMMU_PGSIZES (SZ_4K) @@ -152,21 +112,7 @@ enum { #define SMMU_TRANSLATION_ENABLE_2 0x230 #define SMMU_AFI_ASID 0x238 /* PCIE */ -#define SMMU_AVPC_ASID 0x23c /* AVP */ -#define SMMU_DC_ASID 0x240 /* Display controller */ -#define SMMU_DCB_ASID 0x244 /* Display controller B */ -#define SMMU_EPP_ASID 0x248 /* Encoder pre-processor */ -#define SMMU_G2_ASID 0x24c /* 2D engine */ -#define SMMU_HC_ASID 0x250 /* Host1x */ -#define SMMU_HDA_ASID 0x254 /* High-def audio */ -#define SMMU_ISP_ASID 0x258 /* Image signal processor */ -#define SMMU_MPE_ASID 0x264 /* MPEG encoder */ -#define SMMU_NV_ASID 0x268 /* (3D) */ -#define SMMU_NV2_ASID 0x26c /* (3D) */ -#define SMMU_PPCS_ASID 0x270 /* AHB */ -#define SMMU_SATA_ASID 0x278 /* SATA */ -#define SMMU_VDE_ASID 0x27c /* Video decoder */ -#define SMMU_VI_ASID 0x280 /* Video input */ +#define SMMU_ASID_BASE SMMU_AFI_ASID #define SMMU_PDE_NEXT_SHIFT28 @@ -238,27 +184,7 @@ enum { #define __smmu_client_enable_hwgrp(c, m) __smmu_client_set_hwgrp(c, m, 1) #define __smmu_client_disable_hwgrp(c) __smmu_client_set_hwgrp(c, 0, 0) -#define HWGRP_INIT(client) [HWGRP_##client] = SMMU_##client##_ASID - -static const u32 smmu_hwgrp_asid_reg[] = { - HWGRP_INIT(AFI), - HWGRP_INIT(AVPC), - HWGRP_INIT(DC), - HWGRP_INIT(DCB), - HWGRP_INIT(EPP), - HWGRP_INIT(G2), - HWGRP_INIT(HC), - HWGRP_INIT(HDA), - HWGRP_INIT(ISP), - HWGRP_INIT(MPE), - HWGRP_INIT(NV), - HWGRP_INIT(NV2), - HWGRP_INIT(PPCS), - HWGRP_INIT(SATA), - HWGRP_INIT(VDE), - HWGRP_INIT(VI), -}; -#define HWGRP_ASID_REG(x) (smmu_hwgrp_asid_reg[x]) +#define HWGRP_ASID_REG(x) ((x) * sizeof(u32) + SMMU_ASID_BASE) /* * Per client for address space @@ -267,7 +193,7 @@ struct smmu_client { struct device *dev; struct list_headlist; struct smmu_as *as; - u32 hwgrp; + unsigned long hwgrp[2]; }; /* @@ -384,41 +310,37 @@ static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs) */ #define FLUSH_SMMU_REGS(smmu) smmu_read(smmu, SMMU_CONFIG) -#define smmu_client_hwgrp(c) (u32)((c)->dev->platform_data) - static int __smmu_client_set_hwgrp(struct smmu_client *c, - unsigned long map, int on) + unsigned long *map, int on) { int i; struct smmu_as *as = c->as; u32 val, offs, mask = SMMU_ASID_ENABLE(as-&
[PATCHv7 10/12] iommu/tegra: smmu: allow duplicate ASID wirte
The device, which belongs to the same ASID, can try to enable the same ASID as the other swgroup devices. This should be allowed but just skip the actual register write. If the write value is different, it will return -EINVAL. Signed-off-by: Hiroshi Doyu --- v4: This was the part of v3, which isn't used any more. [PATCHv3 10/19] iommu/tegra: smmu: Get "nvidia,swgroups" from DT Signed-off-by: Hiroshi Doyu --- drivers/iommu/tegra-smmu.c | 20 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index fd4479a..2b8a302 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -418,9 +418,13 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, offs = HWGRP_ASID_REG(i); val = smmu_read(smmu, offs); if (on) { - if (WARN_ON(val & mask)) - goto err_hw_busy; - val |= mask; + if (val) { + if (WARN_ON(val != mask)) + return -EINVAL; + goto skip; + } + + val = mask; memcpy(c->hwgrp, map, sizeof(u64)); } else { WARN_ON((val & mask) == mask); @@ -430,16 +434,8 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, } FLUSH_SMMU_REGS(smmu); +skip: return 0; - -err_hw_busy: - for_each_set_bit(i, map, TEGRA_SWGROUP_MAX) { - offs = HWGRP_ASID_REG(i); - val = smmu_read(smmu, offs); - val &= ~mask; - smmu_write(smmu, val, offs); - } - return -EBUSY; } static int smmu_client_set_hwgrp(struct smmu_client *c, -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 08/12] iommu/tegra: smmu: calculate ASID register offset by ID
ASID register offset is caclulated by SWGROUP ID so that we can get rid of old SoC specific MACROs. This ID conversion is needed for the unified SMMU driver over Tegra SoCs. We use dt-bindings MACRO instead of SoC dependent MACROs. The formula is: MC_SMMU_swgroup name_ASID_0 = MC_SMMU_AFI_ASID_0 + ID * 4; Now SWGROUP ID is the global HardWare Accelerator(HWA) identifier among all Tegra SoC except Tegra2. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v5: Added SMMU_ASID_BASE(== SMMU_AFI_ASID). Removed unused ASID offset definitions. Use 'unsigned long *' instead of u64 for swgroups bitmap. v4: Combined the following patches from v3: [PATCHv3 09/19] iommu/tegra: smmu: Calculate ASID register offset by ID [PATCHv3 16/19] iommu/tegra: smmu: Use dt-bindings MACRO Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/iommu/tegra-smmu.c | 111 +++-- 1 file changed, 17 insertions(+), 94 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 99b4bd4..6ab977a 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -43,46 +43,6 @@ #include dt-bindings/memory/tegra-swgroup.h -enum smmu_hwgrp { - HWGRP_AFI, - HWGRP_AVPC, - HWGRP_DC, - HWGRP_DCB, - HWGRP_EPP, - HWGRP_G2, - HWGRP_HC, - HWGRP_HDA, - HWGRP_ISP, - HWGRP_MPE, - HWGRP_NV, - HWGRP_NV2, - HWGRP_PPCS, - HWGRP_SATA, - HWGRP_VDE, - HWGRP_VI, - - HWGRP_COUNT, - - HWGRP_END = ~0, -}; - -#define HWG_AFI(1 HWGRP_AFI) -#define HWG_AVPC (1 HWGRP_AVPC) -#define HWG_DC (1 HWGRP_DC) -#define HWG_DCB(1 HWGRP_DCB) -#define HWG_EPP(1 HWGRP_EPP) -#define HWG_G2 (1 HWGRP_G2) -#define HWG_HC (1 HWGRP_HC) -#define HWG_HDA(1 HWGRP_HDA) -#define HWG_ISP(1 HWGRP_ISP) -#define HWG_MPE(1 HWGRP_MPE) -#define HWG_NV (1 HWGRP_NV) -#define HWG_NV2(1 HWGRP_NV2) -#define HWG_PPCS (1 HWGRP_PPCS) -#define HWG_SATA (1 HWGRP_SATA) -#define HWG_VDE(1 HWGRP_VDE) -#define HWG_VI (1 HWGRP_VI) - /* bitmap of the page sizes currently supported */ #define SMMU_IOMMU_PGSIZES (SZ_4K) @@ -152,21 +112,7 @@ enum { #define SMMU_TRANSLATION_ENABLE_2 0x230 #define SMMU_AFI_ASID 0x238 /* PCIE */ -#define SMMU_AVPC_ASID 0x23c /* AVP */ -#define SMMU_DC_ASID 0x240 /* Display controller */ -#define SMMU_DCB_ASID 0x244 /* Display controller B */ -#define SMMU_EPP_ASID 0x248 /* Encoder pre-processor */ -#define SMMU_G2_ASID 0x24c /* 2D engine */ -#define SMMU_HC_ASID 0x250 /* Host1x */ -#define SMMU_HDA_ASID 0x254 /* High-def audio */ -#define SMMU_ISP_ASID 0x258 /* Image signal processor */ -#define SMMU_MPE_ASID 0x264 /* MPEG encoder */ -#define SMMU_NV_ASID 0x268 /* (3D) */ -#define SMMU_NV2_ASID 0x26c /* (3D) */ -#define SMMU_PPCS_ASID 0x270 /* AHB */ -#define SMMU_SATA_ASID 0x278 /* SATA */ -#define SMMU_VDE_ASID 0x27c /* Video decoder */ -#define SMMU_VI_ASID 0x280 /* Video input */ +#define SMMU_ASID_BASE SMMU_AFI_ASID #define SMMU_PDE_NEXT_SHIFT28 @@ -238,27 +184,7 @@ enum { #define __smmu_client_enable_hwgrp(c, m) __smmu_client_set_hwgrp(c, m, 1) #define __smmu_client_disable_hwgrp(c) __smmu_client_set_hwgrp(c, 0, 0) -#define HWGRP_INIT(client) [HWGRP_##client] = SMMU_##client##_ASID - -static const u32 smmu_hwgrp_asid_reg[] = { - HWGRP_INIT(AFI), - HWGRP_INIT(AVPC), - HWGRP_INIT(DC), - HWGRP_INIT(DCB), - HWGRP_INIT(EPP), - HWGRP_INIT(G2), - HWGRP_INIT(HC), - HWGRP_INIT(HDA), - HWGRP_INIT(ISP), - HWGRP_INIT(MPE), - HWGRP_INIT(NV), - HWGRP_INIT(NV2), - HWGRP_INIT(PPCS), - HWGRP_INIT(SATA), - HWGRP_INIT(VDE), - HWGRP_INIT(VI), -}; -#define HWGRP_ASID_REG(x) (smmu_hwgrp_asid_reg[x]) +#define HWGRP_ASID_REG(x) ((x) * sizeof(u32) + SMMU_ASID_BASE) /* * Per client for address space @@ -267,7 +193,7 @@ struct smmu_client { struct device *dev; struct list_headlist; struct smmu_as *as; - u32 hwgrp; + unsigned long hwgrp[2]; }; /* @@ -384,41 +310,37 @@ static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs) */ #define FLUSH_SMMU_REGS(smmu) smmu_read(smmu, SMMU_CONFIG) -#define smmu_client_hwgrp(c) (u32)((c)-dev-platform_data) - static int __smmu_client_set_hwgrp(struct smmu_client *c, - unsigned long map, int on) + unsigned long *map, int on) { int i; struct smmu_as *as = c-as; u32 val, offs, mask = SMMU_ASID_ENABLE(as-asid); struct smmu_device *smmu = as-smmu; - WARN_ON
[PATCHv7 06/12] ARM: tegra: create a DT header defining SWGROUP ID
Create a header file to define the swgroup IDs used by the IOMMU(SMMU) binding. swgroup is a group of H/W clients which a Tegra SoC supports. This unique ID can be used to calculate MC_SMMU_swgroup name_ASID_0 register offset and MC_swgroup name_HOTRESET_*_0 register bit. This will allow the same header to be used by both device tree files, and drivers implementing this binding, which guarantees that the two stay in sync. This also makes device trees more readable by using names instead of magic numbers. For HOTRESET bit shifting we need another conversion table, which will come later. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6: Use 0x instead of ~0UL since dtc expand this to ~0ULL. v5: Added new macro TEGRA_SWGROUP_CELLS() and WO_U32_OF_U64(). v4: This is almost same as the previous v3. Just TEGRA_SWGROUP_MAX is added. [PATCHv3 15/19] ARM: tegra: Create a DT header defining SWGROUP ID Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- include/dt-bindings/memory/tegra-swgroup.h | 50 ++ 1 file changed, 50 insertions(+) create mode 100644 include/dt-bindings/memory/tegra-swgroup.h diff --git a/include/dt-bindings/memory/tegra-swgroup.h b/include/dt-bindings/memory/tegra-swgroup.h new file mode 100644 index 000..9c279f1 --- /dev/null +++ b/include/dt-bindings/memory/tegra-swgroup.h @@ -0,0 +1,50 @@ +/* + * This header provides constants for binding nvidia,swgroup ID + */ + +#ifndef _DT_BINDINGS_MEMORY_TEGRA_SWGROUP_H +#define _DT_BINDINGS_MEMORY_TEGRA_SWGROUP_H + +#define TEGRA_SWGROUP_AFI 0 /* 0x238 */ +#define TEGRA_SWGROUP_AVPC 1 /* 0x23c */ +#define TEGRA_SWGROUP_DC 2 /* 0x240 */ +#define TEGRA_SWGROUP_DCB 3 /* 0x244 */ +#define TEGRA_SWGROUP_EPP 4 /* 0x248 */ +#define TEGRA_SWGROUP_G2 5 /* 0x24c */ +#define TEGRA_SWGROUP_HC 6 /* 0x250 */ +#define TEGRA_SWGROUP_HDA 7 /* 0x254 */ +#define TEGRA_SWGROUP_ISP 8 /* 0x258 */ +#define TEGRA_SWGROUP_ISP2 SWGROUP_ISP +#define TEGRA_SWGROUP_DC14 9 /* 0x490 *//* Exceptional non-linear */ +#define TEGRA_SWGROUP_DC12 10 /* 0xa88 *//* Exceptional non-linear */ +#define TEGRA_SWGROUP_MPE 11 /* 0x264 */ +#define TEGRA_SWGROUP_MSENCSWGROUP_MPE +#define TEGRA_SWGROUP_NV 12 /* 0x268 */ +#define TEGRA_SWGROUP_NV2 13 /* 0x26c */ +#define TEGRA_SWGROUP_PPCS 14 /* 0x270 */ +#define TEGRA_SWGROUP_SATA215 /* 0x274 */ +#define TEGRA_SWGROUP_SATA 16 /* 0x278 */ +#define TEGRA_SWGROUP_VDE 17 /* 0x27c */ +#define TEGRA_SWGROUP_VI 18 /* 0x280 */ +#define TEGRA_SWGROUP_VIC 19 /* 0x284 */ +#define TEGRA_SWGROUP_XUSB_HOST20 /* 0x288 */ +#define TEGRA_SWGROUP_XUSB_DEV 21 /* 0x28c */ +#define TEGRA_SWGROUP_A9AVP22 /* 0x290 */ +#define TEGRA_SWGROUP_TSEC 23 /* 0x294 */ +#define TEGRA_SWGROUP_PPCS124 /* 0x298 */ +#define TEGRA_SWGROUP_SDMMC1A 25 /* 0xa94 *//* Linear shift again */ +#define TEGRA_SWGROUP_SDMMC2A 26 /* 0xa98 */ +#define TEGRA_SWGROUP_SDMMC3A 27 /* 0xa9c */ +#define TEGRA_SWGROUP_SDMMC4A 28 /* 0xaa0 */ +#define TEGRA_SWGROUP_ISP2B29 /* 0xaa4 */ +#define TEGRA_SWGROUP_GPU 30 /* 0xaa8 */ +#define TEGRA_SWGROUP_GPUB 31 /* 0xaac */ +#define TEGRA_SWGROUP_PPCS232 /* 0xab0 */ + +#define TWO_U32_OF_U64(x) ((x) 0x) ((x) 32) +#define TEGRA_SWGROUP_BIT(x) (1ULL TEGRA_SWGROUP_##x) +#define TEGRA_SWGROUP_CELLS(x) TWO_U32_OF_U64(TEGRA_SWGROUP_BIT(x)) + +#define TEGRA_SWGROUP_MAX 64 + +#endif /* _DT_BINDINGS_MEMORY_TEGRA_SWGROUP_H */ -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 04/12] driver/core: populate devices in order for IOMMUs
IOMMU devices on the bus need to be poplulated first, then iommu master devices are done later. With CONFIG_OF_IOMMU, iommus= DT binding would be used to identify whether a device can be an iommu msater or not. If a device can, we'll defer to populate that device till an iommu device is populated. Then, those deferred iommu master devices are populated and configured with help of the already populated iommu device. Signed-off-by: Hiroshi Doyu hd...@nvidia.com Cc: Greg Kroah-Hartman gre...@linuxfoundation.org --- This is related to the following discussion: [RFC PATCH] Documentation: devicetree: add description for generic bus properties http://lists.infradead.org/pipermail/linux-arm-kernel/2013-November/215042.html v6: Spinned off only driver core part from: [PATCHv5 2/9] driver/core: populate devices in order for IOMMUs v5: Use iommus= binding instread of arm,smmu's #stream-id-cells. v4: This is newly added, and the successor of the following RFC: [RFC][PATCHv3+ 1/2] driver/core: Add of_iommu_attach() http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006914.html Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/base/dd.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 0605176..0605f52 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -25,6 +25,7 @@ #include linux/async.h #include linux/pm_runtime.h #include linux/pinctrl/devinfo.h +#include linux/of_iommu.h #include base.h #include power/power.h @@ -273,6 +274,10 @@ static int really_probe(struct device *dev, struct device_driver *drv) dev-driver = drv; + ret = of_iommu_attach(dev); + if (ret) + goto probe_failed; + /* If using pinctrl, bind pins now before probing */ ret = pinctrl_bind_pins(dev); if (ret) -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 10/12] iommu/tegra: smmu: allow duplicate ASID wirte
The device, which belongs to the same ASID, can try to enable the same ASID as the other swgroup devices. This should be allowed but just skip the actual register write. If the write value is different, it will return -EINVAL. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v4: This was the part of v3, which isn't used any more. [PATCHv3 10/19] iommu/tegra: smmu: Get nvidia,swgroups from DT Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/iommu/tegra-smmu.c | 20 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index fd4479a..2b8a302 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -418,9 +418,13 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, offs = HWGRP_ASID_REG(i); val = smmu_read(smmu, offs); if (on) { - if (WARN_ON(val mask)) - goto err_hw_busy; - val |= mask; + if (val) { + if (WARN_ON(val != mask)) + return -EINVAL; + goto skip; + } + + val = mask; memcpy(c-hwgrp, map, sizeof(u64)); } else { WARN_ON((val mask) == mask); @@ -430,16 +434,8 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, } FLUSH_SMMU_REGS(smmu); +skip: return 0; - -err_hw_busy: - for_each_set_bit(i, map, TEGRA_SWGROUP_MAX) { - offs = HWGRP_ASID_REG(i); - val = smmu_read(smmu, offs); - val = ~mask; - smmu_write(smmu, val, offs); - } - return -EBUSY; } static int smmu_client_set_hwgrp(struct smmu_client *c, -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 12/12] iommu/tegra: smmu: add SMMU to an global iommu list
This allows to inquire if SMMU is populated or not. Suggested by Thierry Reding and copied his example code. Signed-off-by: Hiroshi Doyu hd...@nvidia.com Cc: Thierry Reding thierry.red...@gmail.com --- v6: New for v6. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/iommu/tegra-smmu.c | 55 +- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 2d4b8b6..d0f0ba7 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -225,6 +225,8 @@ struct smmu_debugfs_info { * Per SMMU device - IOMMU device */ struct smmu_device { + struct iommuiommu; + void __iomem*regbase; /* register offset base */ void __iomem**regs; /* register block start address array */ void __iomem**rege; /* register block end address array */ @@ -234,7 +236,6 @@ struct smmu_device { unsigned long page_count; /* total remappable size */ spinlock_t lock; char*name; - struct device *dev; struct rb_root clients; struct page *avp_vector_page; /* dummy page shared by all AS's */ @@ -371,7 +372,7 @@ static int register_smmu_client(struct smmu_device *smmu, return -EBUSY; } - client = devm_kzalloc(smmu-dev, sizeof(*client), GFP_KERNEL); + client = devm_kzalloc(smmu-iommu.dev, sizeof(*client), GFP_KERNEL); if (!client) return -ENOMEM; @@ -388,7 +389,7 @@ static int smmu_of_get_swgroups(struct device *dev, unsigned long *swgroups) of_property_for_each_phandle_with_args(dev-of_node, iommus, #iommu-cells, 0, args, cur, end) { - if (args.np != smmu_handle-dev-of_node) + if (args.np != smmu_handle-iommu.dev-of_node) continue; BUG_ON(args.args_count != 2); @@ -527,7 +528,7 @@ static void free_ptbl(struct smmu_as *as, dma_addr_t iova) unsigned long *pdir = (unsigned long *)page_address(as-pdir_page); if (pdir[pdn] != _PDE_VACANT(pdn)) { - dev_dbg(as-smmu-dev, pdn: %lx\n, pdn); + dev_dbg(as-smmu-iommu.dev, pdn: %lx\n, pdn); ClearPageReserved(SMMU_EX_PTBL_PAGE(pdir[pdn])); __free_page(SMMU_EX_PTBL_PAGE(pdir[pdn])); @@ -542,7 +543,7 @@ static void free_pdir(struct smmu_as *as) { unsigned addr; int count; - struct device *dev = as-smmu-dev; + struct device *dev = as-smmu-iommu.dev; if (!as-pdir_page) return; @@ -585,11 +586,11 @@ static unsigned long *locate_pte(struct smmu_as *as, unsigned long addr = SMMU_PDN_TO_ADDR(pdn); /* Vacant - allocate a new page table */ - dev_dbg(as-smmu-dev, New PTBL pdn: %lx\n, pdn); + dev_dbg(as-smmu-iommu.dev, New PTBL pdn: %lx\n, pdn); *ptbl_page_p = alloc_page(GFP_ATOMIC); if (!*ptbl_page_p) { - dev_err(as-smmu-dev, + dev_err(as-smmu-iommu.dev, failed to allocate smmu_device page table\n); return NULL; } @@ -649,7 +650,7 @@ static int alloc_pdir(struct smmu_as *as) /* * do the allocation, then grab as-lock */ - cnt = devm_kzalloc(smmu-dev, + cnt = devm_kzalloc(smmu-iommu.dev, sizeof(cnt[0]) * SMMU_PDIR_COUNT, GFP_KERNEL); page = alloc_page(GFP_KERNEL | __GFP_DMA); @@ -663,7 +664,8 @@ static int alloc_pdir(struct smmu_as *as) } if (!page || !cnt) { - dev_err(smmu-dev, failed to allocate at %s\n, __func__); + dev_err(smmu-iommu.dev, + failed to allocate at %s\n, __func__); err = -ENOMEM; goto err_out; } @@ -693,7 +695,7 @@ static int alloc_pdir(struct smmu_as *as) err_out: spin_unlock_irqrestore(as-lock, flags); - devm_kfree(smmu-dev, cnt); + devm_kfree(smmu-iommu.dev, cnt); if (page) __free_page(page); return err; @@ -748,7 +750,7 @@ static int smmu_iommu_map(struct iommu_domain *domain, unsigned long iova, unsigned long pfn = __phys_to_pfn(pa); unsigned long flags; - dev_info(as-smmu-dev, [%d] %08lx:%pa\n, as-asid, iova, pa); + dev_info(as-smmu-iommu.dev, [%d] %08lx:%pa\n, as-asid, iova, pa); if (!pfn_valid(pfn)) return -ENOMEM; @@ -765,7 +767,7 @@ static size_t smmu_iommu_unmap(struct iommu_domain *domain, unsigned long iova, struct smmu_as *as = domain-priv; unsigned long flags; - dev_dbg(as-smmu-dev, [%d] %08lx\n, as-asid, iova); + dev_dbg(as-smmu-iommu.dev
[PATCHv7 11/12] iommu/tegra: smmu: Rename hwgrp - swgroups
Use the correct term for SWGROUP related variables and macros. The term swgroup is the collection of memory client. A memory client usually represents a HardWare Accelerator(HWA) like GPU. Sometimes a strut device can belong to multiple swgroup so that swgroup's' is used here. This swgroups is the term used in Tegra TRM. Rename along with TRM. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v4: New for v4 Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/iommu/tegra-smmu.c | 36 ++-- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 2b8a302..2d4b8b6 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -179,12 +179,12 @@ enum { #define NUM_SMMU_REG_BANKS 3 -#define smmu_client_enable_hwgrp(c, m) smmu_client_set_hwgrp(c, m, 1) -#define smmu_client_disable_hwgrp(c) smmu_client_set_hwgrp(c, 0, 0) -#define __smmu_client_enable_hwgrp(c, m) __smmu_client_set_hwgrp(c, m, 1) -#define __smmu_client_disable_hwgrp(c) __smmu_client_set_hwgrp(c, 0, 0) +#define smmu_client_enable_swgroups(c, m) smmu_client_set_swgroups(c, m, 1) +#define smmu_client_disable_swgroups(c) smmu_client_set_swgroups(c, 0, 0) +#define __smmu_client_enable_swgroups(c, m) __smmu_client_set_swgroups(c, m, 1) +#define __smmu_client_disable_swgroups(c) __smmu_client_set_swgroups(c, 0, 0) -#define HWGRP_ASID_REG(x) ((x) * sizeof(u32) + SMMU_ASID_BASE) +#define SWGROUPS_ASID_REG(x) ((x) * sizeof(u32) + SMMU_ASID_BASE) /* * Per client for address space @@ -195,7 +195,7 @@ struct smmu_client { struct device *dev; struct list_headlist; struct smmu_as *as; - unsigned long hwgrp[2]; + unsigned long swgroups[2]; }; /* @@ -377,7 +377,7 @@ static int register_smmu_client(struct smmu_device *smmu, client-dev = dev; client-of_node = dev-of_node; - memcpy(client-hwgrp, swgroups, sizeof(u64)); + memcpy(client-swgroups, swgroups, sizeof(u64)); return insert_smmu_client(smmu, client); } @@ -403,7 +403,7 @@ static int smmu_of_get_swgroups(struct device *dev, unsigned long *swgroups) return -ENODEV; } -static int __smmu_client_set_hwgrp(struct smmu_client *c, +static int __smmu_client_set_swgroups(struct smmu_client *c, unsigned long *map, int on) { int i; @@ -412,10 +412,10 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, struct smmu_device *smmu = as-smmu; if (!on) - map = c-hwgrp; + map = c-swgroups; for_each_set_bit(i, map, TEGRA_SWGROUP_MAX) { - offs = HWGRP_ASID_REG(i); + offs = SWGROUPS_ASID_REG(i); val = smmu_read(smmu, offs); if (on) { if (val) { @@ -425,7 +425,7 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, } val = mask; - memcpy(c-hwgrp, map, sizeof(u64)); + memcpy(c-swgroups, map, sizeof(u64)); } else { WARN_ON((val mask) == mask); val = ~mask; @@ -438,7 +438,7 @@ skip: return 0; } -static int smmu_client_set_hwgrp(struct smmu_client *c, +static int smmu_client_set_swgroups(struct smmu_client *c, unsigned long *map, int on) { int err; @@ -447,7 +447,7 @@ static int smmu_client_set_hwgrp(struct smmu_client *c, struct smmu_device *smmu = as-smmu; spin_lock_irqsave(smmu-lock, flags); - err = __smmu_client_set_hwgrp(c, map, on); + err = __smmu_client_set_swgroups(c, map, on); spin_unlock_irqrestore(smmu-lock, flags); return err; } @@ -487,7 +487,7 @@ static int smmu_setup_regs(struct smmu_device *smmu) smmu_write(smmu, val, SMMU_PTB_DATA); list_for_each_entry(c, as-client, list) - __smmu_client_set_hwgrp(c, c-hwgrp, 1); + __smmu_client_set_swgroups(c, c-swgroups, 1); } smmu_write(smmu, smmu-translation_enable_0, SMMU_TRANSLATION_ENABLE_0); @@ -815,7 +815,7 @@ static int smmu_iommu_attach_dev(struct iommu_domain *domain, return -ENOMEM; client-as = as; - err = smmu_client_enable_hwgrp(client, client-hwgrp); + err = smmu_client_enable_swgroups(client, client-swgroups); if (err) return -EINVAL; @@ -835,7 +835,7 @@ static int smmu_iommu_attach_dev(struct iommu_domain *domain, * Reserve page zero for AVP vectors using a common dummy * page. */ - if (test_bit(TEGRA_SWGROUP_AVPC, client-hwgrp)) { + if (test_bit(TEGRA_SWGROUP_AVPC, client-swgroups)) { struct page *page; page
[PATCHv7 09/12] iommu/tegra: smmu: get swgroups from DT iommus=
This provides the info about which swgroups a device belongs to. This info is passed from DT. This is necessary for the unified SMMU driver among Tegra SoCs since each has different H/W accelerators. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6: - Explained #iommu-cells in the binding document. - Fixed old nvidia,memory-clients with 'iommus in the binding document. - Move smmu_of_get_swgroups() here from the previous patch not to break git bisecting. v5: iommu= in a device DT is used instead of mmu-masters in an iommu DT. This is iommu= version of: [PATCHv4 5/7] iommu/tegra: smmu: Support mmu-masters binding Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- .../bindings/iommu/nvidia,tegra30-smmu.txt | 30 - drivers/iommu/tegra-smmu.c | 135 ++--- 2 files changed, 145 insertions(+), 20 deletions(-) diff --git a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt index 89fb543..fd53f54 100644 --- a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt +++ b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt @@ -1,6 +1,6 @@ NVIDIA Tegra 30 IOMMU H/W, SMMU (System Memory Management Unit) -Required properties: +Required properties in the IOMMU node: - compatible : nvidia,tegra30-smmu - reg : Should contain 3 register banks(address and length) for each of the SMMU register blocks. @@ -8,9 +8,23 @@ Required properties: - nvidia,#asids : # of ASIDs - dma-window : IOVA start address and length. - nvidia,ahb : phandle to the ahb bus connected to SMMU. +- iommus: phandle to an iommu device which a device is + attached to and indicates which swgroups a device belongs to(SWGROUP ID). + SWGROUP ID is from 0 to 63, and a device can belong to multiple SWGROUPS. +- #iommu-cells. Should be 2. In client IOMMU specifiers, the two cells + represent a 64-bit bitmask of SWGROUP IDs under which the device + initiates transactions. The least significant word is first. See + dt-bindings/memory/tegra-swgroup.h for a list of valid values. + +Required properties in device nodes affected by the IOMMU: +- iommus: A list of phandle plus specifier pairs for each IOMMU that + affects master transactions initiated by the device. The number of + cells in each specifier is defined by the #iommu-cells property in + the IOMMU node referred to by the phandle. The meaning of the + specifier cells is defined by the referenced IOMMU's binding. Example: - smmu { + smmu: iommu { compatible = nvidia,tegra30-smmu; reg = 0x7000f010 0x02c 0x7000f1f0 0x010 @@ -18,4 +32,16 @@ Example: nvidia,#asids = 4;/* # of ASIDs */ dma-window = 0 0x4000;/* IOVA start length */ nvidia,ahb = ahb; + #iommu-cells = 2; }; + + host1x { + compatible = nvidia,tegra30-host1x, simple-bus; + iommus = smmu TEGRA_SWGROUP_CELLS(HC); + + gr3d { + compatible = nvidia,tegra30-gr3d; + iommus = smmu TEGRA_SWGROUP_CELLS(NV) + TEGRA_SWGROUP_CELLS(NV2); + + }; diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 6ab977a..fd4479a 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -190,6 +190,8 @@ enum { * Per client for address space */ struct smmu_client { + struct device_node *of_node; + struct rb_node node; struct device *dev; struct list_headlist; struct smmu_as *as; @@ -233,6 +235,7 @@ struct smmu_device { spinlock_t lock; char*name; struct device *dev; + struct rb_root clients; struct page *avp_vector_page; /* dummy page shared by all AS's */ /* @@ -310,6 +313,96 @@ static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs) */ #define FLUSH_SMMU_REGS(smmu) smmu_read(smmu, SMMU_CONFIG) +static struct smmu_client *find_smmu_client(struct smmu_device *smmu, + struct device_node *dev_node) +{ + struct rb_node *node = smmu-clients.rb_node; + + while (node) { + struct smmu_client *client; + + client = container_of(node, struct smmu_client, node); + if (dev_node client-of_node) + node = node-rb_left; + else if (dev_node client-of_node) + node = node-rb_right; + else + return client; + } + + return NULL; +} + +static int insert_smmu_client(struct smmu_device *smmu, + struct smmu_client *client
[PATCHv7 07/12] iommu/tegra: smmu: register device to iommu dynamically
platform_devices are registered as IOMMU'able dynamically via add_device() and remove_device(). Tegra SMMU can have multiple address spaces(AS). IOMMU'able devices can belong to one of them. Multiple IOVA maps are created at boot-up, which can be attached to devices later. We reserve 2 of them for static assignment, AS[0] for system default, AS[1] for AHB clusters as protected domain from others, where there are many traditional pheripheral devices like USB, SD/MMC. They should be isolated from some smart devices like host1x for system robustness. Even if smart devices behaves wrongly, the traditional devices(SD/MMC, USB) wouldn't be affected, and the system could continue most likely. DMA API(ARM) needs ARM_DMA_USE_IOMMU to be enabled. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6: Use smmu_iommu_{bound,unbind}_driver() instead of smmu_iommu_{add,del}_device() to register devices to SMMU. v5: Add check NUM_OF_STATIC_MAPS #asids. v4: Combined the following from v3. This makes more sense what they do. [PATCHv3 06/19] iommu/tegra: smmu: Select ARM_DMA_USE_IOMMU in Kconfig [PATCHv3 07/19] iommu/tegra: smmu: Create default IOVA maps [PATCHv3 08/19] iommu/tegra: smmu: Register platform_device to IOMMU dynamically [PATCHv3 19/19] iommu/tegra: smmu: Support Multiple ASID Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/iommu/Kconfig | 1 + drivers/iommu/tegra-smmu.c | 70 +- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 3e7fdbb..0a86d63 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -170,6 +170,7 @@ config TEGRA_IOMMU_SMMU bool Tegra SMMU IOMMU Support depends on ARCH_TEGRA TEGRA_AHB select IOMMU_API + select ARM_DMA_USE_IOMMU help Enables support for remapping discontiguous physical memory shared with the operating system into contiguous I/O virtual diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 3c772c9..99b4bd4 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -39,6 +39,9 @@ #include asm/page.h #include asm/cacheflush.h +#include asm/dma-iommu.h + +#include dt-bindings/memory/tegra-swgroup.h enum smmu_hwgrp { HWGRP_AFI, @@ -319,6 +322,8 @@ struct smmu_device { struct device_node *ahb; + struct dma_iommu_mapping **map; + int num_as; struct smmu_as as[0]; /* Run-time allocated array */ }; @@ -947,6 +952,44 @@ static void smmu_iommu_domain_destroy(struct iommu_domain *domain) dev_dbg(smmu-dev, smmu_as@%p\n, as); } +/* + * ASID[0] for the system default + * ASID[1] for PPCS(AHB bus children), which has SDMMC + * ASID[2][3].. open for drivers, first come, first served. + */ +enum { + SYSTEM_DEFAULT, + SYSTEM_PROTECTED, + NUM_OF_STATIC_MAPS, +}; + +static int smmu_iommu_bound_driver(struct device *dev) +{ + int err = -EPROBE_DEFER; + u32 swgroups = dev-platform_data; + struct dma_iommu_mapping *map = NULL; + + if (test_bit(TEGRA_SWGROUP_PPCS, swgroups)) + map = smmu_handle-map[SYSTEM_PROTECTED]; + else + map = smmu_handle-map[SYSTEM_DEFAULT]; + + if (map) + err = arm_iommu_attach_device(dev, map); + else + return -EPROBE_DEFER; + + pr_debug(swgroups=%08lx map=%p err=%d %s\n, +swgroups, map, err, dev_name(dev)); + return err; +} + +static void smmu_iommu_unbind_driver(struct device *dev) +{ + dev_dbg(dev, Detaching from map %p\n, to_dma_iommu_mapping(dev)); + arm_iommu_detach_device(dev); +} + static struct iommu_ops smmu_iommu_ops = { .domain_init= smmu_iommu_domain_init, .domain_destroy = smmu_iommu_domain_destroy, @@ -956,6 +999,8 @@ static struct iommu_ops smmu_iommu_ops = { .unmap = smmu_iommu_unmap, .iova_to_phys = smmu_iommu_iova_to_phys, .domain_has_cap = smmu_iommu_domain_has_cap, + .bound_driver = smmu_iommu_bound_driver, + .unbind_driver = smmu_iommu_unbind_driver, .pgsize_bitmap = SMMU_IOMMU_PGSIZES, }; @@ -1144,6 +1189,23 @@ static int tegra_smmu_resume(struct device *dev) return err; } +static void tegra_smmu_create_default_map(struct smmu_device *smmu) +{ + int i; + + for (i = 0; i smmu-num_as; i++) { + dma_addr_t base = smmu-iovmm_base; + size_t size = smmu-page_count PAGE_SHIFT; + + smmu-map[i] = arm_iommu_create_mapping(platform_bus_type, + base, size, 0); + if (IS_ERR(smmu-map[i])) + dev_err(smmu-dev, + Couldn't create: asid=%d map=%p %pa-%pa\n, + i, smmu-map[i], base, base + size - 1
[PATCHv7 03/12] iommu/of: check if dependee iommu is ready or not
IOMMU devices on the bus need to be poplulated first, then iommu master devices are done later. With CONFIG_OF_IOMMU, iommus= DT binding would be used to identify whether a device can be an iommu msater or not. If a device can, we'll defer to populate that device till an depending iommu device is populated. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6: Spinned off only of_iommu part from: [PATCHv5 2/9] driver/core: populate devices in order for IOMMUs v5: Use iommus= binding instread of arm,smmu's #stream-id-cells. v4: This is newly added, and the successor of the following RFC: [RFC][PATCHv3+ 1/2] driver/core: Add of_iommu_attach() http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006914.html Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/iommu/of_iommu.c | 14 ++ include/linux/of_iommu.h | 6 ++ 2 files changed, 20 insertions(+) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 5d1aeb9..557c0c8 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -125,3 +125,17 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index, return 0; } EXPORT_SYMBOL_GPL(of_get_dma_window); + +int of_iommu_attach(struct device *dev) +{ + const __be32 *cur, *end; + struct of_phandle_args args; + + of_property_for_each_phandle_with_args(dev-of_node, iommus, + #iommu-cells, 0, args, cur, end) { + if (!of_find_iommu_by_node(args.np)) + return -EPROBE_DEFER; + } + + return 0; +} diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index a0aa9d4..14c9a5c 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -14,6 +14,7 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix, extern void iommu_add(struct iommu *iommu); extern void iommu_del(struct iommu *iommu); +extern int of_iommu_attach(struct device *dev); #else @@ -32,6 +33,11 @@ static inline void iommu_del(struct iommu *iommu) { } +static inline int of_iommu_attach(struct device *dev) +{ + return 0; +} + #endif /* CONFIG_OF_IOMMU */ #endif /* __OF_IOMMU_H */ -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 02/12] iommu/of: introduce a global iommu device list
This enables to find an populated IOMMU device via a device node. This can be used to see if an dependee IOMMU is populated or not to keep correct device population order. Client devices need to wait an IOMMU to be populated. Suggested by Thierry Reding and copied his example code. Signed-off-by: Hiroshi Doyu hd...@nvidia.com Cc: Joerg Roedel j...@8bytes.org Cc: Thierry Reding thierry.red...@gmail.com --- v6: New for v6. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/iommu/of_iommu.c | 37 + include/linux/of_iommu.h | 16 2 files changed, 53 insertions(+) diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index ee249bc..5d1aeb9 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -20,6 +20,43 @@ #include linux/export.h #include linux/limits.h #include linux/of.h +#include linux/of_iommu.h +#include linux/device.h + +static DEFINE_MUTEX(iommus_lock); +static LIST_HEAD(iommus_list); + +void iommu_add(struct iommu *iommu) +{ + INIT_LIST_HEAD(iommu-list); + mutex_lock(iommus_lock); + list_add_tail(iommu-list, iommus_list); + mutex_unlock(iommus_lock); +} + +void iommu_del(struct iommu *iommu) +{ + INIT_LIST_HEAD(iommu-list); + mutex_lock(iommus_lock); + list_del(iommu-list); + mutex_unlock(iommus_lock); +} + +static struct iommu *of_find_iommu_by_node(struct device_node *np) +{ + struct iommu *iommu; + + mutex_lock(iommus_lock); + list_for_each_entry(iommu, iommus_list, list) { + if (iommu-dev-of_node == np) { + mutex_unlock(iommus_lock); + return iommu; + } + } + mutex_unlock(iommus_lock); + + return NULL; +} /** * of_get_dma_window - Parse *dma-window property and returns 0 if found. diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index 51a560f..a0aa9d4 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -3,10 +3,18 @@ #ifdef CONFIG_OF_IOMMU +struct iommu { + struct list_head list; + struct device *dev; +}; + extern int of_get_dma_window(struct device_node *dn, const char *prefix, int index, unsigned long *busno, dma_addr_t *addr, size_t *size); +extern void iommu_add(struct iommu *iommu); +extern void iommu_del(struct iommu *iommu); + #else static inline int of_get_dma_window(struct device_node *dn, const char *prefix, @@ -16,6 +24,14 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix, return -EINVAL; } +static inline void iommu_add(struct iommu *iommu) +{ +} + +static inline void iommu_del(struct iommu *iommu) +{ +} + #endif /* CONFIG_OF_IOMMU */ #endif /* __OF_IOMMU_H */ -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 05/12] iommu/core: add ops-{bound,unbind}_driver()
ops-{bound,unbind}_driver() functions are called at BUS_NOTIFY_{BOUND,UNBIND}_DRIVER respectively. This is necessary to control the device population order. IOMMU master devices depend on an IOMMU device instanciation. IOMMU master devices can be registered to an IOMMU only after it's successfully populated. This IOMMU registration is done via ops-bound_driver(). Currently this population can be deferred if depending IOMMU device hasn't yet been populated in driver core. This cannot be done via ops-add_device() since after add_device() device's population/instanciation can be still deferred via probe(). Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6: New for v6. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/iommu/iommu.c | 13 +++-- include/linux/iommu.h | 4 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index efc..5469d36 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -540,14 +540,23 @@ static int iommu_bus_notifier(struct notifier_block *nb, * ADD/DEL call into iommu driver ops if provided, which may * result in ADD/DEL notifiers to group-notifier */ - if (action == BUS_NOTIFY_ADD_DEVICE) { + switch (action) { + case BUS_NOTIFY_ADD_DEVICE: if (ops-add_device) return ops-add_device(dev); - } else if (action == BUS_NOTIFY_DEL_DEVICE) { + case BUS_NOTIFY_DEL_DEVICE: if (ops-remove_device dev-iommu_group) { ops-remove_device(dev); return 0; } + case BUS_NOTIFY_BOUND_DRIVER: + if (ops-bound_driver) + ops-bound_driver(dev); + break; + case BUS_NOTIFY_UNBIND_DRIVER: + if (ops-unbind_driver) + ops-unbind_driver(dev); + break; } /* diff --git a/include/linux/iommu.h b/include/linux/iommu.h index a444c79..a0e92be 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -96,6 +96,8 @@ enum iommu_attr { * @domain_has_cap: domain capabilities query * @add_device: add device to iommu grouping * @remove_device: remove device from iommu grouping + * @bound_driver: called at BUS_NOTIFY_BOUND_DRIVER + * @unbind_driver: called at BUS_NOTIFY_UNBIND_DRIVER * @domain_get_attr: Query domain attributes * @domain_set_attr: Change domain attributes * @pgsize_bitmap: bitmap of supported page sizes @@ -114,6 +116,8 @@ struct iommu_ops { unsigned long cap); int (*add_device)(struct device *dev); void (*remove_device)(struct device *dev); + int (*bound_driver)(struct device *dev); + void (*unbind_driver)(struct device *dev); int (*device_group)(struct device *dev, unsigned int *groupid); int (*domain_get_attr)(struct iommu_domain *domain, enum iommu_attr attr, void *data); -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv6+ 01/13] of: introduce of_property_for_earch_phandle_with_args()
Grant Likely grant.lik...@linaro.org wrote @ Thu, 12 Dec 2013 12:34:17 +0100: On Wed, 11 Dec 2013 14:33:38 +0100, Hiroshi Doyu hd...@nvidia.com wrote: Hi Grant, Grant Likely grant.lik...@linaro.org wrote @ Wed, 11 Dec 2013 14:28:45 +0100: On Thu, 21 Nov 2013 11:57:00 -0700, Stephen Warren swar...@wwwdotorg.org wrote: On 11/21/2013 10:17 AM, Hiroshi Doyu wrote: Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007062.html ... That's right, I forgot I said that. Yes please fix the implementation. Here's the latest. I'll include this with the next v7 series. Can I get your Acked-by with this? --8 From 8f7c0404aa68f0e8dbe0babc240590f6528ecc1f Mon Sep 17 00:00:00 2001 From: Hiroshi Doyu hd...@nvidia.com Date: Fri, 15 Nov 2013 10:52:53 +0200 Subject: [PATCH] of: introduce of_property_for_each_phandle_with_args() Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Signed-off-by: Hiroshi Doyu hd...@nvidia.com Cc: Rob Herring robherri...@gmail.com --- v7: Fixed some minors pointed by Rob and Stephen. v6: Iterate without intrducing a new struct. v6+++: Introduced a new struct of_phandle_iter to keep the state when iterating over the list. v6++: Optimized to avoid O(n^2), suggested by Stephen Warren. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007066.html I didn't introduce any struct to hold params and state here. v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. v5: New patch for v5. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/of/base.c | 46 ++ include/linux/of.h | 32 2 files changed, 78 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0e..cd4ab05 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1201,6 +1201,52 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) printk(\n); } +const __be32 *of_phandle_iter_next(const char *cells_name, int cell_count, +const __be32 *cur, const __be32 *end, +struct of_phandle_args *out_args) Having to pass in cells_name, cell_count, cur and end each time seems a little odd. Can a state structure be used instead? struct of_phandle_iter_state { const char *cells_name; int cells_count; const __be32 *cur; const __be32 *end; struct of_phandle_args out_args; } Make the caller provide one of those and fill it in with the init function. I rewrote this a few times and so now I have a few version of this implementations :-) The above proposal is similar to the version v6+++ mentioned in the above patch note: v6+++: Introduced a new struct of_phandle_iter to keep the state when iterating over the list. which is: [RFC][PATCHv6+++ 01/13] of: introduce of_property_for_earch_phandle_with_args() http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007087.html Stephen seemed to prefer the version without state struct. I like the idea to not pass the same arguments repeatly. Instead, wrapping them in a struct with state may look better. So if Stephen agrees, I'll rewrite the version with state struct again. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 01/12] of: introduce of_property_for_each_phandle_with_args()
Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Signed-off-by: Hiroshi Doyu Cc: Rob Herring Cc: Grant Likely --- v7: Fixed some minors pointed by Rob and Stephen. v6: Iterate without intrducing a new struct. v6+++: Introduced a new struct "of_phandle_iter" to keep the state when iterating over the list. v6++: Optimized to avoid O(n^2), suggested by Stephen Warren. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007066.html I didn't introduce any struct to hold params and state here. v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. v5: New patch for v5. Signed-off-by: Hiroshi Doyu --- drivers/of/base.c | 46 ++ include/linux/of.h | 32 2 files changed, 78 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0e..cd4ab05 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1201,6 +1201,52 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) printk("\n"); } +const __be32 *of_phandle_iter_next(const char *cells_name, int cell_count, + const __be32 *cur, const __be32 *end, + struct of_phandle_args *out_args) +{ + struct device_node *dn; + int i; + + if (!cells_name && !cell_count) + return NULL; + + if (!cur || (cur >= end)) + return NULL; + + dn = of_find_node_by_phandle(be32_to_cpup(cur++)); + if (!dn) + return NULL; + + if (cells_name) + if (of_property_read_u32(dn, cells_name, _count)) + return NULL; + + out_args->np = dn; + out_args->args_count = cell_count; + for (i = 0; i < cell_count; i++) + out_args->args[i] = be32_to_cpup(cur++); + + return cur; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_next); + +const __be32 *of_phandle_iter_init(const struct device_node *np, + const char *list_name, + const __be32 **end) +{ + size_t bytes; + const __be32 *cur; + + cur = of_get_property(np, list_name, ); + *end = cur; + if (bytes) + *end += bytes / sizeof(*cur); + + return cur; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_init); + static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, diff --git a/include/linux/of.h b/include/linux/of.h index 276c546..4345582 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -303,6 +303,14 @@ extern int of_parse_phandle_with_fixed_args(const struct device_node *np, extern int of_count_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name); +extern const __be32 *of_phandle_iter_init(const struct device_node *np, + const char *list_name, + const __be32 **end); +extern const __be32 *of_phandle_iter_next(const char *cells_name, + int cell_count, + const __be32 *cur, const __be32 *end, + struct of_phandle_args *out_args); + extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)); extern int of_alias_get_id(struct device_node *np, const char *stem); @@ -527,6 +535,22 @@ static inline int of_count_phandle_with_args(struct device_node *np, return -ENOSYS; } +static inline const __be32 *of_phandle_iter_init(const struct device_node *np, +const char *list_name, +const __be32 **end) +{ + return NULL; +} + +static inline const __be32 *of_phandle_iter_next(const char *cells_name, +int cell_count, +const __be32 *cur, +const __be32 *end, +struct of_phandle_args *out_args); +{ + return NULL; +} + static inline int of_alias_get_id(struct device_node *np, const char *stem) { return -ENOSYS; @@ -613,6 +637,14 @@ static inline int of_property_read_u32(const struct device_node *np, s; \ s = of_prop_next_string(prop, s)) +#define of_property_for_each_ph
[PATCHv7 00/12] Unifying SMMU driver among Tegra SoCs
Hi, This series provide: (0) IOMMU standard DT binding("iommus") (1) Unified IOMMU(SMMU) driver among Tegra SoCs (2) Multiple Address Space support(MASID) in IOMMU(SMMMU) (3) Tegra IOMMU'able devices, most of platform devices are IOMMU'able. There's been some discussion[1] about device population order. Some devices needs to be populated earlier than other devices regardless of their bus topology. For the solution I implemented an IOMMU hook in driver core: [PATCHv7 04/13] driver/core: populate devices in order for IOMMUs which is based on: http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006933.html The main problem here is, IOMMU devices on the bus need to be poplulated first, then iommu master devices are done later. With CONFIG_OF_IOMMU, "iommus=" DT binding would be used to identify whether a device can be an iommu msater or not. If a device can, we'll defer to populate that device till an iommu device is populated. Then, those defered iommu master devices are populated and configured with help of the already populated iommu device via a new IOMMU API iommu_ops->driver_bound(). This "iommus=" binding is expected used as the global/standard binding. Tested IOMMU functionality with T30 SD/MMC. Any further testing with T114 and/or other devices would be really appreciated. v6: Minior fixes. http://lists.infradead.org/pipermail/linux-arm-kernel/2013-November/213082.html v5: Use "iommus=" DT bindings as a standard IOMMU binding. http://lists.infradead.org/pipermail/linux-arm-kernel/2013-November/212331.html v4: Add a hook in driver core to control device populatin order. Introduced arm,smmu "mmu-master" binding instead of tegra own. Removed DT patches from this series. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006931.html v3: Updated based on Stephen Warren's feedback http://lists.linuxfoundation.org/pipermail/iommu/2013-October/006724.html v2: Updated based on Thierry Reding's and Stephen Warren's feedback http://lists.infradead.org/pipermail/linux-arm-kernel/2013-July/181888.html v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2013-June/180267.html Available in the git repository at: git://g...@nv-tegra.nvidia.com/user/hdoyu/linux.git smmu-upstreaming@20131212 Hiroshi Doyu (12): of: introduce of_property_for_each_phandle_with_args() iommu/of: introduce a global iommu device list iommu/of: check if dependee iommu is ready or not driver/core: populate devices in order for IOMMUs iommu/core: add ops->{bound,unbind}_driver() ARM: tegra: create a DT header defining SWGROUP ID iommu/tegra: smmu: register device to iommu dynamically iommu/tegra: smmu: calculate ASID register offset by ID iommu/tegra: smmu: get swgroups from DT "iommus=" iommu/tegra: smmu: allow duplicate ASID wirte iommu/tegra: smmu: Rename hwgrp -> swgroups iommu/tegra: smmu: add SMMU to an global iommu list .../bindings/iommu/nvidia,tegra30-smmu.txt | 30 +- drivers/base/dd.c | 5 + drivers/iommu/Kconfig | 1 + drivers/iommu/iommu.c | 13 +- drivers/iommu/of_iommu.c | 51 +++ drivers/iommu/tegra-smmu.c | 383 + drivers/of/base.c | 46 +++ include/dt-bindings/memory/tegra-swgroup.h | 50 +++ include/linux/iommu.h | 4 + include/linux/of.h | 32 ++ include/linux/of_iommu.h | 22 ++ 11 files changed, 487 insertions(+), 150 deletions(-) create mode 100644 include/dt-bindings/memory/tegra-swgroup.h -- 1.8.1.5 [1] "[RFC] early init and DT platform devices allocation/registration" https://lists.ozlabs.org/pipermail/devicetree-discuss/2013-June/thread.html#36542 "Report from 2013 ARM kernel summit" http://lists.infradead.org/pipermail/linux-arm-kernel/2013-November/210426.html "[RFC PATCH] Documentation: devicetree: add description for generic bus properties" http://lists.infradead.org/pipermail/linux-arm-kernel/2013-November/215042.html -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv6+ 01/13] of: introduce of_property_for_earch_phandle_with_args()
Hi Grant, Grant Likely wrote @ Wed, 11 Dec 2013 14:28:45 +0100: > On Thu, 21 Nov 2013 11:57:00 -0700, Stephen Warren > wrote: > > On 11/21/2013 10:17 AM, Hiroshi Doyu wrote: > > > Iterating over a property containing a list of phandles with arguments > > > is a common operation for device drivers. This patch adds a new > > > of_property_for_each_phandle_with_args() macro to make the iteration > > > simpler. > > > > > > Signed-off-by: Hiroshi Doyu > > > --- > > > v6+: > > > Use the description, which Grant Likely proposed, to be full enough > > > that a future reader can figure out why a patch was written. > > > > > > http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007062.html ... > That's right, I forgot I said that. Yes please fix the implementation. Here's the latest. I'll include this with the next v7 series. Can I get your Acked-by with this? --8< >From 8f7c0404aa68f0e8dbe0babc240590f6528ecc1f Mon Sep 17 00:00:00 2001 From: Hiroshi Doyu Date: Fri, 15 Nov 2013 10:52:53 +0200 Subject: [PATCH] of: introduce of_property_for_each_phandle_with_args() Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Signed-off-by: Hiroshi Doyu Cc: Rob Herring --- v7: Fixed some minors pointed by Rob and Stephen. v6: Iterate without intrducing a new struct. v6+++: Introduced a new struct "of_phandle_iter" to keep the state when iterating over the list. v6++: Optimized to avoid O(n^2), suggested by Stephen Warren. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007066.html I didn't introduce any struct to hold params and state here. v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. v5: New patch for v5. Signed-off-by: Hiroshi Doyu --- drivers/of/base.c | 46 ++ include/linux/of.h | 32 2 files changed, 78 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0e..cd4ab05 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1201,6 +1201,52 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) printk("\n"); } +const __be32 *of_phandle_iter_next(const char *cells_name, int cell_count, + const __be32 *cur, const __be32 *end, + struct of_phandle_args *out_args) +{ + struct device_node *dn; + int i; + + if (!cells_name && !cell_count) + return NULL; + + if (!cur || (cur >= end)) + return NULL; + + dn = of_find_node_by_phandle(be32_to_cpup(cur++)); + if (!dn) + return NULL; + + if (cells_name) + if (of_property_read_u32(dn, cells_name, _count)) + return NULL; + + out_args->np = dn; + out_args->args_count = cell_count; + for (i = 0; i < cell_count; i++) + out_args->args[i] = be32_to_cpup(cur++); + + return cur; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_next); + +const __be32 *of_phandle_iter_init(const struct device_node *np, + const char *list_name, + const __be32 **end) +{ + size_t bytes; + const __be32 *cur; + + cur = of_get_property(np, list_name, ); + *end = cur; + if (bytes) + *end += bytes / sizeof(*cur); + + return cur; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_init); + static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, diff --git a/include/linux/of.h b/include/linux/of.h index 276c546..4345582 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -303,6 +303,14 @@ extern int of_parse_phandle_with_fixed_args(const struct device_node *np, extern int of_count_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name); +extern const __be32 *of_phandle_iter_init(const struct device_node *np, + const char *list_name, + const __be32 **end); +extern const __be32 *of_phandle_iter_next(const char *cells_name, + int cell_count, + const __be32 *cur, const __be32 *end, + struct of_phandle_args *out_args); + extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)); extern int of
Re: [PATCHv6+ 01/13] of: introduce of_property_for_earch_phandle_with_args()
Hi Grant, Grant Likely grant.lik...@linaro.org wrote @ Wed, 11 Dec 2013 14:28:45 +0100: On Thu, 21 Nov 2013 11:57:00 -0700, Stephen Warren swar...@wwwdotorg.org wrote: On 11/21/2013 10:17 AM, Hiroshi Doyu wrote: Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007062.html ... That's right, I forgot I said that. Yes please fix the implementation. Here's the latest. I'll include this with the next v7 series. Can I get your Acked-by with this? --8 From 8f7c0404aa68f0e8dbe0babc240590f6528ecc1f Mon Sep 17 00:00:00 2001 From: Hiroshi Doyu hd...@nvidia.com Date: Fri, 15 Nov 2013 10:52:53 +0200 Subject: [PATCH] of: introduce of_property_for_each_phandle_with_args() Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Signed-off-by: Hiroshi Doyu hd...@nvidia.com Cc: Rob Herring robherri...@gmail.com --- v7: Fixed some minors pointed by Rob and Stephen. v6: Iterate without intrducing a new struct. v6+++: Introduced a new struct of_phandle_iter to keep the state when iterating over the list. v6++: Optimized to avoid O(n^2), suggested by Stephen Warren. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007066.html I didn't introduce any struct to hold params and state here. v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. v5: New patch for v5. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/of/base.c | 46 ++ include/linux/of.h | 32 2 files changed, 78 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0e..cd4ab05 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1201,6 +1201,52 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) printk(\n); } +const __be32 *of_phandle_iter_next(const char *cells_name, int cell_count, + const __be32 *cur, const __be32 *end, + struct of_phandle_args *out_args) +{ + struct device_node *dn; + int i; + + if (!cells_name !cell_count) + return NULL; + + if (!cur || (cur = end)) + return NULL; + + dn = of_find_node_by_phandle(be32_to_cpup(cur++)); + if (!dn) + return NULL; + + if (cells_name) + if (of_property_read_u32(dn, cells_name, cell_count)) + return NULL; + + out_args-np = dn; + out_args-args_count = cell_count; + for (i = 0; i cell_count; i++) + out_args-args[i] = be32_to_cpup(cur++); + + return cur; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_next); + +const __be32 *of_phandle_iter_init(const struct device_node *np, + const char *list_name, + const __be32 **end) +{ + size_t bytes; + const __be32 *cur; + + cur = of_get_property(np, list_name, bytes); + *end = cur; + if (bytes) + *end += bytes / sizeof(*cur); + + return cur; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_init); + static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, diff --git a/include/linux/of.h b/include/linux/of.h index 276c546..4345582 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -303,6 +303,14 @@ extern int of_parse_phandle_with_fixed_args(const struct device_node *np, extern int of_count_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name); +extern const __be32 *of_phandle_iter_init(const struct device_node *np, + const char *list_name, + const __be32 **end); +extern const __be32 *of_phandle_iter_next(const char *cells_name, + int cell_count, + const __be32 *cur, const __be32 *end, + struct of_phandle_args *out_args); + extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)); extern int of_alias_get_id(struct device_node *np, const char *stem); @@ -527,6 +535,22 @@ static inline int
[PATCHv7 00/12] Unifying SMMU driver among Tegra SoCs
Hi, This series provide: (0) IOMMU standard DT binding(iommus) (1) Unified IOMMU(SMMU) driver among Tegra SoCs (2) Multiple Address Space support(MASID) in IOMMU(SMMMU) (3) Tegra IOMMU'able devices, most of platform devices are IOMMU'able. There's been some discussion[1] about device population order. Some devices needs to be populated earlier than other devices regardless of their bus topology. For the solution I implemented an IOMMU hook in driver core: [PATCHv7 04/13] driver/core: populate devices in order for IOMMUs which is based on: http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006933.html The main problem here is, IOMMU devices on the bus need to be poplulated first, then iommu master devices are done later. With CONFIG_OF_IOMMU, iommus= DT binding would be used to identify whether a device can be an iommu msater or not. If a device can, we'll defer to populate that device till an iommu device is populated. Then, those defered iommu master devices are populated and configured with help of the already populated iommu device via a new IOMMU API iommu_ops-driver_bound(). This iommus= binding is expected used as the global/standard binding. Tested IOMMU functionality with T30 SD/MMC. Any further testing with T114 and/or other devices would be really appreciated. v6: Minior fixes. http://lists.infradead.org/pipermail/linux-arm-kernel/2013-November/213082.html v5: Use iommus= DT bindings as a standard IOMMU binding. http://lists.infradead.org/pipermail/linux-arm-kernel/2013-November/212331.html v4: Add a hook in driver core to control device populatin order. Introduced arm,smmu mmu-master binding instead of tegra own. Removed DT patches from this series. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006931.html v3: Updated based on Stephen Warren's feedback http://lists.linuxfoundation.org/pipermail/iommu/2013-October/006724.html v2: Updated based on Thierry Reding's and Stephen Warren's feedback http://lists.infradead.org/pipermail/linux-arm-kernel/2013-July/181888.html v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2013-June/180267.html Available in the git repository at: git://g...@nv-tegra.nvidia.com/user/hdoyu/linux.git smmu-upstreaming@20131212 Hiroshi Doyu (12): of: introduce of_property_for_each_phandle_with_args() iommu/of: introduce a global iommu device list iommu/of: check if dependee iommu is ready or not driver/core: populate devices in order for IOMMUs iommu/core: add ops-{bound,unbind}_driver() ARM: tegra: create a DT header defining SWGROUP ID iommu/tegra: smmu: register device to iommu dynamically iommu/tegra: smmu: calculate ASID register offset by ID iommu/tegra: smmu: get swgroups from DT iommus= iommu/tegra: smmu: allow duplicate ASID wirte iommu/tegra: smmu: Rename hwgrp - swgroups iommu/tegra: smmu: add SMMU to an global iommu list .../bindings/iommu/nvidia,tegra30-smmu.txt | 30 +- drivers/base/dd.c | 5 + drivers/iommu/Kconfig | 1 + drivers/iommu/iommu.c | 13 +- drivers/iommu/of_iommu.c | 51 +++ drivers/iommu/tegra-smmu.c | 383 + drivers/of/base.c | 46 +++ include/dt-bindings/memory/tegra-swgroup.h | 50 +++ include/linux/iommu.h | 4 + include/linux/of.h | 32 ++ include/linux/of_iommu.h | 22 ++ 11 files changed, 487 insertions(+), 150 deletions(-) create mode 100644 include/dt-bindings/memory/tegra-swgroup.h -- 1.8.1.5 [1] [RFC] early init and DT platform devices allocation/registration https://lists.ozlabs.org/pipermail/devicetree-discuss/2013-June/thread.html#36542 Report from 2013 ARM kernel summit http://lists.infradead.org/pipermail/linux-arm-kernel/2013-November/210426.html [RFC PATCH] Documentation: devicetree: add description for generic bus properties http://lists.infradead.org/pipermail/linux-arm-kernel/2013-November/215042.html -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv7 01/12] of: introduce of_property_for_each_phandle_with_args()
Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Signed-off-by: Hiroshi Doyu hd...@nvidia.com Cc: Rob Herring robherri...@gmail.com Cc: Grant Likely grant.lik...@linaro.org --- v7: Fixed some minors pointed by Rob and Stephen. v6: Iterate without intrducing a new struct. v6+++: Introduced a new struct of_phandle_iter to keep the state when iterating over the list. v6++: Optimized to avoid O(n^2), suggested by Stephen Warren. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007066.html I didn't introduce any struct to hold params and state here. v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. v5: New patch for v5. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/of/base.c | 46 ++ include/linux/of.h | 32 2 files changed, 78 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0e..cd4ab05 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1201,6 +1201,52 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) printk(\n); } +const __be32 *of_phandle_iter_next(const char *cells_name, int cell_count, + const __be32 *cur, const __be32 *end, + struct of_phandle_args *out_args) +{ + struct device_node *dn; + int i; + + if (!cells_name !cell_count) + return NULL; + + if (!cur || (cur = end)) + return NULL; + + dn = of_find_node_by_phandle(be32_to_cpup(cur++)); + if (!dn) + return NULL; + + if (cells_name) + if (of_property_read_u32(dn, cells_name, cell_count)) + return NULL; + + out_args-np = dn; + out_args-args_count = cell_count; + for (i = 0; i cell_count; i++) + out_args-args[i] = be32_to_cpup(cur++); + + return cur; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_next); + +const __be32 *of_phandle_iter_init(const struct device_node *np, + const char *list_name, + const __be32 **end) +{ + size_t bytes; + const __be32 *cur; + + cur = of_get_property(np, list_name, bytes); + *end = cur; + if (bytes) + *end += bytes / sizeof(*cur); + + return cur; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_init); + static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, diff --git a/include/linux/of.h b/include/linux/of.h index 276c546..4345582 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -303,6 +303,14 @@ extern int of_parse_phandle_with_fixed_args(const struct device_node *np, extern int of_count_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name); +extern const __be32 *of_phandle_iter_init(const struct device_node *np, + const char *list_name, + const __be32 **end); +extern const __be32 *of_phandle_iter_next(const char *cells_name, + int cell_count, + const __be32 *cur, const __be32 *end, + struct of_phandle_args *out_args); + extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)); extern int of_alias_get_id(struct device_node *np, const char *stem); @@ -527,6 +535,22 @@ static inline int of_count_phandle_with_args(struct device_node *np, return -ENOSYS; } +static inline const __be32 *of_phandle_iter_init(const struct device_node *np, +const char *list_name, +const __be32 **end) +{ + return NULL; +} + +static inline const __be32 *of_phandle_iter_next(const char *cells_name, +int cell_count, +const __be32 *cur, +const __be32 *end, +struct of_phandle_args *out_args); +{ + return NULL; +} + static inline int of_alias_get_id(struct device_node *np, const char *stem) { return -ENOSYS; @@ -613,6 +637,14 @@ static inline int of_property_read_u32(const struct device_node *np, s; \ s = of_prop_next_string(prop, s)) +#define of_property_for_each_phandle_with_args(node
Re: [PATCHv6 05/13] iommu/core: add ops->{bound,unbind}_driver()
On Mon, 25 Nov 2013 14:49:37 +0100 Hiroshi Doyu wrote: > Hi Joerg, > > Do you have some time to review this patch along with the following ones? > > [PATCHv6 02/13] iommu/of: introduce a global iommu device list > http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007050.html > > [PATCHv6 03/13] iommu/of: check if dependee iommu is ready or not > http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007051.html Any chance to get some feedback on them? > With those patches, now I'm trying to populate iommu master devices > after an IOMMU device is populated. Originally [PATCHv6 02/13] was > proposed by Thierry. I'm a bit afraid of adding new IOMMU API as > this, but I think that this new {bound,unbind}_driver() is the right > timiing that depeding devices are populated instead of add_device() > since, even after add_device, a device won't be populated. I'm not so > sure how this affects on the existing IOMMUs. > > It would be nice if you give some feedback on this. > > On Thu, 21 Nov 2013 14:40:41 +0100 > Hiroshi Doyu wrote: > > > ops->{bound,unbind}_driver() functions are called at > > BUS_NOTIFY_{BOUND,UNBIND}_DRIVER respectively. > > > > This is necessary to control the device population order. IOMMU master > > devices depend on an IOMMU device instanciation. IOMMU master devices > > can be registered to an IOMMU only after it's successfully > > populated. This IOMMU registration is done via > > ops->bound_driver(). Currently this population can be deferred if > > depending IOMMU device hasn't yet been populated in driver core. This > > cannot be done via ops->add_device() since after add_device() device's > > population/instanciation can be still deferred via probe(). > > > > Signed-off-by: Hiroshi Doyu > > --- > > v6: > > New for v6. > > --- > > drivers/iommu/iommu.c | 13 +++-- > > include/linux/iommu.h | 4 > > 2 files changed, 15 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > > index efc..5469d36 100644 > > --- a/drivers/iommu/iommu.c > > +++ b/drivers/iommu/iommu.c > > @@ -540,14 +540,23 @@ static int iommu_bus_notifier(struct notifier_block > > *nb, > > * ADD/DEL call into iommu driver ops if provided, which may > > * result in ADD/DEL notifiers to group->notifier > > */ > > - if (action == BUS_NOTIFY_ADD_DEVICE) { > > + switch (action) { > > + case BUS_NOTIFY_ADD_DEVICE: > > if (ops->add_device) > > return ops->add_device(dev); > > - } else if (action == BUS_NOTIFY_DEL_DEVICE) { > > + case BUS_NOTIFY_DEL_DEVICE: > > if (ops->remove_device && dev->iommu_group) { > > ops->remove_device(dev); > > return 0; > > } > > + case BUS_NOTIFY_BOUND_DRIVER: > > + if (ops->bound_driver) > > + ops->bound_driver(dev); > > + break; > > + case BUS_NOTIFY_UNBIND_DRIVER: > > + if (ops->unbind_driver) > > + ops->unbind_driver(dev); > > + break; > > } > > > > /* > > diff --git a/include/linux/iommu.h b/include/linux/iommu.h > > index a444c79..a0e92be 100644 > > --- a/include/linux/iommu.h > > +++ b/include/linux/iommu.h > > @@ -96,6 +96,8 @@ enum iommu_attr { > > * @domain_has_cap: domain capabilities query > > * @add_device: add device to iommu grouping > > * @remove_device: remove device from iommu grouping > > + * @bound_driver: called at BUS_NOTIFY_BOUND_DRIVER > > + * @unbind_driver: called at BUS_NOTIFY_UNBIND_DRIVER > > * @domain_get_attr: Query domain attributes > > * @domain_set_attr: Change domain attributes > > * @pgsize_bitmap: bitmap of supported page sizes > > @@ -114,6 +116,8 @@ struct iommu_ops { > > unsigned long cap); > > int (*add_device)(struct device *dev); > > void (*remove_device)(struct device *dev); > > + int (*bound_driver)(struct device *dev); > > + void (*unbind_driver)(struct device *dev); > > int (*device_group)(struct device *dev, unsigned int *groupid); > > int (*domain_get_attr)(struct iommu_domain *domain, > >enum iommu_attr attr, void *data); > > -- > > 1.8.1.5 > > > ___ > iommu mailing list > io...@lists.linux-foundation.org > https://lists.linuxfoundation.org/mailman/listinfo/iommu -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv6 05/13] iommu/core: add ops-{bound,unbind}_driver()
On Mon, 25 Nov 2013 14:49:37 +0100 Hiroshi Doyu hd...@nvidia.com wrote: Hi Joerg, Do you have some time to review this patch along with the following ones? [PATCHv6 02/13] iommu/of: introduce a global iommu device list http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007050.html [PATCHv6 03/13] iommu/of: check if dependee iommu is ready or not http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007051.html Any chance to get some feedback on them? With those patches, now I'm trying to populate iommu master devices after an IOMMU device is populated. Originally [PATCHv6 02/13] was proposed by Thierry. I'm a bit afraid of adding new IOMMU API as this, but I think that this new {bound,unbind}_driver() is the right timiing that depeding devices are populated instead of add_device() since, even after add_device, a device won't be populated. I'm not so sure how this affects on the existing IOMMUs. It would be nice if you give some feedback on this. On Thu, 21 Nov 2013 14:40:41 +0100 Hiroshi Doyu hd...@nvidia.com wrote: ops-{bound,unbind}_driver() functions are called at BUS_NOTIFY_{BOUND,UNBIND}_DRIVER respectively. This is necessary to control the device population order. IOMMU master devices depend on an IOMMU device instanciation. IOMMU master devices can be registered to an IOMMU only after it's successfully populated. This IOMMU registration is done via ops-bound_driver(). Currently this population can be deferred if depending IOMMU device hasn't yet been populated in driver core. This cannot be done via ops-add_device() since after add_device() device's population/instanciation can be still deferred via probe(). Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6: New for v6. --- drivers/iommu/iommu.c | 13 +++-- include/linux/iommu.h | 4 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index efc..5469d36 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -540,14 +540,23 @@ static int iommu_bus_notifier(struct notifier_block *nb, * ADD/DEL call into iommu driver ops if provided, which may * result in ADD/DEL notifiers to group-notifier */ - if (action == BUS_NOTIFY_ADD_DEVICE) { + switch (action) { + case BUS_NOTIFY_ADD_DEVICE: if (ops-add_device) return ops-add_device(dev); - } else if (action == BUS_NOTIFY_DEL_DEVICE) { + case BUS_NOTIFY_DEL_DEVICE: if (ops-remove_device dev-iommu_group) { ops-remove_device(dev); return 0; } + case BUS_NOTIFY_BOUND_DRIVER: + if (ops-bound_driver) + ops-bound_driver(dev); + break; + case BUS_NOTIFY_UNBIND_DRIVER: + if (ops-unbind_driver) + ops-unbind_driver(dev); + break; } /* diff --git a/include/linux/iommu.h b/include/linux/iommu.h index a444c79..a0e92be 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -96,6 +96,8 @@ enum iommu_attr { * @domain_has_cap: domain capabilities query * @add_device: add device to iommu grouping * @remove_device: remove device from iommu grouping + * @bound_driver: called at BUS_NOTIFY_BOUND_DRIVER + * @unbind_driver: called at BUS_NOTIFY_UNBIND_DRIVER * @domain_get_attr: Query domain attributes * @domain_set_attr: Change domain attributes * @pgsize_bitmap: bitmap of supported page sizes @@ -114,6 +116,8 @@ struct iommu_ops { unsigned long cap); int (*add_device)(struct device *dev); void (*remove_device)(struct device *dev); + int (*bound_driver)(struct device *dev); + void (*unbind_driver)(struct device *dev); int (*device_group)(struct device *dev, unsigned int *groupid); int (*domain_get_attr)(struct iommu_domain *domain, enum iommu_attr attr, void *data); -- 1.8.1.5 ___ iommu mailing list io...@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC][PATCHv6+++ 01/13] of: introduce of_property_for_earch_phandle_with_args()
On Mon, 2 Dec 2013 15:39:25 +0100 Rob Herring wrote: > On Mon, Dec 2, 2013 at 5:02 AM, Hiroshi Doyu wrote: > > Stephen Warren wrote @ Sun, 1 Dec 2013 20:00:09 > > +0100: > > > >> On 11/29/2013 04:46 AM, Hiroshi Doyu wrote: > >> ... > >> > Iterating over a property containing a list of phandles with arguments > >> > is a common operation for device drivers. This patch adds a new > >> > of_property_for_each_phandle_with_args() macro to make the iteration > >> > simpler. > >> > > >> > Introduced a new struct "of_phandle_iter" to keep the state when > >> > iterating over the list. > >> > > >> > Signed-off-by: Hiroshi Doyu Rob, thank you for review. I'll fix them and put this one into the next v7 series. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC][PATCHv6+++ 01/13] of: introduce of_property_for_earch_phandle_with_args()
Stephen Warren wrote @ Sun, 1 Dec 2013 20:00:09 +0100: > On 11/29/2013 04:46 AM, Hiroshi Doyu wrote: > ... > > Iterating over a property containing a list of phandles with arguments > > is a common operation for device drivers. This patch adds a new > > of_property_for_each_phandle_with_args() macro to make the iteration > > simpler. > > > > Introduced a new struct "of_phandle_iter" to keep the state when > > iterating over the list. > > > > Signed-off-by: Hiroshi Doyu > > --- > > v6+++: > > Surely that's v9; "+++" is rather unusual. My intention was to put this into the next v7 series after I get this reviewed as RFC. ... > Together with removing: > > > + const char *cells_name; > > + int cell_count; > > ... then you'd only be left with cur/end, so I think you could get away > without a struct at all, but simply "cur" as the iterator variable, plus > "end" as the one temp variable. Although the above proposal would be alsmot same as "[RFC][PATCHv6++ 01/13]"(*1) where I use *list(cur) and rem as remaining count, here's the update. I'll put this into v7 series. ---8<--8<--8<--8<--8<--8<--8<--8<--8<--- From: Hiroshi Doyu Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Signed-off-by: Hiroshi Doyu --- v6: Iterate without intrducing a new struct. v6+++: Introduced a new struct "of_phandle_iter" to keep the state when iterating over the list. v6++: Optimized to avoid O(n^2), suggested by Stephen Warren. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007066.html I didn't introduce any struct to hold params and state here. v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. v5: New patch for v5. Signed-off-by: Hiroshi Doyu --- drivers/of/base.c | 53 + include/linux/of.h | 34 ++ 2 files changed, 87 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0e..7501f24 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1201,6 +1201,59 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) printk("\n"); } +const __be32 *of_phandle_iter_next(const char *cells_name, int cell_count, + const __be32 *cur, const __be32 *end, + struct of_phandle_args *out_args) +{ + phandle phandle; + struct device_node *dn; + int i; + + if (!cells_name && !cell_count) + return NULL; + + if (!cur) + return NULL; + + if (end - cur <= 0) + return NULL; + + phandle = be32_to_cpup(cur++); + if (!phandle) + return NULL; + + dn = of_find_node_by_phandle(phandle); + if (!dn) + return NULL; + + if (cells_name) + if (of_property_read_u32(dn, cells_name, _count)) + return NULL; + + out_args->np = dn; + out_args->args_count = cell_count; + for (i = 0; i < cell_count; i++) + out_args->args[i] = be32_to_cpup(cur++); + + return cur; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_next); + +const __be32 *of_phandle_iter_init(const struct device_node *np, + const char *list_name, + const __be32 **end) +{ + size_t bytes; + const __be32 *cur; + + cur = of_get_property(np, list_name, ); + if (bytes) + *end = cur + bytes / sizeof(*cur); + + return cur; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_init); + static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, diff --git a/include/linux/of.h b/include/linux/of.h index 276c546..c23710b 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -303,6 +303,14 @@ extern int of_parse_phandle_with_fixed_args(const struct device_node *np, extern int of_count_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name); +extern const __be32 *of_phandle_iter_init(const struct device_node *np, + const char *list_name, + const __be32 **end); +extern const __be32 *of_phandle_iter_next(const char *cells_name, + int cell_count, +
Re: [RFC][PATCHv6+++ 01/13] of: introduce of_property_for_earch_phandle_with_args()
Stephen Warren swar...@wwwdotorg.org wrote @ Sun, 1 Dec 2013 20:00:09 +0100: On 11/29/2013 04:46 AM, Hiroshi Doyu wrote: ... Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Introduced a new struct of_phandle_iter to keep the state when iterating over the list. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6+++: Surely that's v9; +++ is rather unusual. My intention was to put this into the next v7 series after I get this reviewed as RFC. ... Together with removing: + const char *cells_name; + int cell_count; ... then you'd only be left with cur/end, so I think you could get away without a struct at all, but simply cur as the iterator variable, plus end as the one temp variable. Although the above proposal would be alsmot same as [RFC][PATCHv6++ 01/13](*1) where I use *list(cur) and rem as remaining count, here's the update. I'll put this into v7 series. ---8--8--8--8--8--8--8--8--8--- From: Hiroshi Doyu hd...@nvidia.com Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6: Iterate without intrducing a new struct. v6+++: Introduced a new struct of_phandle_iter to keep the state when iterating over the list. v6++: Optimized to avoid O(n^2), suggested by Stephen Warren. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007066.html I didn't introduce any struct to hold params and state here. v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. v5: New patch for v5. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/of/base.c | 53 + include/linux/of.h | 34 ++ 2 files changed, 87 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0e..7501f24 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1201,6 +1201,59 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) printk(\n); } +const __be32 *of_phandle_iter_next(const char *cells_name, int cell_count, + const __be32 *cur, const __be32 *end, + struct of_phandle_args *out_args) +{ + phandle phandle; + struct device_node *dn; + int i; + + if (!cells_name !cell_count) + return NULL; + + if (!cur) + return NULL; + + if (end - cur = 0) + return NULL; + + phandle = be32_to_cpup(cur++); + if (!phandle) + return NULL; + + dn = of_find_node_by_phandle(phandle); + if (!dn) + return NULL; + + if (cells_name) + if (of_property_read_u32(dn, cells_name, cell_count)) + return NULL; + + out_args-np = dn; + out_args-args_count = cell_count; + for (i = 0; i cell_count; i++) + out_args-args[i] = be32_to_cpup(cur++); + + return cur; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_next); + +const __be32 *of_phandle_iter_init(const struct device_node *np, + const char *list_name, + const __be32 **end) +{ + size_t bytes; + const __be32 *cur; + + cur = of_get_property(np, list_name, bytes); + if (bytes) + *end = cur + bytes / sizeof(*cur); + + return cur; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_init); + static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, diff --git a/include/linux/of.h b/include/linux/of.h index 276c546..c23710b 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -303,6 +303,14 @@ extern int of_parse_phandle_with_fixed_args(const struct device_node *np, extern int of_count_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name); +extern const __be32 *of_phandle_iter_init(const struct device_node *np, + const char *list_name, + const __be32 **end); +extern const __be32 *of_phandle_iter_next(const char *cells_name, + int cell_count, + const __be32 *cur, const __be32 *end, + struct of_phandle_args *out_args); + extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64
Re: [RFC][PATCHv6+++ 01/13] of: introduce of_property_for_earch_phandle_with_args()
On Mon, 2 Dec 2013 15:39:25 +0100 Rob Herring robherri...@gmail.com wrote: On Mon, Dec 2, 2013 at 5:02 AM, Hiroshi Doyu hd...@nvidia.com wrote: Stephen Warren swar...@wwwdotorg.org wrote @ Sun, 1 Dec 2013 20:00:09 +0100: On 11/29/2013 04:46 AM, Hiroshi Doyu wrote: ... Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Introduced a new struct of_phandle_iter to keep the state when iterating over the list. Signed-off-by: Hiroshi Doyu hd...@nvidia.com Rob, thank you for review. I'll fix them and put this one into the next v7 series. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[RFC][PATCHv6+++ 01/13] of: introduce of_property_for_earch_phandle_with_args()
Hiroshi Doyu wrote @ Thu, 28 Nov 2013 14:58:18 +0200 (EET): > > In other words, an implementation more along the lines of > > include/linux/of.h's: > > > > #define of_property_for_each_u32(np, propname, prop, p, u) \ > > for (prop = of_find_property(np, propname, NULL), \ > > p = of_prop_next_u32(prop, NULL, ); \ > > p; \ > > p = of_prop_next_u32(prop, p, )) > > > > ... so you'd need functions like of_prop_first_specifier() and > > of_prop_next_specifier(), and perhaps some associated set of state > > variables, perhaps with all the state wrapped into a single struct for > > simplicity. > > Although I couldn't invent any struct to hold params and state here, > I'd like you to review the following interface is ok or not. Tried again to introduce a new struct to keep track of iteration state as below: 8<-8<-8<-8<-8<-8<-- From: Hiroshi Doyu Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Introduced a new struct "of_phandle_iter" to keep the state when iterating over the list. Signed-off-by: Hiroshi Doyu --- v6+++: Introduced a new struct "of_phandle_iter" to keep the state when iterating over the list. v6++: Optimized to avoid O(n^2), suggested by Stephen Warren. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007066.html I didn't introduce any struct to hold params and state here. v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. v5: New patch for v5. Signed-off-by: Hiroshi Doyu --- drivers/of/base.c | 71 ++ include/linux/of.h | 45 ++ 2 files changed, 116 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0e..16fb2d9 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1201,6 +1201,77 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) printk("\n"); } +void of_phandle_iter_next(struct of_phandle_iter *iter, + struct of_phandle_args *out_args) +{ + phandle phandle; + struct device_node *dn; + int i, count = iter->cell_count; + + iter->err = -EINVAL; + if (!iter->cells_name && !iter->cell_count) + return; + + phandle = be32_to_cpup(iter->cur++); + if (!phandle) + return; + + dn = of_find_node_by_phandle(phandle); + if (!dn) + return; + + if (iter->cells_name) + if (of_property_read_u32(dn, iter->cells_name, )) + return; + + out_args->np = dn; + out_args->args_count = count; + for (i = 0; i < count; i++) + out_args->args[i] = be32_to_cpup(iter->cur++); + + iter->err = 0; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_next); + +static void __of_phandle_iter_set(struct of_phandle_iter *iter, + const struct device_node *np, + const char *list_name) +{ + size_t bytes; + const __be32 *prop; + + prop = of_get_property(np, list_name, ); + if (!prop) { + iter->err = -EINVAL; + return; + } + + iter->cur = prop; + iter->end = prop + bytes / sizeof(*prop); + iter->err = 0; +} + +void of_phandle_iter_start(struct of_phandle_iter *iter, + const struct device_node *np, + const char *list_name, + const char *cells_name, + int cell_count, + struct of_phandle_args *out_args) +{ + iter->err = -EINVAL; + if (!cells_name && !cell_count) + return; + + iter->cells_name = cells_name; + iter->cell_count = cell_count; + __of_phandle_iter_set(iter, np, list_name); + if (iter->err) + return; + + of_phandle_iter_next(iter, out_args); +} +EXPORT_SYMBOL_GPL(of_phandle_iter_start); + static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, diff --git a/include/linux/of.h b/include/linux/of.h index 276c546..1132b49 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -74,6 +74,18 @@ struct of_phandle_args { uint32_t args[MAX_PHANDLE_ARGS]; }; +/* + * k
[RFC][PATCHv6+++ 01/13] of: introduce of_property_for_earch_phandle_with_args()
Hiroshi Doyu hd...@nvidia.com wrote @ Thu, 28 Nov 2013 14:58:18 +0200 (EET): In other words, an implementation more along the lines of include/linux/of.h's: #define of_property_for_each_u32(np, propname, prop, p, u) \ for (prop = of_find_property(np, propname, NULL), \ p = of_prop_next_u32(prop, NULL, u); \ p; \ p = of_prop_next_u32(prop, p, u)) ... so you'd need functions like of_prop_first_specifier() and of_prop_next_specifier(), and perhaps some associated set of state variables, perhaps with all the state wrapped into a single struct for simplicity. Although I couldn't invent any struct to hold params and state here, I'd like you to review the following interface is ok or not. Tried again to introduce a new struct to keep track of iteration state as below: 8-8-8-8-8-8-- From: Hiroshi Doyu hd...@nvidia.com Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Introduced a new struct of_phandle_iter to keep the state when iterating over the list. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6+++: Introduced a new struct of_phandle_iter to keep the state when iterating over the list. v6++: Optimized to avoid O(n^2), suggested by Stephen Warren. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007066.html I didn't introduce any struct to hold params and state here. v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. v5: New patch for v5. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/of/base.c | 71 ++ include/linux/of.h | 45 ++ 2 files changed, 116 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0e..16fb2d9 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1201,6 +1201,77 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) printk(\n); } +void of_phandle_iter_next(struct of_phandle_iter *iter, + struct of_phandle_args *out_args) +{ + phandle phandle; + struct device_node *dn; + int i, count = iter-cell_count; + + iter-err = -EINVAL; + if (!iter-cells_name !iter-cell_count) + return; + + phandle = be32_to_cpup(iter-cur++); + if (!phandle) + return; + + dn = of_find_node_by_phandle(phandle); + if (!dn) + return; + + if (iter-cells_name) + if (of_property_read_u32(dn, iter-cells_name, count)) + return; + + out_args-np = dn; + out_args-args_count = count; + for (i = 0; i count; i++) + out_args-args[i] = be32_to_cpup(iter-cur++); + + iter-err = 0; +} +EXPORT_SYMBOL_GPL(of_phandle_iter_next); + +static void __of_phandle_iter_set(struct of_phandle_iter *iter, + const struct device_node *np, + const char *list_name) +{ + size_t bytes; + const __be32 *prop; + + prop = of_get_property(np, list_name, bytes); + if (!prop) { + iter-err = -EINVAL; + return; + } + + iter-cur = prop; + iter-end = prop + bytes / sizeof(*prop); + iter-err = 0; +} + +void of_phandle_iter_start(struct of_phandle_iter *iter, + const struct device_node *np, + const char *list_name, + const char *cells_name, + int cell_count, + struct of_phandle_args *out_args) +{ + iter-err = -EINVAL; + if (!cells_name !cell_count) + return; + + iter-cells_name = cells_name; + iter-cell_count = cell_count; + __of_phandle_iter_set(iter, np, list_name); + if (iter-err) + return; + + of_phandle_iter_next(iter, out_args); +} +EXPORT_SYMBOL_GPL(of_phandle_iter_start); + static int __of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, diff --git a/include/linux/of.h b/include/linux/of.h index 276c546..1132b49 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -74,6 +74,18 @@ struct of_phandle_args { uint32_t args[MAX_PHANDLE_ARGS]; }; +/* + * keep the state at iterating a list of phandles with variable number + * of args + */ +struct of_phandle_iter { + int err; + const __be32*cur; /* current phandle
[RFC][PATCHv6++ 01/13] of: introduce of_property_for_earch_phandle_with_args()
Stephen Warren wrote @ Thu, 21 Nov 2013 19:57:00 +0100: > On 11/21/2013 10:17 AM, Hiroshi Doyu wrote: > > Iterating over a property containing a list of phandles with arguments > > is a common operation for device drivers. This patch adds a new > > of_property_for_each_phandle_with_args() macro to make the iteration > > simpler. > > > > Signed-off-by: Hiroshi Doyu > > --- > > v6+: > > Use the description, which Grant Likely proposed, to be full enough > > that a future reader can figure out why a patch was written. > > http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007062.html > > This new version only addresses one of the concerns that Grant had, > namely the commit message. > > > diff --git a/include/linux/of.h b/include/linux/of.h > > > +#define of_property_for_each_phandle_with_args(np, list, cells, i, args) \ > > + for (i = 0; !of_parse_phandle_with_args(np, list, cells, i, args); i++) > > + > > Grant also wanted the actual implementation fixed so that it wasn't so > inefficient. > > What this current patch does is basically: > > for every entry in the property: > for every entry in the property before the current index: > parse the phandle+specifier > > That's roughly O(n^2). (n is # entries in the property) > > Instead, what should happen is: > > for every entry in the property: > parse the phandle+specifier > yield the result > > That's roughly O(n). > > In other words, an implementation more along the lines of > include/linux/of.h's: > > #define of_property_for_each_u32(np, propname, prop, p, u) \ > for (prop = of_find_property(np, propname, NULL), \ > p = of_prop_next_u32(prop, NULL, ); \ > p; \ > p = of_prop_next_u32(prop, p, )) > > ... so you'd need functions like of_prop_first_specifier() and > of_prop_next_specifier(), and perhaps some associated set of state > variables, perhaps with all the state wrapped into a single struct for > simplicity. Although I couldn't invent any struct to hold params and state here, I'd like you to review the following interface is ok or not. At first, I thought to refactor __of_parse_phandle_with_args() but it's a bit highly optimized by Stephen and it looked a bit hard to refactor without perf regressions. Instread, I introduced 2 new functions "of_parse_{first,next}_phandle_with_args()" to parse phandles. If this interface is ok, I'll include this into the next v7 series. -8<-8<-8<-8<-8<-8<-8<-8<-8<- From: Hiroshi Doyu Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Introduced "of_parse_{first,next}_phandle_with_args()", where "const __be32 **list" is used to hold the next list to be processed as a state pramameter, and both "of_parse_{first,next}_phandle_with_args()" returns the remaining list in the number of cell(4 byte). If any error happens, "list" is set NULL not to proceed the rest. Signed-off-by: Hiroshi Doyu --- v6++: Optimized to avoid O(n^2), suggested by Stephen Warren. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007066.html v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. v5: New patch for v5. Signed-off-by: Hiroshi Doyu --- drivers/of/base.c | 82 ++ include/linux/of.h | 52 ++ 2 files changed, 134 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0e..3e29b10 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1201,6 +1201,88 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) printk("\n"); } +int __of_parse_next_phandle_with_args(const __be32 **plist, + const char *cells_name, int cell_count, + struct of_phandle_args *out_args) +{ + phandle phandle; + int i, count = 0, err; + struct device_node *dn; + const __be32 *list; + + BUG_ON(!out_args); + BUG_ON(!cells_name && !cell_count); + + /* +* "*plist" should hold phandle, and it's updated to the next +* phandle at return if no error. +*/ + list = *plist; + out_args->np = NULL; + + phandle = be32_to_cpup(list); + if (!phandle) + goto err_out; + + dn = of_f
[RFC][PATCHv6++ 01/13] of: introduce of_property_for_earch_phandle_with_args()
Stephen Warren swar...@wwwdotorg.org wrote @ Thu, 21 Nov 2013 19:57:00 +0100: On 11/21/2013 10:17 AM, Hiroshi Doyu wrote: Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007062.html This new version only addresses one of the concerns that Grant had, namely the commit message. diff --git a/include/linux/of.h b/include/linux/of.h +#define of_property_for_each_phandle_with_args(np, list, cells, i, args) \ + for (i = 0; !of_parse_phandle_with_args(np, list, cells, i, args); i++) + Grant also wanted the actual implementation fixed so that it wasn't so inefficient. What this current patch does is basically: for every entry in the property: for every entry in the property before the current index: parse the phandle+specifier That's roughly O(n^2). (n is # entries in the property) Instead, what should happen is: for every entry in the property: parse the phandle+specifier yield the result That's roughly O(n). In other words, an implementation more along the lines of include/linux/of.h's: #define of_property_for_each_u32(np, propname, prop, p, u) \ for (prop = of_find_property(np, propname, NULL), \ p = of_prop_next_u32(prop, NULL, u); \ p; \ p = of_prop_next_u32(prop, p, u)) ... so you'd need functions like of_prop_first_specifier() and of_prop_next_specifier(), and perhaps some associated set of state variables, perhaps with all the state wrapped into a single struct for simplicity. Although I couldn't invent any struct to hold params and state here, I'd like you to review the following interface is ok or not. At first, I thought to refactor __of_parse_phandle_with_args() but it's a bit highly optimized by Stephen and it looked a bit hard to refactor without perf regressions. Instread, I introduced 2 new functions of_parse_{first,next}_phandle_with_args() to parse phandles. If this interface is ok, I'll include this into the next v7 series. -8-8-8-8-8-8-8-8-8- From: Hiroshi Doyu hd...@nvidia.com Iterating over a property containing a list of phandles with arguments is a common operation for device drivers. This patch adds a new of_property_for_each_phandle_with_args() macro to make the iteration simpler. Introduced of_parse_{first,next}_phandle_with_args(), where const __be32 **list is used to hold the next list to be processed as a state pramameter, and both of_parse_{first,next}_phandle_with_args() returns the remaining list in the number of cell(4 byte). If any error happens, list is set NULL not to proceed the rest. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6++: Optimized to avoid O(n^2), suggested by Stephen Warren. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007066.html v6+: Use the description, which Grant Likely proposed, to be full enough that a future reader can figure out why a patch was written. v5: New patch for v5. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/of/base.c | 82 ++ include/linux/of.h | 52 ++ 2 files changed, 134 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index f807d0e..3e29b10 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1201,6 +1201,88 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) printk(\n); } +int __of_parse_next_phandle_with_args(const __be32 **plist, + const char *cells_name, int cell_count, + struct of_phandle_args *out_args) +{ + phandle phandle; + int i, count = 0, err; + struct device_node *dn; + const __be32 *list; + + BUG_ON(!out_args); + BUG_ON(!cells_name !cell_count); + + /* +* *plist should hold phandle, and it's updated to the next +* phandle at return if no error. +*/ + list = *plist; + out_args-np = NULL; + + phandle = be32_to_cpup(list); + if (!phandle) + goto err_out; + + dn = of_find_node_by_phandle(phandle); + if (!dn) + goto err_out; + + if (cells_name) { + err = of_property_read_u32(dn, cells_name, count); + if (err) + goto err_out; + } else { + count = cell_count; + } + + out_args-np = dn
Re: [PATCHv6 05/13] iommu/core: add ops->{bound,unbind}_driver()
Hi Joerg, Do you have some time to review this patch along with the following ones? [PATCHv6 02/13] iommu/of: introduce a global iommu device list http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007050.html [PATCHv6 03/13] iommu/of: check if dependee iommu is ready or not http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007051.html With those patches, now I'm trying to populate iommu master devices after an IOMMU device is populated. Originally [PATCHv6 02/13] was proposed by Thierry. I'm a bit afraid of adding new IOMMU API as this, but I think that this new {bound,unbind}_driver() is the right timiing that depeding devices are populated instead of add_device() since, even after add_device, a device won't be populated. I'm not so sure how this affects on the existing IOMMUs. It would be nice if you give some feedback on this. On Thu, 21 Nov 2013 14:40:41 +0100 Hiroshi Doyu wrote: > ops->{bound,unbind}_driver() functions are called at > BUS_NOTIFY_{BOUND,UNBIND}_DRIVER respectively. > > This is necessary to control the device population order. IOMMU master > devices depend on an IOMMU device instanciation. IOMMU master devices > can be registered to an IOMMU only after it's successfully > populated. This IOMMU registration is done via > ops->bound_driver(). Currently this population can be deferred if > depending IOMMU device hasn't yet been populated in driver core. This > cannot be done via ops->add_device() since after add_device() device's > population/instanciation can be still deferred via probe(). > > Signed-off-by: Hiroshi Doyu > --- > v6: > New for v6. > --- > drivers/iommu/iommu.c | 13 +++-- > include/linux/iommu.h | 4 > 2 files changed, 15 insertions(+), 2 deletions(-) > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index efc..5469d36 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -540,14 +540,23 @@ static int iommu_bus_notifier(struct notifier_block *nb, >* ADD/DEL call into iommu driver ops if provided, which may >* result in ADD/DEL notifiers to group->notifier >*/ > - if (action == BUS_NOTIFY_ADD_DEVICE) { > + switch (action) { > + case BUS_NOTIFY_ADD_DEVICE: > if (ops->add_device) > return ops->add_device(dev); > - } else if (action == BUS_NOTIFY_DEL_DEVICE) { > + case BUS_NOTIFY_DEL_DEVICE: > if (ops->remove_device && dev->iommu_group) { > ops->remove_device(dev); > return 0; > } > + case BUS_NOTIFY_BOUND_DRIVER: > + if (ops->bound_driver) > + ops->bound_driver(dev); > + break; > + case BUS_NOTIFY_UNBIND_DRIVER: > + if (ops->unbind_driver) > + ops->unbind_driver(dev); > + break; > } > > /* > diff --git a/include/linux/iommu.h b/include/linux/iommu.h > index a444c79..a0e92be 100644 > --- a/include/linux/iommu.h > +++ b/include/linux/iommu.h > @@ -96,6 +96,8 @@ enum iommu_attr { > * @domain_has_cap: domain capabilities query > * @add_device: add device to iommu grouping > * @remove_device: remove device from iommu grouping > + * @bound_driver: called at BUS_NOTIFY_BOUND_DRIVER > + * @unbind_driver: called at BUS_NOTIFY_UNBIND_DRIVER > * @domain_get_attr: Query domain attributes > * @domain_set_attr: Change domain attributes > * @pgsize_bitmap: bitmap of supported page sizes > @@ -114,6 +116,8 @@ struct iommu_ops { > unsigned long cap); > int (*add_device)(struct device *dev); > void (*remove_device)(struct device *dev); > + int (*bound_driver)(struct device *dev); > + void (*unbind_driver)(struct device *dev); > int (*device_group)(struct device *dev, unsigned int *groupid); > int (*domain_get_attr)(struct iommu_domain *domain, > enum iommu_attr attr, void *data); > -- > 1.8.1.5 > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv6 05/13] iommu/core: add ops-{bound,unbind}_driver()
Hi Joerg, Do you have some time to review this patch along with the following ones? [PATCHv6 02/13] iommu/of: introduce a global iommu device list http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007050.html [PATCHv6 03/13] iommu/of: check if dependee iommu is ready or not http://lists.linuxfoundation.org/pipermail/iommu/2013-November/007051.html With those patches, now I'm trying to populate iommu master devices after an IOMMU device is populated. Originally [PATCHv6 02/13] was proposed by Thierry. I'm a bit afraid of adding new IOMMU API as this, but I think that this new {bound,unbind}_driver() is the right timiing that depeding devices are populated instead of add_device() since, even after add_device, a device won't be populated. I'm not so sure how this affects on the existing IOMMUs. It would be nice if you give some feedback on this. On Thu, 21 Nov 2013 14:40:41 +0100 Hiroshi Doyu hd...@nvidia.com wrote: ops-{bound,unbind}_driver() functions are called at BUS_NOTIFY_{BOUND,UNBIND}_DRIVER respectively. This is necessary to control the device population order. IOMMU master devices depend on an IOMMU device instanciation. IOMMU master devices can be registered to an IOMMU only after it's successfully populated. This IOMMU registration is done via ops-bound_driver(). Currently this population can be deferred if depending IOMMU device hasn't yet been populated in driver core. This cannot be done via ops-add_device() since after add_device() device's population/instanciation can be still deferred via probe(). Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v6: New for v6. --- drivers/iommu/iommu.c | 13 +++-- include/linux/iommu.h | 4 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index efc..5469d36 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -540,14 +540,23 @@ static int iommu_bus_notifier(struct notifier_block *nb, * ADD/DEL call into iommu driver ops if provided, which may * result in ADD/DEL notifiers to group-notifier */ - if (action == BUS_NOTIFY_ADD_DEVICE) { + switch (action) { + case BUS_NOTIFY_ADD_DEVICE: if (ops-add_device) return ops-add_device(dev); - } else if (action == BUS_NOTIFY_DEL_DEVICE) { + case BUS_NOTIFY_DEL_DEVICE: if (ops-remove_device dev-iommu_group) { ops-remove_device(dev); return 0; } + case BUS_NOTIFY_BOUND_DRIVER: + if (ops-bound_driver) + ops-bound_driver(dev); + break; + case BUS_NOTIFY_UNBIND_DRIVER: + if (ops-unbind_driver) + ops-unbind_driver(dev); + break; } /* diff --git a/include/linux/iommu.h b/include/linux/iommu.h index a444c79..a0e92be 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -96,6 +96,8 @@ enum iommu_attr { * @domain_has_cap: domain capabilities query * @add_device: add device to iommu grouping * @remove_device: remove device from iommu grouping + * @bound_driver: called at BUS_NOTIFY_BOUND_DRIVER + * @unbind_driver: called at BUS_NOTIFY_UNBIND_DRIVER * @domain_get_attr: Query domain attributes * @domain_set_attr: Change domain attributes * @pgsize_bitmap: bitmap of supported page sizes @@ -114,6 +116,8 @@ struct iommu_ops { unsigned long cap); int (*add_device)(struct device *dev); void (*remove_device)(struct device *dev); + int (*bound_driver)(struct device *dev); + void (*unbind_driver)(struct device *dev); int (*device_group)(struct device *dev, unsigned int *groupid); int (*domain_get_attr)(struct iommu_domain *domain, enum iommu_attr attr, void *data); -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv5 2/9] driver/core: populate devices in order for IOMMUs
Thierry Reding wrote @ Wed, 20 Nov 2013 14:14:48 +0100: > > Does the above mean the following? > > > > int of_iommu_attach(struct device *dev) > > { > > int i; > > struct of_phandle_args args; > > > > of_property_for_each_phandle_with_args(dev->of_node, "iommus", > >"#iommu-cells", i, ) > > if (!args->np->dev->driver) > > return -EPROBE_DEFER; > > return 0; > > } > > Not quite. The above would only check that a driver was bound to the > device. But if that device isn't an IOMMU then this doesn't help you. I thought that, as long as a device is a normal one, it's ok to let it go to be populated. We only care about that, IOMMU devices comes first, and clients should come later than IOMMUs, for population. In the above if all IOMMUs are not populated, client devices are always deferred. "args->np->dev" always points an IOMMU device in a loop. Otherwise(no "iommus=") it goes out from the loop immediately. +#define of_property_for_each_phandle_with_args(np, list, cells, i, args) \ +for (i = 0; !of_parse_phandle_with_args(np, list, cells, i, args); i++) > The standard way to solve this issue is to add the IOMMU to a global > list upon registration. Typically subsystems have some way to do that > already, Your implementation has some possibiity that we could construct any hierarchy of IOMMUs. > already, but it seems like IOMMU doesn't. It looks like that's one of > the side-effects of the assumption that there will always only be a > single IOMMU (per bus). There's the following case at least we have already had. "memory controller"---"smmu_a"---bus--+--"smmu_b"--"device_a" | | +--"device_b" "smmu_b" isn't related to a bus at all. > There's also no base object that IOMMU drivers implement, which is the > way it's usually done in other subsystems. The absence of that makes it > more difficult. I suspect the easiest way to do that would be to add a > new type, something like this: > With that you can use of_find_iommu_by_node() in the loop to check > whether an IOMMU has really been registered. Do you think if it's acceptable to see if a device is populated or not via "dev->driver"[1]? Grant Likely proposed to use flag[2] instead of struct device[2], though. [1] http://lists.linuxfoundation.org/pipermail/iommu/2013-July/006023.html [2] http://lists.linuxfoundation.org/pipermail/iommu/2013-October/006763.html -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv5 2/9] driver/core: populate devices in order for IOMMUs
Thierry Reding thierry.red...@gmail.com wrote @ Wed, 20 Nov 2013 14:14:48 +0100: Does the above mean the following? int of_iommu_attach(struct device *dev) { int i; struct of_phandle_args args; of_property_for_each_phandle_with_args(dev-of_node, iommus, #iommu-cells, i, args) if (!args-np-dev-driver) return -EPROBE_DEFER; return 0; } Not quite. The above would only check that a driver was bound to the device. But if that device isn't an IOMMU then this doesn't help you. I thought that, as long as a device is a normal one, it's ok to let it go to be populated. We only care about that, IOMMU devices comes first, and clients should come later than IOMMUs, for population. In the above if all IOMMUs are not populated, client devices are always deferred. args-np-dev always points an IOMMU device in a loop. Otherwise(no iommus=) it goes out from the loop immediately. +#define of_property_for_each_phandle_with_args(np, list, cells, i, args) \ +for (i = 0; !of_parse_phandle_with_args(np, list, cells, i, args); i++) The standard way to solve this issue is to add the IOMMU to a global list upon registration. Typically subsystems have some way to do that already, Your implementation has some possibiity that we could construct any hierarchy of IOMMUs. already, but it seems like IOMMU doesn't. It looks like that's one of the side-effects of the assumption that there will always only be a single IOMMU (per bus). There's the following case at least we have already had. memory controller---smmu_a---bus--+--smmu_b--device_a | | +--device_b smmu_b isn't related to a bus at all. There's also no base object that IOMMU drivers implement, which is the way it's usually done in other subsystems. The absence of that makes it more difficult. I suspect the easiest way to do that would be to add a new type, something like this: With that you can use of_find_iommu_by_node() in the loop to check whether an IOMMU has really been registered. Do you think if it's acceptable to see if a device is populated or not via dev-driver[1]? Grant Likely proposed to use flag[2] instead of struct device[2], though. [1] http://lists.linuxfoundation.org/pipermail/iommu/2013-July/006023.html [2] http://lists.linuxfoundation.org/pipermail/iommu/2013-October/006763.html -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] fs: partitions: efi: Fix bound check
Antti Miettinen wrote @ Wed, 20 Nov 2013 08:18:50 +0100: > On 20.11.2013 02:04, Andrew Morton wrote: > > On Fri, 15 Nov 2013 19:14:22 +0200 (EET) Antti P Miettinen > > wrote: > > > > > Use ARRAY_SIZE instead of sizeof to get proper max for label > > > length. > > > > > > Signed-off-by: Antti P Miettinen > > > Reviewed-by: Hiroshi Doyu > > > Tested-by: Hiroshi Doyu > > > > When fixing a bug, please provide a description of the user-visible > > impact of that bug. This is so that others can decide which kernel > > version(s) need the patch. > > > > Hiroshi Doyu tested this patch, so I assume there was some observable > > misbehaviour to test. Please fully describe that. > > Since this is just a read out of bounds it's not that bad, but the > problem becomes user-visible e.g. if one tries to use > CONFIG_DEBUG_PAGEALLOC and CONFIG_DEBUG_RODATA, at least with some > enhancements from Hiroshi. The above enhancement is almost ARCH_SUPPORTS_DEBUG_PAGEALLOC for ARM, which could catch illegal memory access(read/write) with a page fault although that enhancement itself needs some cleanups before being upstreamed. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv5 2/9] driver/core: populate devices in order for IOMMUs
Stephen Warren wrote @ Tue, 19 Nov 2013 22:22:47 +0100: > On 11/19/2013 05:03 AM, Hiroshi Doyu wrote: > > Hi Thierry, > > > > Thierry Reding wrote @ Tue, 19 Nov 2013 11:25:07 > > +0100: > > > >> From earlier discussions I thought the goal was to actually defer this > >> until all nodes referred to by the iommus property were actually > >> registered. The above only checks that the phandles can be resolved to > >> valid struct device_node:s. That doesn't mean that an actual IOMMU has > >> been registered for it, only that the devices have been created. > > > > Currently "bus->iommu_ops" is set at the end of tegra_smmu_probe(). So > > if "bus->iommu_ops" is set, it means that an iommu instance is > > populated at that time. > > Yes, but that's the register bus, upon which the device is a client, not > the bus upon which the device is a bus master. They aren't necessarily > the same. > > There's no getting around the fact that, as Thierry said, you need to > search for a registered IOMMU device for each phandle, and defer probe > if any aren't registered yet. > > If we do that, then you shouldn't need to look at the value of > dev->bus->iommu_ops at all; if all IOMMUs in the list were registered, > then iommu_ops must have been set when (one of them) was registered, and > if not, then it possibly wasn't, so defer probe. > > That way, this code won't have to change if the core IOMMU code gets > extended to support multiple IOMMUs, devices mastering transactions onto > buses other than their register bus, etc. Does the above mean the following? int of_iommu_attach(struct device *dev) { int i; struct of_phandle_args args; of_property_for_each_phandle_with_args(dev->of_node, "iommus", "#iommu-cells", i, ) if (!args->np->dev->driver) return -EPROBE_DEFER; return 0; } "args->np->dev->driver" needs the following patch: http://lists.linuxfoundation.org/pipermail/iommu/2013-July/006023.html -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv5 7/9] iommu/tegra: smmu: allow duplicate ASID wirte
The device, which belongs to the same ASID, can try to enable the same ASID as the other swgroup devices. This should be allowed but just skip the actual register write. If the write value is different, it will return -EINVAL. Signed-off-by: Hiroshi Doyu --- v4: This was the part of v3, which isn't used any more. [PATCHv3 10/19] iommu/tegra: smmu: Get "nvidia,swgroups" from DT --- drivers/iommu/tegra-smmu.c | 20 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index e915201a..c2ed075 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -418,9 +418,13 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, offs = HWGRP_ASID_REG(i); val = smmu_read(smmu, offs); if (on) { - if (WARN_ON(val & mask)) - goto err_hw_busy; - val |= mask; + if (val) { + if (WARN_ON(val != mask)) + return -EINVAL; + goto skip; + } + + val = mask; memcpy(c->hwgrp, map, sizeof(u64)); } else { WARN_ON((val & mask) == mask); @@ -430,16 +434,8 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, } FLUSH_SMMU_REGS(smmu); +skip: return 0; - -err_hw_busy: - for_each_set_bit(i, map, TEGRA_SWGROUP_MAX) { - offs = HWGRP_ASID_REG(i); - val = smmu_read(smmu, offs); - val &= ~mask; - smmu_write(smmu, val, offs); - } - return -EBUSY; } static int smmu_client_set_hwgrp(struct smmu_client *c, -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv5 8/9] iommu/tegra: smmu: Rename hwgrp -> swgroups
Use the correct term for SWGROUP related variables and macros. The term "swgroup" is the collection of "memory client". A "memory client" usually represents a HardWare Accelerator(HWA) like GPU. Sometimes a strut device can belong to multiple "swgroup" so that "swgroup's'" is used here. This "swgroups" is the term used in Tegra TRM. Rename along with TRM. Signed-off-by: Hiroshi Doyu --- v4: New for v4 --- drivers/iommu/tegra-smmu.c | 36 ++-- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index c2ed075..003a491 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -179,12 +179,12 @@ enum { #define NUM_SMMU_REG_BANKS 3 -#define smmu_client_enable_hwgrp(c, m) smmu_client_set_hwgrp(c, m, 1) -#define smmu_client_disable_hwgrp(c) smmu_client_set_hwgrp(c, 0, 0) -#define __smmu_client_enable_hwgrp(c, m) __smmu_client_set_hwgrp(c, m, 1) -#define __smmu_client_disable_hwgrp(c) __smmu_client_set_hwgrp(c, 0, 0) +#define smmu_client_enable_swgroups(c, m) smmu_client_set_swgroups(c, m, 1) +#define smmu_client_disable_swgroups(c) smmu_client_set_swgroups(c, 0, 0) +#define __smmu_client_enable_swgroups(c, m) __smmu_client_set_swgroups(c, m, 1) +#define __smmu_client_disable_swgroups(c) __smmu_client_set_swgroups(c, 0, 0) -#define HWGRP_ASID_REG(x) ((x) * sizeof(u32) + SMMU_ASID_BASE) +#define SWGROUPS_ASID_REG(x) ((x) * sizeof(u32) + SMMU_ASID_BASE) /* * Per client for address space @@ -195,7 +195,7 @@ struct smmu_client { struct device *dev; struct list_headlist; struct smmu_as *as; - unsigned long hwgrp[2]; + unsigned long swgroups[2]; }; /* @@ -377,7 +377,7 @@ static int register_smmu_client(struct smmu_device *smmu, client->dev = dev; client->of_node = dev->of_node; - memcpy(client->hwgrp, swgroups, sizeof(u64)); + memcpy(client->swgroups, swgroups, sizeof(u64)); return insert_smmu_client(smmu, client); } @@ -403,7 +403,7 @@ static int smmu_of_get_swgroups(struct device *dev, unsigned long *swgroups) return -ENODEV; } -static int __smmu_client_set_hwgrp(struct smmu_client *c, +static int __smmu_client_set_swgroups(struct smmu_client *c, unsigned long *map, int on) { int i; @@ -412,10 +412,10 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, struct smmu_device *smmu = as->smmu; if (!on) - map = c->hwgrp; + map = c->swgroups; for_each_set_bit(i, map, TEGRA_SWGROUP_MAX) { - offs = HWGRP_ASID_REG(i); + offs = SWGROUPS_ASID_REG(i); val = smmu_read(smmu, offs); if (on) { if (val) { @@ -425,7 +425,7 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, } val = mask; - memcpy(c->hwgrp, map, sizeof(u64)); + memcpy(c->swgroups, map, sizeof(u64)); } else { WARN_ON((val & mask) == mask); val &= ~mask; @@ -438,7 +438,7 @@ skip: return 0; } -static int smmu_client_set_hwgrp(struct smmu_client *c, +static int smmu_client_set_swgroups(struct smmu_client *c, unsigned long *map, int on) { int err; @@ -447,7 +447,7 @@ static int smmu_client_set_hwgrp(struct smmu_client *c, struct smmu_device *smmu = as->smmu; spin_lock_irqsave(>lock, flags); - err = __smmu_client_set_hwgrp(c, map, on); + err = __smmu_client_set_swgroups(c, map, on); spin_unlock_irqrestore(>lock, flags); return err; } @@ -487,7 +487,7 @@ static int smmu_setup_regs(struct smmu_device *smmu) smmu_write(smmu, val, SMMU_PTB_DATA); list_for_each_entry(c, >client, list) - __smmu_client_set_hwgrp(c, c->hwgrp, 1); + __smmu_client_set_swgroups(c, c->swgroups, 1); } smmu_write(smmu, smmu->translation_enable_0, SMMU_TRANSLATION_ENABLE_0); @@ -815,7 +815,7 @@ static int smmu_iommu_attach_dev(struct iommu_domain *domain, return -ENOMEM; client->as = as; - err = smmu_client_enable_hwgrp(client, client->hwgrp); + err = smmu_client_enable_swgroups(client, client->swgroups); if (err) return -EINVAL; @@ -835,7 +835,7 @@ static int smmu_iommu_attach_dev(struct iommu_domain *domain, * Reserve "page zero" for AVP vectors using a common dummy * page. */ - if (test_bit(TEGRA_SWGROUP_AVPC, client->hwgrp)) { + if (test_
[PATCHv5 3/9] ARM: tegra: create a DT header defining SWGROUP ID
Create a header file to define the swgroup IDs used by the IOMMU(SMMU) binding. "swgroup" is a group of H/W clients which a Tegra SoC supports. This unique ID can be used to calculate MC_SMMU__ASID_0 register offset and MC__HOTRESET_*_0 register bit. This will allow the same header to be used by both device tree files, and drivers implementing this binding, which guarantees that the two stay in sync. This also makes device trees more readable by using names instead of magic numbers. For HOTRESET bit shifting we need another conversion table, which will come later. Signed-off-by: Hiroshi Doyu --- v5: Added new macro TEGRA_SWGROUP_CELLS() and WO_U32_OF_U64(). v4: This is almost same as the previous v3. Just TEGRA_SWGROUP_MAX is added. [PATCHv3 15/19] ARM: tegra: Create a DT header defining SWGROUP ID --- include/dt-bindings/memory/tegra-swgroup.h | 50 ++ 1 file changed, 50 insertions(+) create mode 100644 include/dt-bindings/memory/tegra-swgroup.h diff --git a/include/dt-bindings/memory/tegra-swgroup.h b/include/dt-bindings/memory/tegra-swgroup.h new file mode 100644 index 000..73079ad --- /dev/null +++ b/include/dt-bindings/memory/tegra-swgroup.h @@ -0,0 +1,50 @@ +/* + * This header provides constants for binding nvidia,swgroup ID + */ + +#ifndef _DT_BINDINGS_MEMORY_TEGRA_SWGROUP_H +#define _DT_BINDINGS_MEMORY_TEGRA_SWGROUP_H + +#define TEGRA_SWGROUP_AFI 0 /* 0x238 */ +#define TEGRA_SWGROUP_AVPC 1 /* 0x23c */ +#define TEGRA_SWGROUP_DC 2 /* 0x240 */ +#define TEGRA_SWGROUP_DCB 3 /* 0x244 */ +#define TEGRA_SWGROUP_EPP 4 /* 0x248 */ +#define TEGRA_SWGROUP_G2 5 /* 0x24c */ +#define TEGRA_SWGROUP_HC 6 /* 0x250 */ +#define TEGRA_SWGROUP_HDA 7 /* 0x254 */ +#define TEGRA_SWGROUP_ISP 8 /* 0x258 */ +#define TEGRA_SWGROUP_ISP2 SWGROUP_ISP +#define TEGRA_SWGROUP_DC14 9 /* 0x490 *//* Exceptional non-linear */ +#define TEGRA_SWGROUP_DC12 10 /* 0xa88 *//* Exceptional non-linear */ +#define TEGRA_SWGROUP_MPE 11 /* 0x264 */ +#define TEGRA_SWGROUP_MSENCSWGROUP_MPE +#define TEGRA_SWGROUP_NV 12 /* 0x268 */ +#define TEGRA_SWGROUP_NV2 13 /* 0x26c */ +#define TEGRA_SWGROUP_PPCS 14 /* 0x270 */ +#define TEGRA_SWGROUP_SATA215 /* 0x274 */ +#define TEGRA_SWGROUP_SATA 16 /* 0x278 */ +#define TEGRA_SWGROUP_VDE 17 /* 0x27c */ +#define TEGRA_SWGROUP_VI 18 /* 0x280 */ +#define TEGRA_SWGROUP_VIC 19 /* 0x284 */ +#define TEGRA_SWGROUP_XUSB_HOST20 /* 0x288 */ +#define TEGRA_SWGROUP_XUSB_DEV 21 /* 0x28c */ +#define TEGRA_SWGROUP_A9AVP22 /* 0x290 */ +#define TEGRA_SWGROUP_TSEC 23 /* 0x294 */ +#define TEGRA_SWGROUP_PPCS124 /* 0x298 */ +#define TEGRA_SWGROUP_SDMMC1A 25 /* 0xa94 *//* Linear shift again */ +#define TEGRA_SWGROUP_SDMMC2A 26 /* 0xa98 */ +#define TEGRA_SWGROUP_SDMMC3A 27 /* 0xa9c */ +#define TEGRA_SWGROUP_SDMMC4A 28 /* 0xaa0 */ +#define TEGRA_SWGROUP_ISP2B29 /* 0xaa4 */ +#define TEGRA_SWGROUP_GPU 30 /* 0xaa8 */ +#define TEGRA_SWGROUP_GPUB 31 /* 0xaac */ +#define TEGRA_SWGROUP_PPCS232 /* 0xab0 */ + +#define TWO_U32_OF_U64(x) ((x) & ~0UL) ((x) >> 32) +#define TEGRA_SWGROUP_BIT(x) (1ULL << TEGRA_SWGROUP_##x) +#define TEGRA_SWGROUP_CELLS(x) TWO_U32_OF_U64(TEGRA_SWGROUP_BIT(x)) + +#define TEGRA_SWGROUP_MAX 64 + +#endif /* _DT_BINDINGS_MEMORY_TEGRA_SWGROUP_H */ -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv5 6/9] iommu/tegra: smmu: get swgroups from DT "iommus="
This provides the info about which swgroups a device belongs to. This info is passed from DT. This is necessary for the unified SMMU driver among Tegra SoCs since each has different H/W accelerators. Signed-off-by: Hiroshi Doyu --- v5: "iommu=" in a device DT is used instead of "mmu-masters" in an iommu DT. This is "iommu=" version of: [PATCHv4 5/7] iommu/tegra: smmu: Support "mmu-masters" binding --- .../bindings/iommu/nvidia,tegra30-smmu.txt | 17 ++- drivers/iommu/tegra-smmu.c | 125 ++--- 2 files changed, 126 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt index 89fb543..44a4dc3 100644 --- a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt +++ b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt @@ -8,9 +8,12 @@ Required properties: - nvidia,#asids : # of ASIDs - dma-window : IOVA start address and length. - nvidia,ahb : phandle to the ahb bus connected to SMMU. +- iommus: phandle to an iommu device which a device is + attached to and indicates which swgroups a device belongs to(SWGROUP ID). + SWGROUP ID is from 0 to 63, and a device can belong to multiple SWGROUPS. Example: - smmu { + smmu: iommu { compatible = "nvidia,tegra30-smmu"; reg = <0x7000f010 0x02c 0x7000f1f0 0x010 @@ -18,4 +21,16 @@ Example: nvidia,#asids = <4>;/* # of ASIDs */ dma-window = <0 0x4000>;/* IOVA start & length */ nvidia,ahb = <>; + #iommu-cells = <2>; }; + + host1x { + compatible = "nvidia,tegra30-host1x", "simple-bus"; + iommus = < TEGRA_SWGROUP_CELLS(HC)>; + + gr3d { + compatible = "nvidia,tegra30-gr3d"; + nvidia,memory-clients = < TEGRA_SWGROUP_CELLS(NV) + TEGRA_SWGROUP_CELLS(NV2)>; + + }; diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index e999ad0..e915201a 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -190,6 +190,8 @@ enum { * Per client for address space */ struct smmu_client { + struct device_node *of_node; + struct rb_node node; struct device *dev; struct list_headlist; struct smmu_as *as; @@ -233,6 +235,7 @@ struct smmu_device { spinlock_t lock; char*name; struct device *dev; + struct rb_root clients; struct page *avp_vector_page; /* dummy page shared by all AS's */ /* @@ -310,6 +313,96 @@ static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs) */ #define FLUSH_SMMU_REGS(smmu) smmu_read(smmu, SMMU_CONFIG) +static struct smmu_client *find_smmu_client(struct smmu_device *smmu, + struct device_node *dev_node) +{ + struct rb_node *node = smmu->clients.rb_node; + + while (node) { + struct smmu_client *client; + + client = container_of(node, struct smmu_client, node); + if (dev_node < client->of_node) + node = node->rb_left; + else if (dev_node > client->of_node) + node = node->rb_right; + else + return client; + } + + return NULL; +} + +static int insert_smmu_client(struct smmu_device *smmu, + struct smmu_client *client) +{ + struct rb_node **new, *parent; + + new = >clients.rb_node; + parent = NULL; + while (*new) { + struct smmu_client *this; + this = container_of(*new, struct smmu_client, node); + + parent = *new; + if (client->of_node < this->of_node) + new = &((*new)->rb_left); + else if (client->of_node > this->of_node) + new = &((*new)->rb_right); + else + return -EEXIST; + } + + rb_link_node(>node, parent, new); + rb_insert_color(>node, >clients); + return 0; +} + +static int register_smmu_client(struct smmu_device *smmu, + struct device *dev, unsigned long *swgroups) +{ + struct smmu_client *client; + + client = find_smmu_client(smmu, dev->of_node); + if (client) { + dev_err(dev, + "rejecting multiple regis
[PATCHv5 0/9] Unifying Tegra IOMMU(SMMU) driver among Tegra SoCs
Hi, This series provide: (1) Unified IOMMU(SMMU) driver among Tegra SoCs (2) Multiple Address Space support(MASID) in IOMMU(SMMMU) (3) Tegra IOMMU'able devices, most of platform devices are IOMMU'able. There's been some discussion[1] about device population order, and for the solution I implemented an IOMMU hook in driver core: [PATCHv5 2/9] driver/core: populate devices in order for IOMMUs which is based on: http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006933.html The main problem here is, IOMMU devices on the bus need to be poplulated first, then iommu master devices are done later. With CONFIG_OF_IOMMU, "iommus=" DT binding would be used to identify whether a device can be an iommu msater or not. If a device can, we'll defer to populate that device till an iommu device is populated. Once an iommu device is populated, "dev->bus->iommu_ops" is set in the bus. Then, those defered iommu master devices are populated and configured for IOMMU with help of the already populated iommu device via iommu_ops->add_device(). Multiple IOMMUs can be listed on this "iommus" binding so that a device can have multiple IOMMUs attached. Currenly this "iommus=" binding is used as the global binding. Tested IOMMU functionality with T30 SD/MMC. Any further testing with T114 and/or other devices would be really appreciated. v4: Add a hook in driver core to control device populatin order. Introduced arm,smmu "mmu-master" binding instead of tegra own. Removed DT patches from this series. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006931.html v3: Updated based on Stephen Warren's feedback http://lists.linuxfoundation.org/pipermail/iommu/2013-October/006724.html v2: Updated based on Thierry Reding's and Stephen Warren's feedback http://lists.infradead.org/pipermail/linux-arm-kernel/2013-July/181888.html v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2013-June/180267.html Available in the git repository at: git://g...@nv-tegra.nvidia.com/user/hdoyu/linux.git smmu-upstreaming@20131119 Hiroshi Doyu (9): of: introduce of_property_for_earch_phandle_with_args() driver/core: populate devices in order for IOMMUs ARM: tegra: create a DT header defining SWGROUP ID iommu/tegra: smmu: register device to iommu dynamically iommu/tegra: smmu: calculate ASID register offset by ID iommu/tegra: smmu: get swgroups from DT "iommus=" iommu/tegra: smmu: allow duplicate ASID wirte iommu/tegra: smmu: Rename hwgrp -> swgroups [FOR TEST] ARM: dt: tegra30: add "iommus" binding .../bindings/iommu/nvidia,tegra30-smmu.txt | 17 +- arch/arm/boot/dts/tegra30.dtsi | 23 +- drivers/base/dd.c | 5 + drivers/iommu/Kconfig | 1 + drivers/iommu/of_iommu.c | 22 ++ drivers/iommu/tegra-smmu.c | 334 + include/dt-bindings/memory/tegra-swgroup.h | 50 +++ include/linux/of.h | 3 + include/linux/of_iommu.h | 7 + 9 files changed, 336 insertions(+), 126 deletions(-) create mode 100644 include/dt-bindings/memory/tegra-swgroup.h [1] https://lists.ozlabs.org/pipermail/devicetree-discuss/2013-June/thread.html#36542 -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv5 4/9] iommu/tegra: smmu: register device to iommu dynamically
platform_devices are registered as IOMMU'able dynamically via add_device() and remove_device(). Tegra SMMU can have multiple address spaces(AS). IOMMU'able devices can belong to one of them. Multiple IOVA maps are created at boot-up, which can be attached to devices later. We reserve 2 of them for static assignment, AS[0] for system default, AS[1] for AHB clusters as protected domain from others, where there are many traditional pheripheral devices like USB, SD/MMC. They should be isolated from some smart devices like host1x for system robustness. Even if smart devices behaves wrongly, the traditional devices(SD/MMC, USB) wouldn't be affected, and the system could continue most likely. DMA API(ARM) needs ARM_DMA_USE_IOMMU to be enabled. Signed-off-by: Hiroshi Doyu --- v5: Add check NUM_OF_STATIC_MAPS < #asids. v4: Combined the following from v3. This makes more sense what they do. [PATCHv3 06/19] iommu/tegra: smmu: Select ARM_DMA_USE_IOMMU in Kconfig [PATCHv3 07/19] iommu/tegra: smmu: Create default IOVA maps [PATCHv3 08/19] iommu/tegra: smmu: Register platform_device to IOMMU dynamically [PATCHv3 19/19] iommu/tegra: smmu: Support Multiple ASID --- drivers/iommu/Kconfig | 1 + drivers/iommu/tegra-smmu.c | 70 +- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index c880eba..d1bc65d 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -170,6 +170,7 @@ config TEGRA_IOMMU_SMMU bool "Tegra SMMU IOMMU Support" depends on ARCH_TEGRA && TEGRA_AHB select IOMMU_API + select ARM_DMA_USE_IOMMU help Enables support for remapping discontiguous physical memory shared with the operating system into contiguous I/O virtual diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 37dd862..d836a6b 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -39,6 +39,9 @@ #include #include +#include + +#include enum smmu_hwgrp { HWGRP_AFI, @@ -319,6 +322,8 @@ struct smmu_device { struct device_node *ahb; + struct dma_iommu_mapping **map; + int num_as; struct smmu_as as[0]; /* Run-time allocated array */ }; @@ -947,6 +952,44 @@ static void smmu_iommu_domain_destroy(struct iommu_domain *domain) dev_dbg(smmu->dev, "smmu_as@%p\n", as); } +/* + * ASID[0] for the system default + * ASID[1] for PPCS("AHB bus children"), which has SDMMC + * ASID[2][3].. open for drivers, first come, first served. + */ +enum { + SYSTEM_DEFAULT, + SYSTEM_PROTECTED, + NUM_OF_STATIC_MAPS, +}; + +static int smmu_iommu_add_device(struct device *dev) +{ + int err = -EPROBE_DEFER; + u32 swgroups = dev->platform_data; + struct dma_iommu_mapping *map = NULL; + + if (test_bit(TEGRA_SWGROUP_PPCS, swgroups)) + map = smmu_handle->map[SYSTEM_PROTECTED]; + else + map = smmu_handle->map[SYSTEM_DEFAULT]; + + if (map) + err = arm_iommu_attach_device(dev, map); + else + return -EPROBE_DEFER; + + pr_debug("swgroups=%08lx map=%p err=%d %s\n", +swgroups, map, err, dev_name(dev)); + return err; +} + +static void smmu_iommu_remove_device(struct device *dev) +{ + dev_dbg(dev, "Detaching from map %p\n", to_dma_iommu_mapping(dev)); + arm_iommu_detach_device(dev); +} + static struct iommu_ops smmu_iommu_ops = { .domain_init= smmu_iommu_domain_init, .domain_destroy = smmu_iommu_domain_destroy, @@ -956,6 +999,8 @@ static struct iommu_ops smmu_iommu_ops = { .unmap = smmu_iommu_unmap, .iova_to_phys = smmu_iommu_iova_to_phys, .domain_has_cap = smmu_iommu_domain_has_cap, + .add_device = smmu_iommu_add_device, + .remove_device = smmu_iommu_remove_device, .pgsize_bitmap = SMMU_IOMMU_PGSIZES, }; @@ -1144,6 +1189,23 @@ static int tegra_smmu_resume(struct device *dev) return err; } +static void tegra_smmu_create_default_map(struct smmu_device *smmu) +{ + int i; + + for (i = 0; i < smmu->num_as; i++) { + dma_addr_t base = smmu->iovmm_base; + size_t size = smmu->page_count << PAGE_SHIFT; + + smmu->map[i] = arm_iommu_create_mapping(_bus_type, + base, size, 0); + if (IS_ERR(smmu->map[i])) + dev_err(smmu->dev, + "Couldn't create: asid=%d map=%p %pa-%pa\n", + i, smmu->map[i], , + size - 1); + } +} + static int tegra_smmu_probe(struct platform_device *pdev) { struct smmu_device *smmu; @@ -1160,13 +1222,18 @@
[PATCHv5 1/9] of: introduce of_property_for_earch_phandle_with_args()
The following pattern of code is tempting: for (i = 0; !of_parse_phandle_with_args(np, list, cells, i, args); i++) Signed-off-by: Hiroshi Doyu --- v5: New patch for v5. --- include/linux/of.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/of.h b/include/linux/of.h index 276c546..131fef5 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -613,6 +613,9 @@ static inline int of_property_read_u32(const struct device_node *np, s; \ s = of_prop_next_string(prop, s)) +#define of_property_for_each_phandle_with_args(np, list, cells, i, args) \ + for (i = 0; !of_parse_phandle_with_args(np, list, cells, i, args); i++) + #if defined(CONFIG_PROC_FS) && defined(CONFIG_PROC_DEVICETREE) extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv5 1/9] of: introduce of_property_for_earch_phandle_with_args()
The following pattern of code is tempting: for (i = 0; !of_parse_phandle_with_args(np, list, cells, i, args); i++) Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v5: New patch for v5. --- include/linux/of.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/of.h b/include/linux/of.h index 276c546..131fef5 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -613,6 +613,9 @@ static inline int of_property_read_u32(const struct device_node *np, s; \ s = of_prop_next_string(prop, s)) +#define of_property_for_each_phandle_with_args(np, list, cells, i, args) \ + for (i = 0; !of_parse_phandle_with_args(np, list, cells, i, args); i++) + #if defined(CONFIG_PROC_FS) defined(CONFIG_PROC_DEVICETREE) extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv5 4/9] iommu/tegra: smmu: register device to iommu dynamically
platform_devices are registered as IOMMU'able dynamically via add_device() and remove_device(). Tegra SMMU can have multiple address spaces(AS). IOMMU'able devices can belong to one of them. Multiple IOVA maps are created at boot-up, which can be attached to devices later. We reserve 2 of them for static assignment, AS[0] for system default, AS[1] for AHB clusters as protected domain from others, where there are many traditional pheripheral devices like USB, SD/MMC. They should be isolated from some smart devices like host1x for system robustness. Even if smart devices behaves wrongly, the traditional devices(SD/MMC, USB) wouldn't be affected, and the system could continue most likely. DMA API(ARM) needs ARM_DMA_USE_IOMMU to be enabled. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v5: Add check NUM_OF_STATIC_MAPS #asids. v4: Combined the following from v3. This makes more sense what they do. [PATCHv3 06/19] iommu/tegra: smmu: Select ARM_DMA_USE_IOMMU in Kconfig [PATCHv3 07/19] iommu/tegra: smmu: Create default IOVA maps [PATCHv3 08/19] iommu/tegra: smmu: Register platform_device to IOMMU dynamically [PATCHv3 19/19] iommu/tegra: smmu: Support Multiple ASID --- drivers/iommu/Kconfig | 1 + drivers/iommu/tegra-smmu.c | 70 +- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index c880eba..d1bc65d 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -170,6 +170,7 @@ config TEGRA_IOMMU_SMMU bool Tegra SMMU IOMMU Support depends on ARCH_TEGRA TEGRA_AHB select IOMMU_API + select ARM_DMA_USE_IOMMU help Enables support for remapping discontiguous physical memory shared with the operating system into contiguous I/O virtual diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 37dd862..d836a6b 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -39,6 +39,9 @@ #include asm/page.h #include asm/cacheflush.h +#include asm/dma-iommu.h + +#include dt-bindings/memory/tegra-swgroup.h enum smmu_hwgrp { HWGRP_AFI, @@ -319,6 +322,8 @@ struct smmu_device { struct device_node *ahb; + struct dma_iommu_mapping **map; + int num_as; struct smmu_as as[0]; /* Run-time allocated array */ }; @@ -947,6 +952,44 @@ static void smmu_iommu_domain_destroy(struct iommu_domain *domain) dev_dbg(smmu-dev, smmu_as@%p\n, as); } +/* + * ASID[0] for the system default + * ASID[1] for PPCS(AHB bus children), which has SDMMC + * ASID[2][3].. open for drivers, first come, first served. + */ +enum { + SYSTEM_DEFAULT, + SYSTEM_PROTECTED, + NUM_OF_STATIC_MAPS, +}; + +static int smmu_iommu_add_device(struct device *dev) +{ + int err = -EPROBE_DEFER; + u32 swgroups = dev-platform_data; + struct dma_iommu_mapping *map = NULL; + + if (test_bit(TEGRA_SWGROUP_PPCS, swgroups)) + map = smmu_handle-map[SYSTEM_PROTECTED]; + else + map = smmu_handle-map[SYSTEM_DEFAULT]; + + if (map) + err = arm_iommu_attach_device(dev, map); + else + return -EPROBE_DEFER; + + pr_debug(swgroups=%08lx map=%p err=%d %s\n, +swgroups, map, err, dev_name(dev)); + return err; +} + +static void smmu_iommu_remove_device(struct device *dev) +{ + dev_dbg(dev, Detaching from map %p\n, to_dma_iommu_mapping(dev)); + arm_iommu_detach_device(dev); +} + static struct iommu_ops smmu_iommu_ops = { .domain_init= smmu_iommu_domain_init, .domain_destroy = smmu_iommu_domain_destroy, @@ -956,6 +999,8 @@ static struct iommu_ops smmu_iommu_ops = { .unmap = smmu_iommu_unmap, .iova_to_phys = smmu_iommu_iova_to_phys, .domain_has_cap = smmu_iommu_domain_has_cap, + .add_device = smmu_iommu_add_device, + .remove_device = smmu_iommu_remove_device, .pgsize_bitmap = SMMU_IOMMU_PGSIZES, }; @@ -1144,6 +1189,23 @@ static int tegra_smmu_resume(struct device *dev) return err; } +static void tegra_smmu_create_default_map(struct smmu_device *smmu) +{ + int i; + + for (i = 0; i smmu-num_as; i++) { + dma_addr_t base = smmu-iovmm_base; + size_t size = smmu-page_count PAGE_SHIFT; + + smmu-map[i] = arm_iommu_create_mapping(platform_bus_type, + base, size, 0); + if (IS_ERR(smmu-map[i])) + dev_err(smmu-dev, + Couldn't create: asid=%d map=%p %pa-%pa\n, + i, smmu-map[i], base, base + size - 1); + } +} + static int tegra_smmu_probe(struct platform_device *pdev) { struct smmu_device *smmu; @@ -1160,13 +1222,18 @@ static int tegra_smmu_probe(struct
[PATCHv5 0/9] Unifying Tegra IOMMU(SMMU) driver among Tegra SoCs
Hi, This series provide: (1) Unified IOMMU(SMMU) driver among Tegra SoCs (2) Multiple Address Space support(MASID) in IOMMU(SMMMU) (3) Tegra IOMMU'able devices, most of platform devices are IOMMU'able. There's been some discussion[1] about device population order, and for the solution I implemented an IOMMU hook in driver core: [PATCHv5 2/9] driver/core: populate devices in order for IOMMUs which is based on: http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006933.html The main problem here is, IOMMU devices on the bus need to be poplulated first, then iommu master devices are done later. With CONFIG_OF_IOMMU, iommus= DT binding would be used to identify whether a device can be an iommu msater or not. If a device can, we'll defer to populate that device till an iommu device is populated. Once an iommu device is populated, dev-bus-iommu_ops is set in the bus. Then, those defered iommu master devices are populated and configured for IOMMU with help of the already populated iommu device via iommu_ops-add_device(). Multiple IOMMUs can be listed on this iommus binding so that a device can have multiple IOMMUs attached. Currenly this iommus= binding is used as the global binding. Tested IOMMU functionality with T30 SD/MMC. Any further testing with T114 and/or other devices would be really appreciated. v4: Add a hook in driver core to control device populatin order. Introduced arm,smmu mmu-master binding instead of tegra own. Removed DT patches from this series. http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006931.html v3: Updated based on Stephen Warren's feedback http://lists.linuxfoundation.org/pipermail/iommu/2013-October/006724.html v2: Updated based on Thierry Reding's and Stephen Warren's feedback http://lists.infradead.org/pipermail/linux-arm-kernel/2013-July/181888.html v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2013-June/180267.html Available in the git repository at: git://g...@nv-tegra.nvidia.com/user/hdoyu/linux.git smmu-upstreaming@20131119 Hiroshi Doyu (9): of: introduce of_property_for_earch_phandle_with_args() driver/core: populate devices in order for IOMMUs ARM: tegra: create a DT header defining SWGROUP ID iommu/tegra: smmu: register device to iommu dynamically iommu/tegra: smmu: calculate ASID register offset by ID iommu/tegra: smmu: get swgroups from DT iommus= iommu/tegra: smmu: allow duplicate ASID wirte iommu/tegra: smmu: Rename hwgrp - swgroups [FOR TEST] ARM: dt: tegra30: add iommus binding .../bindings/iommu/nvidia,tegra30-smmu.txt | 17 +- arch/arm/boot/dts/tegra30.dtsi | 23 +- drivers/base/dd.c | 5 + drivers/iommu/Kconfig | 1 + drivers/iommu/of_iommu.c | 22 ++ drivers/iommu/tegra-smmu.c | 334 + include/dt-bindings/memory/tegra-swgroup.h | 50 +++ include/linux/of.h | 3 + include/linux/of_iommu.h | 7 + 9 files changed, 336 insertions(+), 126 deletions(-) create mode 100644 include/dt-bindings/memory/tegra-swgroup.h [1] https://lists.ozlabs.org/pipermail/devicetree-discuss/2013-June/thread.html#36542 -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv5 6/9] iommu/tegra: smmu: get swgroups from DT iommus=
This provides the info about which swgroups a device belongs to. This info is passed from DT. This is necessary for the unified SMMU driver among Tegra SoCs since each has different H/W accelerators. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v5: iommu= in a device DT is used instead of mmu-masters in an iommu DT. This is iommu= version of: [PATCHv4 5/7] iommu/tegra: smmu: Support mmu-masters binding --- .../bindings/iommu/nvidia,tegra30-smmu.txt | 17 ++- drivers/iommu/tegra-smmu.c | 125 ++--- 2 files changed, 126 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt index 89fb543..44a4dc3 100644 --- a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt +++ b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt @@ -8,9 +8,12 @@ Required properties: - nvidia,#asids : # of ASIDs - dma-window : IOVA start address and length. - nvidia,ahb : phandle to the ahb bus connected to SMMU. +- iommus: phandle to an iommu device which a device is + attached to and indicates which swgroups a device belongs to(SWGROUP ID). + SWGROUP ID is from 0 to 63, and a device can belong to multiple SWGROUPS. Example: - smmu { + smmu: iommu { compatible = nvidia,tegra30-smmu; reg = 0x7000f010 0x02c 0x7000f1f0 0x010 @@ -18,4 +21,16 @@ Example: nvidia,#asids = 4;/* # of ASIDs */ dma-window = 0 0x4000;/* IOVA start length */ nvidia,ahb = ahb; + #iommu-cells = 2; }; + + host1x { + compatible = nvidia,tegra30-host1x, simple-bus; + iommus = smmu TEGRA_SWGROUP_CELLS(HC); + + gr3d { + compatible = nvidia,tegra30-gr3d; + nvidia,memory-clients = smmu TEGRA_SWGROUP_CELLS(NV) + TEGRA_SWGROUP_CELLS(NV2); + + }; diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index e999ad0..e915201a 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -190,6 +190,8 @@ enum { * Per client for address space */ struct smmu_client { + struct device_node *of_node; + struct rb_node node; struct device *dev; struct list_headlist; struct smmu_as *as; @@ -233,6 +235,7 @@ struct smmu_device { spinlock_t lock; char*name; struct device *dev; + struct rb_root clients; struct page *avp_vector_page; /* dummy page shared by all AS's */ /* @@ -310,6 +313,96 @@ static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs) */ #define FLUSH_SMMU_REGS(smmu) smmu_read(smmu, SMMU_CONFIG) +static struct smmu_client *find_smmu_client(struct smmu_device *smmu, + struct device_node *dev_node) +{ + struct rb_node *node = smmu-clients.rb_node; + + while (node) { + struct smmu_client *client; + + client = container_of(node, struct smmu_client, node); + if (dev_node client-of_node) + node = node-rb_left; + else if (dev_node client-of_node) + node = node-rb_right; + else + return client; + } + + return NULL; +} + +static int insert_smmu_client(struct smmu_device *smmu, + struct smmu_client *client) +{ + struct rb_node **new, *parent; + + new = smmu-clients.rb_node; + parent = NULL; + while (*new) { + struct smmu_client *this; + this = container_of(*new, struct smmu_client, node); + + parent = *new; + if (client-of_node this-of_node) + new = ((*new)-rb_left); + else if (client-of_node this-of_node) + new = ((*new)-rb_right); + else + return -EEXIST; + } + + rb_link_node(client-node, parent, new); + rb_insert_color(client-node, smmu-clients); + return 0; +} + +static int register_smmu_client(struct smmu_device *smmu, + struct device *dev, unsigned long *swgroups) +{ + struct smmu_client *client; + + client = find_smmu_client(smmu, dev-of_node); + if (client) { + dev_err(dev, + rejecting multiple registrations for client device %s\n, + dev-of_node-full_name); + return -EBUSY; + } + + client = devm_kzalloc(smmu-dev, sizeof(*client), GFP_KERNEL
[PATCHv5 3/9] ARM: tegra: create a DT header defining SWGROUP ID
Create a header file to define the swgroup IDs used by the IOMMU(SMMU) binding. swgroup is a group of H/W clients which a Tegra SoC supports. This unique ID can be used to calculate MC_SMMU_swgroup name_ASID_0 register offset and MC_swgroup name_HOTRESET_*_0 register bit. This will allow the same header to be used by both device tree files, and drivers implementing this binding, which guarantees that the two stay in sync. This also makes device trees more readable by using names instead of magic numbers. For HOTRESET bit shifting we need another conversion table, which will come later. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v5: Added new macro TEGRA_SWGROUP_CELLS() and WO_U32_OF_U64(). v4: This is almost same as the previous v3. Just TEGRA_SWGROUP_MAX is added. [PATCHv3 15/19] ARM: tegra: Create a DT header defining SWGROUP ID --- include/dt-bindings/memory/tegra-swgroup.h | 50 ++ 1 file changed, 50 insertions(+) create mode 100644 include/dt-bindings/memory/tegra-swgroup.h diff --git a/include/dt-bindings/memory/tegra-swgroup.h b/include/dt-bindings/memory/tegra-swgroup.h new file mode 100644 index 000..73079ad --- /dev/null +++ b/include/dt-bindings/memory/tegra-swgroup.h @@ -0,0 +1,50 @@ +/* + * This header provides constants for binding nvidia,swgroup ID + */ + +#ifndef _DT_BINDINGS_MEMORY_TEGRA_SWGROUP_H +#define _DT_BINDINGS_MEMORY_TEGRA_SWGROUP_H + +#define TEGRA_SWGROUP_AFI 0 /* 0x238 */ +#define TEGRA_SWGROUP_AVPC 1 /* 0x23c */ +#define TEGRA_SWGROUP_DC 2 /* 0x240 */ +#define TEGRA_SWGROUP_DCB 3 /* 0x244 */ +#define TEGRA_SWGROUP_EPP 4 /* 0x248 */ +#define TEGRA_SWGROUP_G2 5 /* 0x24c */ +#define TEGRA_SWGROUP_HC 6 /* 0x250 */ +#define TEGRA_SWGROUP_HDA 7 /* 0x254 */ +#define TEGRA_SWGROUP_ISP 8 /* 0x258 */ +#define TEGRA_SWGROUP_ISP2 SWGROUP_ISP +#define TEGRA_SWGROUP_DC14 9 /* 0x490 *//* Exceptional non-linear */ +#define TEGRA_SWGROUP_DC12 10 /* 0xa88 *//* Exceptional non-linear */ +#define TEGRA_SWGROUP_MPE 11 /* 0x264 */ +#define TEGRA_SWGROUP_MSENCSWGROUP_MPE +#define TEGRA_SWGROUP_NV 12 /* 0x268 */ +#define TEGRA_SWGROUP_NV2 13 /* 0x26c */ +#define TEGRA_SWGROUP_PPCS 14 /* 0x270 */ +#define TEGRA_SWGROUP_SATA215 /* 0x274 */ +#define TEGRA_SWGROUP_SATA 16 /* 0x278 */ +#define TEGRA_SWGROUP_VDE 17 /* 0x27c */ +#define TEGRA_SWGROUP_VI 18 /* 0x280 */ +#define TEGRA_SWGROUP_VIC 19 /* 0x284 */ +#define TEGRA_SWGROUP_XUSB_HOST20 /* 0x288 */ +#define TEGRA_SWGROUP_XUSB_DEV 21 /* 0x28c */ +#define TEGRA_SWGROUP_A9AVP22 /* 0x290 */ +#define TEGRA_SWGROUP_TSEC 23 /* 0x294 */ +#define TEGRA_SWGROUP_PPCS124 /* 0x298 */ +#define TEGRA_SWGROUP_SDMMC1A 25 /* 0xa94 *//* Linear shift again */ +#define TEGRA_SWGROUP_SDMMC2A 26 /* 0xa98 */ +#define TEGRA_SWGROUP_SDMMC3A 27 /* 0xa9c */ +#define TEGRA_SWGROUP_SDMMC4A 28 /* 0xaa0 */ +#define TEGRA_SWGROUP_ISP2B29 /* 0xaa4 */ +#define TEGRA_SWGROUP_GPU 30 /* 0xaa8 */ +#define TEGRA_SWGROUP_GPUB 31 /* 0xaac */ +#define TEGRA_SWGROUP_PPCS232 /* 0xab0 */ + +#define TWO_U32_OF_U64(x) ((x) ~0UL) ((x) 32) +#define TEGRA_SWGROUP_BIT(x) (1ULL TEGRA_SWGROUP_##x) +#define TEGRA_SWGROUP_CELLS(x) TWO_U32_OF_U64(TEGRA_SWGROUP_BIT(x)) + +#define TEGRA_SWGROUP_MAX 64 + +#endif /* _DT_BINDINGS_MEMORY_TEGRA_SWGROUP_H */ -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCHv5 8/9] iommu/tegra: smmu: Rename hwgrp - swgroups
Use the correct term for SWGROUP related variables and macros. The term swgroup is the collection of memory client. A memory client usually represents a HardWare Accelerator(HWA) like GPU. Sometimes a strut device can belong to multiple swgroup so that swgroup's' is used here. This swgroups is the term used in Tegra TRM. Rename along with TRM. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v4: New for v4 --- drivers/iommu/tegra-smmu.c | 36 ++-- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index c2ed075..003a491 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -179,12 +179,12 @@ enum { #define NUM_SMMU_REG_BANKS 3 -#define smmu_client_enable_hwgrp(c, m) smmu_client_set_hwgrp(c, m, 1) -#define smmu_client_disable_hwgrp(c) smmu_client_set_hwgrp(c, 0, 0) -#define __smmu_client_enable_hwgrp(c, m) __smmu_client_set_hwgrp(c, m, 1) -#define __smmu_client_disable_hwgrp(c) __smmu_client_set_hwgrp(c, 0, 0) +#define smmu_client_enable_swgroups(c, m) smmu_client_set_swgroups(c, m, 1) +#define smmu_client_disable_swgroups(c) smmu_client_set_swgroups(c, 0, 0) +#define __smmu_client_enable_swgroups(c, m) __smmu_client_set_swgroups(c, m, 1) +#define __smmu_client_disable_swgroups(c) __smmu_client_set_swgroups(c, 0, 0) -#define HWGRP_ASID_REG(x) ((x) * sizeof(u32) + SMMU_ASID_BASE) +#define SWGROUPS_ASID_REG(x) ((x) * sizeof(u32) + SMMU_ASID_BASE) /* * Per client for address space @@ -195,7 +195,7 @@ struct smmu_client { struct device *dev; struct list_headlist; struct smmu_as *as; - unsigned long hwgrp[2]; + unsigned long swgroups[2]; }; /* @@ -377,7 +377,7 @@ static int register_smmu_client(struct smmu_device *smmu, client-dev = dev; client-of_node = dev-of_node; - memcpy(client-hwgrp, swgroups, sizeof(u64)); + memcpy(client-swgroups, swgroups, sizeof(u64)); return insert_smmu_client(smmu, client); } @@ -403,7 +403,7 @@ static int smmu_of_get_swgroups(struct device *dev, unsigned long *swgroups) return -ENODEV; } -static int __smmu_client_set_hwgrp(struct smmu_client *c, +static int __smmu_client_set_swgroups(struct smmu_client *c, unsigned long *map, int on) { int i; @@ -412,10 +412,10 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, struct smmu_device *smmu = as-smmu; if (!on) - map = c-hwgrp; + map = c-swgroups; for_each_set_bit(i, map, TEGRA_SWGROUP_MAX) { - offs = HWGRP_ASID_REG(i); + offs = SWGROUPS_ASID_REG(i); val = smmu_read(smmu, offs); if (on) { if (val) { @@ -425,7 +425,7 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, } val = mask; - memcpy(c-hwgrp, map, sizeof(u64)); + memcpy(c-swgroups, map, sizeof(u64)); } else { WARN_ON((val mask) == mask); val = ~mask; @@ -438,7 +438,7 @@ skip: return 0; } -static int smmu_client_set_hwgrp(struct smmu_client *c, +static int smmu_client_set_swgroups(struct smmu_client *c, unsigned long *map, int on) { int err; @@ -447,7 +447,7 @@ static int smmu_client_set_hwgrp(struct smmu_client *c, struct smmu_device *smmu = as-smmu; spin_lock_irqsave(smmu-lock, flags); - err = __smmu_client_set_hwgrp(c, map, on); + err = __smmu_client_set_swgroups(c, map, on); spin_unlock_irqrestore(smmu-lock, flags); return err; } @@ -487,7 +487,7 @@ static int smmu_setup_regs(struct smmu_device *smmu) smmu_write(smmu, val, SMMU_PTB_DATA); list_for_each_entry(c, as-client, list) - __smmu_client_set_hwgrp(c, c-hwgrp, 1); + __smmu_client_set_swgroups(c, c-swgroups, 1); } smmu_write(smmu, smmu-translation_enable_0, SMMU_TRANSLATION_ENABLE_0); @@ -815,7 +815,7 @@ static int smmu_iommu_attach_dev(struct iommu_domain *domain, return -ENOMEM; client-as = as; - err = smmu_client_enable_hwgrp(client, client-hwgrp); + err = smmu_client_enable_swgroups(client, client-swgroups); if (err) return -EINVAL; @@ -835,7 +835,7 @@ static int smmu_iommu_attach_dev(struct iommu_domain *domain, * Reserve page zero for AVP vectors using a common dummy * page. */ - if (test_bit(TEGRA_SWGROUP_AVPC, client-hwgrp)) { + if (test_bit(TEGRA_SWGROUP_AVPC, client-swgroups)) { struct page *page; page = as-smmu-avp_vector_page; @@ -848,7 +848,7
[PATCHv5 7/9] iommu/tegra: smmu: allow duplicate ASID wirte
The device, which belongs to the same ASID, can try to enable the same ASID as the other swgroup devices. This should be allowed but just skip the actual register write. If the write value is different, it will return -EINVAL. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- v4: This was the part of v3, which isn't used any more. [PATCHv3 10/19] iommu/tegra: smmu: Get nvidia,swgroups from DT --- drivers/iommu/tegra-smmu.c | 20 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index e915201a..c2ed075 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -418,9 +418,13 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, offs = HWGRP_ASID_REG(i); val = smmu_read(smmu, offs); if (on) { - if (WARN_ON(val mask)) - goto err_hw_busy; - val |= mask; + if (val) { + if (WARN_ON(val != mask)) + return -EINVAL; + goto skip; + } + + val = mask; memcpy(c-hwgrp, map, sizeof(u64)); } else { WARN_ON((val mask) == mask); @@ -430,16 +434,8 @@ static int __smmu_client_set_hwgrp(struct smmu_client *c, } FLUSH_SMMU_REGS(smmu); +skip: return 0; - -err_hw_busy: - for_each_set_bit(i, map, TEGRA_SWGROUP_MAX) { - offs = HWGRP_ASID_REG(i); - val = smmu_read(smmu, offs); - val = ~mask; - smmu_write(smmu, val, offs); - } - return -EBUSY; } static int smmu_client_set_hwgrp(struct smmu_client *c, -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv5 2/9] driver/core: populate devices in order for IOMMUs
Stephen Warren swar...@wwwdotorg.org wrote @ Tue, 19 Nov 2013 22:22:47 +0100: On 11/19/2013 05:03 AM, Hiroshi Doyu wrote: Hi Thierry, Thierry Reding thierry.red...@gmail.com wrote @ Tue, 19 Nov 2013 11:25:07 +0100: From earlier discussions I thought the goal was to actually defer this until all nodes referred to by the iommus property were actually registered. The above only checks that the phandles can be resolved to valid struct device_node:s. That doesn't mean that an actual IOMMU has been registered for it, only that the devices have been created. Currently bus-iommu_ops is set at the end of tegra_smmu_probe(). So if bus-iommu_ops is set, it means that an iommu instance is populated at that time. Yes, but that's the register bus, upon which the device is a client, not the bus upon which the device is a bus master. They aren't necessarily the same. There's no getting around the fact that, as Thierry said, you need to search for a registered IOMMU device for each phandle, and defer probe if any aren't registered yet. If we do that, then you shouldn't need to look at the value of dev-bus-iommu_ops at all; if all IOMMUs in the list were registered, then iommu_ops must have been set when (one of them) was registered, and if not, then it possibly wasn't, so defer probe. That way, this code won't have to change if the core IOMMU code gets extended to support multiple IOMMUs, devices mastering transactions onto buses other than their register bus, etc. Does the above mean the following? int of_iommu_attach(struct device *dev) { int i; struct of_phandle_args args; of_property_for_each_phandle_with_args(dev-of_node, iommus, #iommu-cells, i, args) if (!args-np-dev-driver) return -EPROBE_DEFER; return 0; } args-np-dev-driver needs the following patch: http://lists.linuxfoundation.org/pipermail/iommu/2013-July/006023.html -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] fs: partitions: efi: Fix bound check
Antti Miettinen amietti...@nvidia.com wrote @ Wed, 20 Nov 2013 08:18:50 +0100: On 20.11.2013 02:04, Andrew Morton wrote: On Fri, 15 Nov 2013 19:14:22 +0200 (EET) Antti P Miettinen amietti...@nvidia.com wrote: Use ARRAY_SIZE instead of sizeof to get proper max for label length. Signed-off-by: Antti P Miettinen amietti...@nvidia.com Reviewed-by: Hiroshi Doyu hd...@nvidia.com Tested-by: Hiroshi Doyu hd...@nvidia.com When fixing a bug, please provide a description of the user-visible impact of that bug. This is so that others can decide which kernel version(s) need the patch. Hiroshi Doyu tested this patch, so I assume there was some observable misbehaviour to test. Please fully describe that. Since this is just a read out of bounds it's not that bad, but the problem becomes user-visible e.g. if one tries to use CONFIG_DEBUG_PAGEALLOC and CONFIG_DEBUG_RODATA, at least with some enhancements from Hiroshi. The above enhancement is almost ARCH_SUPPORTS_DEBUG_PAGEALLOC for ARM, which could catch illegal memory access(read/write) with a page fault although that enhancement itself needs some cleanups before being upstreamed. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/1] ARM: dma-mapping: Drop GFP_COMP for DMA memory allocations
arm_iommu_alloc_attrs wants to split pages after allocation in order to reduce the memory footprint. This does not work well with GFP_COMP pages, so drop this flag before allocation. ref: ea2e7057c0234cfb8b09467d8f137760d371fc72: ARM: 7172/1: dma: Drop GFP_COMP for DMA memory allocations dma_alloc_coherent wants to split pages after allocation in order to reduce the memory footprint. This does not work well with GFP_COMP pages, so drop this flag before allocation. Signed-off-by: Hiroshi Doyu --- arch/arm/mm/dma-mapping.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index f5e1a84..955dd3e 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1321,6 +1321,13 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, struct page **pages; void *addr = NULL; + /* Following is a work-around (a.k.a. hack) to prevent pages +* with __GFP_COMP being passed to split_page() which cannot +* handle them. The real problem is that this flag probably +* should be 0 on ARM as it is not supported on this +* platform--see CONFIG_HUGETLB_PAGE. */ + gfp &= ~(__GFP_COMP); + *handle = DMA_ERROR_CODE; size = PAGE_ALIGN(size); -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/1] ARM: dma-mapping: Drop GFP_COMP for DMA memory allocations
arm_iommu_alloc_attrs wants to split pages after allocation in order to reduce the memory footprint. This does not work well with GFP_COMP pages, so drop this flag before allocation. ref: ea2e7057c0234cfb8b09467d8f137760d371fc72: ARM: 7172/1: dma: Drop GFP_COMP for DMA memory allocations dma_alloc_coherent wants to split pages after allocation in order to reduce the memory footprint. This does not work well with GFP_COMP pages, so drop this flag before allocation. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- arch/arm/mm/dma-mapping.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index f5e1a84..955dd3e 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1321,6 +1321,13 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, struct page **pages; void *addr = NULL; + /* Following is a work-around (a.k.a. hack) to prevent pages +* with __GFP_COMP being passed to split_page() which cannot +* handle them. The real problem is that this flag probably +* should be 0 on ARM as it is not supported on this +* platform--see CONFIG_HUGETLB_PAGE. */ + gfp = ~(__GFP_COMP); + *handle = DMA_ERROR_CODE; size = PAGE_ALIGN(size); -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] ARM: dma-mapping: Get pages if the cpu_addr is out of atomic_pool
YoungJun Cho wrote @ Mon, 17 Jun 2013 06:18:52 +0200: > In __iommu_get_pages(), the cpu_addr is checked wheather in > atomic_pool range or not. So if the cpu_addr is in atomic_pool > range, it does not need to check twice. > > Signed-off-by: YoungJun Cho > Signed-off-by: Kyungmin Park Looks ok to me, at least. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] ARM: dma-mapping: Get pages if the cpu_addr is out of atomic_pool
YoungJun Cho yj44@samsung.com wrote @ Mon, 17 Jun 2013 06:18:52 +0200: In __iommu_get_pages(), the cpu_addr is checked wheather in atomic_pool range or not. So if the cpu_addr is in atomic_pool range, it does not need to check twice. Signed-off-by: YoungJun Cho yj44@samsung.com Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com Looks ok to me, at least. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/1] amba: tegra-ahb: Fix build error w/ PM_SLEEP w/o PM_RUNTIME
Stephen Warren wrote @ Fri, 15 Mar 2013 06:23:38 +0100: > On 03/14/2013 03:08 AM, Hiroshi Doyu wrote: > > Make this depend on CONFIG_PM. This protection is necessary to not > > cause any build errors with any combination of PM features especially > > when supporting a new SoC where each PM features are being enabled > > one-by-one during its depelopment. > > Looks fine to me. > > Acked-by: Stephen Warren > > I assume Russell will want this to go through his patch tracker. FYI: Patch has been accepted as patch 7675/1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/1] amba: tegra-ahb: Fix build error w/ PM_SLEEP w/o PM_RUNTIME
Stephen Warren swar...@wwwdotorg.org wrote @ Fri, 15 Mar 2013 06:23:38 +0100: On 03/14/2013 03:08 AM, Hiroshi Doyu wrote: Make this depend on CONFIG_PM. This protection is necessary to not cause any build errors with any combination of PM features especially when supporting a new SoC where each PM features are being enabled one-by-one during its depelopment. Looks fine to me. Acked-by: Stephen Warren swar...@nvidia.com I assume Russell will want this to go through his patch tracker. FYI: Patch has been accepted as patch 7675/1 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/1] memory: tegra30: Fix build error w/o PM
Make this depend on CONFIG_PM. Signed-off-by: Hiroshi Doyu --- drivers/memory/tegra30-mc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c index 0b97598..f4ae074 100644 --- a/drivers/memory/tegra30-mc.c +++ b/drivers/memory/tegra30-mc.c @@ -268,6 +268,7 @@ static const u32 tegra30_mc_ctx[] = { MC_INTMASK, }; +#ifdef CONFIG_PM static int tegra30_mc_suspend(struct device *dev) { int i; @@ -291,6 +292,7 @@ static int tegra30_mc_resume(struct device *dev) mc_readl(mc, MC_TIMING_CONTROL); return 0; } +#endif static UNIVERSAL_DEV_PM_OPS(tegra30_mc_pm, tegra30_mc_suspend, -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/1] amba: tegra-ahb: Fix build error w/ PM_SLEEP w/o PM_RUNTIME
Make this depend on CONFIG_PM. This protection is necessary to not cause any build errors with any combination of PM features especially when supporting a new SoC where each PM features are being enabled one-by-one during its depelopment. Signed-off-by: Hiroshi Doyu Reported-by: Joseph Lo --- drivers/amba/tegra-ahb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c index 093c435..1f44e56 100644 --- a/drivers/amba/tegra-ahb.c +++ b/drivers/amba/tegra-ahb.c @@ -158,7 +158,7 @@ int tegra_ahb_enable_smmu(struct device_node *dn) EXPORT_SYMBOL(tegra_ahb_enable_smmu); #endif -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int tegra_ahb_suspend(struct device *dev) { int i; -- 1.8.1.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/1] amba: tegra-ahb: Fix build error w/ PM_SLEEP w/o PM_RUNTIME
Make this depend on CONFIG_PM. This protection is necessary to not cause any build errors with any combination of PM features especially when supporting a new SoC where each PM features are being enabled one-by-one during its depelopment. Signed-off-by: Hiroshi Doyu hd...@nvidia.com Reported-by: Joseph Lo jose...@nvidia.com --- drivers/amba/tegra-ahb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c index 093c435..1f44e56 100644 --- a/drivers/amba/tegra-ahb.c +++ b/drivers/amba/tegra-ahb.c @@ -158,7 +158,7 @@ int tegra_ahb_enable_smmu(struct device_node *dn) EXPORT_SYMBOL(tegra_ahb_enable_smmu); #endif -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int tegra_ahb_suspend(struct device *dev) { int i; -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/1] memory: tegra30: Fix build error w/o PM
Make this depend on CONFIG_PM. Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- drivers/memory/tegra30-mc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c index 0b97598..f4ae074 100644 --- a/drivers/memory/tegra30-mc.c +++ b/drivers/memory/tegra30-mc.c @@ -268,6 +268,7 @@ static const u32 tegra30_mc_ctx[] = { MC_INTMASK, }; +#ifdef CONFIG_PM static int tegra30_mc_suspend(struct device *dev) { int i; @@ -291,6 +292,7 @@ static int tegra30_mc_resume(struct device *dev) mc_readl(mc, MC_TIMING_CONTROL); return 0; } +#endif static UNIVERSAL_DEV_PM_OPS(tegra30_mc_pm, tegra30_mc_suspend, -- 1.8.1.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [REPOST PATCH 1/2] clk: add table lookup to mux
On Fri, 22 Feb 2013 16:02:28 +0100 Peter De Schrijver wrote: > Add a table lookup feature to the mux clock. Also allow arbitrary masks > instead of the width. This will be used by some clocks on Tegra114. > > Signed-off-by: Peter De Schrijver > @@ -42,7 +43,17 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) >* val = 0x4 really means "bit 2, index starts at bit 0" >*/ > + if (mux->table) { > + int i; > + > + for (i = 0; i < num_parents; i++) > + if (mux->table[i] == val) > + return i; > + if (i == num_parents) > + return -EINVAL; > + } Can't we just return after for-loop without checking i == num_parents as below? + for (i = 0; i < num_parents; i++) { + if (mux->table[i] == val) + return i; + } + + return -EINVAL; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [REPOST PATCH 1/2] clk: add table lookup to mux
On Fri, 22 Feb 2013 16:02:28 +0100 Peter De Schrijver pdeschrij...@nvidia.com wrote: Add a table lookup feature to the mux clock. Also allow arbitrary masks instead of the width. This will be used by some clocks on Tegra114. Signed-off-by: Peter De Schrijver pdeschrij...@nvidia.com @@ -42,7 +43,17 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) * val = 0x4 really means bit 2, index starts at bit 0 */ + if (mux-table) { + int i; + + for (i = 0; i num_parents; i++) + if (mux-table[i] == val) + return i; + if (i == num_parents) + return -EINVAL; + } Can't we just return after for-loop without checking i == num_parents as below? + for (i = 0; i num_parents; i++) { + if (mux-table[i] == val) + return i; + } + + return -EINVAL; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[RFC 2/2] clk: tegra20: Use DT defines for CLK ID
To avoid the duplication of CLK ID defines both in boot/dts and kernel source, use the one from the DT header file and get rid of own definitions in kernel source. Signed-off-by: Hiroshi Doyu --- drivers/clk/tegra/clk-tegra20.c | 307 ++- 1 file changed, 145 insertions(+), 162 deletions(-) diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 847dabc..b2009c9 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -23,6 +23,8 @@ #include #include +#include + #include "clk.h" #define RST_DEVICES_L 0x004 @@ -201,21 +203,21 @@ static DEFINE_SPINLOCK(sysrate_lock); TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \ _regs, _clk_num, periph_clk_enb_refcnt, \ - _gate_flags, _clk_id) + _gate_flags, TEGRA20_CLK_##_clk_id) #define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _regs, _gate_flags, _clk_id) \ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\ _clk_num, periph_clk_enb_refcnt, _gate_flags, \ - _clk_id) + TEGRA20_CLK_##_clk_id) #define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \ _clk_num, _regs, _gate_flags, _clk_id)\ TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ 30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, _regs, \ _clk_num, periph_clk_enb_refcnt, _gate_flags, \ - _clk_id) + TEGRA20_CLK_##_clk_id) #define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ _mux_shift, _mux_width, _clk_num, _regs, \ @@ -223,28 +225,9 @@ static DEFINE_SPINLOCK(sysrate_lock); TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset, \ _mux_shift, _mux_width, 0, 0, 0, 0, 0, _regs, \ _clk_num, periph_clk_enb_refcnt, _gate_flags, \ - _clk_id) - -/* IDs assigned here must be in sync with DT bindings definition - * for Tegra20 clocks . - */ -enum tegra20_clk { - cpu, ac97 = 3, rtc, timer, uarta, gpio = 8, sdmmc2, i2s1 = 11, i2c1, - ndflash, sdmmc1, sdmmc4, twc, pwm, i2s2, epp, gr2d = 21, usbd, isp, - gr3d, ide, disp2, disp1, host1x, vcp, cache2 = 31, mem, ahbdma, apbdma, - kbc = 36, stat_mon, pmc, fuse, kfuse, sbc1, nor, spi, sbc2, xio, sbc3, - dvc, dsi, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2, - usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3, - pex, owr, afi, csite, pcie_xclk, avpucq = 75, la, irama = 84, iramb, - iramc, iramd, cram2, audio_2x, clk_d, csus = 92, cdev1, cdev2, - uartb = 96, vfir, spdif_in, spdif_out, vi, vi_sensor, tvo, cve, - osc, clk_32k, clk_m, sclk, cclk, hclk, pclk, blink, pll_a, pll_a_out0, - pll_c, pll_c_out1, pll_d, pll_d_out0, pll_e, pll_m, pll_m_out1, - pll_p, pll_p_out1, pll_p_out2, pll_p_out3, pll_p_out4, pll_s, pll_u, - pll_x, cop, audio, pll_ref, twd, clk_max, -}; + TEGRA20_CLK_##_clk_id) -static struct clk *clks[clk_max]; +static struct clk *clks[TEGRA20_CLK_MAX]; static struct clk_onecell_data clk_data; static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { @@ -580,7 +563,7 @@ static void tegra20_pll_init(void) 0, _c_params, TEGRA_PLL_HAS_CPCON, pll_c_freq_table, NULL); clk_register_clkdev(clk, "pll_c", NULL); - clks[pll_c] = clk; + clks[TEGRA20_CLK_PLL_C] = clk; /* PLLC_OUT1 */ clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c", @@ -590,14 +573,14 @@ static void tegra20_pll_init(void) clk_base + PLLC_OUT, 1, 0, CLK_SET_RATE_PARENT, 0, NULL); clk_register_clkdev(clk, "pll_c_out1", NULL); - clks[pll_c_out1] = clk; + clks[TEGRA20_CLK_PLL_C_OUT1] = clk; /* PLLP */ clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, NULL, 0, 21600, _p_params, TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON, pll_p_freq_table, NULL); clk_register_clkdev(clk, "pll_p", NULL); - clks[pll_p] = clk; + clks[TEGRA20_CLK_PLL_P] = clk; /* PLLP_OUT1 */ clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p", @@ -609,7 +592,7 @@ static vo
[RFC 1/2] Makefile: Add arch/arch/$(hdr-arch)/boot in header include path
With a new feature dtc+cpp, DT can introduces some definitions in its header files for their own. Some of those DT info can be used in kernel source as well, instead of having the duplicate info in kernel headers. This patch allows kernel source to include those DT headers. For example: + #include Signed-off-by: Hiroshi Doyu --- Makefile |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0b4bf62..7f54cdb 100644 --- a/Makefile +++ b/Makefile @@ -364,7 +364,7 @@ LINUXINCLUDE:= \ -I$(srctree)/arch/$(hdr-arch)/include \ -Iarch/$(hdr-arch)/include/generated \ $(if $(KBUILD_SRC), -I$(srctree)/include) \ - -Iinclude \ + -Iinclude -Iarch/$(hdr-arch)/boot \ $(USERINCLUDE) KBUILD_CPPFLAGS := -D__KERNEL__ -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[v3 6/6] ARM: tegra114: convert device tree files to use CLK defines
Replace magic number in tegra_car: - clocks = <_car 28>; + clocks = <_car CLK_HOST1X>; Signed-off-by: Hiroshi Doyu --- .../bindings/clock/nvidia,tegra114-car.txt | 261 +--- arch/arm/boot/dts/tegra114.dtsip | 13 +- 2 files changed, 8 insertions(+), 266 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt index 25e088d..c8956ed 100644 --- a/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt +++ b/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt @@ -14,265 +14,6 @@ Required properties : - #clock-cells : Should be 1. In clock consumers, this cell represents the clock ID exposed by the CAR. - The first 160 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB - registers. These IDs often match those in the CAR's RST_DEVICES registers, - but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In - this case, those clocks are assigned IDs above 160 in order to highlight - this issue. Implementations that interpret these clock IDs as bit values - within the CLK_OUT_ENB or RST_DEVICES registers should be careful to - explicitly handle these special cases. - - The balance of the clocks controlled by the CAR are assigned IDs of 160 and - above. - - 0cpu - 1unassigned - 2unassigned - 3unassigned - 4rtc - 5timer - 6uarta - 7unassigned (register bit affects uartb and vfir) - 8unassigned - 9sdmmc2 - 10 unassigned (register bit affects spdif_in and spdif_out) - 11 i2s1 - 12 i2c1 - 13 ndflash - 14 sdmmc1 - 15 sdmmc4 - 16 unassigned - 17 pwm - 18 i2s2 - 19 epp - 20 unassigned (register bit affects vi and vi_sensor) - 21 2d - 22 usbd - 23 isp - 24 3d - 25 unassigned - 26 disp2 - 27 disp1 - 28 host1x - 29 vcp - 30 i2s0 - 31 unassigned - - 32 unassigned - 33 unassigned - 34 apbdma - 35 unassigned - 36 kbc - 37 unassigned - 38 unassigned - 39 unassigned (register bit affects fuse and fuse_burn) - 40 kfuse - 41 sbc1 - 42 nor - 43 unassigned - 44 sbc2 - 45 unassigned - 46 sbc3 - 47 i2c5 - 48 dsia - 49 unassigned - 50 mipi - 51 hdmi - 52 csi - 53 unassigned - 54 i2c2 - 55 uartc - 56 mipi-cal - 57 unassigned - 58 usb2 - 59 usb3 - 60 msenc - 61 vde - 62 bsea - 63 bsev - - 64 unassigned - 65 uartd - 66 unassigned - 67 i2c3 - 68 sbc4 - 69 sdmmc3 - 70 unassigned - 71 owr - 72 afi - 73 csite - 74 unassigned - 75 unassigned - 76 la - 77 trace - 78 soc_therm - 79 dtv - 80 ndspeed - 81 i2cslow - 82 dsib - 83 tsec - 84 unassigned - 85 unassigned - 86 unassigned - 87 unassigned - 88 unassigned - 89 xusb_host - 90 unassigned - 91 msenc - 92 csus - 93 unassigned - 94 unassigned - 95 unassigned (bit affects xusb_dev and xusb_dev_src) - - 96 unassigned - 97 unassigned - 98 unassigned - 99 mselect - 100 tsensor - 101 i2s3 - 102 i2s4 - 103 i2c4 - 104 sbc5 - 105 sbc6 - 106 d_audio - 107 apbif - 108 dam0 - 109 dam1 - 110 dam2 - 111 hda2codec_2x - 112 unassigned - 113 audio0_2x - 114 audio1_2x - 115 audio2_2x - 116 audio3_2x - 117 audio4_2x - 118 spdif_2x - 119 actmon - 120 extern1 - 121 extern2 - 122 extern3 - 123 unassigned - 124 unassigned - 125 hda - 126 unassigned - 127 se - - 128 hda2hdmi - 129 unassigned - 130 unassigned - 131 unassigned - 132 unassigned - 133 unassigned - 134 unassigned - 135 unassigned - 136 unassigned - 137 unassigned - 138 unassigned - 139 unassigned - 140 unassigned - 141 unassigned - 142 unassigned - 143 unassigned (bit affects xusb_falcon_src, xusb_fs_src, -xusb_host_src and xusb_ss_src) - 144 cilab - 145 cilcd - 146 cile - 147 dsialp - 148 dsiblp - 149 unassigned - 150 dds - 151 unassigned - 152 dp2 - 153 amx - 154 adx - 155 unassigned - 156 xusb_ss - - 192 uartb - 193 vfir - 194 spdif_in - 195 spdif_out - 196 vi - 197 vi_sensor - 198 fuse - 199 fuse_burn - 200 clk_32k - 201 clk_m - 202 clk_m_div2 - 203 clk_m_div4 - 204 pll_ref - 205 pll_c - 206 pll_c_out1 - 207 pll_c2 - 208 pll_c3 - 209 pll_m - 210 pll_m_out1 - 211 pll_p - 212 pll_p_out1 - 213 pll_p_out2 - 214 pll_p_out3 - 214 mipi_cal_fast - 214 dsi1_fixed - 214 dsi2_fixed - 215 pll_p_out4 - 216 pll_a - 217 pll_a_out1 - 218 pll_d - 219 pll_d_out0 - 220 pll_d2 - 221 pll_d2_out0 - 222 pll_u - 223 pll_u_480M - 224 pll_u_60M - 225 pll_u_48M - 226 pll_u_12M - 227 pll_x - 228 pll_x_out0 - 229 pll_re_vco - 230 pll_re_out - 231 pll_e_out0 - 232 s
[v3 5/6] ARM: tegra114: create a DT header defining CLK IDs
To replace magic number in tegra_car: - clocks = <_car 28>; + clocks = <_car CLK_HOST1X>; Signed-off-by: Hiroshi Doyu --- arch/arm/boot/dts/tegra114-car.h | 272 ++ 1 file changed, 272 insertions(+) create mode 100644 arch/arm/boot/dts/tegra114-car.h diff --git a/arch/arm/boot/dts/tegra114-car.h b/arch/arm/boot/dts/tegra114-car.h new file mode 100644 index 000..1fa425a --- /dev/null +++ b/arch/arm/boot/dts/tegra114-car.h @@ -0,0 +1,272 @@ +/* + * This header provides constants for binding nvidia,tegra114-car. + * + * The first 160 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB + * registers. These IDs often match those in the CAR's RST_DEVICES registers, + * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In + * this case, those clocks are assigned IDs above 160 in order to highlight + * this issue. Implementations that interpret these clock IDs as bit values + * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to + * explicitly handle these special cases. + * + * The balance of the clocks controlled by the CAR are assigned IDs of 160 and + * above. + */ + +#ifndef _DT_TEGRA114_CAR_H +#define _DT_TEGRA114_CAR_H + +#define TEGRA114_CLK_CPU 0 +/* 1 */ +/* 2 */ +/* 3 */ +#define TEGRA114_CLK_RTC 4 +#define TEGRA114_CLK_TIMER 5 +#define TEGRA114_CLK_UARTA 6 +/* 7 */ /* register bit affects uartb and vfir */ +/* 8 */ +#define TEGRA114_CLK_SDMMC2 9 +/* 10 */ /* register bit affects spdif_in and spdif_out */ +#define TEGRA114_CLK_I2S1 11 +#define TEGRA114_CLK_I2C1 12 +#define TEGRA114_CLK_NDFLASH 13 +#define TEGRA114_CLK_SDMMC1 14 +#define TEGRA114_CLK_SDMMC4 15 +/* 16 */ +#define TEGRA114_CLK_PWM 17 +#define TEGRA114_CLK_I2S2 18 +#define TEGRA114_CLK_EPP 19 +/* 20 */ /* register bit affects vi and vi_sensor */ +#define TEGRA114_CLK_GR_2D 21 +#define TEGRA114_CLK_USBD 22 +#define TEGRA114_CLK_ISP 23 +#define TEGRA114_CLK_GR_3D 24 +/* 25 */ +#define TEGRA114_CLK_DISP2 26 +#define TEGRA114_CLK_DISP1 27 +#define TEGRA114_CLK_HOST1X 28 +#define TEGRA114_CLK_VCP 29 +#define TEGRA114_CLK_I2S0 30 +/* 31 */ + +/* 32 */ +/* 33 */ +#define TEGRA114_CLK_APBDMA 34 +/* 35 */ +#define TEGRA114_CLK_KBC 36 +/* 37 */ +/* 38 */ +/* 39 */ +#define TEGRA114_CLK_KFUSE 40 +#define TEGRA114_CLK_SBC1 41 +#define TEGRA114_CLK_NOR 42 +/* 43 */ +#define TEGRA114_CLK_SBC2 44 +/* 45 */ +#define TEGRA114_CLK_SBC3 46 +#define TEGRA114_CLK_I2C5 47 +#define TEGRA114_CLK_DSIA 48 +/* 49 */ +#define TEGRA114_CLK_MIPI 50 +#define TEGRA114_CLK_HDMI 51 +#define TEGRA114_CLK_CSI 52 +/* 53 */ +#define TEGRA114_CLK_I2C2 54 +#define TEGRA114_CLK_UARTC 55 +#define TEGRA114_CLK_MIPI_CAL 56 +/* 57 */ +#define TEGRA114_CLK_USB2 58 +#define TEGRA114_CLK_USB3 59 +/* 60 */ +#define TEGRA114_CLK_VDE 61 +#define TEGRA114_CLK_BSEA 62 +#define TEGRA114_CLK_BSEV 63 + +/* 64 */ +#define TEGRA114_CLK_UARTD 65 +#define TEGRA114_CLK_UARTE 66 +#define TEGRA114_CLK_I2C3 67 +#define TEGRA114_CLK_SBC4 68 +#define TEGRA114_CLK_SDMMC3 69 +/* 70 */ +#define TEGRA114_CLK_OWR 71 +/* 72 */ +#define TEGRA114_CLK_CSITE 73 +/* 74 */ +/* 75 */ +#define TEGRA114_CLK_LA 76 +#define TEGRA114_CLK_TRACE 77 +#define TEGRA114_CLK_SOC_THERM 78 +#define TEGRA114_CLK_DTV 79 +#define TEGRA114_CLK_NDSPEED 80 +#define TEGRA114_CLK_I2CSLOW 81 +#define TEGRA114_CLK_DSIB 82 +#define TEGRA114_CLK_TSEC 83 +/* 84 */ +/* 85 */ +/* 86 */ +/* 87 */ +/* 88 */ +#define TEGRA114_CLK_XUSB_HOST 89 +/* 90 */ +#define TEGRA114_CLK_MSENC 91 +#define TEGRA114_CLK_CSUS 92 +/* 93 */ +/* 94 */ +/* 95 */ /* bit affects xusb_dev and xusb_dev_src */ + +/* 96 */ +/* 97 */ +/* 98 */ +#define TEGRA114_CLK_MSELECT 99 +#define TEGRA114_CLK_TSENSOR 100 +#define TEGRA114_CLK_I2S3 101 +#define TEGRA114_CLK_I2S4 102 +#define TEGRA114_CLK_I2C4 103 +#define TEGRA114_CLK_SBC5 104 +#define TEGRA114_CLK_SBC6 105 +#define TEGRA114_CLK_D_AUDIO 106 +#define TEGRA114_CLK_APBIF 107 +#define TEGRA114_CLK_DAM0 108 +#define TEGRA114_CLK_DAM1 109 +#define TEGRA114_CLK_DAM2 110 +#define TEGRA114_CLK_HDA2CODEC_2X 111 +/* 112 */ +#define TEGRA114_CLK_AUDIO0_2X 113 +#define TEGRA114_CLK_AUDIO1_2X 114 +#define TEGRA114_CLK_AUDIO2_2X 115 +#define TEGRA114_CLK_AUDIO3_2X 116 +#define TEGRA114_CLK_AUDIO4_2X 117 +#define TEGRA114_CLK_SPDIF_2X 118 +#define TEGRA114_CLK_ACTMON 119 +#define TEGRA114_CLK_EXTERN1 120 +#define TEGRA114_CLK_EXTERN2 121 +#define TEGRA114_CLK_EXTERN3 122 +/* 123 */ +/* 124 */ +#define TEGRA114_CLK_HDA 125 +/* 126 */ +#define TEGRA114_CLK_SE 127 + +#define TEGRA114_CLK_HDA2HDMI 128 +/* 129 */ +/* 130 */ +/* 131 */ +/* 132 */ +/* 133 */ +/* 134 */ +/* 135 */ +/* 136 */ +/* 137 */ +/* 138 */ +/* 139 */ +/* 140 */ +/* 141 */ +/* 142 */ +/* 143 */ /* bit affects xusb_falcon_src, xusb_fs_src, xusb_host_src and xusb_ss_src */ +#define TEGRA114_CLK_CILAB 144 +#define TEGRA114_CLK_CILCD 145 +#define TEGRA114_CLK_CILE 146 +#define TEGRA114_CLK_DSIALP 147 +#define TEGRA114_CLK_DSIBLP 148 +/* 149
[v3 4/6] ARM: tegra30: convert device tree files to use CLK defines
Replace magic number in tegra_car: - clocks = <_car 28>; + clocks = <_car CLK_HOST1X>; Signed-off-by: Hiroshi Doyu --- .../bindings/clock/nvidia,tegra30-car.txt | 207 +--- arch/arm/boot/dts/tegra30.dtsip| 87 2 files changed, 45 insertions(+), 249 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra30-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra30-car.txt index f3da3be..ac5797b 100644 --- a/Documentation/devicetree/bindings/clock/nvidia,tegra30-car.txt +++ b/Documentation/devicetree/bindings/clock/nvidia,tegra30-car.txt @@ -14,211 +14,6 @@ Required properties : - #clock-cells : Should be 1. In clock consumers, this cell represents the clock ID exposed by the CAR. - The first 130 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB - registers. These IDs often match those in the CAR's RST_DEVICES registers, - but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In - this case, those clocks are assigned IDs above 160 in order to highlight - this issue. Implementations that interpret these clock IDs as bit values - within the CLK_OUT_ENB or RST_DEVICES registers should be careful to - explicitly handle these special cases. - - The balance of the clocks controlled by the CAR are assigned IDs of 160 and - above. - - 0cpu - 1unassigned - 2unassigned - 3unassigned - 4rtc - 5timer - 6uarta - 7unassigned (register bit affects uartb and vfir) - 8gpio - 9sdmmc2 - 10 unassigned (register bit affects spdif_in and spdif_out) - 11 i2s1 - 12 i2c1 - 13 ndflash - 14 sdmmc1 - 15 sdmmc4 - 16 unassigned - 17 pwm - 18 i2s2 - 19 epp - 20 unassigned (register bit affects vi and vi_sensor) - 21 2d - 22 usbd - 23 isp - 24 3d - 25 unassigned - 26 disp2 - 27 disp1 - 28 host1x - 29 vcp - 30 i2s0 - 31 cop_cache - - 32 mc - 33 ahbdma - 34 apbdma - 35 unassigned - 36 kbc - 37 statmon - 38 pmc - 39 unassigned (register bit affects fuse and fuse_burn) - 40 kfuse - 41 sbc1 - 42 nor - 43 unassigned - 44 sbc2 - 45 unassigned - 46 sbc3 - 47 i2c5 - 48 dsia - 49 unassigned (register bit affects cve and tvo) - 50 mipi - 51 hdmi - 52 csi - 53 tvdac - 54 i2c2 - 55 uartc - 56 unassigned - 57 emc - 58 usb2 - 59 usb3 - 60 mpe - 61 vde - 62 bsea - 63 bsev - - 64 speedo - 65 uartd - 66 uarte - 67 i2c3 - 68 sbc4 - 69 sdmmc3 - 70 pcie - 71 owr - 72 afi - 73 csite - 74 pciex - 75 avpucq - 76 la - 77 unassigned - 78 unassigned - 79 dtv - 80 ndspeed - 81 i2cslow - 82 dsib - 83 unassigned - 84 irama - 85 iramb - 86 iramc - 87 iramd - 88 cram2 - 89 unassigned - 90 audio_2xa/k/a audio_2x_sync_clk - 91 unassigned - 92 csus - 93 cdev2 - 94 cdev1 - 95 unassigned - - 96 cpu_g - 97 cpu_lp - 98 3d2 - 99 mselect - 100 tsensor - 101 i2s3 - 102 i2s4 - 103 i2c4 - 104 sbc5 - 105 sbc6 - 106 d_audio - 107 apbif - 108 dam0 - 109 dam1 - 110 dam2 - 111 hda2codec_2x - 112 atomics - 113 audio0_2x - 114 audio1_2x - 115 audio2_2x - 116 audio3_2x - 117 audio4_2x - 118 audio5_2x - 119 actmon - 120 extern1 - 121 extern2 - 122 extern3 - 123 sata_oob - 124 sata - 125 hda - 127 se - 128 hda2hdmi - 129 sata_cold - - 160 uartb - 161 vfir - 162 spdif_in - 163 spdif_out - 164 vi - 165 vi_sensor - 166 fuse - 167 fuse_burn - 168 cve - 169 tvo - - 170 clk_32k - 171 clk_m - 172 clk_m_div2 - 173 clk_m_div4 - 174 pll_ref - 175 pll_c - 176 pll_c_out1 - 177 pll_m - 178 pll_m_out1 - 179 pll_p - 180 pll_p_out1 - 181 pll_p_out2 - 182 pll_p_out3 - 183 pll_p_out4 - 184 pll_a - 185 pll_a_out0 - 186 pll_d - 187 pll_d_out0 - 188 pll_d2 - 189 pll_d2_out0 - 190 pll_u - 191 pll_x - 192 pll_x_out0 - 193 pll_e - 194 spdif_in_sync - 195 i2s0_sync - 196 i2s1_sync - 197 i2s2_sync - 198 i2s3_sync - 199 i2s4_sync - 200 vimclk - 201 audio0 - 202 audio1 - 203 audio2 - 204 audio3 - 205 audio4 - 206 audio5 - 207 clk_out_1 (extern1) - 208 clk_out_2 (extern2) - 209 clk_out_3 (extern3) - 210 sclk - 211 blink - 212 cclk_g - 213 cclk_lp - 214 twd - 215 cml0 - 216 cml1 - 217 hclk - 218 pclk - Example SoC include file: / { @@ -229,7 +24,7 @@ Example SoC include file: }; usb@c5004000 { - clocks = <_car 58>; /* usb2 */ + clocks = <_car TEGRA30_CLK_USB2>; }; }; diff --git a/arch/arm/boot/dts/tegra30.dtsip b/arch/arm/boot/dts/tegra30.dtsip index 0148459..3c87b71 100644 --- a/arch/arm/boot/dts/tegra30.dtsip +++ b/arch/arm/boot/dts/tegra30.dtsip @
[v3 3/6] ARM: tegra30: create a DT header defining CLK IDs
To replace magic number in tegra_car: - clocks = <_car 28>; + clocks = <_car CLK_HOST1X>; Signed-off-by: Hiroshi Doyu --- arch/arm/boot/dts/tegra30-car.h | 218 +++ 1 file changed, 218 insertions(+) create mode 100644 arch/arm/boot/dts/tegra30-car.h diff --git a/arch/arm/boot/dts/tegra30-car.h b/arch/arm/boot/dts/tegra30-car.h new file mode 100644 index 000..75edf761 --- /dev/null +++ b/arch/arm/boot/dts/tegra30-car.h @@ -0,0 +1,218 @@ +/* + * This header provides constants for binding nvidia,tegra30-car. + * + * The first 130 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB + * registers. These IDs often match those in the CAR's RST_DEVICES registers, + * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In + * this case, those clocks are assigned IDs above 160 in order to highlight + * this issue. Implementations that interpret these clock IDs as bit values + * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to + * explicitly handle these special cases. + * + * The balance of the clocks controlled by the CAR are assigned IDs of 160 and + * above. + */ + +#ifndef _DT_TEGRA30_CAR_H +#define _DT_TEGRA30_CAR_H + +#define TEGRA30_CLK_CPU 0 +/* 1 */ +/* 2 */ +/* 3 */ +#define TEGRA30_CLK_RTC 4 +#define TEGRA30_CLK_TIMER 5 +#define TEGRA30_CLK_UARTA 6 +/* 7 */ /* register bit affects uartb and vfir */ +#define TEGRA30_CLK_GPIO 8 +#define TEGRA30_CLK_SDMMC2 9 +/* 10 */ /* register bit affects spdif_in and spdif_out */ +#define TEGRA30_CLK_I2S1 11 +#define TEGRA30_CLK_I2C1 12 +#define TEGRA30_CLK_NDFLASH 13 +#define TEGRA30_CLK_SDMMC1 14 +#define TEGRA30_CLK_SDMMC4 15 +/* 16 */ +#define TEGRA30_CLK_PWM 17 +#define TEGRA30_CLK_I2S2 18 +#define TEGRA30_CLK_EPP 19 +/* 20 */ /* register bit affects vi and vi_sensor */ +#define TEGRA30_CLK_GR2D 21 +#define TEGRA30_CLK_USBD 22 +#define TEGRA30_CLK_ISP 23 +#define TEGRA30_CLK_GR3D 24 +/* 25 */ +#define TEGRA30_CLK_DISP2 26 +#define TEGRA30_CLK_DISP1 27 +#define TEGRA30_CLK_HOST1X 28 +#define TEGRA30_CLK_VCP 29 +#define TEGRA30_CLK_I2S0 30 +#define TEGRA30_CLK_COP_CACHE 31 + +#define TEGRA30_CLK_MC 32 +#define TEGRA30_CLK_AHBDMA 33 +#define TEGRA30_CLK_APBDMA 34 +/* 35 */ +#define TEGRA30_CLK_KBC 36 +#define TEGRA30_CLK_STATMON 37 +#define TEGRA30_CLK_PMC 38 +/* 39 */ /* register bit affects fuse and fuse_burn */ +#define TEGRA30_CLK_KFUSE 40 +#define TEGRA30_CLK_SBC1 41 +#define TEGRA30_CLK_NOR 42 +/* 43 */ +#define TEGRA30_CLK_SBC2 44 +/* 45 */ +#define TEGRA30_CLK_SBC3 46 +#define TEGRA30_CLK_I2C5 47 +#define TEGRA30_CLK_DSIA 48 +/* 49 */ /* register bit affects cve and tvo */ +#define TEGRA30_CLK_MIPI 50 +#define TEGRA30_CLK_HDMI 51 +#define TEGRA30_CLK_CSI 52 +#define TEGRA30_CLK_TVDAC 53 +#define TEGRA30_CLK_I2C2 54 +#define TEGRA30_CLK_UARTC 55 +/* 56 */ +#define TEGRA30_CLK_EMC 57 +#define TEGRA30_CLK_USB2 58 +#define TEGRA30_CLK_USB3 59 +#define TEGRA30_CLK_MPE 60 +#define TEGRA30_CLK_VDE 61 +#define TEGRA30_CLK_BSEA 62 +#define TEGRA30_CLK_BSEV 63 + +#define TEGRA30_CLK_SPEEDO 64 +#define TEGRA30_CLK_UARTD 65 +#define TEGRA30_CLK_UARTE 66 +#define TEGRA30_CLK_I2C3 67 +#define TEGRA30_CLK_SBC4 68 +#define TEGRA30_CLK_SDMMC3 69 +#define TEGRA30_CLK_PCIE 70 +#define TEGRA30_CLK_OWR 71 +#define TEGRA30_CLK_AFI 72 +#define TEGRA30_CLK_CSITE 73 +#define TEGRA30_CLK_PCIEX 74 +#define TEGRA30_CLK_AVPUCQ 75 +#define TEGRA30_CLK_LA 76 +/* 77 */ +/* 78 */ +#define TEGRA30_CLK_DTV 79 +#define TEGRA30_CLK_NDSPEED 80 +#define TEGRA30_CLK_I2CSLOW 81 +#define TEGRA30_CLK_DSIB 82 +/* 83 */ +#define TEGRA30_CLK_IRAMA 84 +#define TEGRA30_CLK_IRAMB 85 +#define TEGRA30_CLK_IRAMC 86 +#define TEGRA30_CLK_IRAMD 87 +#define TEGRA30_CLK_CRAM2 88 +/* 89 */ +#define TEGRA30_CLK_AUDIO_2X 90 /* audio_2x_sync_clk */ +/* 91 */ +#define TEGRA30_CLK_CSUS 92 +#define TEGRA30_CLK_CDEV1 93 +#define TEGRA30_CLK_CDEV2 94 +/* 95 */ + +#define TEGRA30_CLK_CPU_G 96 +#define TEGRA30_CLK_CPU_LP 97 +#define TEGRA30_CLK_GR3D2 98 +#define TEGRA30_CLK_MSELECT 99 +#define TEGRA30_CLK_TSENSOR 100 +#define TEGRA30_CLK_I2S3 101 +#define TEGRA30_CLK_I2S4 102 +#define TEGRA30_CLK_I2C4 103 +#define TEGRA30_CLK_SBC5 104 +#define TEGRA30_CLK_SBC6 105 +#define TEGRA30_CLK_D_AUDIO 106 +#define TEGRA30_CLK_APBIF 107 +#define TEGRA30_CLK_DAM0 108 +#define TEGRA30_CLK_DAM1 109 +#define TEGRA30_CLK_DAM2 110 +#define TEGRA30_CLK_HDA2CODEC_2X 111 +#define TEGRA30_CLK_ATOMICS 112 +#define TEGRA30_CLK_AUDIO0_2X 113 +#define TEGRA30_CLK_AUDIO1_2X 114 +#define TEGRA30_CLK_AUDIO2_2X 115 +#define TEGRA30_CLK_AUDIO3_2X 116 +#define TEGRA30_CLK_AUDIO4_2X 117 +#define TEGRA30_CLK_SPDIF_2X 118 +#define TEGRA30_CLK_ACTMON 119 +#define TEGRA30_CLK_EXTERN1 120 +#define TEGRA30_CLK_EXTERN2 121 +#define TEGRA30_CLK_EXTERN3 122 +#define TEGRA30_CLK_SATA_OOB 123 +#define TEGRA30_CLK_SATA 124 +#define TEGRA30_CLK_HDA 125 +/* 126 */ +#define TEGRA30_CLK_SE 127 + +#define TEGRA30_CLK_HDA2HDMI
[v3 2/6] ARM: tegra20: convert device tree files to use CLK defines
Replace magic number in tegra_car: - clocks = <_car 28>; + clocks = <_car CLK_HOST1X>; Signed-off-by: Hiroshi Doyu --- .../bindings/clock/nvidia,tegra20-car.txt | 150 +--- arch/arm/boot/dts/tegra20-paz00.dtsp |2 +- arch/arm/boot/dts/tegra20.dtsip| 85 +-- 3 files changed, 45 insertions(+), 192 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.txt index 0921fac..18eda44 100644 --- a/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.txt +++ b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.txt @@ -14,154 +14,6 @@ Required properties : - #clock-cells : Should be 1. In clock consumers, this cell represents the clock ID exposed by the CAR. - The first 96 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB - registers. These IDs often match those in the CAR's RST_DEVICES registers, - but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In - this case, those clocks are assigned IDs above 95 in order to highlight - this issue. Implementations that interpret these clock IDs as bit values - within the CLK_OUT_ENB or RST_DEVICES registers should be careful to - explicitly handle these special cases. - - The balance of the clocks controlled by the CAR are assigned IDs of 96 and - above. - - 0cpu - 1unassigned - 2unassigned - 3ac97 - 4rtc - 5tmr - 6uart1 - 7unassigned (register bit affects uart2 and vfir) - 8gpio - 9sdmmc2 - 10 unassigned (register bit affects spdif_in and spdif_out) - 11 i2s1 - 12 i2c1 - 13 ndflash - 14 sdmmc1 - 15 sdmmc4 - 16 twc - 17 pwm - 18 i2s2 - 19 epp - 20 unassigned (register bit affects vi and vi_sensor) - 21 2d - 22 usbd - 23 isp - 24 3d - 25 ide - 26 disp2 - 27 disp1 - 28 host1x - 29 vcp - 30 unassigned - 31 cache2 - - 32 mem - 33 ahbdma - 34 apbdma - 35 unassigned - 36 kbc - 37 stat_mon - 38 pmc - 39 fuse - 40 kfuse - 41 sbc1 - 42 snor - 43 spi1 - 44 sbc2 - 45 xio - 46 sbc3 - 47 dvc - 48 dsi - 49 unassigned (register bit affects tvo and cve) - 50 mipi - 51 hdmi - 52 csi - 53 tvdac - 54 i2c2 - 55 uart3 - 56 unassigned - 57 emc - 58 usb2 - 59 usb3 - 60 mpe - 61 vde - 62 bsea - 63 bsev - - 64 speedo - 65 uart4 - 66 uart5 - 67 i2c3 - 68 sbc4 - 69 sdmmc3 - 70 pcie - 71 owr - 72 afi - 73 csite - 74 unassigned - 75 avpucq - 76 la - 77 unassigned - 78 unassigned - 79 unassigned - 80 unassigned - 81 unassigned - 82 unassigned - 83 unassigned - 84 irama - 85 iramb - 86 iramc - 87 iramd - 88 cram2 - 89 audio_2xa/k/a audio_2x_sync_clk - 90 clk_d - 91 unassigned - 92 sus - 93 cdev1 - 94 cdev2 - 95 unassigned - - 96 uart2 - 97 vfir - 98 spdif_in - 99 spdif_out - 100 vi - 101 vi_sensor - 102 tvo - 103 cve - 104 osc - 105 clk_32k a/k/a clk_s - 106 clk_m - 107 sclk - 108 cclk - 109 hclk - 110 pclk - 111 blink - 112 pll_a - 113 pll_a_out0 - 114 pll_c - 115 pll_c_out1 - 116 pll_d - 117 pll_d_out0 - 118 pll_e - 119 pll_m - 120 pll_m_out1 - 121 pll_p - 122 pll_p_out1 - 123 pll_p_out2 - 124 pll_p_out3 - 125 pll_p_out4 - 126 pll_s - 127 pll_u - 128 pll_x - 129 cop a/k/a avp - 130 audio a/k/a audio_sync_clk - 131 pll_ref - 132 twd - Example SoC include file: / { @@ -172,7 +24,7 @@ Example SoC include file: }; usb@c5004000 { - clocks = <_car 58>; /* usb2 */ + clocks = <_car TEGRA20_CLK_USB2>; }; }; diff --git a/arch/arm/boot/dts/tegra20-paz00.dtsp b/arch/arm/boot/dts/tegra20-paz00.dtsp index e63473b..3aa9f7a 100644 --- a/arch/arm/boot/dts/tegra20-paz00.dtsp +++ b/arch/arm/boot/dts/tegra20-paz00.dtsp @@ -277,7 +277,7 @@ clock-frequency = <8>; request-gpios = < TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>; slave-addr = <138>; - clocks = <_car 67>, <_car 124>; + clocks = <_car TEGRA20_CLK_I2C3>, <_car TEGRA20_CLK_PLL_P_OUT3>; clock-names = "div-clk", "fast-clk"; }; diff --git a/arch/arm/boot/dts/tegra20.dtsip b/arch/arm/boot/dts/tegra20.dtsip index 7b05f53..db118ec 100644 --- a/arch/arm/boot/dts/tegra20.dtsip +++ b/arch/arm/boot/dts/tegra20.dtsip @@ -1,6 +1,7 @@ #include "skeleton.dtsi" #include "tegra-gpio.h" #include "arm-gic.h" +#include "tegra20-car.h" / { compatible = "nvidia,tegra20"; @@ -19,7 +20,7
[v3 1/6] ARM: tegra20: create a DT header defining CLK IDs
To replace magic number in tegra_car: - clocks = <_car 28>; + clocks = <_car CLK_HOST1X>; Signed-off-by: Hiroshi Doyu --- arch/arm/boot/dts/tegra20-car.h | 158 +++ 1 file changed, 158 insertions(+) create mode 100644 arch/arm/boot/dts/tegra20-car.h diff --git a/arch/arm/boot/dts/tegra20-car.h b/arch/arm/boot/dts/tegra20-car.h new file mode 100644 index 000..5508b66 --- /dev/null +++ b/arch/arm/boot/dts/tegra20-car.h @@ -0,0 +1,158 @@ +/* + * This header provides constants for binding nvidia,tegra20-car. + * + * The first 96 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB + * registers. These IDs often match those in the CAR's RST_DEVICES registers, + * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In + * this case, those clocks are assigned IDs above 95 in order to highlight + * this issue. Implementations that interpret these clock IDs as bit values + * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to + * explicitly handle these special cases. + * + * The balance of the clocks controlled by the CAR are assigned IDs of 96 and + * above. + */ + +#ifndef _DT_TEGRA20_CAR_H +#define _DT_TEGRA20_CAR_H + +#define TEGRA20_CLK_CPU 0 +/* 1 */ +/* 2 */ +#define TEGRA20_CLK_AC97 3 +#define TEGRA20_CLK_RTC 4 +#define TEGRA20_CLK_TIMER 5 +#define TEGRA20_CLK_UARTA 6 +/* 7 */ /* register bit affects uart2 and vfir */ +#define TEGRA20_CLK_GPIO 8 +#define TEGRA20_CLK_SDMMC2 9 +/* 10 */ /* register bit affects spdif_in and spdif_out */ +#define TEGRA20_CLK_I2S1 11 +#define TEGRA20_CLK_I2C1 12 +#define TEGRA20_CLK_NDFLASH 13 +#define TEGRA20_CLK_SDMMC1 14 +#define TEGRA20_CLK_SDMMC4 15 +#define TEGRA20_CLK_TWC 16 +#define TEGRA20_CLK_PWM 17 +#define TEGRA20_CLK_I2S2 18 +#define TEGRA20_CLK_EPP 19 +/* 20 */ /* register bit affects vi and vi_sensor */ +#define TEGRA20_CLK_GR2D 21 +#define TEGRA20_CLK_USBD 22 +#define TEGRA20_CLK_ISP 23 +#define TEGRA20_CLK_GR3D 24 +#define TEGRA20_CLK_IDE 25 +#define TEGRA20_CLK_DISP2 26 +#define TEGRA20_CLK_DISP1 27 +#define TEGRA20_CLK_HOST1X 28 +#define TEGRA20_CLK_VCP 29 +/* 30 */ +#define TEGRA20_CLK_CACHE2 31 + +#define TEGRA20_CLK_MEM 32 +#define TEGRA20_CLK_AHBDMA 33 +#define TEGRA20_CLK_APBDMA 34 +/* 35 */ +#define TEGRA20_CLK_KBC 36 +#define TEGRA20_CLK_STAT_MON 37 +#define TEGRA20_CLK_PMC 38 +#define TEGRA20_CLK_FUSE 39 +#define TEGRA20_CLK_KFUSE 40 +#define TEGRA20_CLK_SBC1 41 +#define TEGRA20_CLK_NOR 42 +#define TEGRA20_CLK_SPI 43 +#define TEGRA20_CLK_SBC2 44 +#define TEGRA20_CLK_XIO 45 +#define TEGRA20_CLK_SBC3 46 +#define TEGRA20_CLK_DVC 47 +#define TEGRA20_CLK_DSI 48 +/* 49 */ /* register bit affects tvo and cve */ +#define TEGRA20_CLK_MIPI 50 +#define TEGRA20_CLK_HDMI 51 +#define TEGRA20_CLK_CSI 52 +#define TEGRA20_CLK_TVDAC 53 +#define TEGRA20_CLK_I2C2 54 +#define TEGRA20_CLK_UARTC 55 +/* 56 */ +#define TEGRA20_CLK_EMC 57 +#define TEGRA20_CLK_USB2 58 +#define TEGRA20_CLK_USB3 59 +#define TEGRA20_CLK_MPE 60 +#define TEGRA20_CLK_VDE 61 +#define TEGRA20_CLK_BSEA 62 +#define TEGRA20_CLK_BSEV 63 + +#define TEGRA20_CLK_SPEEDO 64 +#define TEGRA20_CLK_UARTD 65 +#define TEGRA20_CLK_UARTE 66 +#define TEGRA20_CLK_I2C3 67 +#define TEGRA20_CLK_SBC4 68 +#define TEGRA20_CLK_SDMMC3 69 +#define TEGRA20_CLK_PEX 70 +#define TEGRA20_CLK_OWR 71 +#define TEGRA20_CLK_AFI 72 +#define TEGRA20_CLK_CSITE 73 +#define TEGRA20_CLK_PCIE_XCLK 74 +#define TEGRA20_CLK_AVPUCQ 75 +#define TEGRA20_CLK_LA 76 +/* 77 */ +/* 78 */ +/* 79 */ +/* 80 */ +/* 81 */ +/* 82 */ +/* 83 */ +#define TEGRA20_CLK_IRAMA 84 +#define TEGRA20_CLK_IRAMB 85 +#define TEGRA20_CLK_IRAMC 86 +#define TEGRA20_CLK_IRAMD 87 +#define TEGRA20_CLK_CRAM2 88 +#define TEGRA20_CLK_AUDIO_2X 89 /* audio_2x_sync_clk */ +#define TEGRA20_CLK_D 90 +/* 91 */ +#define TEGRA20_CLK_CSUS 92 +#define TEGRA20_CLK_CDEV1 93 +#define TEGRA20_CLK_CDEV2 94 +/* 95 */ + +#define TEGRA20_CLK_UARTB 96 +#define TEGRA20_CLK_VFIR 97 +#define TEGRA20_CLK_SPDIF_IN 98 +#define TEGRA20_CLK_SPDIF_OUT 99 +#define TEGRA20_CLK_VI 100 +#define TEGRA20_CLK_VI_SENSOR 101 +#define TEGRA20_CLK_TVO 102 +#define TEGRA20_CLK_CVE 103 +#define TEGRA20_CLK_OSC 104 +#define TEGRA20_CLK_32K 105 /* clk_s */ +#define TEGRA20_CLK_M 106 +#define TEGRA20_CLK_SCLK 107 +#define TEGRA20_CLK_CCLK 108 +#define TEGRA20_CLK_HCLK 109 +#define TEGRA20_CLK_PCLK 110 +#define TEGRA20_CLK_BLINK 111 +#define TEGRA20_CLK_PLL_A 112 +#define TEGRA20_CLK_PLL_A_OUT0 113 +#define TEGRA20_CLK_PLL_C 114 +#define TEGRA20_CLK_PLL_C_OUT1 115 +#define TEGRA20_CLK_PLL_D 116 +#define TEGRA20_CLK_PLL_D_OUT0 117 +#define TEGRA20_CLK_PLL_E 118 +#define TEGRA20_CLK_PLL_M 119 +#define TEGRA20_CLK_PLL_M_OUT1 120 +#define TEGRA20_CLK_PLL_P 121 +#define TEGRA20_CLK_PLL_P_OUT1 122 +#define TEGRA20_CLK_PLL_P_OUT2 123 +#define TEGRA20_CLK_PLL_P_OUT3 124 +#define TEGRA20_CLK_PLL_P_OUT4 125 +#define TEGRA20_CLK_PLL_S 126 +#define TEGRA20_CLK_PLL_U 127 + +#define TEGRA20_CLK_PLL_X
[v3 0/6] ARM: tegra: convert device tree files to use CLK defines
Hi, With new dtc+cpp feature, we could get rid of magic numbers in dts* files. This patch replaces CLK IDs. We also plan to share those DT header files with kernel source later[1]. This series depends on: [PATCH 0/9] ARM: tegra: use new dtc+cpp feature http://lists.infradead.org/pipermail/linux-arm-kernel/2013-February/149613.html [5/6] and [6/6] depend on: [PATCH v6 00/10] Tegra114 clockframework http://lists.infradead.org/pipermail/linux-arm-kernel/2013-February/148895.html v2: http://lists.infradead.org/pipermail/linux-arm-kernel/2013-February/149816.html v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2013-February/149672.html [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2013-February/149804.html Hiroshi Doyu (6): ARM: tegra20: create a DT header defining CLK IDs ARM: tegra20: convert device tree files to use CLK defines ARM: tegra30: create a DT header defining CLK IDs ARM: tegra30: convert device tree files to use CLK defines ARM: tegra114: create a DT header defining CLK IDs ARM: tegra114: convert device tree files to use CLK defines .../bindings/clock/nvidia,tegra114-car.txt | 261 +-- .../bindings/clock/nvidia,tegra20-car.txt | 150 +-- .../bindings/clock/nvidia,tegra30-car.txt | 207 +-- arch/arm/boot/dts/tegra114-car.h | 272 arch/arm/boot/dts/tegra114.dtsip | 13 +- arch/arm/boot/dts/tegra20-car.h| 158 arch/arm/boot/dts/tegra20-paz00.dtsp |2 +- arch/arm/boot/dts/tegra20.dtsip| 85 +++--- arch/arm/boot/dts/tegra30-car.h| 218 arch/arm/boot/dts/tegra30.dtsip| 87 +++ 10 files changed, 746 insertions(+), 707 deletions(-) create mode 100644 arch/arm/boot/dts/tegra114-car.h create mode 100644 arch/arm/boot/dts/tegra20-car.h create mode 100644 arch/arm/boot/dts/tegra30-car.h -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[v3 0/6] ARM: tegra: convert device tree files to use CLK defines
Hi, With new dtc+cpp feature, we could get rid of magic numbers in dts* files. This patch replaces CLK IDs. We also plan to share those DT header files with kernel source later[1]. This series depends on: [PATCH 0/9] ARM: tegra: use new dtc+cpp feature http://lists.infradead.org/pipermail/linux-arm-kernel/2013-February/149613.html [5/6] and [6/6] depend on: [PATCH v6 00/10] Tegra114 clockframework http://lists.infradead.org/pipermail/linux-arm-kernel/2013-February/148895.html v2: http://lists.infradead.org/pipermail/linux-arm-kernel/2013-February/149816.html v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2013-February/149672.html [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2013-February/149804.html Hiroshi Doyu (6): ARM: tegra20: create a DT header defining CLK IDs ARM: tegra20: convert device tree files to use CLK defines ARM: tegra30: create a DT header defining CLK IDs ARM: tegra30: convert device tree files to use CLK defines ARM: tegra114: create a DT header defining CLK IDs ARM: tegra114: convert device tree files to use CLK defines .../bindings/clock/nvidia,tegra114-car.txt | 261 +-- .../bindings/clock/nvidia,tegra20-car.txt | 150 +-- .../bindings/clock/nvidia,tegra30-car.txt | 207 +-- arch/arm/boot/dts/tegra114-car.h | 272 arch/arm/boot/dts/tegra114.dtsip | 13 +- arch/arm/boot/dts/tegra20-car.h| 158 arch/arm/boot/dts/tegra20-paz00.dtsp |2 +- arch/arm/boot/dts/tegra20.dtsip| 85 +++--- arch/arm/boot/dts/tegra30-car.h| 218 arch/arm/boot/dts/tegra30.dtsip| 87 +++ 10 files changed, 746 insertions(+), 707 deletions(-) create mode 100644 arch/arm/boot/dts/tegra114-car.h create mode 100644 arch/arm/boot/dts/tegra20-car.h create mode 100644 arch/arm/boot/dts/tegra30-car.h -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[v3 1/6] ARM: tegra20: create a DT header defining CLK IDs
To replace magic number in tegra_car: - clocks = tegra_car 28; + clocks = tegra_car CLK_HOST1X; Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- arch/arm/boot/dts/tegra20-car.h | 158 +++ 1 file changed, 158 insertions(+) create mode 100644 arch/arm/boot/dts/tegra20-car.h diff --git a/arch/arm/boot/dts/tegra20-car.h b/arch/arm/boot/dts/tegra20-car.h new file mode 100644 index 000..5508b66 --- /dev/null +++ b/arch/arm/boot/dts/tegra20-car.h @@ -0,0 +1,158 @@ +/* + * This header provides constants for binding nvidia,tegra20-car. + * + * The first 96 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB + * registers. These IDs often match those in the CAR's RST_DEVICES registers, + * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In + * this case, those clocks are assigned IDs above 95 in order to highlight + * this issue. Implementations that interpret these clock IDs as bit values + * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to + * explicitly handle these special cases. + * + * The balance of the clocks controlled by the CAR are assigned IDs of 96 and + * above. + */ + +#ifndef _DT_TEGRA20_CAR_H +#define _DT_TEGRA20_CAR_H + +#define TEGRA20_CLK_CPU 0 +/* 1 */ +/* 2 */ +#define TEGRA20_CLK_AC97 3 +#define TEGRA20_CLK_RTC 4 +#define TEGRA20_CLK_TIMER 5 +#define TEGRA20_CLK_UARTA 6 +/* 7 */ /* register bit affects uart2 and vfir */ +#define TEGRA20_CLK_GPIO 8 +#define TEGRA20_CLK_SDMMC2 9 +/* 10 */ /* register bit affects spdif_in and spdif_out */ +#define TEGRA20_CLK_I2S1 11 +#define TEGRA20_CLK_I2C1 12 +#define TEGRA20_CLK_NDFLASH 13 +#define TEGRA20_CLK_SDMMC1 14 +#define TEGRA20_CLK_SDMMC4 15 +#define TEGRA20_CLK_TWC 16 +#define TEGRA20_CLK_PWM 17 +#define TEGRA20_CLK_I2S2 18 +#define TEGRA20_CLK_EPP 19 +/* 20 */ /* register bit affects vi and vi_sensor */ +#define TEGRA20_CLK_GR2D 21 +#define TEGRA20_CLK_USBD 22 +#define TEGRA20_CLK_ISP 23 +#define TEGRA20_CLK_GR3D 24 +#define TEGRA20_CLK_IDE 25 +#define TEGRA20_CLK_DISP2 26 +#define TEGRA20_CLK_DISP1 27 +#define TEGRA20_CLK_HOST1X 28 +#define TEGRA20_CLK_VCP 29 +/* 30 */ +#define TEGRA20_CLK_CACHE2 31 + +#define TEGRA20_CLK_MEM 32 +#define TEGRA20_CLK_AHBDMA 33 +#define TEGRA20_CLK_APBDMA 34 +/* 35 */ +#define TEGRA20_CLK_KBC 36 +#define TEGRA20_CLK_STAT_MON 37 +#define TEGRA20_CLK_PMC 38 +#define TEGRA20_CLK_FUSE 39 +#define TEGRA20_CLK_KFUSE 40 +#define TEGRA20_CLK_SBC1 41 +#define TEGRA20_CLK_NOR 42 +#define TEGRA20_CLK_SPI 43 +#define TEGRA20_CLK_SBC2 44 +#define TEGRA20_CLK_XIO 45 +#define TEGRA20_CLK_SBC3 46 +#define TEGRA20_CLK_DVC 47 +#define TEGRA20_CLK_DSI 48 +/* 49 */ /* register bit affects tvo and cve */ +#define TEGRA20_CLK_MIPI 50 +#define TEGRA20_CLK_HDMI 51 +#define TEGRA20_CLK_CSI 52 +#define TEGRA20_CLK_TVDAC 53 +#define TEGRA20_CLK_I2C2 54 +#define TEGRA20_CLK_UARTC 55 +/* 56 */ +#define TEGRA20_CLK_EMC 57 +#define TEGRA20_CLK_USB2 58 +#define TEGRA20_CLK_USB3 59 +#define TEGRA20_CLK_MPE 60 +#define TEGRA20_CLK_VDE 61 +#define TEGRA20_CLK_BSEA 62 +#define TEGRA20_CLK_BSEV 63 + +#define TEGRA20_CLK_SPEEDO 64 +#define TEGRA20_CLK_UARTD 65 +#define TEGRA20_CLK_UARTE 66 +#define TEGRA20_CLK_I2C3 67 +#define TEGRA20_CLK_SBC4 68 +#define TEGRA20_CLK_SDMMC3 69 +#define TEGRA20_CLK_PEX 70 +#define TEGRA20_CLK_OWR 71 +#define TEGRA20_CLK_AFI 72 +#define TEGRA20_CLK_CSITE 73 +#define TEGRA20_CLK_PCIE_XCLK 74 +#define TEGRA20_CLK_AVPUCQ 75 +#define TEGRA20_CLK_LA 76 +/* 77 */ +/* 78 */ +/* 79 */ +/* 80 */ +/* 81 */ +/* 82 */ +/* 83 */ +#define TEGRA20_CLK_IRAMA 84 +#define TEGRA20_CLK_IRAMB 85 +#define TEGRA20_CLK_IRAMC 86 +#define TEGRA20_CLK_IRAMD 87 +#define TEGRA20_CLK_CRAM2 88 +#define TEGRA20_CLK_AUDIO_2X 89 /* audio_2x_sync_clk */ +#define TEGRA20_CLK_D 90 +/* 91 */ +#define TEGRA20_CLK_CSUS 92 +#define TEGRA20_CLK_CDEV1 93 +#define TEGRA20_CLK_CDEV2 94 +/* 95 */ + +#define TEGRA20_CLK_UARTB 96 +#define TEGRA20_CLK_VFIR 97 +#define TEGRA20_CLK_SPDIF_IN 98 +#define TEGRA20_CLK_SPDIF_OUT 99 +#define TEGRA20_CLK_VI 100 +#define TEGRA20_CLK_VI_SENSOR 101 +#define TEGRA20_CLK_TVO 102 +#define TEGRA20_CLK_CVE 103 +#define TEGRA20_CLK_OSC 104 +#define TEGRA20_CLK_32K 105 /* clk_s */ +#define TEGRA20_CLK_M 106 +#define TEGRA20_CLK_SCLK 107 +#define TEGRA20_CLK_CCLK 108 +#define TEGRA20_CLK_HCLK 109 +#define TEGRA20_CLK_PCLK 110 +#define TEGRA20_CLK_BLINK 111 +#define TEGRA20_CLK_PLL_A 112 +#define TEGRA20_CLK_PLL_A_OUT0 113 +#define TEGRA20_CLK_PLL_C 114 +#define TEGRA20_CLK_PLL_C_OUT1 115 +#define TEGRA20_CLK_PLL_D 116 +#define TEGRA20_CLK_PLL_D_OUT0 117 +#define TEGRA20_CLK_PLL_E 118 +#define TEGRA20_CLK_PLL_M 119 +#define TEGRA20_CLK_PLL_M_OUT1 120 +#define TEGRA20_CLK_PLL_P 121 +#define TEGRA20_CLK_PLL_P_OUT1 122 +#define TEGRA20_CLK_PLL_P_OUT2 123 +#define TEGRA20_CLK_PLL_P_OUT3 124 +#define TEGRA20_CLK_PLL_P_OUT4 125 +#define TEGRA20_CLK_PLL_S 126 +#define TEGRA20_CLK_PLL_U 127 + +#define TEGRA20_CLK_PLL_X
[v3 3/6] ARM: tegra30: create a DT header defining CLK IDs
To replace magic number in tegra_car: - clocks = tegra_car 28; + clocks = tegra_car CLK_HOST1X; Signed-off-by: Hiroshi Doyu hd...@nvidia.com --- arch/arm/boot/dts/tegra30-car.h | 218 +++ 1 file changed, 218 insertions(+) create mode 100644 arch/arm/boot/dts/tegra30-car.h diff --git a/arch/arm/boot/dts/tegra30-car.h b/arch/arm/boot/dts/tegra30-car.h new file mode 100644 index 000..75edf761 --- /dev/null +++ b/arch/arm/boot/dts/tegra30-car.h @@ -0,0 +1,218 @@ +/* + * This header provides constants for binding nvidia,tegra30-car. + * + * The first 130 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB + * registers. These IDs often match those in the CAR's RST_DEVICES registers, + * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In + * this case, those clocks are assigned IDs above 160 in order to highlight + * this issue. Implementations that interpret these clock IDs as bit values + * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to + * explicitly handle these special cases. + * + * The balance of the clocks controlled by the CAR are assigned IDs of 160 and + * above. + */ + +#ifndef _DT_TEGRA30_CAR_H +#define _DT_TEGRA30_CAR_H + +#define TEGRA30_CLK_CPU 0 +/* 1 */ +/* 2 */ +/* 3 */ +#define TEGRA30_CLK_RTC 4 +#define TEGRA30_CLK_TIMER 5 +#define TEGRA30_CLK_UARTA 6 +/* 7 */ /* register bit affects uartb and vfir */ +#define TEGRA30_CLK_GPIO 8 +#define TEGRA30_CLK_SDMMC2 9 +/* 10 */ /* register bit affects spdif_in and spdif_out */ +#define TEGRA30_CLK_I2S1 11 +#define TEGRA30_CLK_I2C1 12 +#define TEGRA30_CLK_NDFLASH 13 +#define TEGRA30_CLK_SDMMC1 14 +#define TEGRA30_CLK_SDMMC4 15 +/* 16 */ +#define TEGRA30_CLK_PWM 17 +#define TEGRA30_CLK_I2S2 18 +#define TEGRA30_CLK_EPP 19 +/* 20 */ /* register bit affects vi and vi_sensor */ +#define TEGRA30_CLK_GR2D 21 +#define TEGRA30_CLK_USBD 22 +#define TEGRA30_CLK_ISP 23 +#define TEGRA30_CLK_GR3D 24 +/* 25 */ +#define TEGRA30_CLK_DISP2 26 +#define TEGRA30_CLK_DISP1 27 +#define TEGRA30_CLK_HOST1X 28 +#define TEGRA30_CLK_VCP 29 +#define TEGRA30_CLK_I2S0 30 +#define TEGRA30_CLK_COP_CACHE 31 + +#define TEGRA30_CLK_MC 32 +#define TEGRA30_CLK_AHBDMA 33 +#define TEGRA30_CLK_APBDMA 34 +/* 35 */ +#define TEGRA30_CLK_KBC 36 +#define TEGRA30_CLK_STATMON 37 +#define TEGRA30_CLK_PMC 38 +/* 39 */ /* register bit affects fuse and fuse_burn */ +#define TEGRA30_CLK_KFUSE 40 +#define TEGRA30_CLK_SBC1 41 +#define TEGRA30_CLK_NOR 42 +/* 43 */ +#define TEGRA30_CLK_SBC2 44 +/* 45 */ +#define TEGRA30_CLK_SBC3 46 +#define TEGRA30_CLK_I2C5 47 +#define TEGRA30_CLK_DSIA 48 +/* 49 */ /* register bit affects cve and tvo */ +#define TEGRA30_CLK_MIPI 50 +#define TEGRA30_CLK_HDMI 51 +#define TEGRA30_CLK_CSI 52 +#define TEGRA30_CLK_TVDAC 53 +#define TEGRA30_CLK_I2C2 54 +#define TEGRA30_CLK_UARTC 55 +/* 56 */ +#define TEGRA30_CLK_EMC 57 +#define TEGRA30_CLK_USB2 58 +#define TEGRA30_CLK_USB3 59 +#define TEGRA30_CLK_MPE 60 +#define TEGRA30_CLK_VDE 61 +#define TEGRA30_CLK_BSEA 62 +#define TEGRA30_CLK_BSEV 63 + +#define TEGRA30_CLK_SPEEDO 64 +#define TEGRA30_CLK_UARTD 65 +#define TEGRA30_CLK_UARTE 66 +#define TEGRA30_CLK_I2C3 67 +#define TEGRA30_CLK_SBC4 68 +#define TEGRA30_CLK_SDMMC3 69 +#define TEGRA30_CLK_PCIE 70 +#define TEGRA30_CLK_OWR 71 +#define TEGRA30_CLK_AFI 72 +#define TEGRA30_CLK_CSITE 73 +#define TEGRA30_CLK_PCIEX 74 +#define TEGRA30_CLK_AVPUCQ 75 +#define TEGRA30_CLK_LA 76 +/* 77 */ +/* 78 */ +#define TEGRA30_CLK_DTV 79 +#define TEGRA30_CLK_NDSPEED 80 +#define TEGRA30_CLK_I2CSLOW 81 +#define TEGRA30_CLK_DSIB 82 +/* 83 */ +#define TEGRA30_CLK_IRAMA 84 +#define TEGRA30_CLK_IRAMB 85 +#define TEGRA30_CLK_IRAMC 86 +#define TEGRA30_CLK_IRAMD 87 +#define TEGRA30_CLK_CRAM2 88 +/* 89 */ +#define TEGRA30_CLK_AUDIO_2X 90 /* audio_2x_sync_clk */ +/* 91 */ +#define TEGRA30_CLK_CSUS 92 +#define TEGRA30_CLK_CDEV1 93 +#define TEGRA30_CLK_CDEV2 94 +/* 95 */ + +#define TEGRA30_CLK_CPU_G 96 +#define TEGRA30_CLK_CPU_LP 97 +#define TEGRA30_CLK_GR3D2 98 +#define TEGRA30_CLK_MSELECT 99 +#define TEGRA30_CLK_TSENSOR 100 +#define TEGRA30_CLK_I2S3 101 +#define TEGRA30_CLK_I2S4 102 +#define TEGRA30_CLK_I2C4 103 +#define TEGRA30_CLK_SBC5 104 +#define TEGRA30_CLK_SBC6 105 +#define TEGRA30_CLK_D_AUDIO 106 +#define TEGRA30_CLK_APBIF 107 +#define TEGRA30_CLK_DAM0 108 +#define TEGRA30_CLK_DAM1 109 +#define TEGRA30_CLK_DAM2 110 +#define TEGRA30_CLK_HDA2CODEC_2X 111 +#define TEGRA30_CLK_ATOMICS 112 +#define TEGRA30_CLK_AUDIO0_2X 113 +#define TEGRA30_CLK_AUDIO1_2X 114 +#define TEGRA30_CLK_AUDIO2_2X 115 +#define TEGRA30_CLK_AUDIO3_2X 116 +#define TEGRA30_CLK_AUDIO4_2X 117 +#define TEGRA30_CLK_SPDIF_2X 118 +#define TEGRA30_CLK_ACTMON 119 +#define TEGRA30_CLK_EXTERN1 120 +#define TEGRA30_CLK_EXTERN2 121 +#define TEGRA30_CLK_EXTERN3 122 +#define TEGRA30_CLK_SATA_OOB 123 +#define TEGRA30_CLK_SATA 124 +#define TEGRA30_CLK_HDA 125 +/* 126 */ +#define TEGRA30_CLK_SE 127 + +#define TEGRA30_CLK_HDA2HDMI 128