aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m32r/kernel/smpboot.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2018-03-07 15:36:19 -0500
committerArnd Bergmann <arnd@arndb.de>2018-03-09 17:20:00 -0500
commit553b085c2075f6a4a2591108554f830fa61e881f (patch)
tree68d63911f2c12e0fb9fa23498df9300442a88f92 /arch/m32r/kernel/smpboot.c
parentfd8773f9f544955f6f47dc2ac3ab85ad64376b7f (diff)
arch: remove m32r port
The Mitsubishi/Renesas m32r architecture has been around for many years, but the Linux port has been obsolete for a very long time as well, with the last significant updates done for linux-2.6.14. While some m32r microcontrollers are still being marketed by Renesas, those are apparently no longer possible to support, mainly due to the lack of an external memory interface. Hirokazu Takata was the maintainer until the architecture got marked Orphaned in 2014. Link: http://www.linux-m32r.org/ Link: https://www.renesas.com/en-eu/products/microcontrollers-microprocessors/m32r.html Cc: Hirokazu Takata <takata@linux-m32r.org> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/m32r/kernel/smpboot.c')
-rw-r--r--arch/m32r/kernel/smpboot.c627
1 files changed, 0 insertions, 627 deletions
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
deleted file mode 100644
index a7d04684d2c7..000000000000
--- a/arch/m32r/kernel/smpboot.c
+++ /dev/null
@@ -1,627 +0,0 @@
1/*
2 * linux/arch/m32r/kernel/smpboot.c
3 * orig : i386 2.4.10
4 *
5 * M32R SMP booting functions
6 *
7 * Copyright (c) 2001, 2002, 2003 Hitoshi Yamamoto
8 *
9 * Taken from i386 version.
10 * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
11 * (c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
12 *
13 * Much of the core SMP work is based on previous work by Thomas Radke, to
14 * whom a great many thanks are extended.
15 *
16 * Thanks to Intel for making available several different Pentium,
17 * Pentium Pro and Pentium-II/Xeon MP machines.
18 * Original development of Linux SMP code supported by Caldera.
19 *
20 * This code is released under the GNU General Public License version 2 or
21 * later.
22 *
23 * Fixes
24 * Felix Koop : NR_CPUS used properly
25 * Jose Renau : Handle single CPU case.
26 * Alan Cox : By repeated request
27 * 8) - Total BogoMIP report.
28 * Greg Wright : Fix for kernel stacks panic.
29 * Erich Boleyn : MP v1.4 and additional changes.
30 * Matthias Sattler : Changes for 2.1 kernel map.
31 * Michel Lespinasse : Changes for 2.1 kernel map.
32 * Michael Chastain : Change trampoline.S to gnu as.
33 * Alan Cox : Dumb bug: 'B' step PPro's are fine
34 * Ingo Molnar : Added APIC timers, based on code
35 * from Jose Renau
36 * Ingo Molnar : various cleanups and rewrites
37 * Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug.
38 * Maciej W. Rozycki : Bits for genuine 82489DX APICs
39 * Martin J. Bligh : Added support for multi-quad systems
40 */
41
42#include <linux/module.h>
43#include <linux/cpu.h>
44#include <linux/init.h>
45#include <linux/kernel.h>
46#include <linux/mm.h>
47#include <linux/sched.h>
48#include <linux/sched/task.h>
49#include <linux/err.h>
50#include <linux/irq.h>
51#include <linux/bootmem.h>
52#include <linux/delay.h>
53
54#include <asm/io.h>
55#include <asm/pgalloc.h>
56#include <asm/tlbflush.h>
57
58#define DEBUG_SMP
59#ifdef DEBUG_SMP
60#define Dprintk(x...) printk(x)
61#else
62#define Dprintk(x...)
63#endif
64
65extern cpumask_t cpu_initialized;
66
67/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
68/* Data structures and variables */
69/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
70
71/* Processor that is doing the boot up */
72static unsigned int bsp_phys_id = -1;
73
74/* Bitmask of physically existing CPUs */
75physid_mask_t phys_cpu_present_map;
76
77cpumask_t cpu_bootout_map;
78cpumask_t cpu_bootin_map;
79static cpumask_t cpu_callin_map;
80cpumask_t cpu_callout_map;
81EXPORT_SYMBOL(cpu_callout_map);
82
83/* Per CPU bogomips and other parameters */
84struct cpuinfo_m32r cpu_data[NR_CPUS] __cacheline_aligned;
85
86static int cpucount;
87static cpumask_t smp_commenced_mask;
88
89extern struct {
90 void * spi;
91 unsigned short ss;
92} stack_start;
93
94/* which physical physical ID maps to which logical CPU number */
95static volatile int physid_2_cpu[NR_CPUS];
96#define physid_to_cpu(physid) physid_2_cpu[physid]
97
98/* which logical CPU number maps to which physical ID */
99volatile int cpu_2_physid[NR_CPUS];
100
101DEFINE_PER_CPU(int, prof_multiplier) = 1;
102DEFINE_PER_CPU(int, prof_old_multiplier) = 1;
103DEFINE_PER_CPU(int, prof_counter) = 1;
104
105spinlock_t ipi_lock[NR_IPIS];
106
107static unsigned int calibration_result;
108
109/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
110/* Function Prototypes */
111/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
112
113static void init_ipi_lock(void);
114static void do_boot_cpu(int);
115
116int start_secondary(void *);
117static void smp_callin(void);
118static void smp_online(void);
119
120static void show_mp_info(int);
121static void smp_store_cpu_info(int);
122static void show_cpu_info(int);
123int setup_profiling_timer(unsigned int);
124static void init_cpu_to_physid(void);
125static void map_cpu_to_physid(int, int);
126static void unmap_cpu_to_physid(int, int);
127
128/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
129/* Boot up APs Routines : BSP */
130/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
131void smp_prepare_boot_cpu(void)
132{
133 bsp_phys_id = hard_smp_processor_id();
134 physid_set(bsp_phys_id, phys_cpu_present_map);
135 set_cpu_online(0, true); /* BSP's cpu_id == 0 */
136 cpumask_set_cpu(0, &cpu_callout_map);
137 cpumask_set_cpu(0, &cpu_callin_map);
138
139 /*
140 * Initialize the logical to physical CPU number mapping
141 */
142 init_cpu_to_physid();
143 map_cpu_to_physid(0, bsp_phys_id);
144 current_thread_info()->cpu = 0;
145}
146
147/*==========================================================================*
148 * Name: smp_prepare_cpus (old smp_boot_cpus)
149 *
150 * Description: This routine boot up APs.
151 *
152 * Born on Date: 2002.02.05
153 *
154 * Arguments: NONE
155 *
156 * Returns: void (cannot fail)
157 *
158 * Modification log:
159 * Date Who Description
160 * ---------- --- --------------------------------------------------------
161 * 2003-06-24 hy modify for linux-2.5.69
162 *
163 *==========================================================================*/
164void __init smp_prepare_cpus(unsigned int max_cpus)
165{
166 int phys_id;
167 unsigned long nr_cpu;
168
169 nr_cpu = inl(M32R_FPGA_NUM_OF_CPUS_PORTL);
170 if (nr_cpu > NR_CPUS) {
171 printk(KERN_INFO "NUM_OF_CPUS reg. value [%ld] > NR_CPU [%d]",
172 nr_cpu, NR_CPUS);
173 goto smp_done;
174 }
175 for (phys_id = 0 ; phys_id < nr_cpu ; phys_id++)
176 physid_set(phys_id, phys_cpu_present_map);
177#ifndef CONFIG_HOTPLUG_CPU
178 init_cpu_present(cpu_possible_mask);
179#endif
180
181 show_mp_info(nr_cpu);
182
183 init_ipi_lock();
184
185 /*
186 * Setup boot CPU information
187 */
188 smp_store_cpu_info(0); /* Final full version of the data */
189
190 /*
191 * If SMP should be disabled, then really disable it!
192 */
193 if (!max_cpus) {
194 printk(KERN_INFO "SMP mode deactivated by commandline.\n");
195 goto smp_done;
196 }
197
198 /*
199 * Now scan the CPU present map and fire up the other CPUs.
200 */
201 Dprintk("CPU present map : %lx\n", physids_coerce(phys_cpu_present_map));
202
203 for (phys_id = 0 ; phys_id < NR_CPUS ; phys_id++) {
204 /*
205 * Don't even attempt to start the boot CPU!
206 */
207 if (phys_id == bsp_phys_id)
208 continue;
209
210 if (!physid_isset(phys_id, phys_cpu_present_map))
211 continue;
212
213 if (max_cpus <= cpucount + 1)
214 continue;
215
216 do_boot_cpu(phys_id);
217
218 /*
219 * Make sure we unmap all failed CPUs
220 */
221 if (physid_to_cpu(phys_id) == -1) {
222 physid_clear(phys_id, phys_cpu_present_map);
223 printk("phys CPU#%d not responding - " \
224 "cannot use it.\n", phys_id);
225 }
226 }
227
228smp_done:
229 Dprintk("Boot done.\n");
230}
231
232/*
233 * init_ipi_lock : Initialize IPI locks.
234 */
235static void __init init_ipi_lock(void)
236{
237 int ipi;
238
239 for (ipi = 0 ; ipi < NR_IPIS ; ipi++)
240 spin_lock_init(&ipi_lock[ipi]);
241}
242
243/*==========================================================================*
244 * Name: do_boot_cpu
245 *
246 * Description: This routine boot up one AP.
247 *
248 * Born on Date: 2002.02.05
249 *
250 * Arguments: phys_id - Target CPU physical ID
251 *
252 * Returns: void (cannot fail)
253 *
254 * Modification log:
255 * Date Who Description
256 * ---------- --- --------------------------------------------------------
257 * 2003-06-24 hy modify for linux-2.5.69
258 *
259 *==========================================================================*/
260static void __init do_boot_cpu(int phys_id)
261{
262 struct task_struct *idle;
263 unsigned long send_status, boot_status;
264 int timeout, cpu_id;
265
266 cpu_id = ++cpucount;
267
268 /*
269 * We can't use kernel_thread since we must avoid to
270 * reschedule the child.
271 */
272 idle = fork_idle(cpu_id);
273 if (IS_ERR(idle))
274 panic("failed fork for CPU#%d.", cpu_id);
275
276 idle->thread.lr = (unsigned long)start_secondary;
277
278 map_cpu_to_physid(cpu_id, phys_id);
279
280 /* So we see what's up */
281 printk("Booting processor %d/%d\n", phys_id, cpu_id);
282 stack_start.spi = (void *)idle->thread.sp;
283 task_thread_info(idle)->cpu = cpu_id;
284
285 /*
286 * Send Startup IPI
287 * 1.IPI received by CPU#(phys_id).
288 * 2.CPU#(phys_id) enter startup_AP (arch/m32r/kernel/head.S)
289 * 3.CPU#(phys_id) enter start_secondary()
290 */
291 send_status = 0;
292 boot_status = 0;
293
294 cpumask_set_cpu(phys_id, &cpu_bootout_map);
295
296 /* Send Startup IPI */
297 send_IPI_mask_phys(cpumask_of(phys_id), CPU_BOOT_IPI, 0);
298
299 Dprintk("Waiting for send to finish...\n");
300 timeout = 0;
301
302 /* Wait 100[ms] */
303 do {
304 Dprintk("+");
305 udelay(1000);
306 send_status = !cpumask_test_cpu(phys_id, &cpu_bootin_map);
307 } while (send_status && (timeout++ < 100));
308
309 Dprintk("After Startup.\n");
310
311 if (!send_status) {
312 /*
313 * allow APs to start initializing.
314 */
315 Dprintk("Before Callout %d.\n", cpu_id);
316 cpumask_set_cpu(cpu_id, &cpu_callout_map);
317 Dprintk("After Callout %d.\n", cpu_id);
318
319 /*
320 * Wait 5s total for a response
321 */
322 for (timeout = 0; timeout < 5000; timeout++) {
323 if (cpumask_test_cpu(cpu_id, &cpu_callin_map))
324 break; /* It has booted */
325 udelay(1000);
326 }
327
328 if (cpumask_test_cpu(cpu_id, &cpu_callin_map)) {
329 /* number CPUs logically, starting from 1 (BSP is 0) */
330 Dprintk("OK.\n");
331 } else {
332 boot_status = 1;
333 printk("Not responding.\n");
334 }
335 } else
336 printk("IPI never delivered???\n");
337
338 if (send_status || boot_status) {
339 unmap_cpu_to_physid(cpu_id, phys_id);
340 cpumask_clear_cpu(cpu_id, &cpu_callout_map);
341 cpumask_clear_cpu(cpu_id, &cpu_callin_map);
342 cpumask_clear_cpu(cpu_id, &cpu_initialized);
343 cpucount--;
344 }
345}
346
347int __cpu_up(unsigned int cpu_id, struct task_struct *tidle)
348{
349 int timeout;
350
351 cpumask_set_cpu(cpu_id, &smp_commenced_mask);
352
353 /*
354 * Wait 5s total for a response
355 */
356 for (timeout = 0; timeout < 5000; timeout++) {
357 if (cpu_online(cpu_id))
358 break;
359 udelay(1000);
360 }
361 if (!cpu_online(cpu_id))
362 BUG();
363
364 return 0;
365}
366
367void __init smp_cpus_done(unsigned int max_cpus)
368{
369 int cpu_id, timeout;
370 unsigned long bogosum = 0;
371
372 for (timeout = 0; timeout < 5000; timeout++) {
373 if (cpumask_equal(&cpu_callin_map, cpu_online_mask))
374 break;
375 udelay(1000);
376 }
377 if (!cpumask_equal(&cpu_callin_map, cpu_online_mask))
378 BUG();
379
380 for_each_online_cpu(cpu_id)
381 show_cpu_info(cpu_id);
382
383 /*
384 * Allow the user to impress friends.
385 */
386 Dprintk("Before bogomips.\n");
387 if (cpucount) {
388 for_each_cpu(cpu_id,cpu_online_mask)
389 bogosum += cpu_data[cpu_id].loops_per_jiffy;
390
391 printk(KERN_INFO "Total of %d processors activated " \
392 "(%lu.%02lu BogoMIPS).\n", cpucount + 1,
393 bogosum / (500000 / HZ),
394 (bogosum / (5000 / HZ)) % 100);
395 Dprintk("Before bogocount - setting activated=1.\n");
396 }
397}
398
399/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
400/* Activate a secondary processor Routines */
401/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
402
403/*==========================================================================*
404 * Name: start_secondary
405 *
406 * Description: This routine activate a secondary processor.
407 *
408 * Born on Date: 2002.02.05
409 *
410 * Arguments: *unused - currently unused.
411 *
412 * Returns: void (cannot fail)
413 *
414 * Modification log:
415 * Date Who Description
416 * ---------- --- --------------------------------------------------------
417 * 2003-06-24 hy modify for linux-2.5.69
418 *
419 *==========================================================================*/
420int __init start_secondary(void *unused)
421{
422 cpu_init();
423 preempt_disable();
424 smp_callin();
425 while (!cpumask_test_cpu(smp_processor_id(), &smp_commenced_mask))
426 cpu_relax();
427
428 smp_online();
429
430 /*
431 * low-memory mappings have been cleared, flush them from
432 * the local TLBs too.
433 */
434 local_flush_tlb_all();
435
436 cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
437 return 0;
438}
439
440/*==========================================================================*
441 * Name: smp_callin
442 *
443 * Description: This routine activate a secondary processor.
444 *
445 * Born on Date: 2002.02.05
446 *
447 * Arguments: NONE
448 *
449 * Returns: void (cannot fail)
450 *
451 * Modification log:
452 * Date Who Description
453 * ---------- --- --------------------------------------------------------
454 * 2003-06-24 hy modify for linux-2.5.69
455 *
456 *==========================================================================*/
457static void __init smp_callin(void)
458{
459 int phys_id = hard_smp_processor_id();
460 int cpu_id = smp_processor_id();
461 unsigned long timeout;
462
463 if (cpumask_test_cpu(cpu_id, &cpu_callin_map)) {
464 printk("huh, phys CPU#%d, CPU#%d already present??\n",
465 phys_id, cpu_id);
466 BUG();
467 }
468 Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpu_id, phys_id);
469
470 /* Waiting 2s total for startup (udelay is not yet working) */
471 timeout = jiffies + (2 * HZ);
472 while (time_before(jiffies, timeout)) {
473 /* Has the boot CPU finished it's STARTUP sequence ? */
474 if (cpumask_test_cpu(cpu_id, &cpu_callout_map))
475 break;
476 cpu_relax();
477 }
478
479 if (!time_before(jiffies, timeout)) {
480 printk("BUG: CPU#%d started up but did not get a callout!\n",
481 cpu_id);
482 BUG();
483 }
484
485 /* Allow the master to continue. */
486 cpumask_set_cpu(cpu_id, &cpu_callin_map);
487}
488
489static void __init smp_online(void)
490{
491 int cpu_id = smp_processor_id();
492
493 notify_cpu_starting(cpu_id);
494
495 local_irq_enable();
496
497 /* Get our bogomips. */
498 calibrate_delay();
499
500 /* Save our processor parameters */
501 smp_store_cpu_info(cpu_id);
502
503 set_cpu_online(cpu_id, true);
504}
505
506/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
507/* Boot up CPUs common Routines */
508/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
509static void __init show_mp_info(int nr_cpu)
510{
511 int i;
512 char cpu_model0[17], cpu_model1[17], cpu_ver[9];
513
514 strncpy(cpu_model0, (char *)M32R_FPGA_CPU_NAME_ADDR, 16);
515 strncpy(cpu_model1, (char *)M32R_FPGA_MODEL_ID_ADDR, 16);
516 strncpy(cpu_ver, (char *)M32R_FPGA_VERSION_ADDR, 8);
517
518 cpu_model0[16] = '\0';
519 for (i = 15 ; i >= 0 ; i--) {
520 if (cpu_model0[i] != ' ')
521 break;
522 cpu_model0[i] = '\0';
523 }
524 cpu_model1[16] = '\0';
525 for (i = 15 ; i >= 0 ; i--) {
526 if (cpu_model1[i] != ' ')
527 break;
528 cpu_model1[i] = '\0';
529 }
530 cpu_ver[8] = '\0';
531 for (i = 7 ; i >= 0 ; i--) {
532 if (cpu_ver[i] != ' ')
533 break;
534 cpu_ver[i] = '\0';
535 }
536
537 printk(KERN_INFO "M32R-mp information\n");
538 printk(KERN_INFO " On-chip CPUs : %d\n", nr_cpu);
539 printk(KERN_INFO " CPU model : %s/%s(%s)\n", cpu_model0,
540 cpu_model1, cpu_ver);
541}
542
543/*
544 * The bootstrap kernel entry code has set these up. Save them for
545 * a given CPU
546 */
547static void __init smp_store_cpu_info(int cpu_id)
548{
549 struct cpuinfo_m32r *ci = cpu_data + cpu_id;
550
551 *ci = boot_cpu_data;
552 ci->loops_per_jiffy = loops_per_jiffy;
553}
554
555static void __init show_cpu_info(int cpu_id)
556{
557 struct cpuinfo_m32r *ci = &cpu_data[cpu_id];
558
559 printk("CPU#%d : ", cpu_id);
560
561#define PRINT_CLOCK(name, value) \
562 printk(name " clock %d.%02dMHz", \
563 ((value) / 1000000), ((value) % 1000000) / 10000)
564
565 PRINT_CLOCK("CPU", (int)ci->cpu_clock);
566 PRINT_CLOCK(", Bus", (int)ci->bus_clock);
567 printk(", loops_per_jiffy[%ld]\n", ci->loops_per_jiffy);
568}
569
570/*
571 * the frequency of the profiling timer can be changed
572 * by writing a multiplier value into /proc/profile.
573 */
574int setup_profiling_timer(unsigned int multiplier)
575{
576 int i;
577
578 /*
579 * Sanity check. [at least 500 APIC cycles should be
580 * between APIC interrupts as a rule of thumb, to avoid
581 * irqs flooding us]
582 */
583 if ( (!multiplier) || (calibration_result / multiplier < 500))
584 return -EINVAL;
585
586 /*
587 * Set the new multiplier for each CPU. CPUs don't start using the
588 * new values until the next timer interrupt in which they do process
589 * accounting. At that time they also adjust their APIC timers
590 * accordingly.
591 */
592 for_each_possible_cpu(i)
593 per_cpu(prof_multiplier, i) = multiplier;
594
595 return 0;
596}
597
598/* Initialize all maps between cpu number and apicids */
599static void __init init_cpu_to_physid(void)
600{
601 int i;
602
603 for (i = 0 ; i < NR_CPUS ; i++) {
604 cpu_2_physid[i] = -1;
605 physid_2_cpu[i] = -1;
606 }
607}
608
609/*
610 * set up a mapping between cpu and apicid. Uses logical apicids for multiquad,
611 * else physical apic ids
612 */
613static void __init map_cpu_to_physid(int cpu_id, int phys_id)
614{
615 physid_2_cpu[phys_id] = cpu_id;
616 cpu_2_physid[cpu_id] = phys_id;
617}
618
619/*
620 * undo a mapping between cpu and apicid. Uses logical apicids for multiquad,
621 * else physical apic ids
622 */
623static void __init unmap_cpu_to_physid(int cpu_id, int phys_id)
624{
625 physid_2_cpu[phys_id] = -1;
626 cpu_2_physid[cpu_id] = -1;
627}