aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/arm/coherency-fabric.txt9
-rw-r--r--arch/arm/boot/dts/armada-370-xp.dtsi3
-rw-r--r--arch/arm/mach-mvebu/addr-map.c3
-rw-r--r--arch/arm/mach-mvebu/coherency.c73
4 files changed, 85 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/arm/coherency-fabric.txt b/Documentation/devicetree/bindings/arm/coherency-fabric.txt
index 2bfbf67dd77e..17d8cd107559 100644
--- a/Documentation/devicetree/bindings/arm/coherency-fabric.txt
+++ b/Documentation/devicetree/bindings/arm/coherency-fabric.txt
@@ -5,12 +5,17 @@ Available on Marvell SOCs: Armada 370 and Armada XP
5Required properties: 5Required properties:
6 6
7- compatible: "marvell,coherency-fabric" 7- compatible: "marvell,coherency-fabric"
8- reg: Should contain,coherency fabric registers location and length. 8
9- reg: Should contain coherency fabric registers location and
10 length. First pair for the coherency fabric registers, second pair
11 for the per-CPU fabric registers registers.
9 12
10Example: 13Example:
11 14
12coherency-fabric@d0020200 { 15coherency-fabric@d0020200 {
13 compatible = "marvell,coherency-fabric"; 16 compatible = "marvell,coherency-fabric";
14 reg = <0xd0020200 0xb0>; 17 reg = <0xd0020200 0xb0>,
18 <0xd0021810 0x1c>;
19
15}; 20};
16 21
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index b0d075b50f29..98a6b26a7dc8 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -38,7 +38,8 @@
38 38
39 coherency-fabric@d0020200 { 39 coherency-fabric@d0020200 {
40 compatible = "marvell,coherency-fabric"; 40 compatible = "marvell,coherency-fabric";
41 reg = <0xd0020200 0xb0>; 41 reg = <0xd0020200 0xb0>,
42 <0xd0021810 0x1c>;
42 }; 43 };
43 44
44 soc { 45 soc {
diff --git a/arch/arm/mach-mvebu/addr-map.c b/arch/arm/mach-mvebu/addr-map.c
index fe454a4430be..595f6b722a8f 100644
--- a/arch/arm/mach-mvebu/addr-map.c
+++ b/arch/arm/mach-mvebu/addr-map.c
@@ -108,6 +108,9 @@ static int __init armada_setup_cpu_mbus(void)
108 108
109 addr_map_cfg.bridge_virt_base = mbus_unit_addr_decoding_base; 109 addr_map_cfg.bridge_virt_base = mbus_unit_addr_decoding_base;
110 110
111 if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"))
112 addr_map_cfg.hw_io_coherency = 1;
113
111 /* 114 /*
112 * Disable, clear and configure windows. 115 * Disable, clear and configure windows.
113 */ 116 */
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index 596ee66a9cc4..8278960066c3 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -22,6 +22,8 @@
22#include <linux/of_address.h> 22#include <linux/of_address.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/smp.h> 24#include <linux/smp.h>
25#include <linux/dma-mapping.h>
26#include <linux/platform_device.h>
25#include <asm/smp_plat.h> 27#include <asm/smp_plat.h>
26#include "armada-370-xp.h" 28#include "armada-370-xp.h"
27 29
@@ -33,10 +35,13 @@
33 * value matching its virtual mapping 35 * value matching its virtual mapping
34 */ 36 */
35static void __iomem *coherency_base = ARMADA_370_XP_REGS_VIRT_BASE + 0x20200; 37static void __iomem *coherency_base = ARMADA_370_XP_REGS_VIRT_BASE + 0x20200;
38static void __iomem *coherency_cpu_base;
36 39
37/* Coherency fabric registers */ 40/* Coherency fabric registers */
38#define COHERENCY_FABRIC_CFG_OFFSET 0x4 41#define COHERENCY_FABRIC_CFG_OFFSET 0x4
39 42
43#define IO_SYNC_BARRIER_CTL_OFFSET 0x0
44
40static struct of_device_id of_coherency_table[] = { 45static struct of_device_id of_coherency_table[] = {
41 {.compatible = "marvell,coherency-fabric"}, 46 {.compatible = "marvell,coherency-fabric"},
42 { /* end of list */ }, 47 { /* end of list */ },
@@ -68,6 +73,70 @@ int set_cpu_coherent(unsigned int hw_cpu_id, int smp_group_id)
68 return ll_set_cpu_coherent(coherency_base, hw_cpu_id); 73 return ll_set_cpu_coherent(coherency_base, hw_cpu_id);
69} 74}
70 75
76static inline void mvebu_hwcc_sync_io_barrier(void)
77{
78 writel(0x1, coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET);
79 while (readl(coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET) & 0x1);
80}
81
82static dma_addr_t mvebu_hwcc_dma_map_page(struct device *dev, struct page *page,
83 unsigned long offset, size_t size,
84 enum dma_data_direction dir,
85 struct dma_attrs *attrs)
86{
87 if (dir != DMA_TO_DEVICE)
88 mvebu_hwcc_sync_io_barrier();
89 return pfn_to_dma(dev, page_to_pfn(page)) + offset;
90}
91
92
93static void mvebu_hwcc_dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
94 size_t size, enum dma_data_direction dir,
95 struct dma_attrs *attrs)
96{
97 if (dir != DMA_TO_DEVICE)
98 mvebu_hwcc_sync_io_barrier();
99}
100
101static void mvebu_hwcc_dma_sync(struct device *dev, dma_addr_t dma_handle,
102 size_t size, enum dma_data_direction dir)
103{
104 if (dir != DMA_TO_DEVICE)
105 mvebu_hwcc_sync_io_barrier();
106}
107
108static struct dma_map_ops mvebu_hwcc_dma_ops = {
109 .alloc = arm_dma_alloc,
110 .free = arm_dma_free,
111 .mmap = arm_dma_mmap,
112 .map_page = mvebu_hwcc_dma_map_page,
113 .unmap_page = mvebu_hwcc_dma_unmap_page,
114 .get_sgtable = arm_dma_get_sgtable,
115 .map_sg = arm_dma_map_sg,
116 .unmap_sg = arm_dma_unmap_sg,
117 .sync_single_for_cpu = mvebu_hwcc_dma_sync,
118 .sync_single_for_device = mvebu_hwcc_dma_sync,
119 .sync_sg_for_cpu = arm_dma_sync_sg_for_cpu,
120 .sync_sg_for_device = arm_dma_sync_sg_for_device,
121 .set_dma_mask = arm_dma_set_mask,
122};
123
124static int mvebu_hwcc_platform_notifier(struct notifier_block *nb,
125 unsigned long event, void *__dev)
126{
127 struct device *dev = __dev;
128
129 if (event != BUS_NOTIFY_ADD_DEVICE)
130 return NOTIFY_DONE;
131 set_dma_ops(dev, &mvebu_hwcc_dma_ops);
132
133 return NOTIFY_OK;
134}
135
136static struct notifier_block mvebu_hwcc_platform_nb = {
137 .notifier_call = mvebu_hwcc_platform_notifier,
138};
139
71int __init coherency_init(void) 140int __init coherency_init(void)
72{ 141{
73 struct device_node *np; 142 struct device_node *np;
@@ -76,6 +145,10 @@ int __init coherency_init(void)
76 if (np) { 145 if (np) {
77 pr_info("Initializing Coherency fabric\n"); 146 pr_info("Initializing Coherency fabric\n");
78 coherency_base = of_iomap(np, 0); 147 coherency_base = of_iomap(np, 0);
148 coherency_cpu_base = of_iomap(np, 1);
149 set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
150 bus_register_notifier(&platform_bus_type,
151 &mvebu_hwcc_platform_nb);
79 } 152 }
80 153
81 return 0; 154 return 0;