"Das U-Boot" Source Tree
at master 522 lines 13 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com> 4 * 5 * Derived from linux/arch/mips/bcm63xx/cpu.c: 6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> 7 * Copyright (C) 2009 Florian Fainelli <florian@openwrt.org> 8 */ 9 10#include <cpu.h> 11#include <display_options.h> 12#include <dm.h> 13#include <errno.h> 14#include <init.h> 15#include <asm/io.h> 16#include <linux/bitops.h> 17 18#define REV_CHIPID_SHIFT 16 19#define REV_CHIPID_MASK (0xffff << REV_CHIPID_SHIFT) 20#define REV_LONG_CHIPID_SHIFT 12 21#define REV_LONG_CHIPID_MASK (0xfffff << REV_LONG_CHIPID_SHIFT) 22#define REV_REVID_SHIFT 0 23#define REV_REVID_MASK (0xff << REV_REVID_SHIFT) 24 25#define REG_BCM6328_OTP 0x62c 26#define BCM6328_TP1_DISABLED BIT(9) 27 28#define REG_BCM6318_STRAP_OVRDBUS 0x900 29#define OVRDBUS_6318_FREQ_SHIFT 23 30#define OVRDBUS_6318_FREQ_MASK (0x3 << OVRDBUS_6318_FREQ_SHIFT) 31 32#define REG_BCM6328_MISC_STRAPBUS 0x1a40 33#define STRAPBUS_6328_FCVO_SHIFT 7 34#define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT) 35 36#define REG_BCM6348_PERF_MIPSPLLCFG 0x34 37#define MIPSPLLCFG_6348_M1CPU_SHIFT 6 38#define MIPSPLLCFG_6348_M1CPU_MASK (0x7 << MIPSPLLCFG_6348_M1CPU_SHIFT) 39#define MIPSPLLCFG_6348_N2_SHIFT 15 40#define MIPSPLLCFG_6348_N2_MASK (0x1F << MIPSPLLCFG_6348_N2_SHIFT) 41#define MIPSPLLCFG_6348_N1_SHIFT 20 42#define MIPSPLLCFG_6348_N1_MASK (0x7 << MIPSPLLCFG_6348_N1_SHIFT) 43 44#define REG_BCM6358_DDR_DMIPSPLLCFG 0x12b8 45#define DMIPSPLLCFG_6358_M1_SHIFT 0 46#define DMIPSPLLCFG_6358_M1_MASK (0xff << DMIPSPLLCFG_6358_M1_SHIFT) 47#define DMIPSPLLCFG_6358_N1_SHIFT 23 48#define DMIPSPLLCFG_6358_N1_MASK (0x3f << DMIPSPLLCFG_6358_N1_SHIFT) 49#define DMIPSPLLCFG_6358_N2_SHIFT 29 50#define DMIPSPLLCFG_6358_N2_MASK (0x7 << DMIPSPLLCFG_6358_N2_SHIFT) 51 52#define REG_BCM6362_MISC_STRAPBUS 0x1814 53#define STRAPBUS_6362_FCVO_SHIFT 1 54#define STRAPBUS_6362_FCVO_MASK (0x1f << STRAPBUS_6362_FCVO_SHIFT) 55 56#define REG_BCM6368_DDR_DMIPSPLLCFG 0x12a0 57#define DMIPSPLLCFG_6368_P1_SHIFT 0 58#define DMIPSPLLCFG_6368_P1_MASK (0xf << DMIPSPLLCFG_6368_P1_SHIFT) 59#define DMIPSPLLCFG_6368_P2_SHIFT 4 60#define DMIPSPLLCFG_6368_P2_MASK (0xf << DMIPSPLLCFG_6368_P2_SHIFT) 61#define DMIPSPLLCFG_6368_NDIV_SHIFT 16 62#define DMIPSPLLCFG_6368_NDIV_MASK (0x1ff << DMIPSPLLCFG_6368_NDIV_SHIFT) 63#define REG_BCM6368_DDR_DMIPSPLLDIV 0x12a4 64#define DMIPSPLLDIV_6368_MDIV_SHIFT 0 65#define DMIPSPLLDIV_6368_MDIV_MASK (0xff << DMIPSPLLDIV_6368_MDIV_SHIFT) 66 67#define REG_BCM63268_MISC_STRAPBUS 0x1814 68#define STRAPBUS_63268_FCVO_SHIFT 21 69#define STRAPBUS_63268_FCVO_MASK (0xf << STRAPBUS_63268_FCVO_SHIFT) 70 71#define REG_BCM6838_OTP_BRCMBITS0 0x440 72#define VIPER_6838_FREQ_SHIFT 18 73#define VIPER_6838_FREQ_MASK (0x7 << VIPER_6838_FREQ_SHIFT) 74 75struct bmips_cpu_priv; 76 77struct bmips_cpu_hw { 78 int (*get_cpu_desc)(struct bmips_cpu_priv *priv, char *buf, int size); 79 ulong (*get_cpu_freq)(struct bmips_cpu_priv *); 80 int (*get_cpu_count)(struct bmips_cpu_priv *); 81}; 82 83struct bmips_cpu_priv { 84 void __iomem *regs; 85 const struct bmips_cpu_hw *hw; 86}; 87 88/* Specific CPU Ops */ 89static int bmips_short_cpu_desc(struct bmips_cpu_priv *priv, char *buf, 90 int size) 91{ 92 unsigned short cpu_id; 93 unsigned char cpu_rev; 94 u32 val; 95 96 val = readl_be(priv->regs); 97 cpu_id = (val & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT; 98 cpu_rev = (val & REV_REVID_MASK) >> REV_REVID_SHIFT; 99 100 snprintf(buf, size, "BCM%04X%02X", cpu_id, cpu_rev); 101 102 return 0; 103} 104 105static int bmips_long_cpu_desc(struct bmips_cpu_priv *priv, char *buf, 106 int size) 107{ 108 unsigned int cpu_id; 109 unsigned char cpu_rev; 110 u32 val; 111 112 val = readl_be(priv->regs); 113 cpu_id = (val & REV_LONG_CHIPID_MASK) >> REV_LONG_CHIPID_SHIFT; 114 cpu_rev = (val & REV_REVID_MASK) >> REV_REVID_SHIFT; 115 116 snprintf(buf, size, "BCM%05X%02X", cpu_id, cpu_rev); 117 118 return 0; 119} 120 121static ulong bcm3380_get_cpu_freq(struct bmips_cpu_priv *priv) 122{ 123 return 333000000; 124} 125 126static ulong bcm6318_get_cpu_freq(struct bmips_cpu_priv *priv) 127{ 128 unsigned int mips_pll_fcvo; 129 130 mips_pll_fcvo = readl_be(priv->regs + REG_BCM6318_STRAP_OVRDBUS); 131 mips_pll_fcvo = (mips_pll_fcvo & OVRDBUS_6318_FREQ_MASK) 132 >> OVRDBUS_6318_FREQ_SHIFT; 133 134 switch (mips_pll_fcvo) { 135 case 0: 136 return 166000000; 137 case 1: 138 return 400000000; 139 case 2: 140 return 250000000; 141 case 3: 142 return 333000000; 143 default: 144 return 0; 145 } 146} 147 148static ulong bcm6328_get_cpu_freq(struct bmips_cpu_priv *priv) 149{ 150 unsigned int mips_pll_fcvo; 151 152 mips_pll_fcvo = readl_be(priv->regs + REG_BCM6328_MISC_STRAPBUS); 153 mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_6328_FCVO_MASK) 154 >> STRAPBUS_6328_FCVO_SHIFT; 155 156 switch (mips_pll_fcvo) { 157 case 0x12: 158 case 0x14: 159 case 0x19: 160 return 160000000; 161 case 0x1c: 162 return 192000000; 163 case 0x13: 164 case 0x15: 165 return 200000000; 166 case 0x1a: 167 return 384000000; 168 case 0x16: 169 return 400000000; 170 default: 171 return 320000000; 172 } 173} 174 175static ulong bcm6338_get_cpu_freq(struct bmips_cpu_priv *priv) 176{ 177 return 240000000; 178} 179 180static ulong bcm6348_get_cpu_freq(struct bmips_cpu_priv *priv) 181{ 182 unsigned int tmp, n1, n2, m1; 183 184 tmp = readl_be(priv->regs + REG_BCM6348_PERF_MIPSPLLCFG); 185 n1 = (tmp & MIPSPLLCFG_6348_N1_MASK) >> MIPSPLLCFG_6348_N1_SHIFT; 186 n2 = (tmp & MIPSPLLCFG_6348_N2_MASK) >> MIPSPLLCFG_6348_N2_SHIFT; 187 m1 = (tmp & MIPSPLLCFG_6348_M1CPU_MASK) >> MIPSPLLCFG_6348_M1CPU_SHIFT; 188 189 return (16 * 1000000 * (n1 + 1) * (n2 + 2)) / (m1 + 1); 190} 191 192static ulong bcm6358_get_cpu_freq(struct bmips_cpu_priv *priv) 193{ 194 unsigned int tmp, n1, n2, m1; 195 196 tmp = readl_be(priv->regs + REG_BCM6358_DDR_DMIPSPLLCFG); 197 n1 = (tmp & DMIPSPLLCFG_6358_N1_MASK) >> DMIPSPLLCFG_6358_N1_SHIFT; 198 n2 = (tmp & DMIPSPLLCFG_6358_N2_MASK) >> DMIPSPLLCFG_6358_N2_SHIFT; 199 m1 = (tmp & DMIPSPLLCFG_6358_M1_MASK) >> DMIPSPLLCFG_6358_M1_SHIFT; 200 201 return (16 * 1000000 * n1 * n2) / m1; 202} 203 204static ulong bcm6362_get_cpu_freq(struct bmips_cpu_priv *priv) 205{ 206 unsigned int mips_pll_fcvo; 207 208 mips_pll_fcvo = readl_be(priv->regs + REG_BCM6362_MISC_STRAPBUS); 209 mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_6362_FCVO_MASK) 210 >> STRAPBUS_6362_FCVO_SHIFT; 211 212 switch (mips_pll_fcvo) { 213 case 0x03: 214 case 0x0b: 215 case 0x13: 216 case 0x1b: 217 return 240000000; 218 case 0x04: 219 case 0x0c: 220 case 0x14: 221 case 0x1c: 222 return 160000000; 223 case 0x05: 224 case 0x0e: 225 case 0x16: 226 case 0x1e: 227 case 0x1f: 228 return 400000000; 229 case 0x06: 230 return 440000000; 231 case 0x07: 232 case 0x17: 233 return 384000000; 234 case 0x15: 235 case 0x1d: 236 return 200000000; 237 default: 238 return 320000000; 239 } 240} 241 242static ulong bcm6368_get_cpu_freq(struct bmips_cpu_priv *priv) 243{ 244 unsigned int tmp, p1, p2, ndiv, m1; 245 246 tmp = readl_be(priv->regs + REG_BCM6368_DDR_DMIPSPLLCFG); 247 p1 = (tmp & DMIPSPLLCFG_6368_P1_MASK) >> DMIPSPLLCFG_6368_P1_SHIFT; 248 p2 = (tmp & DMIPSPLLCFG_6368_P2_MASK) >> DMIPSPLLCFG_6368_P2_SHIFT; 249 ndiv = (tmp & DMIPSPLLCFG_6368_NDIV_MASK) >> 250 DMIPSPLLCFG_6368_NDIV_SHIFT; 251 252 tmp = readl_be(priv->regs + REG_BCM6368_DDR_DMIPSPLLDIV); 253 m1 = (tmp & DMIPSPLLDIV_6368_MDIV_MASK) >> DMIPSPLLDIV_6368_MDIV_SHIFT; 254 255 return (((64 * 1000000) / p1) * p2 * ndiv) / m1; 256} 257 258static ulong bcm63268_get_cpu_freq(struct bmips_cpu_priv *priv) 259{ 260 unsigned int mips_pll_fcvo; 261 262 mips_pll_fcvo = readl_be(priv->regs + REG_BCM63268_MISC_STRAPBUS); 263 mips_pll_fcvo = (mips_pll_fcvo & STRAPBUS_63268_FCVO_MASK) 264 >> STRAPBUS_63268_FCVO_SHIFT; 265 266 switch (mips_pll_fcvo) { 267 case 0x3: 268 case 0xe: 269 return 320000000; 270 case 0xa: 271 return 333000000; 272 case 0x2: 273 case 0xb: 274 case 0xf: 275 return 400000000; 276 default: 277 return 0; 278 } 279} 280 281static ulong bcm6838_get_cpu_freq(struct bmips_cpu_priv *priv) 282{ 283 unsigned int mips_viper_freq; 284 285 mips_viper_freq = readl_be(priv->regs + REG_BCM6838_OTP_BRCMBITS0); 286 mips_viper_freq = (mips_viper_freq & VIPER_6838_FREQ_MASK) 287 >> VIPER_6838_FREQ_SHIFT; 288 289 switch (mips_viper_freq) { 290 case 0x0: 291 return 600000000; 292 case 0x1: 293 return 400000000; 294 case 0x2: 295 return 240000000; 296 default: 297 return 0; 298 } 299} 300 301static int bcm6328_get_cpu_count(struct bmips_cpu_priv *priv) 302{ 303 u32 val = readl_be(priv->regs + REG_BCM6328_OTP); 304 305 if (val & BCM6328_TP1_DISABLED) 306 return 1; 307 else 308 return 2; 309} 310 311static int bcm6345_get_cpu_count(struct bmips_cpu_priv *priv) 312{ 313 return 1; 314} 315 316static int bcm6358_get_cpu_count(struct bmips_cpu_priv *priv) 317{ 318 return 2; 319} 320 321static const struct bmips_cpu_hw bmips_cpu_bcm3380 = { 322 .get_cpu_desc = bmips_short_cpu_desc, 323 .get_cpu_freq = bcm3380_get_cpu_freq, 324 .get_cpu_count = bcm6358_get_cpu_count, 325}; 326 327static const struct bmips_cpu_hw bmips_cpu_bcm6318 = { 328 .get_cpu_desc = bmips_short_cpu_desc, 329 .get_cpu_freq = bcm6318_get_cpu_freq, 330 .get_cpu_count = bcm6345_get_cpu_count, 331}; 332 333static const struct bmips_cpu_hw bmips_cpu_bcm6328 = { 334 .get_cpu_desc = bmips_long_cpu_desc, 335 .get_cpu_freq = bcm6328_get_cpu_freq, 336 .get_cpu_count = bcm6328_get_cpu_count, 337}; 338 339static const struct bmips_cpu_hw bmips_cpu_bcm6338 = { 340 .get_cpu_desc = bmips_short_cpu_desc, 341 .get_cpu_freq = bcm6338_get_cpu_freq, 342 .get_cpu_count = bcm6345_get_cpu_count, 343}; 344 345static const struct bmips_cpu_hw bmips_cpu_bcm6348 = { 346 .get_cpu_desc = bmips_short_cpu_desc, 347 .get_cpu_freq = bcm6348_get_cpu_freq, 348 .get_cpu_count = bcm6345_get_cpu_count, 349}; 350 351static const struct bmips_cpu_hw bmips_cpu_bcm6358 = { 352 .get_cpu_desc = bmips_short_cpu_desc, 353 .get_cpu_freq = bcm6358_get_cpu_freq, 354 .get_cpu_count = bcm6358_get_cpu_count, 355}; 356 357static const struct bmips_cpu_hw bmips_cpu_bcm6362 = { 358 .get_cpu_desc = bmips_short_cpu_desc, 359 .get_cpu_freq = bcm6362_get_cpu_freq, 360 .get_cpu_count = bcm6358_get_cpu_count, 361}; 362 363static const struct bmips_cpu_hw bmips_cpu_bcm6368 = { 364 .get_cpu_desc = bmips_short_cpu_desc, 365 .get_cpu_freq = bcm6368_get_cpu_freq, 366 .get_cpu_count = bcm6358_get_cpu_count, 367}; 368 369static const struct bmips_cpu_hw bmips_cpu_bcm63268 = { 370 .get_cpu_desc = bmips_long_cpu_desc, 371 .get_cpu_freq = bcm63268_get_cpu_freq, 372 .get_cpu_count = bcm6358_get_cpu_count, 373}; 374 375static const struct bmips_cpu_hw bmips_cpu_bcm6838 = { 376 .get_cpu_desc = bmips_short_cpu_desc, 377 .get_cpu_freq = bcm6838_get_cpu_freq, 378 .get_cpu_count = bcm6358_get_cpu_count, 379}; 380 381/* Generic CPU Ops */ 382static int bmips_cpu_get_desc(const struct udevice *dev, char *buf, int size) 383{ 384 struct bmips_cpu_priv *priv = dev_get_priv(dev); 385 const struct bmips_cpu_hw *hw = priv->hw; 386 387 return hw->get_cpu_desc(priv, buf, size); 388} 389 390static int bmips_cpu_get_info(const struct udevice *dev, struct cpu_info *info) 391{ 392 struct bmips_cpu_priv *priv = dev_get_priv(dev); 393 const struct bmips_cpu_hw *hw = priv->hw; 394 395 info->cpu_freq = hw->get_cpu_freq(priv); 396 info->features = BIT(CPU_FEAT_L1_CACHE); 397 info->features |= BIT(CPU_FEAT_MMU); 398 info->features |= BIT(CPU_FEAT_DEVICE_ID); 399 400 return 0; 401} 402 403static int bmips_cpu_get_count(const struct udevice *dev) 404{ 405 struct bmips_cpu_priv *priv = dev_get_priv(dev); 406 const struct bmips_cpu_hw *hw = priv->hw; 407 408 return hw->get_cpu_count(priv); 409} 410 411static int bmips_cpu_get_vendor(const struct udevice *dev, char *buf, int size) 412{ 413 snprintf(buf, size, "Broadcom"); 414 415 return 0; 416} 417 418static const struct cpu_ops bmips_cpu_ops = { 419 .get_desc = bmips_cpu_get_desc, 420 .get_info = bmips_cpu_get_info, 421 .get_count = bmips_cpu_get_count, 422 .get_vendor = bmips_cpu_get_vendor, 423}; 424 425/* BMIPS CPU driver */ 426int bmips_cpu_bind(struct udevice *dev) 427{ 428 struct cpu_plat *plat = dev_get_parent_plat(dev); 429 430 plat->cpu_id = dev_read_u32_default(dev, "reg", -1); 431 plat->device_id = read_c0_prid(); 432 433 return 0; 434} 435 436int bmips_cpu_probe(struct udevice *dev) 437{ 438 struct bmips_cpu_priv *priv = dev_get_priv(dev); 439 const struct bmips_cpu_hw *hw = 440 (const struct bmips_cpu_hw *)dev_get_driver_data(dev); 441 442 priv->regs = dev_remap_addr(dev_get_parent(dev)); 443 if (!priv->regs) 444 return -EINVAL; 445 446 priv->hw = hw; 447 448 return 0; 449} 450 451static const struct udevice_id bmips_cpu_ids[] = { 452 { 453 .compatible = "brcm,bcm3380-cpu", 454 .data = (ulong)&bmips_cpu_bcm3380, 455 }, { 456 .compatible = "brcm,bcm6318-cpu", 457 .data = (ulong)&bmips_cpu_bcm6318, 458 }, { 459 .compatible = "brcm,bcm6328-cpu", 460 .data = (ulong)&bmips_cpu_bcm6328, 461 }, { 462 .compatible = "brcm,bcm6338-cpu", 463 .data = (ulong)&bmips_cpu_bcm6338, 464 }, { 465 .compatible = "brcm,bcm6348-cpu", 466 .data = (ulong)&bmips_cpu_bcm6348, 467 }, { 468 .compatible = "brcm,bcm6358-cpu", 469 .data = (ulong)&bmips_cpu_bcm6358, 470 }, { 471 .compatible = "brcm,bcm6362-cpu", 472 .data = (ulong)&bmips_cpu_bcm6362, 473 }, { 474 .compatible = "brcm,bcm6368-cpu", 475 .data = (ulong)&bmips_cpu_bcm6368, 476 }, { 477 .compatible = "brcm,bcm63268-cpu", 478 .data = (ulong)&bmips_cpu_bcm63268, 479 }, { 480 .compatible = "brcm,bcm6838-cpu", 481 .data = (ulong)&bmips_cpu_bcm6838, 482 }, 483 { /* sentinel */ } 484}; 485 486U_BOOT_DRIVER(bmips_cpu_drv) = { 487 .name = "bmips_cpu", 488 .id = UCLASS_CPU, 489 .of_match = bmips_cpu_ids, 490 .bind = bmips_cpu_bind, 491 .probe = bmips_cpu_probe, 492 .priv_auto = sizeof(struct bmips_cpu_priv), 493 .ops = &bmips_cpu_ops, 494 .flags = DM_FLAG_PRE_RELOC, 495}; 496 497#ifdef CONFIG_DISPLAY_CPUINFO 498int print_cpuinfo(void) 499{ 500 struct cpu_info cpu; 501 struct udevice *dev; 502 int err; 503 char desc[100]; 504 505 err = uclass_get_device(UCLASS_CPU, 0, &dev); 506 if (err) 507 return 0; 508 509 err = cpu_get_info(dev, &cpu); 510 if (err) 511 return 0; 512 513 err = cpu_get_desc(dev, desc, sizeof(desc)); 514 if (err) 515 return 0; 516 517 printf("Chip ID: %s, MIPS: ", desc); 518 print_freq(cpu.cpu_freq, "\n"); 519 520 return 0; 521} 522#endif