summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorRob Herring <rob.herring@calxeda.com>2012-08-21 12:31:06 +0200
committerMarek Szyprowski <m.szyprowski@samsung.com>2012-10-02 08:58:07 +0200
commit1dc737c44a11c66f23ebeb09796f52f4b60d59c7 (patch)
tree35d2020f28bdd4c406eaf2e6909c648ce12a66e5 /arch
parent48aa820f1e3824e46dde6251db98e5961abf605d (diff)
downloadlinux-3.10-1dc737c44a11c66f23ebeb09796f52f4b60d59c7.tar.gz
linux-3.10-1dc737c44a11c66f23ebeb09796f52f4b60d59c7.tar.bz2
linux-3.10-1dc737c44a11c66f23ebeb09796f52f4b60d59c7.zip
ARM: highbank: add coherent DMA setup
Some highbank DMA masters can support coherent (ACP) or non-coherent DMA. This sets up dma_map_ops for masters which are configured for coherent DMA. Signed-off-by: Rob Herring <rob.herring@calxeda.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/boot/dts/highbank.dts1
-rw-r--r--arch/arm/mach-highbank/highbank.c52
2 files changed, 53 insertions, 0 deletions
diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts
index 9fecf1ae777..7414577c177 100644
--- a/arch/arm/boot/dts/highbank.dts
+++ b/arch/arm/boot/dts/highbank.dts
@@ -121,6 +121,7 @@
compatible = "calxeda,hb-ahci";
reg = <0xffe08000 0x10000>;
interrupts = <0 83 4>;
+ dma-coherent;
};
sdhci@ffe0e000 {
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index d75b0a78d88..93617d61f4b 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -15,6 +15,7 @@
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
+#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
@@ -23,6 +24,7 @@
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/smp.h>
+#include <linux/amba/bus.h>
#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
@@ -149,10 +151,60 @@ static void highbank_power_off(void)
cpu_do_idle();
}
+static int highbank_platform_notifier(struct notifier_block *nb,
+ unsigned long event, void *__dev)
+{
+ struct resource *res;
+ int reg = -1;
+ struct device *dev = __dev;
+
+ if (event != BUS_NOTIFY_ADD_DEVICE)
+ return NOTIFY_DONE;
+
+ if (of_device_is_compatible(dev->of_node, "calxeda,hb-ahci"))
+ reg = 0xc;
+ else if (of_device_is_compatible(dev->of_node, "calxeda,hb-sdhci"))
+ reg = 0x18;
+ else if (of_device_is_compatible(dev->of_node, "arm,pl330"))
+ reg = 0x20;
+ else if (of_device_is_compatible(dev->of_node, "calxeda,hb-xgmac")) {
+ res = platform_get_resource(to_platform_device(dev),
+ IORESOURCE_MEM, 0);
+ if (res) {
+ if (res->start == 0xfff50000)
+ reg = 0;
+ else if (res->start == 0xfff51000)
+ reg = 4;
+ }
+ }
+
+ if (reg < 0)
+ return NOTIFY_DONE;
+
+ if (of_property_read_bool(dev->of_node, "dma-coherent")) {
+ writel(0xff31, sregs_base + reg);
+ set_dma_ops(dev, &arm_coherent_dma_ops);
+ } else
+ writel(0, sregs_base + reg);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block highbank_amba_nb = {
+ .notifier_call = highbank_platform_notifier,
+};
+
+static struct notifier_block highbank_platform_nb = {
+ .notifier_call = highbank_platform_notifier,
+};
+
static void __init highbank_init(void)
{
pm_power_off = highbank_power_off;
+ bus_register_notifier(&platform_bus_type, &highbank_platform_nb);
+ bus_register_notifier(&amba_bustype, &highbank_amba_nb);
+
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}