aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mvebu/board-v7.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mvebu/board-v7.c')
-rw-r--r--arch/arm/mach-mvebu/board-v7.c89
1 files changed, 84 insertions, 5 deletions
diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
index 333fca8fdc41..8bb742fdf5ca 100644
--- a/arch/arm/mach-mvebu/board-v7.c
+++ b/arch/arm/mach-mvebu/board-v7.c
@@ -27,12 +27,30 @@
27#include <asm/mach/arch.h> 27#include <asm/mach/arch.h>
28#include <asm/mach/map.h> 28#include <asm/mach/map.h>
29#include <asm/mach/time.h> 29#include <asm/mach/time.h>
30#include <asm/smp_scu.h>
30#include "armada-370-xp.h" 31#include "armada-370-xp.h"
31#include "common.h" 32#include "common.h"
32#include "coherency.h" 33#include "coherency.h"
33#include "mvebu-soc-id.h" 34#include "mvebu-soc-id.h"
34 35
35/* 36/*
37 * Enables the SCU when available. Obviously, this is only useful on
38 * Cortex-A based SOCs, not on PJ4B based ones.
39 */
40static void __init mvebu_scu_enable(void)
41{
42 void __iomem *scu_base;
43
44 struct device_node *np =
45 of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
46 if (np) {
47 scu_base = of_iomap(np, 0);
48 scu_enable(scu_base);
49 of_node_put(np);
50 }
51}
52
53/*
36 * Early versions of Armada 375 SoC have a bug where the BootROM 54 * Early versions of Armada 375 SoC have a bug where the BootROM
37 * leaves an external data abort pending. The kernel is hit by this 55 * leaves an external data abort pending. The kernel is hit by this
38 * data abort as soon as it enters userspace, because it unmasks the 56 * data abort as soon as it enters userspace, because it unmasks the
@@ -57,11 +75,9 @@ static void __init mvebu_timer_and_clk_init(void)
57{ 75{
58 of_clk_init(NULL); 76 of_clk_init(NULL);
59 clocksource_of_init(); 77 clocksource_of_init();
78 mvebu_scu_enable();
60 coherency_init(); 79 coherency_init();
61 BUG_ON(mvebu_mbus_dt_init()); 80 BUG_ON(mvebu_mbus_dt_init(coherency_available()));
62#ifdef CONFIG_CACHE_L2X0
63 l2x0_of_init(0, ~0UL);
64#endif
65 81
66 if (of_machine_is_compatible("marvell,armada375")) 82 if (of_machine_is_compatible("marvell,armada375"))
67 hook_fault_code(16 + 6, armada_375_external_abort_wa, SIGBUS, 0, 83 hook_fault_code(16 + 6, armada_375_external_abort_wa, SIGBUS, 0,
@@ -78,7 +94,7 @@ static void __init i2c_quirk(void)
78 * mechanism. We can exit only if we are sure that we can 94 * mechanism. We can exit only if we are sure that we can
79 * get the SoC revision and it is more recent than A0. 95 * get the SoC revision and it is more recent than A0.
80 */ 96 */
81 if (mvebu_get_soc_id(&rev, &dev) == 0 && dev > MV78XX0_A0_REV) 97 if (mvebu_get_soc_id(&dev, &rev) == 0 && rev > MV78XX0_A0_REV)
82 return; 98 return;
83 99
84 for_each_compatible_node(np, NULL, "marvell,mv78230-i2c") { 100 for_each_compatible_node(np, NULL, "marvell,mv78230-i2c") {
@@ -96,10 +112,66 @@ static void __init i2c_quirk(void)
96 return; 112 return;
97} 113}
98 114
115#define A375_Z1_THERMAL_FIXUP_OFFSET 0xc
116
117static void __init thermal_quirk(void)
118{
119 struct device_node *np;
120 u32 dev, rev;
121
122 if (mvebu_get_soc_id(&dev, &rev) == 0 && rev > ARMADA_375_Z1_REV)
123 return;
124
125 for_each_compatible_node(np, NULL, "marvell,armada375-thermal") {
126 struct property *prop;
127 __be32 newval, *newprop, *oldprop;
128 int len;
129
130 /*
131 * The register offset is at a wrong location. This quirk
132 * creates a new reg property as a clone of the previous
133 * one and corrects the offset.
134 */
135 oldprop = (__be32 *)of_get_property(np, "reg", &len);
136 if (!oldprop)
137 continue;
138
139 /* Create a duplicate of the 'reg' property */
140 prop = kzalloc(sizeof(*prop), GFP_KERNEL);
141 prop->length = len;
142 prop->name = kstrdup("reg", GFP_KERNEL);
143 prop->value = kzalloc(len, GFP_KERNEL);
144 memcpy(prop->value, oldprop, len);
145
146 /* Fixup the register offset of the second entry */
147 oldprop += 2;
148 newprop = (__be32 *)prop->value + 2;
149 newval = cpu_to_be32(be32_to_cpu(*oldprop) -
150 A375_Z1_THERMAL_FIXUP_OFFSET);
151 *newprop = newval;
152 of_update_property(np, prop);
153
154 /*
155 * The thermal controller needs some quirk too, so let's change
156 * the compatible string to reflect this.
157 */
158 prop = kzalloc(sizeof(*prop), GFP_KERNEL);
159 prop->name = kstrdup("compatible", GFP_KERNEL);
160 prop->length = sizeof("marvell,armada375-z1-thermal");
161 prop->value = kstrdup("marvell,armada375-z1-thermal",
162 GFP_KERNEL);
163 of_update_property(np, prop);
164 }
165 return;
166}
167
99static void __init mvebu_dt_init(void) 168static void __init mvebu_dt_init(void)
100{ 169{
101 if (of_machine_is_compatible("plathome,openblocks-ax3-4")) 170 if (of_machine_is_compatible("plathome,openblocks-ax3-4"))
102 i2c_quirk(); 171 i2c_quirk();
172 if (of_machine_is_compatible("marvell,a375-db"))
173 thermal_quirk();
174
103 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); 175 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
104} 176}
105 177
@@ -109,6 +181,8 @@ static const char * const armada_370_xp_dt_compat[] = {
109}; 181};
110 182
111DT_MACHINE_START(ARMADA_370_XP_DT, "Marvell Armada 370/XP (Device Tree)") 183DT_MACHINE_START(ARMADA_370_XP_DT, "Marvell Armada 370/XP (Device Tree)")
184 .l2c_aux_val = 0,
185 .l2c_aux_mask = ~0,
112 .smp = smp_ops(armada_xp_smp_ops), 186 .smp = smp_ops(armada_xp_smp_ops),
113 .init_machine = mvebu_dt_init, 187 .init_machine = mvebu_dt_init,
114 .init_time = mvebu_timer_and_clk_init, 188 .init_time = mvebu_timer_and_clk_init,
@@ -122,7 +196,10 @@ static const char * const armada_375_dt_compat[] = {
122}; 196};
123 197
124DT_MACHINE_START(ARMADA_375_DT, "Marvell Armada 375 (Device Tree)") 198DT_MACHINE_START(ARMADA_375_DT, "Marvell Armada 375 (Device Tree)")
199 .l2c_aux_val = 0,
200 .l2c_aux_mask = ~0,
125 .init_time = mvebu_timer_and_clk_init, 201 .init_time = mvebu_timer_and_clk_init,
202 .init_machine = mvebu_dt_init,
126 .restart = mvebu_restart, 203 .restart = mvebu_restart,
127 .dt_compat = armada_375_dt_compat, 204 .dt_compat = armada_375_dt_compat,
128MACHINE_END 205MACHINE_END
@@ -134,6 +211,8 @@ static const char * const armada_38x_dt_compat[] = {
134}; 211};
135 212
136DT_MACHINE_START(ARMADA_38X_DT, "Marvell Armada 380/385 (Device Tree)") 213DT_MACHINE_START(ARMADA_38X_DT, "Marvell Armada 380/385 (Device Tree)")
214 .l2c_aux_val = 0,
215 .l2c_aux_mask = ~0,
137 .init_time = mvebu_timer_and_clk_init, 216 .init_time = mvebu_timer_and_clk_init,
138 .restart = mvebu_restart, 217 .restart = mvebu_restart,
139 .dt_compat = armada_38x_dt_compat, 218 .dt_compat = armada_38x_dt_compat,