Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/bcm63xx/cpu.c
26424 views
1
/*
2
* This file is subject to the terms and conditions of the GNU General Public
3
* License. See the file "COPYING" in the main directory of this archive
4
* for more details.
5
*
6
* Copyright (C) 2008 Maxime Bizon <[email protected]>
7
* Copyright (C) 2009 Florian Fainelli <[email protected]>
8
*/
9
10
#include <linux/kernel.h>
11
#include <linux/export.h>
12
#include <linux/cpu.h>
13
#include <asm/cpu.h>
14
#include <asm/cpu-info.h>
15
#include <asm/mipsregs.h>
16
#include <bcm63xx_cpu.h>
17
#include <bcm63xx_regs.h>
18
#include <bcm63xx_io.h>
19
#include <bcm63xx_irq.h>
20
21
const unsigned long *bcm63xx_regs_base;
22
EXPORT_SYMBOL(bcm63xx_regs_base);
23
24
const int *bcm63xx_irqs;
25
EXPORT_SYMBOL(bcm63xx_irqs);
26
27
u16 bcm63xx_cpu_id __read_mostly;
28
EXPORT_SYMBOL(bcm63xx_cpu_id);
29
30
static u8 bcm63xx_cpu_rev;
31
static unsigned int bcm63xx_cpu_freq;
32
static unsigned int bcm63xx_memory_size;
33
34
static const unsigned long bcm3368_regs_base[] = {
35
__GEN_CPU_REGS_TABLE(3368)
36
};
37
38
static const int bcm3368_irqs[] = {
39
__GEN_CPU_IRQ_TABLE(3368)
40
};
41
42
static const unsigned long bcm6328_regs_base[] = {
43
__GEN_CPU_REGS_TABLE(6328)
44
};
45
46
static const int bcm6328_irqs[] = {
47
__GEN_CPU_IRQ_TABLE(6328)
48
};
49
50
static const unsigned long bcm6338_regs_base[] = {
51
__GEN_CPU_REGS_TABLE(6338)
52
};
53
54
static const int bcm6338_irqs[] = {
55
__GEN_CPU_IRQ_TABLE(6338)
56
};
57
58
static const unsigned long bcm6345_regs_base[] = {
59
__GEN_CPU_REGS_TABLE(6345)
60
};
61
62
static const int bcm6345_irqs[] = {
63
__GEN_CPU_IRQ_TABLE(6345)
64
};
65
66
static const unsigned long bcm6348_regs_base[] = {
67
__GEN_CPU_REGS_TABLE(6348)
68
};
69
70
static const int bcm6348_irqs[] = {
71
__GEN_CPU_IRQ_TABLE(6348)
72
73
};
74
75
static const unsigned long bcm6358_regs_base[] = {
76
__GEN_CPU_REGS_TABLE(6358)
77
};
78
79
static const int bcm6358_irqs[] = {
80
__GEN_CPU_IRQ_TABLE(6358)
81
82
};
83
84
static const unsigned long bcm6362_regs_base[] = {
85
__GEN_CPU_REGS_TABLE(6362)
86
};
87
88
static const int bcm6362_irqs[] = {
89
__GEN_CPU_IRQ_TABLE(6362)
90
91
};
92
93
static const unsigned long bcm6368_regs_base[] = {
94
__GEN_CPU_REGS_TABLE(6368)
95
};
96
97
static const int bcm6368_irqs[] = {
98
__GEN_CPU_IRQ_TABLE(6368)
99
100
};
101
102
u8 bcm63xx_get_cpu_rev(void)
103
{
104
return bcm63xx_cpu_rev;
105
}
106
107
EXPORT_SYMBOL(bcm63xx_get_cpu_rev);
108
109
unsigned int bcm63xx_get_cpu_freq(void)
110
{
111
return bcm63xx_cpu_freq;
112
}
113
114
unsigned int bcm63xx_get_memory_size(void)
115
{
116
return bcm63xx_memory_size;
117
}
118
119
static unsigned int detect_cpu_clock(void)
120
{
121
u16 cpu_id = bcm63xx_get_cpu_id();
122
123
switch (cpu_id) {
124
case BCM3368_CPU_ID:
125
return 300000000;
126
127
case BCM6328_CPU_ID:
128
{
129
unsigned int tmp, mips_pll_fcvo;
130
131
tmp = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
132
mips_pll_fcvo = (tmp & STRAPBUS_6328_FCVO_MASK)
133
>> STRAPBUS_6328_FCVO_SHIFT;
134
135
switch (mips_pll_fcvo) {
136
case 0x12:
137
case 0x14:
138
case 0x19:
139
return 160000000;
140
case 0x1c:
141
return 192000000;
142
case 0x13:
143
case 0x15:
144
return 200000000;
145
case 0x1a:
146
return 384000000;
147
case 0x16:
148
return 400000000;
149
default:
150
return 320000000;
151
}
152
153
}
154
case BCM6338_CPU_ID:
155
/* BCM6338 has a fixed 240 Mhz frequency */
156
return 240000000;
157
158
case BCM6345_CPU_ID:
159
/* BCM6345 has a fixed 140Mhz frequency */
160
return 140000000;
161
162
case BCM6348_CPU_ID:
163
{
164
unsigned int tmp, n1, n2, m1;
165
166
/* 16MHz * (N1 + 1) * (N2 + 2) / (M1_CPU + 1) */
167
tmp = bcm_perf_readl(PERF_MIPSPLLCTL_REG);
168
n1 = (tmp & MIPSPLLCTL_N1_MASK) >> MIPSPLLCTL_N1_SHIFT;
169
n2 = (tmp & MIPSPLLCTL_N2_MASK) >> MIPSPLLCTL_N2_SHIFT;
170
m1 = (tmp & MIPSPLLCTL_M1CPU_MASK) >> MIPSPLLCTL_M1CPU_SHIFT;
171
n1 += 1;
172
n2 += 2;
173
m1 += 1;
174
return (16 * 1000000 * n1 * n2) / m1;
175
}
176
177
case BCM6358_CPU_ID:
178
{
179
unsigned int tmp, n1, n2, m1;
180
181
/* 16MHz * N1 * N2 / M1_CPU */
182
tmp = bcm_ddr_readl(DDR_DMIPSPLLCFG_REG);
183
n1 = (tmp & DMIPSPLLCFG_N1_MASK) >> DMIPSPLLCFG_N1_SHIFT;
184
n2 = (tmp & DMIPSPLLCFG_N2_MASK) >> DMIPSPLLCFG_N2_SHIFT;
185
m1 = (tmp & DMIPSPLLCFG_M1_MASK) >> DMIPSPLLCFG_M1_SHIFT;
186
return (16 * 1000000 * n1 * n2) / m1;
187
}
188
189
case BCM6362_CPU_ID:
190
{
191
unsigned int tmp, mips_pll_fcvo;
192
193
tmp = bcm_misc_readl(MISC_STRAPBUS_6362_REG);
194
mips_pll_fcvo = (tmp & STRAPBUS_6362_FCVO_MASK)
195
>> STRAPBUS_6362_FCVO_SHIFT;
196
switch (mips_pll_fcvo) {
197
case 0x03:
198
case 0x0b:
199
case 0x13:
200
case 0x1b:
201
return 240000000;
202
case 0x04:
203
case 0x0c:
204
case 0x14:
205
case 0x1c:
206
return 160000000;
207
case 0x05:
208
case 0x0e:
209
case 0x16:
210
case 0x1e:
211
case 0x1f:
212
return 400000000;
213
case 0x06:
214
return 440000000;
215
case 0x07:
216
case 0x17:
217
return 384000000;
218
case 0x15:
219
case 0x1d:
220
return 200000000;
221
default:
222
return 320000000;
223
}
224
}
225
case BCM6368_CPU_ID:
226
{
227
unsigned int tmp, p1, p2, ndiv, m1;
228
229
/* (64MHz / P1) * P2 * NDIV / M1_CPU */
230
tmp = bcm_ddr_readl(DDR_DMIPSPLLCFG_6368_REG);
231
232
p1 = (tmp & DMIPSPLLCFG_6368_P1_MASK) >>
233
DMIPSPLLCFG_6368_P1_SHIFT;
234
235
p2 = (tmp & DMIPSPLLCFG_6368_P2_MASK) >>
236
DMIPSPLLCFG_6368_P2_SHIFT;
237
238
ndiv = (tmp & DMIPSPLLCFG_6368_NDIV_MASK) >>
239
DMIPSPLLCFG_6368_NDIV_SHIFT;
240
241
tmp = bcm_ddr_readl(DDR_DMIPSPLLDIV_6368_REG);
242
m1 = (tmp & DMIPSPLLDIV_6368_MDIV_MASK) >>
243
DMIPSPLLDIV_6368_MDIV_SHIFT;
244
245
return (((64 * 1000000) / p1) * p2 * ndiv) / m1;
246
}
247
248
default:
249
panic("Failed to detect clock for CPU with id=%04X\n", cpu_id);
250
}
251
}
252
253
/*
254
* attempt to detect the amount of memory installed
255
*/
256
static unsigned int detect_memory_size(void)
257
{
258
unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0;
259
u32 val;
260
261
if (BCMCPU_IS_6328() || BCMCPU_IS_6362())
262
return bcm_ddr_readl(DDR_CSEND_REG) << 24;
263
264
if (BCMCPU_IS_6345()) {
265
val = bcm_sdram_readl(SDRAM_MBASE_REG);
266
return val * 8 * 1024 * 1024;
267
}
268
269
if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
270
val = bcm_sdram_readl(SDRAM_CFG_REG);
271
rows = (val & SDRAM_CFG_ROW_MASK) >> SDRAM_CFG_ROW_SHIFT;
272
cols = (val & SDRAM_CFG_COL_MASK) >> SDRAM_CFG_COL_SHIFT;
273
is_32bits = (val & SDRAM_CFG_32B_MASK) ? 1 : 0;
274
banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1;
275
}
276
277
if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
278
val = bcm_memc_readl(MEMC_CFG_REG);
279
rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT;
280
cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT;
281
is_32bits = (val & MEMC_CFG_32B_MASK) ? 0 : 1;
282
banks = 2;
283
}
284
285
/* 0 => 11 address bits ... 2 => 13 address bits */
286
rows += 11;
287
288
/* 0 => 8 address bits ... 2 => 10 address bits */
289
cols += 8;
290
291
return 1 << (cols + rows + (is_32bits + 1) + banks);
292
}
293
294
void __init bcm63xx_cpu_init(void)
295
{
296
unsigned int tmp;
297
unsigned int cpu = smp_processor_id();
298
u32 chipid_reg;
299
300
/* soc registers location depends on cpu type */
301
chipid_reg = 0;
302
303
switch (current_cpu_type()) {
304
case CPU_BMIPS3300:
305
if ((read_c0_prid() & PRID_IMP_MASK) != PRID_IMP_BMIPS3300_ALT)
306
__cpu_name[cpu] = "Broadcom BCM6338";
307
fallthrough;
308
case CPU_BMIPS32:
309
chipid_reg = BCM_6345_PERF_BASE;
310
break;
311
case CPU_BMIPS4350:
312
switch ((read_c0_prid() & PRID_REV_MASK)) {
313
case 0x04:
314
chipid_reg = BCM_3368_PERF_BASE;
315
break;
316
case 0x10:
317
chipid_reg = BCM_6345_PERF_BASE;
318
break;
319
default:
320
chipid_reg = BCM_6368_PERF_BASE;
321
break;
322
}
323
break;
324
}
325
326
/*
327
* really early to panic, but delaying panic would not help since we
328
* will never get any working console
329
*/
330
if (!chipid_reg)
331
panic("unsupported Broadcom CPU");
332
333
/* read out CPU type */
334
tmp = bcm_readl(chipid_reg);
335
bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT;
336
bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT;
337
338
switch (bcm63xx_cpu_id) {
339
case BCM3368_CPU_ID:
340
bcm63xx_regs_base = bcm3368_regs_base;
341
bcm63xx_irqs = bcm3368_irqs;
342
break;
343
case BCM6328_CPU_ID:
344
bcm63xx_regs_base = bcm6328_regs_base;
345
bcm63xx_irqs = bcm6328_irqs;
346
break;
347
case BCM6338_CPU_ID:
348
bcm63xx_regs_base = bcm6338_regs_base;
349
bcm63xx_irqs = bcm6338_irqs;
350
break;
351
case BCM6345_CPU_ID:
352
bcm63xx_regs_base = bcm6345_regs_base;
353
bcm63xx_irqs = bcm6345_irqs;
354
break;
355
case BCM6348_CPU_ID:
356
bcm63xx_regs_base = bcm6348_regs_base;
357
bcm63xx_irqs = bcm6348_irqs;
358
break;
359
case BCM6358_CPU_ID:
360
bcm63xx_regs_base = bcm6358_regs_base;
361
bcm63xx_irqs = bcm6358_irqs;
362
break;
363
case BCM6362_CPU_ID:
364
bcm63xx_regs_base = bcm6362_regs_base;
365
bcm63xx_irqs = bcm6362_irqs;
366
break;
367
case BCM6368_CPU_ID:
368
bcm63xx_regs_base = bcm6368_regs_base;
369
bcm63xx_irqs = bcm6368_irqs;
370
break;
371
default:
372
panic("unsupported broadcom CPU %x", bcm63xx_cpu_id);
373
break;
374
}
375
376
bcm63xx_cpu_freq = detect_cpu_clock();
377
bcm63xx_memory_size = detect_memory_size();
378
379
pr_info("Detected Broadcom 0x%04x CPU revision %02x\n",
380
bcm63xx_cpu_id, bcm63xx_cpu_rev);
381
pr_info("CPU frequency is %u MHz\n",
382
bcm63xx_cpu_freq / 1000000);
383
pr_info("%uMB of RAM installed\n",
384
bcm63xx_memory_size >> 20);
385
}
386
387