diff options
author | Gregory CLEMENT <gregory.clement@free-electrons.com> | 2012-08-02 04:16:29 -0400 |
---|---|---|
committer | Gregory CLEMENT <gregory.clement@free-electrons.com> | 2012-11-21 10:49:06 -0500 |
commit | 009f13159bfdccd6e06fe3b62a39fee6dce26c39 (patch) | |
tree | 681d68bde140a819f18af537a51131c850dc8edb /arch/arm/mach-mvebu | |
parent | 1611f872513735ac7105535689c0dd668fbf1c04 (diff) |
arm: mvebu: Add support for coherency fabric in mach-mvebu
The Armada 370 and Armada XP SOCs have a coherency fabric unit which
is responsible for ensuring hardware coherency between all CPUs and
between CPUs and I/O masters. This patch provides the basic support
needed for SMP.
Signed-off-by: Yehuda Yitschak <yehuday@marvell.com>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Reviewed-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm/mach-mvebu')
-rw-r--r-- | arch/arm/mach-mvebu/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/coherency.c | 82 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/coherency.h | 24 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/coherency_ll.S | 49 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/common.h | 1 |
5 files changed, 157 insertions, 1 deletions
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index 57f996b6aa0e..5ce4b42c2697 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile | |||
@@ -2,4 +2,4 @@ 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 | ||
4 | obj-y += system-controller.o | 4 | obj-y += system-controller.o |
5 | obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o | 5 | obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o |
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c new file mode 100644 index 000000000000..596ee66a9cc4 --- /dev/null +++ b/arch/arm/mach-mvebu/coherency.c | |||
@@ -0,0 +1,82 @@ | |||
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 <asm/smp_plat.h> | ||
26 | #include "armada-370-xp.h" | ||
27 | |||
28 | /* | ||
29 | * Some functions in this file are called very early during SMP | ||
30 | * initialization. At that time the device tree framework is not yet | ||
31 | * ready, and it is not possible to get the register address to | ||
32 | * ioremap it. That's why the pointer below is given with an initial | ||
33 | * value matching its virtual mapping | ||
34 | */ | ||
35 | static void __iomem *coherency_base = ARMADA_370_XP_REGS_VIRT_BASE + 0x20200; | ||
36 | |||
37 | /* Coherency fabric registers */ | ||
38 | #define COHERENCY_FABRIC_CFG_OFFSET 0x4 | ||
39 | |||
40 | static struct of_device_id of_coherency_table[] = { | ||
41 | {.compatible = "marvell,coherency-fabric"}, | ||
42 | { /* end of list */ }, | ||
43 | }; | ||
44 | |||
45 | #ifdef CONFIG_SMP | ||
46 | int coherency_get_cpu_count(void) | ||
47 | { | ||
48 | int reg, cnt; | ||
49 | |||
50 | reg = readl(coherency_base + COHERENCY_FABRIC_CFG_OFFSET); | ||
51 | cnt = (reg & 0xF) + 1; | ||
52 | |||
53 | return cnt; | ||
54 | } | ||
55 | #endif | ||
56 | |||
57 | /* Function defined in coherency_ll.S */ | ||
58 | int ll_set_cpu_coherent(void __iomem *base_addr, unsigned int hw_cpu_id); | ||
59 | |||
60 | int set_cpu_coherent(unsigned int hw_cpu_id, int smp_group_id) | ||
61 | { | ||
62 | if (!coherency_base) { | ||
63 | pr_warn("Can't make CPU %d cache coherent.\n", hw_cpu_id); | ||
64 | pr_warn("Coherency fabric is not initialized\n"); | ||
65 | return 1; | ||
66 | } | ||
67 | |||
68 | return ll_set_cpu_coherent(coherency_base, hw_cpu_id); | ||
69 | } | ||
70 | |||
71 | int __init coherency_init(void) | ||
72 | { | ||
73 | struct device_node *np; | ||
74 | |||
75 | np = of_find_matching_node(NULL, of_coherency_table); | ||
76 | if (np) { | ||
77 | pr_info("Initializing Coherency fabric\n"); | ||
78 | coherency_base = of_iomap(np, 0); | ||
79 | } | ||
80 | |||
81 | return 0; | ||
82 | } | ||
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 | ||
18 | int coherency_get_cpu_count(void); | ||
19 | #endif | ||
20 | |||
21 | int set_cpu_coherent(int cpu_id, int smp_group_id); | ||
22 | int 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 | */ | ||
28 | ENTRY(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 | ||
49 | ENDPROC(ll_set_cpu_coherent) | ||
diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h index 02f89eaa25fe..ba6b62a42f52 100644 --- a/arch/arm/mach-mvebu/common.h +++ b/arch/arm/mach-mvebu/common.h | |||
@@ -20,4 +20,5 @@ void mvebu_restart(char mode, const char *cmd); | |||
20 | void armada_370_xp_init_irq(void); | 20 | void armada_370_xp_init_irq(void); |
21 | void armada_370_xp_handle_irq(struct pt_regs *regs); | 21 | void armada_370_xp_handle_irq(struct pt_regs *regs); |
22 | 22 | ||
23 | int armada_370_xp_coherency_init(void); | ||
23 | #endif | 24 | #endif |