2 * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
4 * Derived from linux/arch/mips/bcm63xx/cpu.c:
5 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
6 * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org>
8 * SPDX-License-Identifier: GPL-2.0+
17 DECLARE_GLOBAL_DATA_PTR
;
19 #define REV_CHIPID_SHIFT 16
20 #define REV_CHIPID_MASK (0xffff << REV_CHIPID_SHIFT)
21 #define REV_LONG_CHIPID_SHIFT 12
22 #define REV_LONG_CHIPID_MASK (0xfffff << REV_LONG_CHIPID_SHIFT)
23 #define REV_REVID_SHIFT 0
24 #define REV_REVID_MASK (0xff << REV_REVID_SHIFT)
26 #define REG_BCM6328_OTP 0x62c
27 #define BCM6328_TP1_DISABLED BIT(9)
29 #define REG_BCM6318_STRAP_OVRDBUS 0x900
30 #define OVRDBUS_6318_FREQ_SHIFT 23
31 #define OVRDBUS_6318_FREQ_MASK (0x3 << OVRDBUS_6318_FREQ_SHIFT)
33 #define REG_BCM6328_MISC_STRAPBUS 0x1a40
34 #define STRAPBUS_6328_FCVO_SHIFT 7
35 #define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT)
37 #define REG_BCM6348_PERF_MIPSPLLCFG 0x34
38 #define MIPSPLLCFG_6348_M1CPU_SHIFT 6
39 #define MIPSPLLCFG_6348_M1CPU_MASK (0x7 << MIPSPLLCFG_6348_M1CPU_SHIFT)
40 #define MIPSPLLCFG_6348_N2_SHIFT 15
41 #define MIPSPLLCFG_6348_N2_MASK (0x1F << MIPSPLLCFG_6348_N2_SHIFT)
42 #define MIPSPLLCFG_6348_N1_SHIFT 20
43 #define MIPSPLLCFG_6348_N1_MASK (0x7 << MIPSPLLCFG_6348_N1_SHIFT)
45 #define REG_BCM6358_DDR_DMIPSPLLCFG 0x12b8
46 #define DMIPSPLLCFG_6358_M1_SHIFT 0
47 #define DMIPSPLLCFG_6358_M1_MASK (0xff << DMIPSPLLCFG_6358_M1_SHIFT)
48 #define DMIPSPLLCFG_6358_N1_SHIFT 23
49 #define DMIPSPLLCFG_6358_N1_MASK (0x3f << DMIPSPLLCFG_6358_N1_SHIFT)
50 #define DMIPSPLLCFG_6358_N2_SHIFT 29
51 #define DMIPSPLLCFG_6358_N2_MASK (0x7 << DMIPSPLLCFG_6358_N2_SHIFT)
53 #define REG_BCM6368_DDR_DMIPSPLLCFG 0x12a0
54 #define DMIPSPLLCFG_6368_P1_SHIFT 0
55 #define DMIPSPLLCFG_6368_P1_MASK (0xf << DMIPSPLLCFG_6368_P1_SHIFT)
56 #define DMIPSPLLCFG_6368_P2_SHIFT 4
57 #define DMIPSPLLCFG_6368_P2_MASK (0xf << DMIPSPLLCFG_6368_P2_SHIFT)
58 #define DMIPSPLLCFG_6368_NDIV_SHIFT 16
59 #define DMIPSPLLCFG_6368_NDIV_MASK (0x1ff << DMIPSPLLCFG_6368_NDIV_SHIFT)
60 #define REG_BCM6368_DDR_DMIPSPLLDIV 0x12a4
61 #define DMIPSPLLDIV_6368_MDIV_SHIFT 0
62 #define DMIPSPLLDIV_6368_MDIV_MASK (0xff << DMIPSPLLDIV_6368_MDIV_SHIFT)
64 #define REG_BCM63268_MISC_STRAPBUS 0x1814
65 #define STRAPBUS_63268_FCVO_SHIFT 21
66 #define STRAPBUS_63268_FCVO_MASK (0xf << STRAPBUS_63268_FCVO_SHIFT)
68 struct bmips_cpu_priv
;
71 int (*get_cpu_desc
)(struct bmips_cpu_priv
*priv
, char *buf
, int size
);
72 ulong (*get_cpu_freq
)(struct bmips_cpu_priv
*);
73 int (*get_cpu_count
)(struct bmips_cpu_priv
*);
76 struct bmips_cpu_priv
{
78 const struct bmips_cpu_hw
*hw
;
81 /* Specific CPU Ops */
82 static int bmips_short_cpu_desc(struct bmips_cpu_priv
*priv
, char *buf
,
85 unsigned short cpu_id
;
86 unsigned char cpu_rev
;
89 val
= readl_be(priv
->regs
);
90 cpu_id
= (val
& REV_CHIPID_MASK
) >> REV_CHIPID_SHIFT
;
91 cpu_rev
= (val
& REV_REVID_MASK
) >> REV_REVID_SHIFT
;
93 snprintf(buf
, size
, "BCM%04X%02X", cpu_id
, cpu_rev
);
98 static int bmips_long_cpu_desc(struct bmips_cpu_priv
*priv
, char *buf
,
102 unsigned char cpu_rev
;
105 val
= readl_be(priv
->regs
);
106 cpu_id
= (val
& REV_LONG_CHIPID_MASK
) >> REV_LONG_CHIPID_SHIFT
;
107 cpu_rev
= (val
& REV_REVID_MASK
) >> REV_REVID_SHIFT
;
109 snprintf(buf
, size
, "BCM%05X%02X", cpu_id
, cpu_rev
);
114 static ulong
bcm3380_get_cpu_freq(struct bmips_cpu_priv
*priv
)
119 static ulong
bcm6318_get_cpu_freq(struct bmips_cpu_priv
*priv
)
121 unsigned int mips_pll_fcvo
;
123 mips_pll_fcvo
= readl_be(priv
->regs
+ REG_BCM6318_STRAP_OVRDBUS
);
124 mips_pll_fcvo
= (mips_pll_fcvo
& OVRDBUS_6318_FREQ_MASK
)
125 >> OVRDBUS_6318_FREQ_SHIFT
;
127 switch (mips_pll_fcvo
) {
141 static ulong
bcm6328_get_cpu_freq(struct bmips_cpu_priv
*priv
)
143 unsigned int mips_pll_fcvo
;
145 mips_pll_fcvo
= readl_be(priv
->regs
+ REG_BCM6328_MISC_STRAPBUS
);
146 mips_pll_fcvo
= (mips_pll_fcvo
& STRAPBUS_6328_FCVO_MASK
)
147 >> STRAPBUS_6328_FCVO_SHIFT
;
149 switch (mips_pll_fcvo
) {
168 static ulong
bcm6338_get_cpu_freq(struct bmips_cpu_priv
*priv
)
173 static ulong
bcm6348_get_cpu_freq(struct bmips_cpu_priv
*priv
)
175 unsigned int tmp
, n1
, n2
, m1
;
177 tmp
= readl_be(priv
->regs
+ REG_BCM6348_PERF_MIPSPLLCFG
);
178 n1
= (tmp
& MIPSPLLCFG_6348_N1_MASK
) >> MIPSPLLCFG_6348_N1_SHIFT
;
179 n2
= (tmp
& MIPSPLLCFG_6348_N2_MASK
) >> MIPSPLLCFG_6348_N2_SHIFT
;
180 m1
= (tmp
& MIPSPLLCFG_6348_M1CPU_MASK
) >> MIPSPLLCFG_6348_M1CPU_SHIFT
;
182 return (16 * 1000000 * (n1
+ 1) * (n2
+ 2)) / (m1
+ 1);
185 static ulong
bcm6358_get_cpu_freq(struct bmips_cpu_priv
*priv
)
187 unsigned int tmp
, n1
, n2
, m1
;
189 tmp
= readl_be(priv
->regs
+ REG_BCM6358_DDR_DMIPSPLLCFG
);
190 n1
= (tmp
& DMIPSPLLCFG_6358_N1_MASK
) >> DMIPSPLLCFG_6358_N1_SHIFT
;
191 n2
= (tmp
& DMIPSPLLCFG_6358_N2_MASK
) >> DMIPSPLLCFG_6358_N2_SHIFT
;
192 m1
= (tmp
& DMIPSPLLCFG_6358_M1_MASK
) >> DMIPSPLLCFG_6358_M1_SHIFT
;
194 return (16 * 1000000 * n1
* n2
) / m1
;
197 static ulong
bcm6368_get_cpu_freq(struct bmips_cpu_priv
*priv
)
199 unsigned int tmp
, p1
, p2
, ndiv
, m1
;
201 tmp
= readl_be(priv
->regs
+ REG_BCM6368_DDR_DMIPSPLLCFG
);
202 p1
= (tmp
& DMIPSPLLCFG_6368_P1_MASK
) >> DMIPSPLLCFG_6368_P1_SHIFT
;
203 p2
= (tmp
& DMIPSPLLCFG_6368_P2_MASK
) >> DMIPSPLLCFG_6368_P2_SHIFT
;
204 ndiv
= (tmp
& DMIPSPLLCFG_6368_NDIV_MASK
) >>
205 DMIPSPLLCFG_6368_NDIV_SHIFT
;
207 tmp
= readl_be(priv
->regs
+ REG_BCM6368_DDR_DMIPSPLLDIV
);
208 m1
= (tmp
& DMIPSPLLDIV_6368_MDIV_MASK
) >> DMIPSPLLDIV_6368_MDIV_SHIFT
;
210 return (((64 * 1000000) / p1
) * p2
* ndiv
) / m1
;
213 static ulong
bcm63268_get_cpu_freq(struct bmips_cpu_priv
*priv
)
215 unsigned int mips_pll_fcvo
;
217 mips_pll_fcvo
= readl_be(priv
->regs
+ REG_BCM63268_MISC_STRAPBUS
);
218 mips_pll_fcvo
= (mips_pll_fcvo
& STRAPBUS_63268_FCVO_MASK
)
219 >> STRAPBUS_63268_FCVO_SHIFT
;
221 switch (mips_pll_fcvo
) {
236 static int bcm6328_get_cpu_count(struct bmips_cpu_priv
*priv
)
238 u32 val
= readl_be(priv
->regs
+ REG_BCM6328_OTP
);
240 if (val
& BCM6328_TP1_DISABLED
)
246 static int bcm6345_get_cpu_count(struct bmips_cpu_priv
*priv
)
251 static int bcm6358_get_cpu_count(struct bmips_cpu_priv
*priv
)
256 static const struct bmips_cpu_hw bmips_cpu_bcm3380
= {
257 .get_cpu_desc
= bmips_short_cpu_desc
,
258 .get_cpu_freq
= bcm3380_get_cpu_freq
,
259 .get_cpu_count
= bcm6358_get_cpu_count
,
262 static const struct bmips_cpu_hw bmips_cpu_bcm6318
= {
263 .get_cpu_desc
= bmips_short_cpu_desc
,
264 .get_cpu_freq
= bcm6318_get_cpu_freq
,
265 .get_cpu_count
= bcm6345_get_cpu_count
,
268 static const struct bmips_cpu_hw bmips_cpu_bcm6328
= {
269 .get_cpu_desc
= bmips_long_cpu_desc
,
270 .get_cpu_freq
= bcm6328_get_cpu_freq
,
271 .get_cpu_count
= bcm6328_get_cpu_count
,
274 static const struct bmips_cpu_hw bmips_cpu_bcm6338
= {
275 .get_cpu_desc
= bmips_short_cpu_desc
,
276 .get_cpu_freq
= bcm6338_get_cpu_freq
,
277 .get_cpu_count
= bcm6345_get_cpu_count
,
280 static const struct bmips_cpu_hw bmips_cpu_bcm6348
= {
281 .get_cpu_desc
= bmips_short_cpu_desc
,
282 .get_cpu_freq
= bcm6348_get_cpu_freq
,
283 .get_cpu_count
= bcm6345_get_cpu_count
,
286 static const struct bmips_cpu_hw bmips_cpu_bcm6358
= {
287 .get_cpu_desc
= bmips_short_cpu_desc
,
288 .get_cpu_freq
= bcm6358_get_cpu_freq
,
289 .get_cpu_count
= bcm6358_get_cpu_count
,
292 static const struct bmips_cpu_hw bmips_cpu_bcm6368
= {
293 .get_cpu_desc
= bmips_short_cpu_desc
,
294 .get_cpu_freq
= bcm6368_get_cpu_freq
,
295 .get_cpu_count
= bcm6358_get_cpu_count
,
298 static const struct bmips_cpu_hw bmips_cpu_bcm63268
= {
299 .get_cpu_desc
= bmips_long_cpu_desc
,
300 .get_cpu_freq
= bcm63268_get_cpu_freq
,
301 .get_cpu_count
= bcm6358_get_cpu_count
,
304 /* Generic CPU Ops */
305 static int bmips_cpu_get_desc(struct udevice
*dev
, char *buf
, int size
)
307 struct bmips_cpu_priv
*priv
= dev_get_priv(dev
);
308 const struct bmips_cpu_hw
*hw
= priv
->hw
;
310 return hw
->get_cpu_desc(priv
, buf
, size
);
313 static int bmips_cpu_get_info(struct udevice
*dev
, struct cpu_info
*info
)
315 struct bmips_cpu_priv
*priv
= dev_get_priv(dev
);
316 const struct bmips_cpu_hw
*hw
= priv
->hw
;
318 info
->cpu_freq
= hw
->get_cpu_freq(priv
);
319 info
->features
= BIT(CPU_FEAT_L1_CACHE
);
320 info
->features
|= BIT(CPU_FEAT_MMU
);
321 info
->features
|= BIT(CPU_FEAT_DEVICE_ID
);
326 static int bmips_cpu_get_count(struct udevice
*dev
)
328 struct bmips_cpu_priv
*priv
= dev_get_priv(dev
);
329 const struct bmips_cpu_hw
*hw
= priv
->hw
;
331 return hw
->get_cpu_count(priv
);
334 static int bmips_cpu_get_vendor(struct udevice
*dev
, char *buf
, int size
)
336 snprintf(buf
, size
, "Broadcom");
341 static const struct cpu_ops bmips_cpu_ops
= {
342 .get_desc
= bmips_cpu_get_desc
,
343 .get_info
= bmips_cpu_get_info
,
344 .get_count
= bmips_cpu_get_count
,
345 .get_vendor
= bmips_cpu_get_vendor
,
348 /* BMIPS CPU driver */
349 int bmips_cpu_bind(struct udevice
*dev
)
351 struct cpu_platdata
*plat
= dev_get_parent_platdata(dev
);
353 plat
->cpu_id
= fdtdec_get_int(gd
->fdt_blob
, dev_of_offset(dev
),
355 plat
->device_id
= read_c0_prid();
360 int bmips_cpu_probe(struct udevice
*dev
)
362 struct bmips_cpu_priv
*priv
= dev_get_priv(dev
);
363 const struct bmips_cpu_hw
*hw
=
364 (const struct bmips_cpu_hw
*)dev_get_driver_data(dev
);
368 addr
= devfdt_get_addr_size_index(dev_get_parent(dev
), 0, &size
);
369 if (addr
== FDT_ADDR_T_NONE
)
372 priv
->regs
= ioremap(addr
, size
);
378 static const struct udevice_id bmips_cpu_ids
[] = {
380 .compatible
= "brcm,bcm3380-cpu",
381 .data
= (ulong
)&bmips_cpu_bcm3380
,
383 .compatible
= "brcm,bcm6318-cpu",
384 .data
= (ulong
)&bmips_cpu_bcm6318
,
386 .compatible
= "brcm,bcm6328-cpu",
387 .data
= (ulong
)&bmips_cpu_bcm6328
,
389 .compatible
= "brcm,bcm6338-cpu",
390 .data
= (ulong
)&bmips_cpu_bcm6338
,
392 .compatible
= "brcm,bcm6348-cpu",
393 .data
= (ulong
)&bmips_cpu_bcm6348
,
395 .compatible
= "brcm,bcm6358-cpu",
396 .data
= (ulong
)&bmips_cpu_bcm6358
,
398 .compatible
= "brcm,bcm6368-cpu",
399 .data
= (ulong
)&bmips_cpu_bcm6368
,
401 .compatible
= "brcm,bcm63268-cpu",
402 .data
= (ulong
)&bmips_cpu_bcm63268
,
407 U_BOOT_DRIVER(bmips_cpu_drv
) = {
410 .of_match
= bmips_cpu_ids
,
411 .bind
= bmips_cpu_bind
,
412 .probe
= bmips_cpu_probe
,
413 .priv_auto_alloc_size
= sizeof(struct bmips_cpu_priv
),
414 .ops
= &bmips_cpu_ops
,
415 .flags
= DM_FLAG_PRE_RELOC
,
418 #ifdef CONFIG_DISPLAY_CPUINFO
419 int print_cpuinfo(void)
426 err
= uclass_get_device(UCLASS_CPU
, 0, &dev
);
430 err
= cpu_get_info(dev
, &cpu
);
434 err
= cpu_get_desc(dev
, desc
, sizeof(desc
));
438 printf("Chip ID: %s, MIPS: ", desc
);
439 print_freq(cpu
.cpu_freq
, "\n");