aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-bcm/platsmp-brcmstb.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-bcm/platsmp-brcmstb.c')
-rw-r--r--arch/arm/mach-bcm/platsmp-brcmstb.c85
1 files changed, 63 insertions, 22 deletions
diff --git a/arch/arm/mach-bcm/platsmp-brcmstb.c b/arch/arm/mach-bcm/platsmp-brcmstb.c
index 31c87a284a34..e209e6fc7caf 100644
--- a/arch/arm/mach-bcm/platsmp-brcmstb.c
+++ b/arch/arm/mach-bcm/platsmp-brcmstb.c
@@ -17,6 +17,7 @@
17#include <linux/errno.h> 17#include <linux/errno.h>
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/io.h> 19#include <linux/io.h>
20#include <linux/jiffies.h>
20#include <linux/of_address.h> 21#include <linux/of_address.h>
21#include <linux/of_platform.h> 22#include <linux/of_platform.h>
22#include <linux/printk.h> 23#include <linux/printk.h>
@@ -94,10 +95,35 @@ static u32 pwr_ctrl_rd(u32 cpu)
94 return readl_relaxed(base); 95 return readl_relaxed(base);
95} 96}
96 97
97static void pwr_ctrl_wr(u32 cpu, u32 val) 98static void pwr_ctrl_set(unsigned int cpu, u32 val, u32 mask)
98{ 99{
99 void __iomem *base = pwr_ctrl_get_base(cpu); 100 void __iomem *base = pwr_ctrl_get_base(cpu);
100 writel(val, base); 101 writel((readl(base) & mask) | val, base);
102}
103
104static void pwr_ctrl_clr(unsigned int cpu, u32 val, u32 mask)
105{
106 void __iomem *base = pwr_ctrl_get_base(cpu);
107 writel((readl(base) & mask) & ~val, base);
108}
109
110#define POLL_TMOUT_MS 500
111static int pwr_ctrl_wait_tmout(unsigned int cpu, u32 set, u32 mask)
112{
113 const unsigned long timeo = jiffies + msecs_to_jiffies(POLL_TMOUT_MS);
114 u32 tmp;
115
116 do {
117 tmp = pwr_ctrl_rd(cpu) & mask;
118 if (!set == !tmp)
119 return 0;
120 } while (time_before(jiffies, timeo));
121
122 tmp = pwr_ctrl_rd(cpu) & mask;
123 if (!set == !tmp)
124 return 0;
125
126 return -ETIMEDOUT;
101} 127}
102 128
103static void cpu_rst_cfg_set(u32 cpu, int set) 129static void cpu_rst_cfg_set(u32 cpu, int set)
@@ -139,15 +165,22 @@ static void brcmstb_cpu_power_on(u32 cpu)
139 * The secondary cores power was cut, so we must go through 165 * The secondary cores power was cut, so we must go through
140 * power-on initialization. 166 * power-on initialization.
141 */ 167 */
142 u32 tmp; 168 pwr_ctrl_set(cpu, ZONE_MAN_ISO_CNTL_MASK, 0xffffff00);
169 pwr_ctrl_set(cpu, ZONE_MANUAL_CONTROL_MASK, -1);
170 pwr_ctrl_set(cpu, ZONE_RESERVED_1_MASK, -1);
143 171
144 /* Request zone power up */ 172 pwr_ctrl_set(cpu, ZONE_MAN_MEM_PWR_MASK, -1);
145 pwr_ctrl_wr(cpu, ZONE_PWR_UP_REQ_MASK);
146 173
147 /* Wait for the power up FSM to complete */ 174 if (pwr_ctrl_wait_tmout(cpu, 1, ZONE_MEM_PWR_STATE_MASK))
148 do { 175 panic("ZONE_MEM_PWR_STATE_MASK set timeout");
149 tmp = pwr_ctrl_rd(cpu); 176
150 } while (!(tmp & ZONE_PWR_ON_STATE_MASK)); 177 pwr_ctrl_set(cpu, ZONE_MAN_CLKEN_MASK, -1);
178
179 if (pwr_ctrl_wait_tmout(cpu, 1, ZONE_DPG_PWR_STATE_MASK))
180 panic("ZONE_DPG_PWR_STATE_MASK set timeout");
181
182 pwr_ctrl_clr(cpu, ZONE_MAN_ISO_CNTL_MASK, -1);
183 pwr_ctrl_set(cpu, ZONE_MAN_RESET_CNTL_MASK, -1);
151} 184}
152 185
153static int brcmstb_cpu_get_power_state(u32 cpu) 186static int brcmstb_cpu_get_power_state(u32 cpu)
@@ -174,25 +207,33 @@ static void brcmstb_cpu_die(u32 cpu)
174 207
175static int brcmstb_cpu_kill(u32 cpu) 208static int brcmstb_cpu_kill(u32 cpu)
176{ 209{
177 u32 tmp; 210 /*
211 * Ordinarily, the hardware forbids power-down of CPU0 (which is good
212 * because it is the boot CPU), but this is not true when using BPCM
213 * manual mode. Consequently, we must avoid turning off CPU0 here to
214 * ensure that TI2C master reset will work.
215 */
216 if (cpu == 0) {
217 pr_warn("SMP: refusing to power off CPU0\n");
218 return 1;
219 }
178 220
179 while (per_cpu_sw_state_rd(cpu)) 221 while (per_cpu_sw_state_rd(cpu))
180 ; 222 ;
181 223
182 /* Program zone reset */ 224 pwr_ctrl_set(cpu, ZONE_MANUAL_CONTROL_MASK, -1);
183 pwr_ctrl_wr(cpu, ZONE_RESET_STATE_MASK | ZONE_BLK_RST_ASSERT_MASK | 225 pwr_ctrl_clr(cpu, ZONE_MAN_RESET_CNTL_MASK, -1);
184 ZONE_PWR_DN_REQ_MASK); 226 pwr_ctrl_clr(cpu, ZONE_MAN_CLKEN_MASK, -1);
227 pwr_ctrl_set(cpu, ZONE_MAN_ISO_CNTL_MASK, -1);
228 pwr_ctrl_clr(cpu, ZONE_MAN_MEM_PWR_MASK, -1);
185 229
186 /* Verify zone reset */ 230 if (pwr_ctrl_wait_tmout(cpu, 0, ZONE_MEM_PWR_STATE_MASK))
187 tmp = pwr_ctrl_rd(cpu); 231 panic("ZONE_MEM_PWR_STATE_MASK clear timeout");
188 if (!(tmp & ZONE_RESET_STATE_MASK))
189 pr_err("%s: Zone reset bit for CPU %d not asserted!\n",
190 __func__, cpu);
191 232
192 /* Wait for power down */ 233 pwr_ctrl_clr(cpu, ZONE_RESERVED_1_MASK, -1);
193 do { 234
194 tmp = pwr_ctrl_rd(cpu); 235 if (pwr_ctrl_wait_tmout(cpu, 0, ZONE_DPG_PWR_STATE_MASK))
195 } while (!(tmp & ZONE_PWR_OFF_STATE_MASK)); 236 panic("ZONE_DPG_PWR_STATE_MASK clear timeout");
196 237
197 /* Flush pipeline before resetting CPU */ 238 /* Flush pipeline before resetting CPU */
198 mb(); 239 mb();