diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-16 22:53:01 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-16 22:53:01 (GMT) |
commit | 6f51ee709e4c6b56f2c2a071da2d056a109b9d26 (patch) | |
tree | 3287f25e522e362725b8a2fe72f8862f17ddb8ba /drivers/of/platform.c | |
parent | 205dc205ed3ba748bab9770016bbbffb68558146 (diff) | |
parent | fd522d279235b8bcafc39c1040895fe2d938d1e7 (diff) | |
download | linux-6f51ee709e4c6b56f2c2a071da2d056a109b9d26.tar.xz |
Merge tag 'iommu-config-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC/iommu configuration update from Arnd Bergmann:
"The iomm-config branch contains work from Will Deacon, quoting his
description:
This series adds automatic IOMMU and DMA-mapping configuration for
OF-based DMA masters described using the generic IOMMU devicetree
bindings. Although there is plenty of future work around splitting up
iommu_ops, adding default IOMMU domains and sorting out automatic IOMMU
group creation for the platform_bus, this is already useful enough for
people to port over their IOMMU drivers and start using the new probing
infrastructure (indeed, Marek has patches queued for the Exynos IOMMU).
The branch touches core ARM and IOMMU driver files, and the respective
maintainers (Russell King and Joerg Roedel) agreed to have the
contents merged through the arm-soc tree.
The final version was ready just before the merge window, so we ended
up delaying it a bit longer than the rest, but we don't expect to see
regressions because this is just additional infrastructure that will
get used in drivers starting in 3.20 but is unused so far"
* tag 'iommu-config-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc:
iommu: store DT-probed IOMMU data privately
arm: dma-mapping: plumb our iommu mapping ops into arch_setup_dma_ops
arm: call iommu_init before of_platform_populate
dma-mapping: detect and configure IOMMU in of_dma_configure
iommu: fix initialization without 'add_device' callback
iommu: provide helper function to configure an IOMMU for an of master
iommu: add new iommu_ops callback for adding an OF device
dma-mapping: replace set_arch_dma_coherent_ops with arch_setup_dma_ops
iommu: provide early initialisation hook for IOMMU drivers
Diffstat (limited to 'drivers/of/platform.c')
-rw-r--r-- | drivers/of/platform.c | 50 |
1 files changed, 26 insertions, 24 deletions
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index cd87a36..5b33c6a 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -19,6 +19,7 @@ #include <linux/slab.h> #include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/of_iommu.h> #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/platform_device.h> @@ -164,6 +165,9 @@ static void of_dma_configure(struct device *dev) { u64 dma_addr, paddr, size; int ret; + bool coherent; + unsigned long offset; + struct iommu_ops *iommu; /* * Set default dma-mask to 32 bit. Drivers are expected to setup @@ -178,28 +182,30 @@ static void of_dma_configure(struct device *dev) if (!dev->dma_mask) dev->dma_mask = &dev->coherent_dma_mask; - /* - * if dma-coherent property exist, call arch hook to setup - * dma coherent operations. - */ - if (of_dma_is_coherent(dev->of_node)) { - set_arch_dma_coherent_ops(dev); - dev_dbg(dev, "device is dma coherent\n"); - } - - /* - * if dma-ranges property doesn't exist - just return else - * setup the dma offset - */ ret = of_dma_get_range(dev->of_node, &dma_addr, &paddr, &size); if (ret < 0) { - dev_dbg(dev, "no dma range information to setup\n"); - return; + dma_addr = offset = 0; + size = dev->coherent_dma_mask; + } else { + offset = PFN_DOWN(paddr - dma_addr); + dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", dev->dma_pfn_offset); } + dev->dma_pfn_offset = offset; + + coherent = of_dma_is_coherent(dev->of_node); + dev_dbg(dev, "device is%sdma coherent\n", + coherent ? " " : " not "); + + iommu = of_iommu_configure(dev); + dev_dbg(dev, "device is%sbehind an iommu\n", + iommu ? " " : " not "); - /* DMA ranges found. Calculate and set dma_pfn_offset */ - dev->dma_pfn_offset = PFN_DOWN(paddr - dma_addr); - dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", dev->dma_pfn_offset); + arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent); +} + +static void of_dma_deconfigure(struct device *dev) +{ + arch_teardown_dma_ops(dev); } /** @@ -228,16 +234,12 @@ static struct platform_device *of_platform_device_create_pdata( if (!dev) goto err_clear_flag; - of_dma_configure(&dev->dev); dev->dev.bus = &platform_bus_type; dev->dev.platform_data = platform_data; - - /* We do not fill the DMA ops for platform devices by default. - * This is currently the responsibility of the platform code - * to do such, possibly using a device notifier - */ + of_dma_configure(&dev->dev); if (of_device_add(dev) != 0) { + of_dma_deconfigure(&dev->dev); platform_device_put(dev); goto err_clear_flag; } |