Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/powerpc/boot/4xx.c
26442 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright 2007 David Gibson, IBM Corporation.
4
*
5
* Based on earlier code:
6
* Matt Porter <[email protected]>
7
* Copyright 2002-2005 MontaVista Software Inc.
8
*
9
* Eugene Surovegin <[email protected]> or <[email protected]>
10
* Copyright (c) 2003, 2004 Zultys Technologies
11
*
12
* Copyright (C) 2009 Wind River Systems, Inc.
13
* Updated for supporting PPC405EX on Kilauea.
14
* Tiejun Chen <[email protected]>
15
*/
16
#include <stddef.h>
17
#include "types.h"
18
#include "string.h"
19
#include "stdio.h"
20
#include "ops.h"
21
#include "reg.h"
22
#include "dcr.h"
23
24
static unsigned long chip_11_errata(unsigned long memsize)
25
{
26
unsigned long pvr;
27
28
pvr = mfpvr();
29
30
switch (pvr & 0xf0000ff0) {
31
case 0x40000850:
32
case 0x400008d0:
33
case 0x200008d0:
34
memsize -= 4096;
35
break;
36
default:
37
break;
38
}
39
40
return memsize;
41
}
42
43
/* Read the 4xx SDRAM controller to get size of system memory. */
44
void ibm4xx_sdram_fixup_memsize(void)
45
{
46
int i;
47
unsigned long memsize, bank_config;
48
49
memsize = 0;
50
for (i = 0; i < ARRAY_SIZE(sdram_bxcr); i++) {
51
bank_config = SDRAM0_READ(sdram_bxcr[i]);
52
if (bank_config & SDRAM_CONFIG_BANK_ENABLE)
53
memsize += SDRAM_CONFIG_BANK_SIZE(bank_config);
54
}
55
56
memsize = chip_11_errata(memsize);
57
dt_fixup_memory(0, memsize);
58
}
59
60
/* Read the 440SPe MQ controller to get size of system memory. */
61
#define DCRN_MQ0_B0BAS 0x40
62
#define DCRN_MQ0_B1BAS 0x41
63
#define DCRN_MQ0_B2BAS 0x42
64
#define DCRN_MQ0_B3BAS 0x43
65
66
static u64 ibm440spe_decode_bas(u32 bas)
67
{
68
u64 base = ((u64)(bas & 0xFFE00000u)) << 2;
69
70
/* open coded because I'm paranoid about invalid values */
71
switch ((bas >> 4) & 0xFFF) {
72
case 0:
73
return 0;
74
case 0xffc:
75
return base + 0x000800000ull;
76
case 0xff8:
77
return base + 0x001000000ull;
78
case 0xff0:
79
return base + 0x002000000ull;
80
case 0xfe0:
81
return base + 0x004000000ull;
82
case 0xfc0:
83
return base + 0x008000000ull;
84
case 0xf80:
85
return base + 0x010000000ull;
86
case 0xf00:
87
return base + 0x020000000ull;
88
case 0xe00:
89
return base + 0x040000000ull;
90
case 0xc00:
91
return base + 0x080000000ull;
92
case 0x800:
93
return base + 0x100000000ull;
94
}
95
printf("Memory BAS value 0x%08x unsupported !\n", bas);
96
return 0;
97
}
98
99
void ibm440spe_fixup_memsize(void)
100
{
101
u64 banktop, memsize = 0;
102
103
/* Ultimately, we should directly construct the memory node
104
* so we are able to handle holes in the memory address space
105
*/
106
banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B0BAS));
107
if (banktop > memsize)
108
memsize = banktop;
109
banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B1BAS));
110
if (banktop > memsize)
111
memsize = banktop;
112
banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B2BAS));
113
if (banktop > memsize)
114
memsize = banktop;
115
banktop = ibm440spe_decode_bas(mfdcr(DCRN_MQ0_B3BAS));
116
if (banktop > memsize)
117
memsize = banktop;
118
119
dt_fixup_memory(0, memsize);
120
}
121
122
123
/* 4xx DDR1/2 Denali memory controller support */
124
/* DDR0 registers */
125
#define DDR0_02 2
126
#define DDR0_08 8
127
#define DDR0_10 10
128
#define DDR0_14 14
129
#define DDR0_42 42
130
#define DDR0_43 43
131
132
/* DDR0_02 */
133
#define DDR_START 0x1
134
#define DDR_START_SHIFT 0
135
#define DDR_MAX_CS_REG 0x3
136
#define DDR_MAX_CS_REG_SHIFT 24
137
#define DDR_MAX_COL_REG 0xf
138
#define DDR_MAX_COL_REG_SHIFT 16
139
#define DDR_MAX_ROW_REG 0xf
140
#define DDR_MAX_ROW_REG_SHIFT 8
141
/* DDR0_08 */
142
#define DDR_DDR2_MODE 0x1
143
#define DDR_DDR2_MODE_SHIFT 0
144
/* DDR0_10 */
145
#define DDR_CS_MAP 0x3
146
#define DDR_CS_MAP_SHIFT 8
147
/* DDR0_14 */
148
#define DDR_REDUC 0x1
149
#define DDR_REDUC_SHIFT 16
150
/* DDR0_42 */
151
#define DDR_APIN 0x7
152
#define DDR_APIN_SHIFT 24
153
/* DDR0_43 */
154
#define DDR_COL_SZ 0x7
155
#define DDR_COL_SZ_SHIFT 8
156
#define DDR_BANK8 0x1
157
#define DDR_BANK8_SHIFT 0
158
159
#define DDR_GET_VAL(val, mask, shift) (((val) >> (shift)) & (mask))
160
161
/*
162
* Some U-Boot versions set the number of chipselects to two
163
* for Sequoia/Rainier boards while they only have one chipselect
164
* hardwired. Hardcode the number of chipselects to one
165
* for sequioa/rainer board models or read the actual value
166
* from the memory controller register DDR0_10 otherwise.
167
*/
168
static inline u32 ibm4xx_denali_get_cs(void)
169
{
170
void *devp;
171
char model[64];
172
u32 val, cs;
173
174
devp = finddevice("/");
175
if (!devp)
176
goto read_cs;
177
178
if (getprop(devp, "model", model, sizeof(model)) <= 0)
179
goto read_cs;
180
181
model[sizeof(model)-1] = 0;
182
183
if (!strcmp(model, "amcc,sequoia") ||
184
!strcmp(model, "amcc,rainier"))
185
return 1;
186
187
read_cs:
188
/* get CS value */
189
val = SDRAM0_READ(DDR0_10);
190
191
val = DDR_GET_VAL(val, DDR_CS_MAP, DDR_CS_MAP_SHIFT);
192
cs = 0;
193
while (val) {
194
if (val & 0x1)
195
cs++;
196
val = val >> 1;
197
}
198
return cs;
199
}
200
201
void ibm4xx_denali_fixup_memsize(void)
202
{
203
u32 val, max_cs, max_col, max_row;
204
u32 cs, col, row, bank, dpath;
205
unsigned long memsize;
206
207
val = SDRAM0_READ(DDR0_02);
208
if (!DDR_GET_VAL(val, DDR_START, DDR_START_SHIFT))
209
fatal("DDR controller is not initialized\n");
210
211
/* get maximum cs col and row values */
212
max_cs = DDR_GET_VAL(val, DDR_MAX_CS_REG, DDR_MAX_CS_REG_SHIFT);
213
max_col = DDR_GET_VAL(val, DDR_MAX_COL_REG, DDR_MAX_COL_REG_SHIFT);
214
max_row = DDR_GET_VAL(val, DDR_MAX_ROW_REG, DDR_MAX_ROW_REG_SHIFT);
215
216
cs = ibm4xx_denali_get_cs();
217
if (!cs)
218
fatal("No memory installed\n");
219
if (cs > max_cs)
220
fatal("DDR wrong CS configuration\n");
221
222
/* get data path bytes */
223
val = SDRAM0_READ(DDR0_14);
224
225
if (DDR_GET_VAL(val, DDR_REDUC, DDR_REDUC_SHIFT))
226
dpath = 4; /* 32 bits */
227
else
228
dpath = 8; /* 64 bits */
229
230
/* get address pins (rows) */
231
val = SDRAM0_READ(DDR0_42);
232
233
row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT);
234
if (row > max_row)
235
fatal("DDR wrong APIN configuration\n");
236
row = max_row - row;
237
238
/* get collomn size and banks */
239
val = SDRAM0_READ(DDR0_43);
240
241
col = DDR_GET_VAL(val, DDR_COL_SZ, DDR_COL_SZ_SHIFT);
242
if (col > max_col)
243
fatal("DDR wrong COL configuration\n");
244
col = max_col - col;
245
246
if (DDR_GET_VAL(val, DDR_BANK8, DDR_BANK8_SHIFT))
247
bank = 8; /* 8 banks */
248
else
249
bank = 4; /* 4 banks */
250
251
memsize = cs * (1 << (col+row)) * bank * dpath;
252
memsize = chip_11_errata(memsize);
253
dt_fixup_memory(0, memsize);
254
}
255
256
#define SPRN_DBCR0_44X 0x134
257
#define DBCR0_RST_SYSTEM 0x30000000
258
259
void ibm44x_dbcr_reset(void)
260
{
261
unsigned long tmp;
262
263
asm volatile (
264
"mfspr %0,%1\n"
265
"oris %0,%0,%2@h\n"
266
"mtspr %1,%0"
267
: "=&r"(tmp) : "i"(SPRN_DBCR0_44X), "i"(DBCR0_RST_SYSTEM)
268
);
269
270
}
271
272
#define EMAC_RESET 0x20000000
273
void ibm4xx_quiesce_eth(u32 *emac0, u32 *emac1)
274
{
275
/* Quiesce the MAL and EMAC(s) since PIBS/OpenBIOS don't
276
* do this for us
277
*/
278
if (emac0)
279
*emac0 = EMAC_RESET;
280
if (emac1)
281
*emac1 = EMAC_RESET;
282
283
mtdcr(DCRN_MAL0_CFG, MAL_RESET);
284
while (mfdcr(DCRN_MAL0_CFG) & MAL_RESET)
285
; /* loop until reset takes effect */
286
}
287
288
/* Read 4xx EBC bus bridge registers to get mappings of the peripheral
289
* banks into the OPB address space */
290
void ibm4xx_fixup_ebc_ranges(const char *ebc)
291
{
292
void *devp;
293
u32 bxcr;
294
u32 ranges[EBC_NUM_BANKS*4];
295
u32 *p = ranges;
296
int i;
297
298
for (i = 0; i < EBC_NUM_BANKS; i++) {
299
mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i));
300
bxcr = mfdcr(DCRN_EBC0_CFGDATA);
301
302
if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) {
303
*p++ = i;
304
*p++ = 0;
305
*p++ = bxcr & EBC_BXCR_BAS;
306
*p++ = EBC_BXCR_BANK_SIZE(bxcr);
307
}
308
}
309
310
devp = finddevice(ebc);
311
if (! devp)
312
fatal("Couldn't locate EBC node %s\n\r", ebc);
313
314
setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32));
315
}
316
317
/* Calculate 440GP clocks */
318
void ibm440gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
319
{
320
u32 sys0 = mfdcr(DCRN_CPC0_SYS0);
321
u32 cr0 = mfdcr(DCRN_CPC0_CR0);
322
u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
323
u32 opdv = CPC0_SYS0_OPDV(sys0);
324
u32 epdv = CPC0_SYS0_EPDV(sys0);
325
326
if (sys0 & CPC0_SYS0_BYPASS) {
327
/* Bypass system PLL */
328
cpu = plb = sys_clk;
329
} else {
330
if (sys0 & CPC0_SYS0_EXTSL)
331
/* PerClk */
332
m = CPC0_SYS0_FWDVB(sys0) * opdv * epdv;
333
else
334
/* CPU clock */
335
m = CPC0_SYS0_FBDV(sys0) * CPC0_SYS0_FWDVA(sys0);
336
cpu = sys_clk * m / CPC0_SYS0_FWDVA(sys0);
337
plb = sys_clk * m / CPC0_SYS0_FWDVB(sys0);
338
}
339
340
opb = plb / opdv;
341
ebc = opb / epdv;
342
343
/* FIXME: Check if this is for all 440GP, or just Ebony */
344
if ((mfpvr() & 0xf0000fff) == 0x40000440)
345
/* Rev. B 440GP, use external system clock */
346
tb = sys_clk;
347
else
348
/* Rev. C 440GP, errata force us to use internal clock */
349
tb = cpu;
350
351
if (cr0 & CPC0_CR0_U0EC)
352
/* External UART clock */
353
uart0 = ser_clk;
354
else
355
/* Internal UART clock */
356
uart0 = plb / CPC0_CR0_UDIV(cr0);
357
358
if (cr0 & CPC0_CR0_U1EC)
359
/* External UART clock */
360
uart1 = ser_clk;
361
else
362
/* Internal UART clock */
363
uart1 = plb / CPC0_CR0_UDIV(cr0);
364
365
printf("PPC440GP: SysClk = %dMHz (%x)\n\r",
366
(sys_clk + 500000) / 1000000, sys_clk);
367
368
dt_fixup_cpu_clocks(cpu, tb, 0);
369
370
dt_fixup_clock("/plb", plb);
371
dt_fixup_clock("/plb/opb", opb);
372
dt_fixup_clock("/plb/opb/ebc", ebc);
373
dt_fixup_clock("/plb/opb/serial@40000200", uart0);
374
dt_fixup_clock("/plb/opb/serial@40000300", uart1);
375
}
376
377
#define SPRN_CCR1 0x378
378
379
static inline u32 __fix_zero(u32 v, u32 def)
380
{
381
return v ? v : def;
382
}
383
384
static unsigned int __ibm440eplike_fixup_clocks(unsigned int sys_clk,
385
unsigned int tmr_clk,
386
int per_clk_from_opb)
387
{
388
/* PLL config */
389
u32 pllc = CPR0_READ(DCRN_CPR0_PLLC);
390
u32 plld = CPR0_READ(DCRN_CPR0_PLLD);
391
392
/* Dividers */
393
u32 fbdv = __fix_zero((plld >> 24) & 0x1f, 32);
394
u32 fwdva = __fix_zero((plld >> 16) & 0xf, 16);
395
u32 fwdvb = __fix_zero((plld >> 8) & 7, 8);
396
u32 lfbdv = __fix_zero(plld & 0x3f, 64);
397
u32 pradv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMAD) >> 24) & 7, 8);
398
u32 prbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PRIMBD) >> 24) & 7, 8);
399
u32 opbdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_OPBD) >> 24) & 3, 4);
400
u32 perdv0 = __fix_zero((CPR0_READ(DCRN_CPR0_PERD) >> 24) & 3, 4);
401
402
/* Input clocks for primary dividers */
403
u32 clk_a, clk_b;
404
405
/* Resulting clocks */
406
u32 cpu, plb, opb, ebc, vco;
407
408
/* Timebase */
409
u32 ccr1, tb = tmr_clk;
410
411
if (pllc & 0x40000000) {
412
u32 m;
413
414
/* Feedback path */
415
switch ((pllc >> 24) & 7) {
416
case 0:
417
/* PLLOUTx */
418
m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv;
419
break;
420
case 1:
421
/* CPU */
422
m = fwdva * pradv0;
423
break;
424
case 5:
425
/* PERClk */
426
m = fwdvb * prbdv0 * opbdv0 * perdv0;
427
break;
428
default:
429
printf("WARNING ! Invalid PLL feedback source !\n");
430
goto bypass;
431
}
432
m *= fbdv;
433
vco = sys_clk * m;
434
clk_a = vco / fwdva;
435
clk_b = vco / fwdvb;
436
} else {
437
bypass:
438
/* Bypass system PLL */
439
vco = 0;
440
clk_a = clk_b = sys_clk;
441
}
442
443
cpu = clk_a / pradv0;
444
plb = clk_b / prbdv0;
445
opb = plb / opbdv0;
446
ebc = (per_clk_from_opb ? opb : plb) / perdv0;
447
448
/* Figure out timebase. Either CPU or default TmrClk */
449
ccr1 = mfspr(SPRN_CCR1);
450
451
/* If passed a 0 tmr_clk, force CPU clock */
452
if (tb == 0) {
453
ccr1 &= ~0x80u;
454
mtspr(SPRN_CCR1, ccr1);
455
}
456
if ((ccr1 & 0x0080) == 0)
457
tb = cpu;
458
459
dt_fixup_cpu_clocks(cpu, tb, 0);
460
dt_fixup_clock("/plb", plb);
461
dt_fixup_clock("/plb/opb", opb);
462
dt_fixup_clock("/plb/opb/ebc", ebc);
463
464
return plb;
465
}
466
467
static void eplike_fixup_uart_clk(int index, const char *path,
468
unsigned int ser_clk,
469
unsigned int plb_clk)
470
{
471
unsigned int sdr;
472
unsigned int clock;
473
474
switch (index) {
475
case 0:
476
sdr = SDR0_READ(DCRN_SDR0_UART0);
477
break;
478
case 1:
479
sdr = SDR0_READ(DCRN_SDR0_UART1);
480
break;
481
case 2:
482
sdr = SDR0_READ(DCRN_SDR0_UART2);
483
break;
484
case 3:
485
sdr = SDR0_READ(DCRN_SDR0_UART3);
486
break;
487
default:
488
return;
489
}
490
491
if (sdr & 0x00800000u)
492
clock = ser_clk;
493
else
494
clock = plb_clk / __fix_zero(sdr & 0xff, 256);
495
496
dt_fixup_clock(path, clock);
497
}
498
499
void ibm440ep_fixup_clocks(unsigned int sys_clk,
500
unsigned int ser_clk,
501
unsigned int tmr_clk)
502
{
503
unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 0);
504
505
/* serial clocks need fixup based on int/ext */
506
eplike_fixup_uart_clk(0, "/plb/opb/serial@ef600300", ser_clk, plb_clk);
507
eplike_fixup_uart_clk(1, "/plb/opb/serial@ef600400", ser_clk, plb_clk);
508
eplike_fixup_uart_clk(2, "/plb/opb/serial@ef600500", ser_clk, plb_clk);
509
eplike_fixup_uart_clk(3, "/plb/opb/serial@ef600600", ser_clk, plb_clk);
510
}
511
512
void ibm440gx_fixup_clocks(unsigned int sys_clk,
513
unsigned int ser_clk,
514
unsigned int tmr_clk)
515
{
516
unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
517
518
/* serial clocks need fixup based on int/ext */
519
eplike_fixup_uart_clk(0, "/plb/opb/serial@40000200", ser_clk, plb_clk);
520
eplike_fixup_uart_clk(1, "/plb/opb/serial@40000300", ser_clk, plb_clk);
521
}
522
523
void ibm440spe_fixup_clocks(unsigned int sys_clk,
524
unsigned int ser_clk,
525
unsigned int tmr_clk)
526
{
527
unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
528
529
/* serial clocks need fixup based on int/ext */
530
eplike_fixup_uart_clk(0, "/plb/opb/serial@f0000200", ser_clk, plb_clk);
531
eplike_fixup_uart_clk(1, "/plb/opb/serial@f0000300", ser_clk, plb_clk);
532
eplike_fixup_uart_clk(2, "/plb/opb/serial@f0000600", ser_clk, plb_clk);
533
}
534
535