Blame view

arch/arm/mach-exynos/platsmp.c 9.88 KB
347863d47   Krzysztof Kozlowski   ARM: EXYNOS: Add ...
1
2
3
4
5
6
7
8
  // SPDX-License-Identifier: GPL-2.0
  // Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  //		http://www.samsung.com
  //
  // Cloned from linux/arch/arm/mach-vexpress/platsmp.c
  //
  //  Copyright (C) 2002 ARM Ltd.
  //  All Rights Reserved
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
9
10
11
12
  
  #include <linux/init.h>
  #include <linux/errno.h>
  #include <linux/delay.h>
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
13
14
15
  #include <linux/jiffies.h>
  #include <linux/smp.h>
  #include <linux/io.h>
b3205dea8   Sachin Kamat   ARM: EXYNOS: Map ...
16
  #include <linux/of_address.h>
2262d6ef5   Pankaj Dubey   ARM: EXYNOS: Move...
17
  #include <linux/soc/samsung/exynos-regs-pmu.h>
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
18
19
  
  #include <asm/cacheflush.h>
6f0b7c0c6   Krzysztof Kozlowski   ARM: EXYNOS: Move...
20
  #include <asm/cp15.h>
eb50439b9   Will Deacon   ARM: 7293/1: logi...
21
  #include <asm/smp_plat.h>
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
22
  #include <asm/smp_scu.h>
beddf63fc   Tomasz Figa   ARM: EXYNOS: Add ...
23
  #include <asm/firmware.h>
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
24

06853ae47   Marc Zyngier   ARM: SoC: convert...
25
  #include "common.h"
7d30e8b38   Kukjin Kim   ARM: EXYNOS4: Add...
26
  extern void exynos4_secondary_startup(void);
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
27

6213f70e7   Russell King   ARM: smp: remove ...
28
29
  /* XXX exynos_pen_release is cargo culted code - DO NOT COPY XXX */
  volatile int exynos_pen_release = -1;
6f0b7c0c6   Krzysztof Kozlowski   ARM: EXYNOS: Move...
30
  #ifdef CONFIG_HOTPLUG_CPU
13cfa6c4f   Krzysztof Kozlowski   ARM: EXYNOS: Fix ...
31
  static inline void cpu_leave_lowpower(u32 core_id)
6f0b7c0c6   Krzysztof Kozlowski   ARM: EXYNOS: Move...
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  {
  	unsigned int v;
  
  	asm volatile(
  	"mrc	p15, 0, %0, c1, c0, 0
  "
  	"	orr	%0, %0, %1
  "
  	"	mcr	p15, 0, %0, c1, c0, 0
  "
  	"	mrc	p15, 0, %0, c1, c0, 1
  "
  	"	orr	%0, %0, %2
  "
  	"	mcr	p15, 0, %0, c1, c0, 1
  "
  	  : "=&r" (v)
  	  : "Ir" (CR_C), "Ir" (0x40)
  	  : "cc");
  }
  
  static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
  {
  	u32 mpidr = cpu_logical_map(cpu);
  	u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
  
  	for (;;) {
  
  		/* Turn the CPU off on next WFI instruction. */
  		exynos_cpu_power_down(core_id);
  
  		wfi();
6213f70e7   Russell King   ARM: smp: remove ...
64
  		if (exynos_pen_release == core_id) {
6f0b7c0c6   Krzysztof Kozlowski   ARM: EXYNOS: Move...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  			/*
  			 * OK, proper wakeup, we're done
  			 */
  			break;
  		}
  
  		/*
  		 * Getting here, means that we have come out of WFI without
  		 * having been woken up - this shouldn't happen
  		 *
  		 * Just note it happening - when we're woken, we can report
  		 * its occurrence.
  		 */
  		(*spurious)++;
  	}
  }
  #endif /* CONFIG_HOTPLUG_CPU */
7310d99ff   Krzysztof Kozlowski   ARM: EXYNOS: Fix ...
82
83
84
85
86
87
88
89
90
91
  /**
   * exynos_core_power_down : power down the specified cpu
   * @cpu : the cpu to power down
   *
   * Power down the specified cpu. The sequence must be finished by a
   * call to cpu_do_idle()
   *
   */
  void exynos_cpu_power_down(int cpu)
  {
497ab3b30   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: fix ...
92
  	u32 core_conf;
ca489c58e   Krzysztof Kozlowski   ARM: EXYNOS: Don'...
93
  	if (cpu == 0 && (soc_is_exynos5420() || soc_is_exynos5800())) {
adc548d77   Abhilash Kesavan   ARM: EXYNOS: Use ...
94
95
96
97
98
99
100
101
102
103
  		/*
  		 * Bypass power down for CPU0 during suspend. Check for
  		 * the SYS_PWR_REG value to decide if we are suspending
  		 * the system.
  		 */
  		int val = pmu_raw_readl(EXYNOS5_ARM_CORE0_SYS_PWR_REG);
  
  		if (!(val & S5P_CORE_LOCAL_PWR_EN))
  			return;
  	}
497ab3b30   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: fix ...
104
105
106
107
  
  	core_conf = pmu_raw_readl(EXYNOS_ARM_CORE_CONFIGURATION(cpu));
  	core_conf &= ~S5P_CORE_LOCAL_PWR_EN;
  	pmu_raw_writel(core_conf, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
7310d99ff   Krzysztof Kozlowski   ARM: EXYNOS: Fix ...
108
109
110
111
112
113
114
115
116
117
  }
  
  /**
   * exynos_cpu_power_up : power up the specified cpu
   * @cpu : the cpu to power up
   *
   * Power up the specified cpu
   */
  void exynos_cpu_power_up(int cpu)
  {
497ab3b30   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: fix ...
118
119
120
121
122
123
  	u32 core_conf = S5P_CORE_LOCAL_PWR_EN;
  
  	if (soc_is_exynos3250())
  		core_conf |= S5P_CORE_AUTOWAKEUP_EN;
  
  	pmu_raw_writel(core_conf,
944483d03   Arnd Bergmann   Merge branch 'nex...
124
  			EXYNOS_ARM_CORE_CONFIGURATION(cpu));
7310d99ff   Krzysztof Kozlowski   ARM: EXYNOS: Fix ...
125
126
127
128
129
130
131
132
133
  }
  
  /**
   * exynos_cpu_power_state : returns the power state of the cpu
   * @cpu : the cpu to retrieve the power state from
   *
   */
  int exynos_cpu_power_state(int cpu)
  {
944483d03   Arnd Bergmann   Merge branch 'nex...
134
  	return (pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(cpu)) &
7310d99ff   Krzysztof Kozlowski   ARM: EXYNOS: Fix ...
135
136
137
138
139
140
141
142
143
  			S5P_CORE_LOCAL_PWR_EN);
  }
  
  /**
   * exynos_cluster_power_down : power down the specified cluster
   * @cluster : the cluster to power down
   */
  void exynos_cluster_power_down(int cluster)
  {
944483d03   Arnd Bergmann   Merge branch 'nex...
144
  	pmu_raw_writel(0, EXYNOS_COMMON_CONFIGURATION(cluster));
7310d99ff   Krzysztof Kozlowski   ARM: EXYNOS: Fix ...
145
146
147
148
149
150
151
152
  }
  
  /**
   * exynos_cluster_power_up : power up the specified cluster
   * @cluster : the cluster to power up
   */
  void exynos_cluster_power_up(int cluster)
  {
944483d03   Arnd Bergmann   Merge branch 'nex...
153
154
  	pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
  			EXYNOS_COMMON_CONFIGURATION(cluster));
7310d99ff   Krzysztof Kozlowski   ARM: EXYNOS: Fix ...
155
156
157
158
159
160
161
162
163
  }
  
  /**
   * exynos_cluster_power_state : returns the power state of the cluster
   * @cluster : the cluster to retrieve the power state from
   *
   */
  int exynos_cluster_power_state(int cluster)
  {
944483d03   Arnd Bergmann   Merge branch 'nex...
164
165
  	return (pmu_raw_readl(EXYNOS_COMMON_STATUS(cluster)) &
  		S5P_CORE_LOCAL_PWR_EN);
7310d99ff   Krzysztof Kozlowski   ARM: EXYNOS: Fix ...
166
  }
3c33710b4   Pankaj Dubey   ARM: exynos: Remo...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  /**
   * exynos_scu_enable : enables SCU for Cortex-A9 based system
   */
  void exynos_scu_enable(void)
  {
  	struct device_node *np;
  	static void __iomem *scu_base;
  
  	if (!scu_base) {
  		np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
  		if (np) {
  			scu_base = of_iomap(np, 0);
  			of_node_put(np);
  		} else {
  			scu_base = ioremap(scu_a9_get_base(), SZ_4K);
  		}
  	}
  	scu_enable(scu_base);
  }
af9971144   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: add ...
186
  static void __iomem *cpu_boot_reg_base(void)
1f054f52e   Tomasz Figa   ARM: EXYNOS: Add ...
187
  {
edaff7e1c   Arnd Bergmann   ARM: exynos: use ...
188
  	if (soc_is_exynos4210() && exynos_rev() == EXYNOS4210_REV_1_1)
2e94ac428   Pankaj Dubey   ARM: EXYNOS: Refa...
189
  		return pmu_base_addr + S5P_INFORM5;
b3205dea8   Sachin Kamat   ARM: EXYNOS: Map ...
190
  	return sysram_base_addr;
1f054f52e   Tomasz Figa   ARM: EXYNOS: Add ...
191
192
193
194
195
196
197
  }
  
  static inline void __iomem *cpu_boot_reg(int cpu)
  {
  	void __iomem *boot_reg;
  
  	boot_reg = cpu_boot_reg_base();
b3205dea8   Sachin Kamat   ARM: EXYNOS: Map ...
198
  	if (!boot_reg)
2cc6b8135   Krzysztof Kozlowski   ARM: EXYNOS: Use ...
199
  		return IOMEM_ERR_PTR(-ENODEV);
1f054f52e   Tomasz Figa   ARM: EXYNOS: Add ...
200
201
  	if (soc_is_exynos4412())
  		boot_reg += 4*cpu;
86c6f1488   Arun Kumar K   ARM: EXYNOS: Add ...
202
  	else if (soc_is_exynos5420() || soc_is_exynos5800())
1580be3d3   Chander Kashyap   ARM: EXYNOS: add ...
203
  		boot_reg += 4;
1f054f52e   Tomasz Figa   ARM: EXYNOS: Add ...
204
205
  	return boot_reg;
  }
911c29b0e   JungHi Min   ARM: EXYNOS4: Add...
206

2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
207
  /*
b588aaec6   Krzysztof Kozlowski   ARM: EXYNOS: SWRE...
208
209
210
211
   * Set wake up by local power mode and execute software reset for given core.
   *
   * Currently this is needed only when booting secondary CPU on Exynos3250.
   */
af9971144   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: add ...
212
  void exynos_core_restart(u32 core_id)
b588aaec6   Krzysztof Kozlowski   ARM: EXYNOS: SWRE...
213
  {
98a3308ea   Marek Szyprowski   ARM: exynos: Fix ...
214
  	unsigned int timeout = 16;
b588aaec6   Krzysztof Kozlowski   ARM: EXYNOS: SWRE...
215
216
217
218
  	u32 val;
  
  	if (!of_machine_is_compatible("samsung,exynos3250"))
  		return;
98a3308ea   Marek Szyprowski   ARM: exynos: Fix ...
219
220
  	while (timeout && !pmu_raw_readl(S5P_PMU_SPARE2)) {
  		timeout--;
497ab3b30   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: fix ...
221
  		udelay(10);
98a3308ea   Marek Szyprowski   ARM: exynos: Fix ...
222
223
224
225
226
227
  	}
  	if (timeout == 0) {
  		pr_err("cpu core %u restart failed
  ", core_id);
  		return;
  	}
497ab3b30   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: fix ...
228
  	udelay(10);
b588aaec6   Krzysztof Kozlowski   ARM: EXYNOS: SWRE...
229
230
231
  	val = pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(core_id));
  	val |= S5P_CORE_WAKEUP_FROM_LOCAL_CFG;
  	pmu_raw_writel(val, EXYNOS_ARM_CORE_STATUS(core_id));
b588aaec6   Krzysztof Kozlowski   ARM: EXYNOS: SWRE...
232
233
234
235
  	pmu_raw_writel(EXYNOS_CORE_PO_RESET(core_id), EXYNOS_SWRESET);
  }
  
  /*
6213f70e7   Russell King   ARM: smp: remove ...
236
237
238
239
   * XXX CARGO CULTED CODE - DO NOT COPY XXX
   *
   * Write exynos_pen_release in a way that is guaranteed to be visible to
   * all observers, irrespective of whether they're taking part in coherency
3705ff6da   Russell King   ARM: Fix subtle r...
240
241
   * or not.  This is necessary for the hotplug code to work reliably.
   */
6213f70e7   Russell King   ARM: smp: remove ...
242
  static void exynos_write_pen_release(int val)
3705ff6da   Russell King   ARM: Fix subtle r...
243
  {
6213f70e7   Russell King   ARM: smp: remove ...
244
  	exynos_pen_release = val;
3705ff6da   Russell King   ARM: Fix subtle r...
245
  	smp_wmb();
6213f70e7   Russell King   ARM: smp: remove ...
246
  	sync_cache_w(&exynos_pen_release);
3705ff6da   Russell King   ARM: Fix subtle r...
247
  }
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
248
  static DEFINE_SPINLOCK(boot_lock);
8bd26e3a7   Paul Gortmaker   arm: delete __cpu...
249
  static void exynos_secondary_init(unsigned int cpu)
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
250
  {
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
251
  	/*
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
252
253
254
  	 * let the primary processor know we're out of the
  	 * pen, then head off into the C entry point
  	 */
6213f70e7   Russell King   ARM: smp: remove ...
255
  	exynos_write_pen_release(-1);
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
256
257
258
259
260
261
262
  
  	/*
  	 * Synchronise with the boot thread.
  	 */
  	spin_lock(&boot_lock);
  	spin_unlock(&boot_lock);
  }
af9971144   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: add ...
263
  int exynos_set_boot_addr(u32 core_id, unsigned long boot_addr)
955d4cf82   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: add ...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
  {
  	int ret;
  
  	/*
  	 * Try to set boot address using firmware first
  	 * and fall back to boot register if it fails.
  	 */
  	ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr);
  	if (ret && ret != -ENOSYS)
  		goto fail;
  	if (ret == -ENOSYS) {
  		void __iomem *boot_reg = cpu_boot_reg(core_id);
  
  		if (IS_ERR(boot_reg)) {
  			ret = PTR_ERR(boot_reg);
  			goto fail;
  		}
458ad21df   Ben Dooks   ARM: EXYNOS: Fixu...
281
  		writel_relaxed(boot_addr, boot_reg);
955d4cf82   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: add ...
282
283
284
285
286
  		ret = 0;
  	}
  fail:
  	return ret;
  }
af9971144   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: add ...
287
  int exynos_get_boot_addr(u32 core_id, unsigned long *boot_addr)
1225ad728   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: add ...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
  {
  	int ret;
  
  	/*
  	 * Try to get boot address using firmware first
  	 * and fall back to boot register if it fails.
  	 */
  	ret = call_firmware_op(get_cpu_boot_addr, core_id, boot_addr);
  	if (ret && ret != -ENOSYS)
  		goto fail;
  	if (ret == -ENOSYS) {
  		void __iomem *boot_reg = cpu_boot_reg(core_id);
  
  		if (IS_ERR(boot_reg)) {
  			ret = PTR_ERR(boot_reg);
  			goto fail;
  		}
458ad21df   Ben Dooks   ARM: EXYNOS: Fixu...
305
  		*boot_addr = readl_relaxed(boot_reg);
1225ad728   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: add ...
306
307
308
309
310
  		ret = 0;
  	}
  fail:
  	return ret;
  }
8bd26e3a7   Paul Gortmaker   arm: delete __cpu...
311
  static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
312
313
  {
  	unsigned long timeout;
9637f30e6   Tomasz Figa   ARM: EXYNOS: Fix ...
314
315
  	u32 mpidr = cpu_logical_map(cpu);
  	u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
b3205dea8   Sachin Kamat   ARM: EXYNOS: Map ...
316
  	int ret = -ENOSYS;
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
317
318
319
320
321
322
323
324
325
326
  
  	/*
  	 * Set synchronisation state between this boot processor
  	 * and the secondary one
  	 */
  	spin_lock(&boot_lock);
  
  	/*
  	 * The secondary processor is waiting to be released from
  	 * the holding pen - release it, then wait for it to flag
6213f70e7   Russell King   ARM: smp: remove ...
327
  	 * that it has been released by resetting exynos_pen_release.
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
328
  	 *
6213f70e7   Russell King   ARM: smp: remove ...
329
  	 * Note that "exynos_pen_release" is the hardware CPU core ID, whereas
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
330
331
  	 * "cpu" is Linux's internal ID.
  	 */
6213f70e7   Russell King   ARM: smp: remove ...
332
  	exynos_write_pen_release(core_id);
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
333

9637f30e6   Tomasz Figa   ARM: EXYNOS: Fix ...
334
335
  	if (!exynos_cpu_power_state(core_id)) {
  		exynos_cpu_power_up(core_id);
911c29b0e   JungHi Min   ARM: EXYNOS4: Add...
336
337
338
  		timeout = 10;
  
  		/* wait max 10 ms until cpu1 is on */
9637f30e6   Tomasz Figa   ARM: EXYNOS: Fix ...
339
340
  		while (exynos_cpu_power_state(core_id)
  		       != S5P_CORE_LOCAL_PWR_EN) {
4bdf2f3f2   Stuart Menefy   ARM: exynos: Fix ...
341
  			if (timeout == 0)
911c29b0e   JungHi Min   ARM: EXYNOS4: Add...
342
  				break;
4bdf2f3f2   Stuart Menefy   ARM: exynos: Fix ...
343
  			timeout--;
911c29b0e   JungHi Min   ARM: EXYNOS4: Add...
344
345
346
347
348
349
350
351
352
  			mdelay(1);
  		}
  
  		if (timeout == 0) {
  			printk(KERN_ERR "cpu1 power enable failed");
  			spin_unlock(&boot_lock);
  			return -ETIMEDOUT;
  		}
  	}
b588aaec6   Krzysztof Kozlowski   ARM: EXYNOS: SWRE...
353
354
  
  	exynos_core_restart(core_id);
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
355
356
357
358
359
  	/*
  	 * Send the secondary CPU a soft interrupt, thereby causing
  	 * the boot monitor to read the system wide flags register,
  	 * and branch to the address found there.
  	 */
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
360
361
362
  
  	timeout = jiffies + (1 * HZ);
  	while (time_before(jiffies, timeout)) {
beddf63fc   Tomasz Figa   ARM: EXYNOS: Add ...
363
  		unsigned long boot_addr;
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
364
  		smp_rmb();
911c29b0e   JungHi Min   ARM: EXYNOS4: Add...
365

64fc2a947   Florian Fainelli   ARM: 8641/1: tree...
366
  		boot_addr = __pa_symbol(exynos4_secondary_startup);
beddf63fc   Tomasz Figa   ARM: EXYNOS: Add ...
367

955d4cf82   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: add ...
368
369
  		ret = exynos_set_boot_addr(core_id, boot_addr);
  		if (ret)
b3205dea8   Sachin Kamat   ARM: EXYNOS: Map ...
370
  			goto fail;
beddf63fc   Tomasz Figa   ARM: EXYNOS: Add ...
371

9637f30e6   Tomasz Figa   ARM: EXYNOS: Fix ...
372
  		call_firmware_op(cpu_boot, core_id);
beddf63fc   Tomasz Figa   ARM: EXYNOS: Add ...
373

497ab3b30   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: fix ...
374
375
376
377
  		if (soc_is_exynos3250())
  			dsb_sev();
  		else
  			arch_send_wakeup_ipi_mask(cpumask_of(cpu));
911c29b0e   JungHi Min   ARM: EXYNOS4: Add...
378

6213f70e7   Russell King   ARM: smp: remove ...
379
  		if (exynos_pen_release == -1)
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
380
381
382
383
  			break;
  
  		udelay(10);
  	}
6213f70e7   Russell King   ARM: smp: remove ...
384
  	if (exynos_pen_release != -1)
9f294c178   Bartlomiej Zolnierkiewicz   ARM: EXYNOS: fix ...
385
  		ret = -ETIMEDOUT;
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
386
387
388
389
  	/*
  	 * now the secondary core is starting up let it run its
  	 * calibrations, then wait for it to finish
  	 */
b3205dea8   Sachin Kamat   ARM: EXYNOS: Map ...
390
  fail:
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
391
  	spin_unlock(&boot_lock);
6213f70e7   Russell King   ARM: smp: remove ...
392
  	return exynos_pen_release != -1 ? ret : 0;
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
393
  }
06853ae47   Marc Zyngier   ARM: SoC: convert...
394
  static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
395
  {
1754c42e3   Olof Johansson   ARM: exynos: move...
396
  	exynos_sysram_init();
6f024978e   Krzysztof Kozlowski   ARM: EXYNOS: Fix ...
397
  	exynos_set_delayed_reset_assertion(true);
af040ffc9   Russell King   ARM: make it easi...
398
  	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
3c33710b4   Pankaj Dubey   ARM: exynos: Remo...
399
  		exynos_scu_enable();
2b12b5c4f   Changhwan Youn   ARM: S5PV310: Add...
400
  }
06853ae47   Marc Zyngier   ARM: SoC: convert...
401

6f0b7c0c6   Krzysztof Kozlowski   ARM: EXYNOS: Move...
402
403
404
405
406
407
  #ifdef CONFIG_HOTPLUG_CPU
  /*
   * platform-specific code to shutdown a CPU
   *
   * Called with IRQs disabled
   */
27b9ee852   Krzysztof Kozlowski   ARM: EXYNOS: Remo...
408
  static void exynos_cpu_die(unsigned int cpu)
6f0b7c0c6   Krzysztof Kozlowski   ARM: EXYNOS: Move...
409
410
  {
  	int spurious = 0;
13cfa6c4f   Krzysztof Kozlowski   ARM: EXYNOS: Fix ...
411
412
  	u32 mpidr = cpu_logical_map(cpu);
  	u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
6f0b7c0c6   Krzysztof Kozlowski   ARM: EXYNOS: Move...
413
414
415
416
417
418
419
420
421
  
  	v7_exit_coherency_flush(louis);
  
  	platform_do_lowpower(cpu, &spurious);
  
  	/*
  	 * bring this CPU back into the world of cache
  	 * coherency, and then restore interrupts
  	 */
13cfa6c4f   Krzysztof Kozlowski   ARM: EXYNOS: Fix ...
422
  	cpu_leave_lowpower(core_id);
6f0b7c0c6   Krzysztof Kozlowski   ARM: EXYNOS: Move...
423
424
425
426
427
428
  
  	if (spurious)
  		pr_warn("CPU%u: %u spurious wakeup calls
  ", cpu, spurious);
  }
  #endif /* CONFIG_HOTPLUG_CPU */
75305275a   Masahiro Yamada   ARM: use const an...
429
  const struct smp_operations exynos_smp_ops __initconst = {
06853ae47   Marc Zyngier   ARM: SoC: convert...
430
431
432
433
434
435
436
  	.smp_prepare_cpus	= exynos_smp_prepare_cpus,
  	.smp_secondary_init	= exynos_secondary_init,
  	.smp_boot_secondary	= exynos_boot_secondary,
  #ifdef CONFIG_HOTPLUG_CPU
  	.cpu_die		= exynos_cpu_die,
  #endif
  };