aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt12
-rw-r--r--Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt20
-rw-r--r--Documentation/devicetree/bindings/arm/coherency-fabric.txt21
-rw-r--r--arch/arm/boot/dts/armada-370-xp.dtsi6
-rw-r--r--arch/arm/boot/dts/armada-xp.dtsi8
-rw-r--r--arch/arm/configs/mvebu_defconfig3
-rw-r--r--arch/arm/include/asm/dma-mapping.h2
-rw-r--r--arch/arm/mach-mvebu/Kconfig3
-rw-r--r--arch/arm/mach-mvebu/Makefile4
-rw-r--r--arch/arm/mach-mvebu/addr-map.c3
-rw-r--r--arch/arm/mach-mvebu/armada-370-xp.c3
-rw-r--r--arch/arm/mach-mvebu/armada-370-xp.h7
-rw-r--r--arch/arm/mach-mvebu/coherency.c155
-rw-r--r--arch/arm/mach-mvebu/coherency.h24
-rw-r--r--arch/arm/mach-mvebu/coherency_ll.S49
-rw-r--r--arch/arm/mach-mvebu/common.h5
-rw-r--r--arch/arm/mach-mvebu/headsmp.S49
-rw-r--r--arch/arm/mach-mvebu/hotplug.c30
-rw-r--r--arch/arm/mach-mvebu/irq-armada-370-xp.c92
-rw-r--r--arch/arm/mach-mvebu/platsmp.c122
-rw-r--r--arch/arm/mach-mvebu/pmsu.c75
-rw-r--r--arch/arm/mach-mvebu/pmsu.h16
-rw-r--r--arch/arm/mm/Kconfig4
-rw-r--r--arch/arm/mm/dma-mapping.c4
-rw-r--r--arch/arm/mm/proc-v7.S67
-rw-r--r--arch/arm/plat-orion/addr-map.c4
-rw-r--r--arch/arm/plat-orion/include/plat/addr-map.h1
27 files changed, 774 insertions, 15 deletions
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
index 70c0dc5f00ed..61df564c0d23 100644
--- a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
+++ b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
@@ -6,9 +6,15 @@ Required properties:
6- interrupt-controller: Identifies the node as an interrupt controller. 6- interrupt-controller: Identifies the node as an interrupt controller.
7- #interrupt-cells: The number of cells to define the interrupts. Should be 1. 7- #interrupt-cells: The number of cells to define the interrupts. Should be 1.
8 The cell is the IRQ number 8 The cell is the IRQ number
9
9- reg: Should contain PMIC registers location and length. First pair 10- reg: Should contain PMIC registers location and length. First pair
10 for the main interrupt registers, second pair for the per-CPU 11 for the main interrupt registers, second pair for the per-CPU
11 interrupt registers 12 interrupt registers. For this last pair, to be compliant with SMP
13 support, the "virtual" must be use (For the record, these registers
14 automatically map to the interrupt controller registers of the
15 current CPU)
16
17
12 18
13Example: 19Example:
14 20
@@ -18,6 +24,6 @@ Example:
18 #address-cells = <1>; 24 #address-cells = <1>;
19 #size-cells = <1>; 25 #size-cells = <1>;
20 interrupt-controller; 26 interrupt-controller;
21 reg = <0xd0020000 0x1000>, 27 reg = <0xd0020a00 0x1d0>,
22 <0xd0021000 0x1000>; 28 <0xd0021070 0x58>;
23 }; 29 };
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt
new file mode 100644
index 000000000000..926b4d6aae7e
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/armada-370-xp-pmsu.txt
@@ -0,0 +1,20 @@
1Power Management Service Unit(PMSU)
2-----------------------------------
3Available on Marvell SOCs: Armada 370 and Armada XP
4
5Required properties:
6
7- compatible: "marvell,armada-370-xp-pmsu"
8
9- reg: Should contain PMSU registers location and length. First pair
10 for the per-CPU SW Reset Control registers, second pair for the
11 Power Management Service Unit.
12
13Example:
14
15armada-370-xp-pmsu@d0022000 {
16 compatible = "marvell,armada-370-xp-pmsu";
17 reg = <0xd0022100 0x430>,
18 <0xd0020800 0x20>;
19};
20
diff --git a/Documentation/devicetree/bindings/arm/coherency-fabric.txt b/Documentation/devicetree/bindings/arm/coherency-fabric.txt
new file mode 100644
index 000000000000..17d8cd107559
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/coherency-fabric.txt
@@ -0,0 +1,21 @@
1Coherency fabric
2----------------
3Available on Marvell SOCs: Armada 370 and Armada XP
4
5Required properties:
6
7- compatible: "marvell,coherency-fabric"
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.
12
13Example:
14
15coherency-fabric@d0020200 {
16 compatible = "marvell,coherency-fabric";
17 reg = <0xd0020200 0xb0>,
18 <0xd0021810 0x1c>;
19
20};
21
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index 70c35f8ccf90..cb09d0882c3d 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -36,6 +36,12 @@
36 interrupt-controller; 36 interrupt-controller;
37 }; 37 };
38 38
39 coherency-fabric@d0020200 {
40 compatible = "marvell,coherency-fabric";
41 reg = <0xd0020200 0xb0>,
42 <0xd0021810 0x1c>;
43 };
44
39 soc { 45 soc {
40 #address-cells = <1>; 46 #address-cells = <1>;
41 #size-cells = <1>; 47 #size-cells = <1>;
diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi
index 3c52e7ab1910..45a567c2e9ba 100644
--- a/arch/arm/boot/dts/armada-xp.dtsi
+++ b/arch/arm/boot/dts/armada-xp.dtsi
@@ -24,7 +24,13 @@
24 24
25 mpic: interrupt-controller@d0020000 { 25 mpic: interrupt-controller@d0020000 {
26 reg = <0xd0020a00 0x1d0>, 26 reg = <0xd0020a00 0x1d0>,
27 <0xd0021870 0x58>; 27 <0xd0021070 0x58>;
28 };
29
30 armada-370-xp-pmsu@d0022000 {
31 compatible = "marvell,armada-370-xp-pmsu";
32 reg = <0xd0022100 0x430>,
33 <0xd0020800 0x20>;
28 }; 34 };
29 35
30 soc { 36 soc {
diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig
index 73b53fc06638..a702fb345c01 100644
--- a/arch/arm/configs/mvebu_defconfig
+++ b/arch/arm/configs/mvebu_defconfig
@@ -12,6 +12,9 @@ CONFIG_ARCH_MVEBU=y
12CONFIG_MACH_ARMADA_370=y 12CONFIG_MACH_ARMADA_370=y
13CONFIG_MACH_ARMADA_XP=y 13CONFIG_MACH_ARMADA_XP=y
14# CONFIG_CACHE_L2X0 is not set 14# CONFIG_CACHE_L2X0 is not set
15# CONFIG_SWP_EMULATE is not set
16CONFIG_SMP=y
17# CONFIG_LOCAL_TIMERS is not set
15CONFIG_AEABI=y 18CONFIG_AEABI=y
16CONFIG_HIGHMEM=y 19CONFIG_HIGHMEM=y
17# CONFIG_COMPACTION is not set 20# CONFIG_COMPACTION is not set
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 23004847bb05..98d4dabb2c10 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -111,6 +111,8 @@ static inline void dma_free_noncoherent(struct device *dev, size_t size,
111 111
112extern int dma_supported(struct device *dev, u64 mask); 112extern int dma_supported(struct device *dev, u64 mask);
113 113
114extern int arm_dma_set_mask(struct device *dev, u64 dma_mask);
115
114/** 116/**
115 * arm_dma_alloc - allocate consistent memory for DMA 117 * arm_dma_alloc - allocate consistent memory for DMA
116 * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices 118 * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 79299cd94f0f..c934e1d4933d 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -21,7 +21,8 @@ menu "Marvell SOC with device tree"
21config MACH_ARMADA_370_XP 21config MACH_ARMADA_370_XP
22 bool 22 bool
23 select ARMADA_370_XP_TIMER 23 select ARMADA_370_XP_TIMER
24 select CPU_V7 24 select HAVE_SMP
25 select CPU_PJ4B
25 26
26config MACH_ARMADA_370 27config MACH_ARMADA_370
27 bool "Marvell Armada 370 boards" 28 bool "Marvell Armada 370 boards"
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 57f996b6aa0e..5dcb369b58aa 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -2,4 +2,6 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
2 -I$(srctree)/arch/arm/plat-orion/include 2 -I$(srctree)/arch/arm/plat-orion/include
3 3
4obj-y += system-controller.o 4obj-y += system-controller.o
5obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o 5obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o
6obj-$(CONFIG_SMP) += platsmp.o headsmp.o
7obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
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/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
index cd6eac17fb67..a9cf335c7cb0 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.c
+++ b/arch/arm/mach-mvebu/armada-370-xp.c
@@ -24,6 +24,7 @@
24#include <asm/mach/time.h> 24#include <asm/mach/time.h>
25#include "armada-370-xp.h" 25#include "armada-370-xp.h"
26#include "common.h" 26#include "common.h"
27#include "coherency.h"
27 28
28static struct map_desc armada_370_xp_io_desc[] __initdata = { 29static struct map_desc armada_370_xp_io_desc[] __initdata = {
29 { 30 {
@@ -62,6 +63,7 @@ struct sys_timer armada_370_xp_timer = {
62static void __init armada_370_xp_dt_init(void) 63static void __init armada_370_xp_dt_init(void)
63{ 64{
64 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); 65 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
66 coherency_init();
65} 67}
66 68
67static const char * const armada_370_xp_dt_board_dt_compat[] = { 69static const char * const armada_370_xp_dt_board_dt_compat[] = {
@@ -71,6 +73,7 @@ static const char * const armada_370_xp_dt_board_dt_compat[] = {
71}; 73};
72 74
73DT_MACHINE_START(ARMADA_XP_DT, "Marvell Aramada 370/XP (Device Tree)") 75DT_MACHINE_START(ARMADA_XP_DT, "Marvell Aramada 370/XP (Device Tree)")
76 .smp = smp_ops(armada_xp_smp_ops),
74 .init_machine = armada_370_xp_dt_init, 77 .init_machine = armada_370_xp_dt_init,
75 .map_io = armada_370_xp_map_io, 78 .map_io = armada_370_xp_map_io,
76 .init_early = armada_370_xp_init_early, 79 .init_early = armada_370_xp_init_early,
diff --git a/arch/arm/mach-mvebu/armada-370-xp.h b/arch/arm/mach-mvebu/armada-370-xp.h
index aac9bebc6b03..c6a7d74fddfe 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.h
+++ b/arch/arm/mach-mvebu/armada-370-xp.h
@@ -19,4 +19,11 @@
19#define ARMADA_370_XP_REGS_VIRT_BASE IOMEM(0xfeb00000) 19#define ARMADA_370_XP_REGS_VIRT_BASE IOMEM(0xfeb00000)
20#define ARMADA_370_XP_REGS_SIZE SZ_1M 20#define ARMADA_370_XP_REGS_SIZE SZ_1M
21 21
22#ifdef CONFIG_SMP
23#include <linux/cpumask.h>
24
25void armada_mpic_send_doorbell(const struct cpumask *mask, unsigned int irq);
26void armada_xp_mpic_smp_cpu_init(void);
27#endif
28
22#endif /* __MACH_ARMADA_370_XP_H */ 29#endif /* __MACH_ARMADA_370_XP_H */
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
new file mode 100644
index 000000000000..8278960066c3
--- /dev/null
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -0,0 +1,155 @@
1/*
2 * Coherency fabric (Aurora) support for Armada 370 and XP platforms.
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Yehuda Yitschak <yehuday@marvell.com>
7 * Gregory Clement <gregory.clement@free-electrons.com>
8 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
9 *
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
13 *
14 * The Armada 370 and Armada XP SOCs have a coherency fabric which is
15 * responsible for ensuring hardware coherency between all CPUs and between
16 * CPUs and I/O masters. This file initializes the coherency fabric and
17 * supplies basic routines for configuring and controlling hardware coherency
18 */
19
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/of_address.h>
23#include <linux/io.h>
24#include <linux/smp.h>
25#include <linux/dma-mapping.h>
26#include <linux/platform_device.h>
27#include <asm/smp_plat.h>
28#include "armada-370-xp.h"
29
30/*
31 * Some functions in this file are called very early during SMP
32 * initialization. At that time the device tree framework is not yet
33 * ready, and it is not possible to get the register address to
34 * ioremap it. That's why the pointer below is given with an initial
35 * value matching its virtual mapping
36 */
37static void __iomem *coherency_base = ARMADA_370_XP_REGS_VIRT_BASE + 0x20200;
38static void __iomem *coherency_cpu_base;
39
40/* Coherency fabric registers */
41#define COHERENCY_FABRIC_CFG_OFFSET 0x4
42
43#define IO_SYNC_BARRIER_CTL_OFFSET 0x0
44
45static struct of_device_id of_coherency_table[] = {
46 {.compatible = "marvell,coherency-fabric"},
47 { /* end of list */ },
48};
49
50#ifdef CONFIG_SMP
51int coherency_get_cpu_count(void)
52{
53 int reg, cnt;
54
55 reg = readl(coherency_base + COHERENCY_FABRIC_CFG_OFFSET);
56 cnt = (reg & 0xF) + 1;
57
58 return cnt;
59}
60#endif
61
62/* Function defined in coherency_ll.S */
63int ll_set_cpu_coherent(void __iomem *base_addr, unsigned int hw_cpu_id);
64
65int set_cpu_coherent(unsigned int hw_cpu_id, int smp_group_id)
66{
67 if (!coherency_base) {
68 pr_warn("Can't make CPU %d cache coherent.\n", hw_cpu_id);
69 pr_warn("Coherency fabric is not initialized\n");
70 return 1;
71 }
72
73 return ll_set_cpu_coherent(coherency_base, hw_cpu_id);
74}
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
140int __init coherency_init(void)
141{
142 struct device_node *np;
143
144 np = of_find_matching_node(NULL, of_coherency_table);
145 if (np) {
146 pr_info("Initializing Coherency fabric\n");
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);
152 }
153
154 return 0;
155}
diff --git a/arch/arm/mach-mvebu/coherency.h b/arch/arm/mach-mvebu/coherency.h
new file mode 100644
index 000000000000..2f428137f6fe
--- /dev/null
+++ b/arch/arm/mach-mvebu/coherency.h
@@ -0,0 +1,24 @@
1/*
2 * arch/arm/mach-mvebu/include/mach/coherency.h
3 *
4 *
5 * Coherency fabric (Aurora) support for Armada 370 and XP platforms.
6 *
7 * Copyright (C) 2012 Marvell
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#ifndef __MACH_370_XP_COHERENCY_H
15#define __MACH_370_XP_COHERENCY_H
16
17#ifdef CONFIG_SMP
18int coherency_get_cpu_count(void);
19#endif
20
21int set_cpu_coherent(int cpu_id, int smp_group_id);
22int coherency_init(void);
23
24#endif /* __MACH_370_XP_COHERENCY_H */
diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S
new file mode 100644
index 000000000000..53e8391192cd
--- /dev/null
+++ b/arch/arm/mach-mvebu/coherency_ll.S
@@ -0,0 +1,49 @@
1/*
2 * Coherency fabric: low level functions
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Gregory CLEMENT <gregory.clement@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 *
12 * This file implements the assembly function to add a CPU to the
13 * coherency fabric. This function is called by each of the secondary
14 * CPUs during their early boot in an SMP kernel, this why this
15 * function have to callable from assembly. It can also be called by a
16 * primary CPU from C code during its boot.
17 */
18
19#include <linux/linkage.h>
20#define ARMADA_XP_CFB_CTL_REG_OFFSET 0x0
21#define ARMADA_XP_CFB_CFG_REG_OFFSET 0x4
22
23 .text
24/*
25 * r0: Coherency fabric base register address
26 * r1: HW CPU id
27 */
28ENTRY(ll_set_cpu_coherent)
29 /* Create bit by cpu index */
30 mov r3, #(1 << 24)
31 lsl r1, r3, r1
32
33 /* Add CPU to SMP group - Atomic */
34 add r3, r0, #ARMADA_XP_CFB_CTL_REG_OFFSET
35 ldr r2, [r3]
36 orr r2, r2, r1
37 str r2, [r3]
38
39 /* Enable coherency on CPU - Atomic */
40 add r3, r0, #ARMADA_XP_CFB_CFG_REG_OFFSET
41 ldr r2, [r3]
42 orr r2, r2, r1
43 str r2, [r3]
44
45 dsb
46
47 mov r0, #0
48 mov pc, lr
49ENDPROC(ll_set_cpu_coherent)
diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h
index 02f89eaa25fe..aa27bc2ffb60 100644
--- a/arch/arm/mach-mvebu/common.h
+++ b/arch/arm/mach-mvebu/common.h
@@ -20,4 +20,9 @@ void mvebu_restart(char mode, const char *cmd);
20void armada_370_xp_init_irq(void); 20void armada_370_xp_init_irq(void);
21void armada_370_xp_handle_irq(struct pt_regs *regs); 21void armada_370_xp_handle_irq(struct pt_regs *regs);
22 22
23void armada_xp_cpu_die(unsigned int cpu);
24int armada_370_xp_coherency_init(void);
25int armada_370_xp_pmsu_init(void);
26void armada_xp_secondary_startup(void);
27extern struct smp_operations armada_xp_smp_ops;
23#endif 28#endif
diff --git a/arch/arm/mach-mvebu/headsmp.S b/arch/arm/mach-mvebu/headsmp.S
new file mode 100644
index 000000000000..a06e0ede8c08
--- /dev/null
+++ b/arch/arm/mach-mvebu/headsmp.S
@@ -0,0 +1,49 @@
1/*
2 * SMP support: Entry point for secondary CPUs
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Yehuda Yitschak <yehuday@marvell.com>
7 * Gregory CLEMENT <gregory.clement@free-electrons.com>
8 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
9 *
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
13 *
14 * This file implements the assembly entry point for secondary CPUs in
15 * an SMP kernel. The only thing we need to do is to add the CPU to
16 * the coherency fabric by writing to 2 registers. Currently the base
17 * register addresses are hard coded due to the early initialisation
18 * problems.
19 */
20
21#include <linux/linkage.h>
22#include <linux/init.h>
23
24/*
25 * At this stage the secondary CPUs don't have acces yet to the MMU, so
26 * we have to provide physical addresses
27 */
28#define ARMADA_XP_CFB_BASE 0xD0020200
29
30 __CPUINIT
31
32/*
33 * Armada XP specific entry point for secondary CPUs.
34 * We add the CPU to the coherency fabric and then jump to secondary
35 * startup
36 */
37ENTRY(armada_xp_secondary_startup)
38
39 /* Read CPU id */
40 mrc p15, 0, r1, c0, c0, 5
41 and r1, r1, #0xF
42
43 /* Add CPU to coherency fabric */
44 ldr r0, =ARMADA_XP_CFB_BASE
45
46 bl ll_set_cpu_coherent
47 b secondary_startup
48
49ENDPROC(armada_xp_secondary_startup)
diff --git a/arch/arm/mach-mvebu/hotplug.c b/arch/arm/mach-mvebu/hotplug.c
new file mode 100644
index 000000000000..b228b6a80c85
--- /dev/null
+++ b/arch/arm/mach-mvebu/hotplug.c
@@ -0,0 +1,30 @@
1/*
2 * Symmetric Multi Processing (SMP) support for Armada XP
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Lior Amsalem <alior@marvell.com>
7 * Gregory CLEMENT <gregory.clement@free-electrons.com>
8 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
9 *
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
13 */
14#include <linux/kernel.h>
15#include <linux/errno.h>
16#include <linux/smp.h>
17#include <asm/proc-fns.h>
18
19/*
20 * platform-specific code to shutdown a CPU
21 *
22 * Called with IRQs disabled
23 */
24void __ref armada_xp_cpu_die(unsigned int cpu)
25{
26 cpu_do_idle();
27
28 /* We should never return from idle */
29 panic("mvebu: cpu %d unexpectedly exit from shutdown\n", cpu);
30}
diff --git a/arch/arm/mach-mvebu/irq-armada-370-xp.c b/arch/arm/mach-mvebu/irq-armada-370-xp.c
index 5f5f9394b6b2..549b6846f940 100644
--- a/arch/arm/mach-mvebu/irq-armada-370-xp.c
+++ b/arch/arm/mach-mvebu/irq-armada-370-xp.c
@@ -24,6 +24,7 @@
24#include <linux/irqdomain.h> 24#include <linux/irqdomain.h>
25#include <asm/mach/arch.h> 25#include <asm/mach/arch.h>
26#include <asm/exception.h> 26#include <asm/exception.h>
27#include <asm/smp_plat.h>
27 28
28/* Interrupt Controller Registers Map */ 29/* Interrupt Controller Registers Map */
29#define ARMADA_370_XP_INT_SET_MASK_OFFS (0x48) 30#define ARMADA_370_XP_INT_SET_MASK_OFFS (0x48)
@@ -35,6 +36,12 @@
35 36
36#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) 37#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44)
37 38
39#define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x4)
40#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc)
41#define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS (0x8)
42
43#define ACTIVE_DOORBELLS (8)
44
38static void __iomem *per_cpu_int_base; 45static void __iomem *per_cpu_int_base;
39static void __iomem *main_int_base; 46static void __iomem *main_int_base;
40static struct irq_domain *armada_370_xp_mpic_domain; 47static struct irq_domain *armada_370_xp_mpic_domain;
@@ -51,11 +58,22 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
51 per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); 58 per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
52} 59}
53 60
61#ifdef CONFIG_SMP
62static int armada_xp_set_affinity(struct irq_data *d,
63 const struct cpumask *mask_val, bool force)
64{
65 return 0;
66}
67#endif
68
54static struct irq_chip armada_370_xp_irq_chip = { 69static struct irq_chip armada_370_xp_irq_chip = {
55 .name = "armada_370_xp_irq", 70 .name = "armada_370_xp_irq",
56 .irq_mask = armada_370_xp_irq_mask, 71 .irq_mask = armada_370_xp_irq_mask,
57 .irq_mask_ack = armada_370_xp_irq_mask, 72 .irq_mask_ack = armada_370_xp_irq_mask,
58 .irq_unmask = armada_370_xp_irq_unmask, 73 .irq_unmask = armada_370_xp_irq_unmask,
74#ifdef CONFIG_SMP
75 .irq_set_affinity = armada_xp_set_affinity,
76#endif
59}; 77};
60 78
61static int armada_370_xp_mpic_irq_map(struct irq_domain *h, 79static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
@@ -72,6 +90,41 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
72 return 0; 90 return 0;
73} 91}
74 92
93#ifdef CONFIG_SMP
94void armada_mpic_send_doorbell(const struct cpumask *mask, unsigned int irq)
95{
96 int cpu;
97 unsigned long map = 0;
98
99 /* Convert our logical CPU mask into a physical one. */
100 for_each_cpu(cpu, mask)
101 map |= 1 << cpu_logical_map(cpu);
102
103 /*
104 * Ensure that stores to Normal memory are visible to the
105 * other CPUs before issuing the IPI.
106 */
107 dsb();
108
109 /* submit softirq */
110 writel((map << 8) | irq, main_int_base +
111 ARMADA_370_XP_SW_TRIG_INT_OFFS);
112}
113
114void armada_xp_mpic_smp_cpu_init(void)
115{
116 /* Clear pending IPIs */
117 writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
118
119 /* Enable first 8 IPIs */
120 writel((1 << ACTIVE_DOORBELLS) - 1, per_cpu_int_base +
121 ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
122
123 /* Unmask IPI interrupt */
124 writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
125}
126#endif /* CONFIG_SMP */
127
75static struct irq_domain_ops armada_370_xp_mpic_irq_ops = { 128static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
76 .map = armada_370_xp_mpic_irq_map, 129 .map = armada_370_xp_mpic_irq_map,
77 .xlate = irq_domain_xlate_onecell, 130 .xlate = irq_domain_xlate_onecell,
@@ -91,13 +144,18 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
91 control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL); 144 control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL);
92 145
93 armada_370_xp_mpic_domain = 146 armada_370_xp_mpic_domain =
94 irq_domain_add_linear(node, (control >> 2) & 0x3ff, 147 irq_domain_add_linear(node, (control >> 2) & 0x3ff,
95 &armada_370_xp_mpic_irq_ops, NULL); 148 &armada_370_xp_mpic_irq_ops, NULL);
96 149
97 if (!armada_370_xp_mpic_domain) 150 if (!armada_370_xp_mpic_domain)
98 panic("Unable to add Armada_370_Xp MPIC irq domain (DT)\n"); 151 panic("Unable to add Armada_370_Xp MPIC irq domain (DT)\n");
99 152
100 irq_set_default_host(armada_370_xp_mpic_domain); 153 irq_set_default_host(armada_370_xp_mpic_domain);
154
155#ifdef CONFIG_SMP
156 armada_xp_mpic_smp_cpu_init();
157#endif
158
101 return 0; 159 return 0;
102} 160}
103 161
@@ -111,14 +169,36 @@ asmlinkage void __exception_irq_entry armada_370_xp_handle_irq(struct pt_regs
111 ARMADA_370_XP_CPU_INTACK_OFFS); 169 ARMADA_370_XP_CPU_INTACK_OFFS);
112 irqnr = irqstat & 0x3FF; 170 irqnr = irqstat & 0x3FF;
113 171
114 if (irqnr < 1023) { 172 if (irqnr > 1022)
115 irqnr = 173 break;
116 irq_find_mapping(armada_370_xp_mpic_domain, irqnr); 174
175 if (irqnr >= 8) {
176 irqnr = irq_find_mapping(armada_370_xp_mpic_domain,
177 irqnr);
117 handle_IRQ(irqnr, regs); 178 handle_IRQ(irqnr, regs);
118 continue; 179 continue;
119 } 180 }
181#ifdef CONFIG_SMP
182 /* IPI Handling */
183 if (irqnr == 0) {
184 u32 ipimask, ipinr;
185
186 ipimask = readl_relaxed(per_cpu_int_base +
187 ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
188 & 0xFF;
189
190 writel(0x0, per_cpu_int_base +
191 ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
192
193 /* Handle all pending doorbells */
194 for (ipinr = 0; ipinr < ACTIVE_DOORBELLS; ipinr++) {
195 if (ipimask & (0x1 << ipinr))
196 handle_IPI(ipinr, regs);
197 }
198 continue;
199 }
200#endif
120 201
121 break;
122 } while (1); 202 } while (1);
123} 203}
124 204
diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c
new file mode 100644
index 000000000000..fe16aaf7c19c
--- /dev/null
+++ b/arch/arm/mach-mvebu/platsmp.c
@@ -0,0 +1,122 @@
1/*
2 * Symmetric Multi Processing (SMP) support for Armada XP
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Lior Amsalem <alior@marvell.com>
7 * Yehuda Yitschak <yehuday@marvell.com>
8 * Gregory CLEMENT <gregory.clement@free-electrons.com>
9 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
10 *
11 * This file is licensed under the terms of the GNU General Public
12 * License version 2. This program is licensed "as is" without any
13 * warranty of any kind, whether express or implied.
14 *
15 * The Armada XP SoC has 4 ARMv7 PJ4B CPUs running in full HW coherency
16 * This file implements the routines for preparing the SMP infrastructure
17 * and waking up the secondary CPUs
18 */
19
20#include <linux/init.h>
21#include <linux/smp.h>
22#include <linux/clk.h>
23#include <linux/of.h>
24#include <asm/cacheflush.h>
25#include <asm/smp_plat.h>
26#include "common.h"
27#include "armada-370-xp.h"
28#include "pmsu.h"
29#include "coherency.h"
30
31void __init set_secondary_cpus_clock(void)
32{
33 int thiscpu;
34 unsigned long rate;
35 struct clk *cpu_clk = NULL;
36 struct device_node *np = NULL;
37
38 thiscpu = smp_processor_id();
39 for_each_node_by_type(np, "cpu") {
40 int err;
41 int cpu;
42
43 err = of_property_read_u32(np, "reg", &cpu);
44 if (WARN_ON(err))
45 return;
46
47 if (cpu == thiscpu) {
48 cpu_clk = of_clk_get(np, 0);
49 break;
50 }
51 }
52 if (WARN_ON(IS_ERR(cpu_clk)))
53 return;
54 clk_prepare_enable(cpu_clk);
55 rate = clk_get_rate(cpu_clk);
56
57 /* set all the other CPU clk to the same rate than the boot CPU */
58 for_each_node_by_type(np, "cpu") {
59 int err;
60 int cpu;
61
62 err = of_property_read_u32(np, "reg", &cpu);
63 if (WARN_ON(err))
64 return;
65
66 if (cpu != thiscpu) {
67 cpu_clk = of_clk_get(np, 0);
68 clk_set_rate(cpu_clk, rate);
69 }
70 }
71}
72
73static void __cpuinit armada_xp_secondary_init(unsigned int cpu)
74{
75 armada_xp_mpic_smp_cpu_init();
76}
77
78static int __cpuinit armada_xp_boot_secondary(unsigned int cpu,
79 struct task_struct *idle)
80{
81 pr_info("Booting CPU %d\n", cpu);
82
83 armada_xp_boot_cpu(cpu, armada_xp_secondary_startup);
84
85 return 0;
86}
87
88static void __init armada_xp_smp_init_cpus(void)
89{
90 unsigned int i, ncores;
91 ncores = coherency_get_cpu_count();
92
93 /* Limit possible CPUs to defconfig */
94 if (ncores > nr_cpu_ids) {
95 pr_warn("SMP: %d CPUs physically present. Only %d configured.",
96 ncores, nr_cpu_ids);
97 pr_warn("Clipping CPU count to %d\n", nr_cpu_ids);
98 ncores = nr_cpu_ids;
99 }
100
101 for (i = 0; i < ncores; i++)
102 set_cpu_possible(i, true);
103
104 set_smp_cross_call(armada_mpic_send_doorbell);
105}
106
107void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
108{
109 set_secondary_cpus_clock();
110 flush_cache_all();
111 set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
112}
113
114struct smp_operations armada_xp_smp_ops __initdata = {
115 .smp_init_cpus = armada_xp_smp_init_cpus,
116 .smp_prepare_cpus = armada_xp_smp_prepare_cpus,
117 .smp_secondary_init = armada_xp_secondary_init,
118 .smp_boot_secondary = armada_xp_boot_secondary,
119#ifdef CONFIG_HOTPLUG_CPU
120 .cpu_die = armada_xp_cpu_die,
121#endif
122};
diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c
new file mode 100644
index 000000000000..3cc4bef6401c
--- /dev/null
+++ b/arch/arm/mach-mvebu/pmsu.c
@@ -0,0 +1,75 @@
1/*
2 * Power Management Service Unit(PMSU) support for Armada 370/XP platforms.
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Yehuda Yitschak <yehuday@marvell.com>
7 * Gregory Clement <gregory.clement@free-electrons.com>
8 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
9 *
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
13 *
14 * The Armada 370 and Armada XP SOCs have a power management service
15 * unit which is responsible for powering down and waking up CPUs and
16 * other SOC units
17 */
18
19#include <linux/kernel.h>
20#include <linux/init.h>
21#include <linux/of_address.h>
22#include <linux/io.h>
23#include <linux/smp.h>
24#include <asm/smp_plat.h>
25
26static void __iomem *pmsu_mp_base;
27static void __iomem *pmsu_reset_base;
28
29#define PMSU_BOOT_ADDR_REDIRECT_OFFSET(cpu) ((cpu * 0x100) + 0x24)
30#define PMSU_RESET_CTL_OFFSET(cpu) (cpu * 0x8)
31
32static struct of_device_id of_pmsu_table[] = {
33 {.compatible = "marvell,armada-370-xp-pmsu"},
34 { /* end of list */ },
35};
36
37#ifdef CONFIG_SMP
38int armada_xp_boot_cpu(unsigned int cpu_id, void *boot_addr)
39{
40 int reg, hw_cpu;
41
42 if (!pmsu_mp_base || !pmsu_reset_base) {
43 pr_warn("Can't boot CPU. PMSU is uninitialized\n");
44 return 1;
45 }
46
47 hw_cpu = cpu_logical_map(cpu_id);
48
49 writel(virt_to_phys(boot_addr), pmsu_mp_base +
50 PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu));
51
52 /* Release CPU from reset by clearing reset bit*/
53 reg = readl(pmsu_reset_base + PMSU_RESET_CTL_OFFSET(hw_cpu));
54 reg &= (~0x1);
55 writel(reg, pmsu_reset_base + PMSU_RESET_CTL_OFFSET(hw_cpu));
56
57 return 0;
58}
59#endif
60
61int __init armada_370_xp_pmsu_init(void)
62{
63 struct device_node *np;
64
65 np = of_find_matching_node(NULL, of_pmsu_table);
66 if (np) {
67 pr_info("Initializing Power Management Service Unit\n");
68 pmsu_mp_base = of_iomap(np, 0);
69 pmsu_reset_base = of_iomap(np, 1);
70 }
71
72 return 0;
73}
74
75early_initcall(armada_370_xp_pmsu_init);
diff --git a/arch/arm/mach-mvebu/pmsu.h b/arch/arm/mach-mvebu/pmsu.h
new file mode 100644
index 000000000000..07a737c6b95d
--- /dev/null
+++ b/arch/arm/mach-mvebu/pmsu.h
@@ -0,0 +1,16 @@
1/*
2 * Power Management Service Unit (PMSU) support for Armada 370/XP platforms.
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10
11#ifndef __MACH_MVEBU_PMSU_H
12#define __MACH_MVEBU_PMSU_H
13
14int armada_xp_boot_cpu(unsigned int cpu_id, void *phys_addr);
15
16#endif /* __MACH_370_XP_PMSU_H */
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 94186b6c685f..3fd629d5a513 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -352,6 +352,10 @@ config CPU_PJ4
352 select ARM_THUMBEE 352 select ARM_THUMBEE
353 select CPU_V7 353 select CPU_V7
354 354
355config CPU_PJ4B
356 bool
357 select CPU_V7
358
355# ARMv6 359# ARMv6
356config CPU_V6 360config CPU_V6
357 bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX 361 bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 58bc3e4d3bd0..5383bc018571 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -124,8 +124,6 @@ static void arm_dma_sync_single_for_device(struct device *dev,
124 __dma_page_cpu_to_dev(page, offset, size, dir); 124 __dma_page_cpu_to_dev(page, offset, size, dir);
125} 125}
126 126
127static int arm_dma_set_mask(struct device *dev, u64 dma_mask);
128
129struct dma_map_ops arm_dma_ops = { 127struct dma_map_ops arm_dma_ops = {
130 .alloc = arm_dma_alloc, 128 .alloc = arm_dma_alloc,
131 .free = arm_dma_free, 129 .free = arm_dma_free,
@@ -971,7 +969,7 @@ int dma_supported(struct device *dev, u64 mask)
971} 969}
972EXPORT_SYMBOL(dma_supported); 970EXPORT_SYMBOL(dma_supported);
973 971
974static int arm_dma_set_mask(struct device *dev, u64 dma_mask) 972int arm_dma_set_mask(struct device *dev, u64 dma_mask)
975{ 973{
976 if (!dev->dma_mask || !dma_supported(dev, dma_mask)) 974 if (!dev->dma_mask || !dma_supported(dev, dma_mask))
977 return -EIO; 975 return -EIO;
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 846d279f3176..7cd0028cab8e 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -169,6 +169,63 @@ __v7_ca15mp_setup:
169 orreq r0, r0, r10 @ Enable CPU-specific SMP bits 169 orreq r0, r0, r10 @ Enable CPU-specific SMP bits
170 mcreq p15, 0, r0, c1, c0, 1 170 mcreq p15, 0, r0, c1, c0, 1
171#endif 171#endif
172
173__v7_pj4b_setup:
174#ifdef CONFIG_CPU_PJ4B
175
176/* Auxiliary Debug Modes Control 1 Register */
177#define PJ4B_STATIC_BP (1 << 2) /* Enable Static BP */
178#define PJ4B_INTER_PARITY (1 << 8) /* Disable Internal Parity Handling */
179#define PJ4B_BCK_OFF_STREX (1 << 5) /* Enable the back off of STREX instr */
180#define PJ4B_CLEAN_LINE (1 << 16) /* Disable data transfer for clean line */
181
182/* Auxiliary Debug Modes Control 2 Register */
183#define PJ4B_FAST_LDR (1 << 23) /* Disable fast LDR */
184#define PJ4B_SNOOP_DATA (1 << 25) /* Do not interleave write and snoop data */
185#define PJ4B_CWF (1 << 27) /* Disable Critical Word First feature */
186#define PJ4B_OUTSDNG_NC (1 << 29) /* Disable outstanding non cacheable rqst */
187#define PJ4B_L1_REP_RR (1 << 30) /* L1 replacement - Strict round robin */
188#define PJ4B_AUX_DBG_CTRL2 (PJ4B_SNOOP_DATA | PJ4B_CWF |\
189 PJ4B_OUTSDNG_NC | PJ4B_L1_REP_RR)
190
191/* Auxiliary Functional Modes Control Register 0 */
192#define PJ4B_SMP_CFB (1 << 1) /* Set SMP mode. Join the coherency fabric */
193#define PJ4B_L1_PAR_CHK (1 << 2) /* Support L1 parity checking */
194#define PJ4B_BROADCAST_CACHE (1 << 8) /* Broadcast Cache and TLB maintenance */
195
196/* Auxiliary Debug Modes Control 0 Register */
197#define PJ4B_WFI_WFE (1 << 22) /* WFI/WFE - serve the DVM and back to idle */
198
199 /* Auxiliary Debug Modes Control 1 Register */
200 mrc p15, 1, r0, c15, c1, 1
201 orr r0, r0, #PJ4B_CLEAN_LINE
202 orr r0, r0, #PJ4B_BCK_OFF_STREX
203 orr r0, r0, #PJ4B_INTER_PARITY
204 bic r0, r0, #PJ4B_STATIC_BP
205 mcr p15, 1, r0, c15, c1, 1
206
207 /* Auxiliary Debug Modes Control 2 Register */
208 mrc p15, 1, r0, c15, c1, 2
209 bic r0, r0, #PJ4B_FAST_LDR
210 orr r0, r0, #PJ4B_AUX_DBG_CTRL2
211 mcr p15, 1, r0, c15, c1, 2
212
213 /* Auxiliary Functional Modes Control Register 0 */
214 mrc p15, 1, r0, c15, c2, 0
215#ifdef CONFIG_SMP
216 orr r0, r0, #PJ4B_SMP_CFB
217#endif
218 orr r0, r0, #PJ4B_L1_PAR_CHK
219 orr r0, r0, #PJ4B_BROADCAST_CACHE
220 mcr p15, 1, r0, c15, c2, 0
221
222 /* Auxiliary Debug Modes Control 0 Register */
223 mrc p15, 1, r0, c15, c1, 0
224 orr r0, r0, #PJ4B_WFI_WFE
225 mcr p15, 1, r0, c15, c1, 0
226
227#endif /* CONFIG_CPU_PJ4B */
228
172__v7_setup: 229__v7_setup:
173 adr r12, __v7_setup_stack @ the local stack 230 adr r12, __v7_setup_stack @ the local stack
174 stmia r12, {r0-r5, r7, r9, r11, lr} 231 stmia r12, {r0-r5, r7, r9, r11, lr}
@@ -342,6 +399,16 @@ __v7_ca9mp_proc_info:
342 .long 0xff0ffff0 399 .long 0xff0ffff0
343 __v7_proc __v7_ca9mp_setup 400 __v7_proc __v7_ca9mp_setup
344 .size __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info 401 .size __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
402
403 /*
404 * Marvell PJ4B processor.
405 */
406 .type __v7_pj4b_proc_info, #object
407__v7_pj4b_proc_info:
408 .long 0x562f5840
409 .long 0xfffffff0
410 __v7_proc __v7_pj4b_setup
411 .size __v7_pj4b_proc_info, . - __v7_pj4b_proc_info
345#endif /* CONFIG_ARM_LPAE */ 412#endif /* CONFIG_ARM_LPAE */
346 413
347 /* 414 /*
diff --git a/arch/arm/plat-orion/addr-map.c b/arch/arm/plat-orion/addr-map.c
index a7b8060c293a..febe3862873c 100644
--- a/arch/arm/plat-orion/addr-map.c
+++ b/arch/arm/plat-orion/addr-map.c
@@ -42,6 +42,8 @@ EXPORT_SYMBOL_GPL(mv_mbus_dram_info);
42#define WIN_REMAP_LO_OFF 0x0008 42#define WIN_REMAP_LO_OFF 0x0008
43#define WIN_REMAP_HI_OFF 0x000c 43#define WIN_REMAP_HI_OFF 0x000c
44 44
45#define ATTR_HW_COHERENCY (0x1 << 4)
46
45/* 47/*
46 * Default implementation 48 * Default implementation
47 */ 49 */
@@ -163,6 +165,8 @@ void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
163 w = &orion_mbus_dram_info.cs[cs++]; 165 w = &orion_mbus_dram_info.cs[cs++];
164 w->cs_index = i; 166 w->cs_index = i;
165 w->mbus_attr = 0xf & ~(1 << i); 167 w->mbus_attr = 0xf & ~(1 << i);
168 if (cfg->hw_io_coherency)
169 w->mbus_attr |= ATTR_HW_COHERENCY;
166 w->base = base & 0xffff0000; 170 w->base = base & 0xffff0000;
167 w->size = (size | 0x0000ffff) + 1; 171 w->size = (size | 0x0000ffff) + 1;
168 } 172 }
diff --git a/arch/arm/plat-orion/include/plat/addr-map.h b/arch/arm/plat-orion/include/plat/addr-map.h
index ec63e4a627d0..b76c06569fe5 100644
--- a/arch/arm/plat-orion/include/plat/addr-map.h
+++ b/arch/arm/plat-orion/include/plat/addr-map.h
@@ -17,6 +17,7 @@ struct orion_addr_map_cfg {
17 const int num_wins; /* Total number of windows */ 17 const int num_wins; /* Total number of windows */
18 const int remappable_wins; 18 const int remappable_wins;
19 void __iomem *bridge_virt_base; 19 void __iomem *bridge_virt_base;
20 int hw_io_coherency;
20 21
21 /* If NULL, the default cpu_win_can_remap will be used, using 22 /* If NULL, the default cpu_win_can_remap will be used, using
22 the value in remappable_wins */ 23 the value in remappable_wins */