diff options
author | Murali Karicheri <m-karicheri2@ti.com> | 2015-03-03 12:52:09 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2015-03-03 14:42:56 -0600 |
commit | 1f5c69aa51f9c7c8d2a5c2e4dc339f6c7d5c15cd (patch) | |
tree | 152d30ba274eddb828c0f5ea8d886ab82f96819a /drivers/of/device.c | |
parent | ed748621031c2a205749997421e59fb4dfb1e909 (diff) |
of: Move of_dma_configure() to device.c to help re-use
Move of_dma_configure() to device.c so it can be re-used for PCI devices to
obtain DMA configuration from DT. Also add a second argument so that for
PCI, the DT node of root bus host bridge can be used to obtain the DMA
configuration for the slave PCI device.
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> (AMD Seattle)
Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Acked-by: Rob Herring <robh+dt@kernel.org>
CC: Joerg Roedel <joro@8bytes.org>
CC: Grant Likely <grant.likely@linaro.org>
CC: Russell King <linux@arm.linux.org.uk>
CC: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/of/device.c')
-rw-r--r-- | drivers/of/device.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/of/device.c b/drivers/of/device.c index 46d6c75c1404..31a7875b34a4 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -2,6 +2,9 @@ #include <linux/kernel.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/of_address.h> +#include <linux/of_iommu.h> +#include <linux/dma-mapping.h> #include <linux/init.h> #include <linux/module.h> #include <linux/mod_devicetable.h> @@ -66,6 +69,62 @@ int of_device_add(struct platform_device *ofdev) return device_add(&ofdev->dev); } +/** + * of_dma_configure - Setup DMA configuration + * @dev: Device to apply DMA configuration + * @np: Pointer to OF node having DMA configuration + * + * Try to get devices's DMA configuration from DT and update it + * accordingly. + * + * If platform code needs to use its own special DMA configuration, it + * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events + * to fix up DMA configuration. + */ +void of_dma_configure(struct device *dev, struct device_node *np) +{ + 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 + * the correct supported dma_mask. + */ + dev->coherent_dma_mask = DMA_BIT_MASK(32); + + /* + * Set it to coherent_dma_mask by default if the architecture + * code has not set it. + */ + if (!dev->dma_mask) + dev->dma_mask = &dev->coherent_dma_mask; + + ret = of_dma_get_range(np, &dma_addr, &paddr, &size); + if (ret < 0) { + dma_addr = offset = 0; + size = dev->coherent_dma_mask; + } else { + offset = PFN_DOWN(paddr - dma_addr); + dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset); + } + + dev->dma_pfn_offset = offset; + + coherent = of_dma_is_coherent(np); + dev_dbg(dev, "device is%sdma coherent\n", + coherent ? " " : " not "); + + iommu = of_iommu_configure(dev, np); + dev_dbg(dev, "device is%sbehind an iommu\n", + iommu ? " " : " not "); + + arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent); +} +EXPORT_SYMBOL_GPL(of_dma_configure); + int of_device_register(struct platform_device *pdev) { device_initialize(&pdev->dev); |