Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/platforms/powermac/smp.c
10818 views
1
/*
2
* SMP support for power macintosh.
3
*
4
* We support both the old "powersurge" SMP architecture
5
* and the current Core99 (G4 PowerMac) machines.
6
*
7
* Note that we don't support the very first rev. of
8
* Apple/DayStar 2 CPUs board, the one with the funky
9
* watchdog. Hopefully, none of these should be there except
10
* maybe internally to Apple. I should probably still add some
11
* code to detect this card though and disable SMP. --BenH.
12
*
13
* Support Macintosh G4 SMP by Troy Benjegerdes ([email protected])
14
* and Ben Herrenschmidt <[email protected]>.
15
*
16
* Support for DayStar quad CPU cards
17
* Copyright (C) XLR8, Inc. 1994-2000
18
*
19
* This program is free software; you can redistribute it and/or
20
* modify it under the terms of the GNU General Public License
21
* as published by the Free Software Foundation; either version
22
* 2 of the License, or (at your option) any later version.
23
*/
24
#include <linux/kernel.h>
25
#include <linux/sched.h>
26
#include <linux/smp.h>
27
#include <linux/interrupt.h>
28
#include <linux/kernel_stat.h>
29
#include <linux/delay.h>
30
#include <linux/init.h>
31
#include <linux/spinlock.h>
32
#include <linux/errno.h>
33
#include <linux/hardirq.h>
34
#include <linux/cpu.h>
35
#include <linux/compiler.h>
36
37
#include <asm/ptrace.h>
38
#include <asm/atomic.h>
39
#include <asm/code-patching.h>
40
#include <asm/irq.h>
41
#include <asm/page.h>
42
#include <asm/pgtable.h>
43
#include <asm/sections.h>
44
#include <asm/io.h>
45
#include <asm/prom.h>
46
#include <asm/smp.h>
47
#include <asm/machdep.h>
48
#include <asm/pmac_feature.h>
49
#include <asm/time.h>
50
#include <asm/mpic.h>
51
#include <asm/cacheflush.h>
52
#include <asm/keylargo.h>
53
#include <asm/pmac_low_i2c.h>
54
#include <asm/pmac_pfunc.h>
55
56
#include "pmac.h"
57
58
#undef DEBUG
59
60
#ifdef DEBUG
61
#define DBG(fmt...) udbg_printf(fmt)
62
#else
63
#define DBG(fmt...)
64
#endif
65
66
extern void __secondary_start_pmac_0(void);
67
extern int pmac_pfunc_base_install(void);
68
69
static void (*pmac_tb_freeze)(int freeze);
70
static u64 timebase;
71
static int tb_req;
72
73
#ifdef CONFIG_PPC_PMAC32_PSURGE
74
75
/*
76
* Powersurge (old powermac SMP) support.
77
*/
78
79
/* Addresses for powersurge registers */
80
#define HAMMERHEAD_BASE 0xf8000000
81
#define HHEAD_CONFIG 0x90
82
#define HHEAD_SEC_INTR 0xc0
83
84
/* register for interrupting the primary processor on the powersurge */
85
/* N.B. this is actually the ethernet ROM! */
86
#define PSURGE_PRI_INTR 0xf3019000
87
88
/* register for storing the start address for the secondary processor */
89
/* N.B. this is the PCI config space address register for the 1st bridge */
90
#define PSURGE_START 0xf2800000
91
92
/* Daystar/XLR8 4-CPU card */
93
#define PSURGE_QUAD_REG_ADDR 0xf8800000
94
95
#define PSURGE_QUAD_IRQ_SET 0
96
#define PSURGE_QUAD_IRQ_CLR 1
97
#define PSURGE_QUAD_IRQ_PRIMARY 2
98
#define PSURGE_QUAD_CKSTOP_CTL 3
99
#define PSURGE_QUAD_PRIMARY_ARB 4
100
#define PSURGE_QUAD_BOARD_ID 6
101
#define PSURGE_QUAD_WHICH_CPU 7
102
#define PSURGE_QUAD_CKSTOP_RDBK 8
103
#define PSURGE_QUAD_RESET_CTL 11
104
105
#define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v)))
106
#define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f)
107
#define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v)))
108
#define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))
109
110
/* virtual addresses for the above */
111
static volatile u8 __iomem *hhead_base;
112
static volatile u8 __iomem *quad_base;
113
static volatile u32 __iomem *psurge_pri_intr;
114
static volatile u8 __iomem *psurge_sec_intr;
115
static volatile u32 __iomem *psurge_start;
116
117
/* values for psurge_type */
118
#define PSURGE_NONE -1
119
#define PSURGE_DUAL 0
120
#define PSURGE_QUAD_OKEE 1
121
#define PSURGE_QUAD_COTTON 2
122
#define PSURGE_QUAD_ICEGRASS 3
123
124
/* what sort of powersurge board we have */
125
static int psurge_type = PSURGE_NONE;
126
127
/* irq for secondary cpus to report */
128
static struct irq_host *psurge_host;
129
int psurge_secondary_virq;
130
131
/*
132
* Set and clear IPIs for powersurge.
133
*/
134
static inline void psurge_set_ipi(int cpu)
135
{
136
if (psurge_type == PSURGE_NONE)
137
return;
138
if (cpu == 0)
139
in_be32(psurge_pri_intr);
140
else if (psurge_type == PSURGE_DUAL)
141
out_8(psurge_sec_intr, 0);
142
else
143
PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu);
144
}
145
146
static inline void psurge_clr_ipi(int cpu)
147
{
148
if (cpu > 0) {
149
switch(psurge_type) {
150
case PSURGE_DUAL:
151
out_8(psurge_sec_intr, ~0);
152
case PSURGE_NONE:
153
break;
154
default:
155
PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);
156
}
157
}
158
}
159
160
/*
161
* On powersurge (old SMP powermac architecture) we don't have
162
* separate IPIs for separate messages like openpic does. Instead
163
* use the generic demux helpers
164
* -- paulus.
165
*/
166
static irqreturn_t psurge_ipi_intr(int irq, void *d)
167
{
168
psurge_clr_ipi(smp_processor_id());
169
smp_ipi_demux();
170
171
return IRQ_HANDLED;
172
}
173
174
static void smp_psurge_cause_ipi(int cpu, unsigned long data)
175
{
176
psurge_set_ipi(cpu);
177
}
178
179
static int psurge_host_map(struct irq_host *h, unsigned int virq,
180
irq_hw_number_t hw)
181
{
182
irq_set_chip_and_handler(virq, &dummy_irq_chip, handle_percpu_irq);
183
184
return 0;
185
}
186
187
struct irq_host_ops psurge_host_ops = {
188
.map = psurge_host_map,
189
};
190
191
static int psurge_secondary_ipi_init(void)
192
{
193
int rc = -ENOMEM;
194
195
psurge_host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0,
196
&psurge_host_ops, 0);
197
198
if (psurge_host)
199
psurge_secondary_virq = irq_create_direct_mapping(psurge_host);
200
201
if (psurge_secondary_virq)
202
rc = request_irq(psurge_secondary_virq, psurge_ipi_intr,
203
IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
204
205
if (rc)
206
pr_err("Failed to setup secondary cpu IPI\n");
207
208
return rc;
209
}
210
211
/*
212
* Determine a quad card presence. We read the board ID register, we
213
* force the data bus to change to something else, and we read it again.
214
* It it's stable, then the register probably exist (ugh !)
215
*/
216
static int __init psurge_quad_probe(void)
217
{
218
int type;
219
unsigned int i;
220
221
type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID);
222
if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS
223
|| type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
224
return PSURGE_DUAL;
225
226
/* looks OK, try a slightly more rigorous test */
227
/* bogus is not necessarily cacheline-aligned,
228
though I don't suppose that really matters. -- paulus */
229
for (i = 0; i < 100; i++) {
230
volatile u32 bogus[8];
231
bogus[(0+i)%8] = 0x00000000;
232
bogus[(1+i)%8] = 0x55555555;
233
bogus[(2+i)%8] = 0xFFFFFFFF;
234
bogus[(3+i)%8] = 0xAAAAAAAA;
235
bogus[(4+i)%8] = 0x33333333;
236
bogus[(5+i)%8] = 0xCCCCCCCC;
237
bogus[(6+i)%8] = 0xCCCCCCCC;
238
bogus[(7+i)%8] = 0x33333333;
239
wmb();
240
asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory");
241
mb();
242
if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
243
return PSURGE_DUAL;
244
}
245
return type;
246
}
247
248
static void __init psurge_quad_init(void)
249
{
250
int procbits;
251
252
if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351);
253
procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU);
254
if (psurge_type == PSURGE_QUAD_ICEGRASS)
255
PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
256
else
257
PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits);
258
mdelay(33);
259
out_8(psurge_sec_intr, ~0);
260
PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits);
261
PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
262
if (psurge_type != PSURGE_QUAD_ICEGRASS)
263
PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits);
264
PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits);
265
mdelay(33);
266
PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits);
267
mdelay(33);
268
PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits);
269
mdelay(33);
270
}
271
272
static int __init smp_psurge_probe(void)
273
{
274
int i, ncpus;
275
struct device_node *dn;
276
277
/* We don't do SMP on the PPC601 -- paulus */
278
if (PVR_VER(mfspr(SPRN_PVR)) == 1)
279
return 1;
280
281
/*
282
* The powersurge cpu board can be used in the generation
283
* of powermacs that have a socket for an upgradeable cpu card,
284
* including the 7500, 8500, 9500, 9600.
285
* The device tree doesn't tell you if you have 2 cpus because
286
* OF doesn't know anything about the 2nd processor.
287
* Instead we look for magic bits in magic registers,
288
* in the hammerhead memory controller in the case of the
289
* dual-cpu powersurge board. -- paulus.
290
*/
291
dn = of_find_node_by_name(NULL, "hammerhead");
292
if (dn == NULL)
293
return 1;
294
of_node_put(dn);
295
296
hhead_base = ioremap(HAMMERHEAD_BASE, 0x800);
297
quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024);
298
psurge_sec_intr = hhead_base + HHEAD_SEC_INTR;
299
300
psurge_type = psurge_quad_probe();
301
if (psurge_type != PSURGE_DUAL) {
302
psurge_quad_init();
303
/* All released cards using this HW design have 4 CPUs */
304
ncpus = 4;
305
/* No sure how timebase sync works on those, let's use SW */
306
smp_ops->give_timebase = smp_generic_give_timebase;
307
smp_ops->take_timebase = smp_generic_take_timebase;
308
} else {
309
iounmap(quad_base);
310
if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
311
/* not a dual-cpu card */
312
iounmap(hhead_base);
313
psurge_type = PSURGE_NONE;
314
return 1;
315
}
316
ncpus = 2;
317
}
318
319
if (psurge_secondary_ipi_init())
320
return 1;
321
322
psurge_start = ioremap(PSURGE_START, 4);
323
psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
324
325
/* This is necessary because OF doesn't know about the
326
* secondary cpu(s), and thus there aren't nodes in the
327
* device tree for them, and smp_setup_cpu_maps hasn't
328
* set their bits in cpu_present_mask.
329
*/
330
if (ncpus > NR_CPUS)
331
ncpus = NR_CPUS;
332
for (i = 1; i < ncpus ; ++i)
333
set_cpu_present(i, true);
334
335
if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);
336
337
return ncpus;
338
}
339
340
static int __init smp_psurge_kick_cpu(int nr)
341
{
342
unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8;
343
unsigned long a, flags;
344
int i, j;
345
346
/* Defining this here is evil ... but I prefer hiding that
347
* crap to avoid giving people ideas that they can do the
348
* same.
349
*/
350
extern volatile unsigned int cpu_callin_map[NR_CPUS];
351
352
/* may need to flush here if secondary bats aren't setup */
353
for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
354
asm volatile("dcbf 0,%0" : : "r" (a) : "memory");
355
asm volatile("sync");
356
357
if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
358
359
/* This is going to freeze the timeebase, we disable interrupts */
360
local_irq_save(flags);
361
362
out_be32(psurge_start, start);
363
mb();
364
365
psurge_set_ipi(nr);
366
367
/*
368
* We can't use udelay here because the timebase is now frozen.
369
*/
370
for (i = 0; i < 2000; ++i)
371
asm volatile("nop" : : : "memory");
372
psurge_clr_ipi(nr);
373
374
/*
375
* Also, because the timebase is frozen, we must not return to the
376
* caller which will try to do udelay's etc... Instead, we wait -here-
377
* for the CPU to callin.
378
*/
379
for (i = 0; i < 100000 && !cpu_callin_map[nr]; ++i) {
380
for (j = 1; j < 10000; j++)
381
asm volatile("nop" : : : "memory");
382
asm volatile("sync" : : : "memory");
383
}
384
if (!cpu_callin_map[nr])
385
goto stuck;
386
387
/* And we do the TB sync here too for standard dual CPU cards */
388
if (psurge_type == PSURGE_DUAL) {
389
while(!tb_req)
390
barrier();
391
tb_req = 0;
392
mb();
393
timebase = get_tb();
394
mb();
395
while (timebase)
396
barrier();
397
mb();
398
}
399
stuck:
400
/* now interrupt the secondary, restarting both TBs */
401
if (psurge_type == PSURGE_DUAL)
402
psurge_set_ipi(1);
403
404
if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
405
406
return 0;
407
}
408
409
static struct irqaction psurge_irqaction = {
410
.handler = psurge_ipi_intr,
411
.flags = IRQF_DISABLED|IRQF_PERCPU,
412
.name = "primary IPI",
413
};
414
415
static void __init smp_psurge_setup_cpu(int cpu_nr)
416
{
417
if (cpu_nr != 0)
418
return;
419
420
/* reset the entry point so if we get another intr we won't
421
* try to startup again */
422
out_be32(psurge_start, 0x100);
423
if (setup_irq(irq_create_mapping(NULL, 30), &psurge_irqaction))
424
printk(KERN_ERR "Couldn't get primary IPI interrupt");
425
}
426
427
void __init smp_psurge_take_timebase(void)
428
{
429
if (psurge_type != PSURGE_DUAL)
430
return;
431
432
tb_req = 1;
433
mb();
434
while (!timebase)
435
barrier();
436
mb();
437
set_tb(timebase >> 32, timebase & 0xffffffff);
438
timebase = 0;
439
mb();
440
set_dec(tb_ticks_per_jiffy/2);
441
}
442
443
void __init smp_psurge_give_timebase(void)
444
{
445
/* Nothing to do here */
446
}
447
448
/* PowerSurge-style Macs */
449
struct smp_ops_t psurge_smp_ops = {
450
.message_pass = smp_muxed_ipi_message_pass,
451
.cause_ipi = smp_psurge_cause_ipi,
452
.probe = smp_psurge_probe,
453
.kick_cpu = smp_psurge_kick_cpu,
454
.setup_cpu = smp_psurge_setup_cpu,
455
.give_timebase = smp_psurge_give_timebase,
456
.take_timebase = smp_psurge_take_timebase,
457
};
458
#endif /* CONFIG_PPC_PMAC32_PSURGE */
459
460
/*
461
* Core 99 and later support
462
*/
463
464
465
static void smp_core99_give_timebase(void)
466
{
467
unsigned long flags;
468
469
local_irq_save(flags);
470
471
while(!tb_req)
472
barrier();
473
tb_req = 0;
474
(*pmac_tb_freeze)(1);
475
mb();
476
timebase = get_tb();
477
mb();
478
while (timebase)
479
barrier();
480
mb();
481
(*pmac_tb_freeze)(0);
482
mb();
483
484
local_irq_restore(flags);
485
}
486
487
488
static void __devinit smp_core99_take_timebase(void)
489
{
490
unsigned long flags;
491
492
local_irq_save(flags);
493
494
tb_req = 1;
495
mb();
496
while (!timebase)
497
barrier();
498
mb();
499
set_tb(timebase >> 32, timebase & 0xffffffff);
500
timebase = 0;
501
mb();
502
503
local_irq_restore(flags);
504
}
505
506
#ifdef CONFIG_PPC64
507
/*
508
* G5s enable/disable the timebase via an i2c-connected clock chip.
509
*/
510
static struct pmac_i2c_bus *pmac_tb_clock_chip_host;
511
static u8 pmac_tb_pulsar_addr;
512
513
static void smp_core99_cypress_tb_freeze(int freeze)
514
{
515
u8 data;
516
int rc;
517
518
/* Strangely, the device-tree says address is 0xd2, but darwin
519
* accesses 0xd0 ...
520
*/
521
pmac_i2c_setmode(pmac_tb_clock_chip_host,
522
pmac_i2c_mode_combined);
523
rc = pmac_i2c_xfer(pmac_tb_clock_chip_host,
524
0xd0 | pmac_i2c_read,
525
1, 0x81, &data, 1);
526
if (rc != 0)
527
goto bail;
528
529
data = (data & 0xf3) | (freeze ? 0x00 : 0x0c);
530
531
pmac_i2c_setmode(pmac_tb_clock_chip_host, pmac_i2c_mode_stdsub);
532
rc = pmac_i2c_xfer(pmac_tb_clock_chip_host,
533
0xd0 | pmac_i2c_write,
534
1, 0x81, &data, 1);
535
536
bail:
537
if (rc != 0) {
538
printk("Cypress Timebase %s rc: %d\n",
539
freeze ? "freeze" : "unfreeze", rc);
540
panic("Timebase freeze failed !\n");
541
}
542
}
543
544
545
static void smp_core99_pulsar_tb_freeze(int freeze)
546
{
547
u8 data;
548
int rc;
549
550
pmac_i2c_setmode(pmac_tb_clock_chip_host,
551
pmac_i2c_mode_combined);
552
rc = pmac_i2c_xfer(pmac_tb_clock_chip_host,
553
pmac_tb_pulsar_addr | pmac_i2c_read,
554
1, 0x2e, &data, 1);
555
if (rc != 0)
556
goto bail;
557
558
data = (data & 0x88) | (freeze ? 0x11 : 0x22);
559
560
pmac_i2c_setmode(pmac_tb_clock_chip_host, pmac_i2c_mode_stdsub);
561
rc = pmac_i2c_xfer(pmac_tb_clock_chip_host,
562
pmac_tb_pulsar_addr | pmac_i2c_write,
563
1, 0x2e, &data, 1);
564
bail:
565
if (rc != 0) {
566
printk(KERN_ERR "Pulsar Timebase %s rc: %d\n",
567
freeze ? "freeze" : "unfreeze", rc);
568
panic("Timebase freeze failed !\n");
569
}
570
}
571
572
static void __init smp_core99_setup_i2c_hwsync(int ncpus)
573
{
574
struct device_node *cc = NULL;
575
struct device_node *p;
576
const char *name = NULL;
577
const u32 *reg;
578
int ok;
579
580
/* Look for the clock chip */
581
while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) {
582
p = of_get_parent(cc);
583
ok = p && of_device_is_compatible(p, "uni-n-i2c");
584
of_node_put(p);
585
if (!ok)
586
continue;
587
588
pmac_tb_clock_chip_host = pmac_i2c_find_bus(cc);
589
if (pmac_tb_clock_chip_host == NULL)
590
continue;
591
reg = of_get_property(cc, "reg", NULL);
592
if (reg == NULL)
593
continue;
594
switch (*reg) {
595
case 0xd2:
596
if (of_device_is_compatible(cc,"pulsar-legacy-slewing")) {
597
pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
598
pmac_tb_pulsar_addr = 0xd2;
599
name = "Pulsar";
600
} else if (of_device_is_compatible(cc, "cy28508")) {
601
pmac_tb_freeze = smp_core99_cypress_tb_freeze;
602
name = "Cypress";
603
}
604
break;
605
case 0xd4:
606
pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
607
pmac_tb_pulsar_addr = 0xd4;
608
name = "Pulsar";
609
break;
610
}
611
if (pmac_tb_freeze != NULL)
612
break;
613
}
614
if (pmac_tb_freeze != NULL) {
615
/* Open i2c bus for synchronous access */
616
if (pmac_i2c_open(pmac_tb_clock_chip_host, 1)) {
617
printk(KERN_ERR "Failed top open i2c bus for clock"
618
" sync, fallback to software sync !\n");
619
goto no_i2c_sync;
620
}
621
printk(KERN_INFO "Processor timebase sync using %s i2c clock\n",
622
name);
623
return;
624
}
625
no_i2c_sync:
626
pmac_tb_freeze = NULL;
627
pmac_tb_clock_chip_host = NULL;
628
}
629
630
631
632
/*
633
* Newer G5s uses a platform function
634
*/
635
636
static void smp_core99_pfunc_tb_freeze(int freeze)
637
{
638
struct device_node *cpus;
639
struct pmf_args args;
640
641
cpus = of_find_node_by_path("/cpus");
642
BUG_ON(cpus == NULL);
643
args.count = 1;
644
args.u[0].v = !freeze;
645
pmf_call_function(cpus, "cpu-timebase", &args);
646
of_node_put(cpus);
647
}
648
649
#else /* CONFIG_PPC64 */
650
651
/*
652
* SMP G4 use a GPIO to enable/disable the timebase.
653
*/
654
655
static unsigned int core99_tb_gpio; /* Timebase freeze GPIO */
656
657
static void smp_core99_gpio_tb_freeze(int freeze)
658
{
659
if (freeze)
660
pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);
661
else
662
pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
663
pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
664
}
665
666
667
#endif /* !CONFIG_PPC64 */
668
669
/* L2 and L3 cache settings to pass from CPU0 to CPU1 on G4 cpus */
670
volatile static long int core99_l2_cache;
671
volatile static long int core99_l3_cache;
672
673
static void __devinit core99_init_caches(int cpu)
674
{
675
#ifndef CONFIG_PPC64
676
if (!cpu_has_feature(CPU_FTR_L2CR))
677
return;
678
679
if (cpu == 0) {
680
core99_l2_cache = _get_L2CR();
681
printk("CPU0: L2CR is %lx\n", core99_l2_cache);
682
} else {
683
printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR());
684
_set_L2CR(0);
685
_set_L2CR(core99_l2_cache);
686
printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
687
}
688
689
if (!cpu_has_feature(CPU_FTR_L3CR))
690
return;
691
692
if (cpu == 0){
693
core99_l3_cache = _get_L3CR();
694
printk("CPU0: L3CR is %lx\n", core99_l3_cache);
695
} else {
696
printk("CPU%d: L3CR was %lx\n", cpu, _get_L3CR());
697
_set_L3CR(0);
698
_set_L3CR(core99_l3_cache);
699
printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache);
700
}
701
#endif /* !CONFIG_PPC64 */
702
}
703
704
static void __init smp_core99_setup(int ncpus)
705
{
706
#ifdef CONFIG_PPC64
707
708
/* i2c based HW sync on some G5s */
709
if (of_machine_is_compatible("PowerMac7,2") ||
710
of_machine_is_compatible("PowerMac7,3") ||
711
of_machine_is_compatible("RackMac3,1"))
712
smp_core99_setup_i2c_hwsync(ncpus);
713
714
/* pfunc based HW sync on recent G5s */
715
if (pmac_tb_freeze == NULL) {
716
struct device_node *cpus =
717
of_find_node_by_path("/cpus");
718
if (cpus &&
719
of_get_property(cpus, "platform-cpu-timebase", NULL)) {
720
pmac_tb_freeze = smp_core99_pfunc_tb_freeze;
721
printk(KERN_INFO "Processor timebase sync using"
722
" platform function\n");
723
}
724
}
725
726
#else /* CONFIG_PPC64 */
727
728
/* GPIO based HW sync on ppc32 Core99 */
729
if (pmac_tb_freeze == NULL && !of_machine_is_compatible("MacRISC4")) {
730
struct device_node *cpu;
731
const u32 *tbprop = NULL;
732
733
core99_tb_gpio = KL_GPIO_TB_ENABLE; /* default value */
734
cpu = of_find_node_by_type(NULL, "cpu");
735
if (cpu != NULL) {
736
tbprop = of_get_property(cpu, "timebase-enable", NULL);
737
if (tbprop)
738
core99_tb_gpio = *tbprop;
739
of_node_put(cpu);
740
}
741
pmac_tb_freeze = smp_core99_gpio_tb_freeze;
742
printk(KERN_INFO "Processor timebase sync using"
743
" GPIO 0x%02x\n", core99_tb_gpio);
744
}
745
746
#endif /* CONFIG_PPC64 */
747
748
/* No timebase sync, fallback to software */
749
if (pmac_tb_freeze == NULL) {
750
smp_ops->give_timebase = smp_generic_give_timebase;
751
smp_ops->take_timebase = smp_generic_take_timebase;
752
printk(KERN_INFO "Processor timebase sync using software\n");
753
}
754
755
#ifndef CONFIG_PPC64
756
{
757
int i;
758
759
/* XXX should get this from reg properties */
760
for (i = 1; i < ncpus; ++i)
761
set_hard_smp_processor_id(i, i);
762
}
763
#endif
764
765
/* 32 bits SMP can't NAP */
766
if (!of_machine_is_compatible("MacRISC4"))
767
powersave_nap = 0;
768
}
769
770
static int __init smp_core99_probe(void)
771
{
772
struct device_node *cpus;
773
int ncpus = 0;
774
775
if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
776
777
/* Count CPUs in the device-tree */
778
for (cpus = NULL; (cpus = of_find_node_by_type(cpus, "cpu")) != NULL;)
779
++ncpus;
780
781
printk(KERN_INFO "PowerMac SMP probe found %d cpus\n", ncpus);
782
783
/* Nothing more to do if less than 2 of them */
784
if (ncpus <= 1)
785
return 1;
786
787
/* We need to perform some early initialisations before we can start
788
* setting up SMP as we are running before initcalls
789
*/
790
pmac_pfunc_base_install();
791
pmac_i2c_init();
792
793
/* Setup various bits like timebase sync method, ability to nap, ... */
794
smp_core99_setup(ncpus);
795
796
/* Install IPIs */
797
mpic_request_ipis();
798
799
/* Collect l2cr and l3cr values from CPU 0 */
800
core99_init_caches(0);
801
802
return ncpus;
803
}
804
805
static int __devinit smp_core99_kick_cpu(int nr)
806
{
807
unsigned int save_vector;
808
unsigned long target, flags;
809
unsigned int *vector = (unsigned int *)(PAGE_OFFSET+0x100);
810
811
if (nr < 0 || nr > 3)
812
return -ENOENT;
813
814
if (ppc_md.progress)
815
ppc_md.progress("smp_core99_kick_cpu", 0x346);
816
817
local_irq_save(flags);
818
819
/* Save reset vector */
820
save_vector = *vector;
821
822
/* Setup fake reset vector that does
823
* b __secondary_start_pmac_0 + nr*8
824
*/
825
target = (unsigned long) __secondary_start_pmac_0 + nr * 8;
826
patch_branch(vector, target, BRANCH_SET_LINK);
827
828
/* Put some life in our friend */
829
pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);
830
831
/* FIXME: We wait a bit for the CPU to take the exception, I should
832
* instead wait for the entry code to set something for me. Well,
833
* ideally, all that crap will be done in prom.c and the CPU left
834
* in a RAM-based wait loop like CHRP.
835
*/
836
mdelay(1);
837
838
/* Restore our exception vector */
839
*vector = save_vector;
840
flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
841
842
local_irq_restore(flags);
843
if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
844
845
return 0;
846
}
847
848
static void __devinit smp_core99_setup_cpu(int cpu_nr)
849
{
850
/* Setup L2/L3 */
851
if (cpu_nr != 0)
852
core99_init_caches(cpu_nr);
853
854
/* Setup openpic */
855
mpic_setup_this_cpu();
856
}
857
858
#ifdef CONFIG_PPC64
859
#ifdef CONFIG_HOTPLUG_CPU
860
static int smp_core99_cpu_notify(struct notifier_block *self,
861
unsigned long action, void *hcpu)
862
{
863
int rc;
864
865
switch(action) {
866
case CPU_UP_PREPARE:
867
case CPU_UP_PREPARE_FROZEN:
868
/* Open i2c bus if it was used for tb sync */
869
if (pmac_tb_clock_chip_host) {
870
rc = pmac_i2c_open(pmac_tb_clock_chip_host, 1);
871
if (rc) {
872
pr_err("Failed to open i2c bus for time sync\n");
873
return notifier_from_errno(rc);
874
}
875
}
876
break;
877
case CPU_ONLINE:
878
case CPU_UP_CANCELED:
879
/* Close i2c bus if it was used for tb sync */
880
if (pmac_tb_clock_chip_host)
881
pmac_i2c_close(pmac_tb_clock_chip_host);
882
break;
883
default:
884
break;
885
}
886
return NOTIFY_OK;
887
}
888
889
static struct notifier_block __cpuinitdata smp_core99_cpu_nb = {
890
.notifier_call = smp_core99_cpu_notify,
891
};
892
#endif /* CONFIG_HOTPLUG_CPU */
893
894
static void __init smp_core99_bringup_done(void)
895
{
896
extern void g5_phy_disable_cpu1(void);
897
898
/* Close i2c bus if it was used for tb sync */
899
if (pmac_tb_clock_chip_host)
900
pmac_i2c_close(pmac_tb_clock_chip_host);
901
902
/* If we didn't start the second CPU, we must take
903
* it off the bus.
904
*/
905
if (of_machine_is_compatible("MacRISC4") &&
906
num_online_cpus() < 2) {
907
set_cpu_present(1, false);
908
g5_phy_disable_cpu1();
909
}
910
#ifdef CONFIG_HOTPLUG_CPU
911
register_cpu_notifier(&smp_core99_cpu_nb);
912
#endif
913
914
if (ppc_md.progress)
915
ppc_md.progress("smp_core99_bringup_done", 0x349);
916
}
917
#endif /* CONFIG_PPC64 */
918
919
#ifdef CONFIG_HOTPLUG_CPU
920
921
static int smp_core99_cpu_disable(void)
922
{
923
int rc = generic_cpu_disable();
924
if (rc)
925
return rc;
926
927
mpic_cpu_set_priority(0xf);
928
929
return 0;
930
}
931
932
#ifdef CONFIG_PPC32
933
934
static void pmac_cpu_die(void)
935
{
936
int cpu = smp_processor_id();
937
938
local_irq_disable();
939
idle_task_exit();
940
pr_debug("CPU%d offline\n", cpu);
941
generic_set_cpu_dead(cpu);
942
smp_wmb();
943
mb();
944
low_cpu_die();
945
}
946
947
#else /* CONFIG_PPC32 */
948
949
static void pmac_cpu_die(void)
950
{
951
int cpu = smp_processor_id();
952
953
local_irq_disable();
954
idle_task_exit();
955
956
/*
957
* turn off as much as possible, we'll be
958
* kicked out as this will only be invoked
959
* on core99 platforms for now ...
960
*/
961
962
printk(KERN_INFO "CPU#%d offline\n", cpu);
963
generic_set_cpu_dead(cpu);
964
smp_wmb();
965
966
/*
967
* Re-enable interrupts. The NAP code needs to enable them
968
* anyways, do it now so we deal with the case where one already
969
* happened while soft-disabled.
970
* We shouldn't get any external interrupts, only decrementer, and the
971
* decrementer handler is safe for use on offline CPUs
972
*/
973
local_irq_enable();
974
975
while (1) {
976
/* let's not take timer interrupts too often ... */
977
set_dec(0x7fffffff);
978
979
/* Enter NAP mode */
980
power4_idle();
981
}
982
}
983
984
#endif /* else CONFIG_PPC32 */
985
#endif /* CONFIG_HOTPLUG_CPU */
986
987
/* Core99 Macs (dual G4s and G5s) */
988
struct smp_ops_t core99_smp_ops = {
989
.message_pass = smp_mpic_message_pass,
990
.probe = smp_core99_probe,
991
#ifdef CONFIG_PPC64
992
.bringup_done = smp_core99_bringup_done,
993
#endif
994
.kick_cpu = smp_core99_kick_cpu,
995
.setup_cpu = smp_core99_setup_cpu,
996
.give_timebase = smp_core99_give_timebase,
997
.take_timebase = smp_core99_take_timebase,
998
#if defined(CONFIG_HOTPLUG_CPU)
999
.cpu_disable = smp_core99_cpu_disable,
1000
.cpu_die = generic_cpu_die,
1001
#endif
1002
};
1003
1004
void __init pmac_setup_smp(void)
1005
{
1006
struct device_node *np;
1007
1008
/* Check for Core99 */
1009
np = of_find_node_by_name(NULL, "uni-n");
1010
if (!np)
1011
np = of_find_node_by_name(NULL, "u3");
1012
if (!np)
1013
np = of_find_node_by_name(NULL, "u4");
1014
if (np) {
1015
of_node_put(np);
1016
smp_ops = &core99_smp_ops;
1017
}
1018
#ifdef CONFIG_PPC_PMAC32_PSURGE
1019
else {
1020
/* We have to set bits in cpu_possible_mask here since the
1021
* secondary CPU(s) aren't in the device tree. Various
1022
* things won't be initialized for CPUs not in the possible
1023
* map, so we really need to fix it up here.
1024
*/
1025
int cpu;
1026
1027
for (cpu = 1; cpu < 4 && cpu < NR_CPUS; ++cpu)
1028
set_cpu_possible(cpu, true);
1029
smp_ops = &psurge_smp_ops;
1030
}
1031
#endif /* CONFIG_PPC_PMAC32_PSURGE */
1032
1033
#ifdef CONFIG_HOTPLUG_CPU
1034
ppc_md.cpu_die = pmac_cpu_die;
1035
#endif
1036
}
1037
1038
1039
1040