1/* 2 * BCM47XX Sonics SiliconBackplane MIPS core routines 3 * 4 * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved. 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * $Id: hndmips.c 419467 2013-08-21 09:19:48Z $ 19 */ 20 21#include <bcm_cfg.h> 22#include <typedefs.h> 23#include <bcmdefs.h> 24#include <osl.h> 25#include <bcmutils.h> 26#include <siutils.h> 27#include <bcmdevs.h> 28#include <bcmnvram.h> 29#include <hndsoc.h> 30#include <sbchipc.h> 31#include <sbmemc.h> 32#include <mipsinc.h> 33#include <mips33_core.h> 34#include <mips74k_core.h> 35#include <hndcpu.h> 36#include <hndmips.h> 37#include <hndpmu.h> 38#include <dmemc_core.h> 39 40/* debug/trace */ 41#ifdef BCMDBG_ERR 42#define HNDMIPS_ERROR(args) printf args 43#else 44#define HNDMIPS_ERROR(args) 45#endif /* BCMDBG_ERR */ 46 47#ifdef BCMDBG 48#define HNDMIPS_MSG(args) printf args 49#else 50#define HNDMIPS_MSG(args) 51#endif /* BCMDBG */ 52#define HNDMIPS_NONE(args) 53 54/* sbipsflag register format, indexed by irq. */ 55static const uint32 sbips_int_mask[] = { 56 0, /* placeholder */ 57 SBIPS_INT1_MASK, 58 SBIPS_INT2_MASK, 59 SBIPS_INT3_MASK, 60 SBIPS_INT4_MASK 61}; 62 63static const uint32 sbips_int_shift[] = { 64 0, /* placeholder */ 65 SBIPS_INT1_SHIFT, 66 SBIPS_INT2_SHIFT, 67 SBIPS_INT3_SHIFT, 68 SBIPS_INT4_SHIFT 69}; 70 71/* 72 * Map SB cores sharing the MIPS hardware IRQ0 to virtual dedicated OS IRQs. 73 * Per-port BSP code is required to provide necessary translations between 74 * the shared MIPS IRQ and the virtual OS IRQs based on SB core flag. 75 * 76 * See si_irq() for the mapping. 77 */ 78static uint shirq_map_base = 0; 79 80/* 81 * Returns the MIPS IRQ assignment of the current core. If unassigned, 82 * 0 is returned. 83 */ 84static uint 85si_getirq(si_t *sih) 86{ 87 osl_t *osh; 88 uint idx; 89 void *regs; 90 sbconfig_t *sb; 91 uint32 flag, sbipsflag; 92 uint irq = 0; 93 94 osh = si_osh(sih); 95 flag = si_flag(sih); 96 97 idx = si_coreidx(sih); 98 99 if ((regs = si_setcore(sih, MIPS74K_CORE_ID, 0)) != NULL) { 100 /* IntMask1,2,3,4 regs are configured to enable propagation of 101 * backplane interrupts 0,1,2,3 to mips hw interrupts 1,2,3,4. 102 */ 103 for (irq = 1; irq <= 4; irq++) { 104 if (R_REG(osh, &((mips74kregs_t *)regs)->intmask[irq]) & 105 (1 << flag)) 106 break; 107 } 108 } else if ((regs = si_setcore(sih, MIPS33_CORE_ID, 0)) != NULL) { 109 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); 110 111 /* sbipsflag specifies which core is routed to interrupts 1 to 4 */ 112 sbipsflag = R_REG(osh, &sb->sbipsflag); 113 for (irq = 1; irq <= 4; irq++) { 114 if (((sbipsflag & sbips_int_mask[irq]) >> 115 sbips_int_shift[irq]) == flag) 116 break; 117 } 118 } else { 119 ASSERT("Unknown processor core" == NULL); 120 return 1000; /* An invalid value */ 121 } 122 123 /* If we didn't find it it must be in the shared int (0) */ 124 if (irq == 5) 125 irq = 0; 126 127 si_setcoreidx(sih, idx); 128 129 return irq; 130} 131 132/* 133 * Return the MIPS IRQ assignment of the current core. If necessary 134 * map cores sharing the MIPS hw IRQ0 to virtual dedicated OS IRQs. 135 */ 136uint 137si_irq(si_t *sih) 138{ 139 uint irq = si_getirq(sih); 140 if (irq == 0 && shirq_map_base) 141 irq = si_flag(sih) + shirq_map_base; 142 return irq; 143} 144 145/* Clears the specified MIPS IRQ. */ 146static void 147BCMINITFN(si_clearirq)(si_t *sih, uint irq) 148{ 149 osl_t *osh; 150 void *regs; 151 sbconfig_t *sb; 152 153 osh = si_osh(sih); 154 155 if ((regs = si_setcore(sih, MIPS74K_CORE_ID, 0)) != NULL) { 156 W_REG(osh, &((mips74kregs_t *)regs)->intmask[irq], 0); 157 } else if ((regs = si_setcore(sih, MIPS33_CORE_ID, 0)) != NULL) { 158 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); 159 if (irq == 0) 160 W_REG(osh, &sb->sbintvec, 0); 161 else 162 OR_REG(osh, &sb->sbipsflag, sbips_int_mask[irq]); 163 } else 164 ASSERT("Unknown processor core" == NULL); 165} 166 167/* 168 * Assigns the specified MIPS IRQ to the specified core. Shared MIPS 169 * IRQ 0 may be assigned more than once. 170 * 171 * The old assignment to the specified core is removed first. 172 */ 173static void 174BCMATTACHFN(si_setirq)(si_t *sih, uint irq, uint coreid, uint coreunit) 175{ 176 osl_t *osh; 177 void *regs; 178 sbconfig_t *sb; 179 uint32 flag; 180 uint oldirq; 181 182 osh = si_osh(sih); 183 184 regs = si_setcore(sih, coreid, coreunit); 185 ASSERT(regs); 186 flag = si_flag(sih); 187 oldirq = si_getirq(sih); 188 if (oldirq) 189 si_clearirq(sih, oldirq); 190 191 if ((regs = si_setcore(sih, MIPS74K_CORE_ID, 0)) != NULL) { 192 if (!oldirq) 193 AND_REG(osh, &((mips74kregs_t *)regs)->intmask[0], ~(1 << flag)); 194 195 if (irq == 0) 196 OR_REG(osh, &((mips74kregs_t *)regs)->intmask[0], 1 << flag); 197 else { 198 W_REG(osh, &((mips74kregs_t *)regs)->intmask[irq], 1 << flag); 199 } 200 } else if ((regs = si_setcore(sih, MIPS33_CORE_ID, 0)) != NULL) { 201 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); 202 203 if (!oldirq) 204 AND_REG(osh, &sb->sbintvec, ~(1 << flag)); 205 206 if (irq == 0) 207 OR_REG(osh, &sb->sbintvec, 1 << flag); 208 else { 209 flag <<= sbips_int_shift[irq]; 210 ASSERT(!(flag & ~sbips_int_mask[irq])); 211 flag |= R_REG(osh, &sb->sbipsflag) & ~sbips_int_mask[irq]; 212 W_REG(osh, &sb->sbipsflag, flag); 213 } 214 } else 215 ASSERT("Unknown processor core" == NULL); 216} 217 218/* 219 * Initializes clocks and interrupts. SB and NVRAM access must be 220 * initialized prior to calling. 221 * 222 * 'shirqmap' enables virtual dedicated OS IRQ mapping if non-zero. 223 */ 224void 225BCMATTACHFN(si_mips_init)(si_t *sih, uint shirqmap) 226{ 227 osl_t *osh; 228 uint32 c0reg; 229 ulong hz, ns, tmp; 230 chipcregs_t *cc; 231 uint irq; 232 233 osh = si_osh(sih); 234 235 /* Disable interrupts */ 236 c0reg = MFC0(C0_STATUS, 0); 237 c0reg &= ~ST0_IE; 238 MTC0(C0_STATUS, 0, c0reg); 239 240 /* Figure out current SB clock speed */ 241 if ((hz = si_clock(sih)) == 0) 242 hz = 100000000; 243 ns = 1000000000 / hz; 244 245 /* Setup external interface timing */ 246 cc = si_setcoreidx(sih, SI_CC_IDX); 247 ASSERT(cc); 248 249 /* Set timing for the flash */ 250 tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ 251 tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */ 252 tmp |= CEIL(120, ns); /* W0 = 120nS */ 253 if (sih->ccrev < 9) 254 W_REG(osh, &cc->flash_waitcount, tmp); 255 256 if ((sih->ccrev < 9) || 257 ((CHIPID(sih->chip) == BCM5350_CHIP_ID) && CHIPREV(sih->chiprev) == 0)) { 258 W_REG(osh, &cc->pcmcia_memwait, tmp); 259 } 260 261 /* Save shared IRQ mapping base */ 262 shirq_map_base = shirqmap; 263 264 /* Chip specific initialization */ 265 switch (CHIPID(sih->chip)) { 266 case BCM5350_CHIP_ID: 267 /* Clear interrupt map */ 268 for (irq = 0; irq <= 4; irq++) 269 si_clearirq(sih, irq); 270 si_setirq(sih, 0, CC_CORE_ID, 0); 271 si_setirq(sih, 0, MIPS33_CORE_ID, 0); 272 si_setirq(sih, 1, D11_CORE_ID, 0); 273 si_setirq(sih, 2, ENET_CORE_ID, 0); 274 si_setirq(sih, 3, PCI_CORE_ID, 0); 275 si_setirq(sih, 4, USB_CORE_ID, 0); 276 break; 277 case BCM4785_CHIP_ID: 278 /* Reassign PCI to irq 4 */ 279 si_setirq(sih, 4, PCI_CORE_ID, 0); 280 break; 281 case BCM4716_CHIP_ID: 282 case BCM4748_CHIP_ID: 283 /* Clear interrupt map */ 284 for (irq = 0; irq <= 4; irq++) 285 si_clearirq(sih, irq); 286 si_setirq(sih, 1, D11_CORE_ID, 0); 287 si_setirq(sih, 2, GMAC_CORE_ID, 0); 288 si_setirq(sih, 3, USB20H_CORE_ID, 0); 289 si_setirq(sih, 4, PCIE_CORE_ID, 0); 290 si_setirq(sih, 0, CC_CORE_ID, 0); 291 si_setirq(sih, 0, I2S_CORE_ID, 0); 292 break; 293 case BCM5356_CHIP_ID: 294 case BCM47162_CHIP_ID: 295 case BCM53572_CHIP_ID: 296 /* Clear interrupt map */ 297 for (irq = 0; irq <= 4; irq++) 298 si_clearirq(sih, irq); 299 si_setirq(sih, 1, D11_CORE_ID, 0); 300 si_setirq(sih, 2, GMAC_CORE_ID, 0); 301 si_setirq(sih, 0, CC_CORE_ID, 0); 302 break; 303 case BCM5357_CHIP_ID: 304 case BCM4749_CHIP_ID: 305 /* Clear interrupt map */ 306 for (irq = 0; irq <= 4; irq++) 307 si_clearirq(sih, irq); 308 si_setirq(sih, 1, D11_CORE_ID, 0); 309 si_setirq(sih, 2, GMAC_CORE_ID, 0); 310 si_setirq(sih, 3, USB20H_CORE_ID, 0); 311 si_setirq(sih, 0, CC_CORE_ID, 0); 312 si_setirq(sih, 0, I2S_CORE_ID, 0); 313 break; 314 case BCM4706_CHIP_ID: 315 /* Clear interrupt map */ 316 for (irq = 0; irq <= 4; irq++) 317 si_clearirq(sih, irq); 318 si_setirq(sih, 1, PCIE_CORE_ID, 0); 319 si_setirq(sih, 2, GMAC_CORE_ID, 0); 320 si_setirq(sih, 3, PCIE_CORE_ID, 1); 321 si_setirq(sih, 4, USB20H_CORE_ID, 0); 322 si_setirq(sih, 0, CC_CORE_ID, 0); 323 324 break; 325 } 326} 327 328/* Do any setup necessary to run a new image and jump to it. */ 329void 330hnd_cpu_jumpto(void *addr) 331{ 332 void (*jumpto)(void) = addr; 333 334 (jumpto)(); 335} 336 337uint32 338BCMINITFN(si_cpu_clock)(si_t *sih) 339{ 340 osl_t *osh; 341 chipcregs_t *cc; 342 uint32 n, m; 343 uint idx; 344 uint32 pll_type, rate = 0; 345 346 347 osh = si_osh(sih); 348 349 if (sih->cccaps & CC_CAP_PMU) 350 return si_pmu_cpu_clock(sih, osh); 351 352 /* get index of the current core */ 353 idx = si_coreidx(sih); 354 355 /* switch to chipc core */ 356 cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX); 357 ASSERT(cc); 358 359 pll_type = sih->cccaps & CC_CAP_PLL_MASK; 360 n = R_REG(osh, &cc->clockcontrol_n); 361 if ((pll_type == PLL_TYPE2) || 362 (pll_type == PLL_TYPE4) || 363 (pll_type == PLL_TYPE6) || 364 (pll_type == PLL_TYPE7)) 365 m = R_REG(osh, &cc->clockcontrol_m3); 366 else if (pll_type == PLL_TYPE5) { 367 rate = 200000000; 368 goto out; 369 } else if (pll_type == PLL_TYPE3) { 370 if (CHIPID(sih->chip) == BCM5365_CHIP_ID) { 371 rate = 200000000; 372 goto out; 373 } 374 /* 5350 uses m2 to control mips */ 375 else 376 m = R_REG(osh, &cc->clockcontrol_m2); 377 } else 378 m = R_REG(osh, &cc->clockcontrol_sb); 379 380 /* calculate rate */ 381 rate = si_clock_rate(pll_type, n, m); 382 383 if (pll_type == PLL_TYPE6) 384 rate = SB2MIPS_T6(rate); 385 386out: 387 /* switch back to previous core */ 388 si_setcoreidx(sih, idx); 389 390 return rate; 391} 392 393uint32 394BCMINITFN(si_mem_clock)(si_t *sih) 395{ 396 osl_t *osh; 397 398 osh = si_osh(sih); 399 400 if (sih->cccaps & CC_CAP_PMU) 401 return si_pmu_mem_clock(sih, osh); 402 403 return si_clock(sih); 404} 405 406#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4) 407 408static void __attribute__ ((__noinline__)) 409ephy_poll_phyaccess(void) 410{ 411 asm("phypoll: \tlui $8, 0xb800\n\t" 412 "lw $9, 0x2180($8)\n\t" 413 "lui $8, 0x4000\n\t" 414 "and $9, $9, $8\n\t" 415 "bnez $9, phypoll\n\t" 416 "nop"); 417} 418 419static void __attribute__ ((__noinline__)) 420coma_delay(void) 421{ 422 /* for (i = 0; i < 3000000; i++); */ 423 asm("lui $8, 0x2d\n\t" 424 "ori $8,$8,0xc6c0\n\t" 425 "coma_delay_loop: \taddiu $8,$8,-1\n\t" 426 "bnez $8,coma_delay_loop\n\t" 427 "nop"); 428} 429 430static void __attribute__ ((__noinline__)) 431do_router_coma(si_t *sih, void *dmem, int delay) 432{ 433 uint8 phy; 434 435 /* set jtag user reg 0 = 0x80 to set DDR pad power saving mode */ 436 asm("lui $8, 0xb800"); 437 asm("li $9, 0xff03ff3a"); /* (16 + addr) << 20 | 0xfe03ff3a */ 438 asm("sw $9, 0x0034($8)"); 439 asm("li $9, 0x80"); /* data */ 440 asm("sw $9, 0x0038($8)"); 441 asm("li $9, 0x80071f1f"); 442 asm("sw $9, 0x0030($8)"); 443 asm("sync"); 444 445 coma_delay(); 446 447 /* ephy ports powerdown */ 448 449 /* robo_wreg 0x0 0xf 0x1f 0x2 */ 450 asm("lui $8, 0xb800"); 451 asm("li $9, 0x0090001e"); 452 asm("sw $9, 0x2188($8)"); 453 asm("sync"); 454 asm("nop"); 455 asm("lui $8, 0xb800"); 456 asm("li $9, 0x701e0001"); 457 asm("sw $9, 0x2180($8)"); 458 asm("sync"); 459 asm("nop"); 460 461 ephy_poll_phyaccess(); 462 463 asm("lui $8, 0xb800"); 464 asm("li $9, 0x0090001e"); 465 asm("sw $9, 0x2188($8)"); 466 asm("sync"); 467 asm("nop"); 468 asm("lui $8, 0xb800"); 469 asm("li $9, 0x781e001f"); 470 asm("sw $9, 0x2180($8)"); 471 asm("sync"); 472 asm("nop"); 473 474 ephy_poll_phyaccess(); 475 476 asm("lui $8, 0xb800"); 477 asm("li $9, 0x0090001e"); 478 asm("sw $9, 0x2188($8)"); 479 asm("sync"); 480 asm("nop"); 481 asm("lui $8, 0xb800"); 482 asm("li $9, 0x711e0f01"); 483 asm("sw $9, 0x2180($8)"); 484 asm("sync"); 485 asm("nop"); 486 487 ephy_poll_phyaccess(); 488 489 asm("lui $8, 0xb800"); 490 asm("li $9, 0x0090001e"); 491 asm("sw $9, 0x2188($8)"); 492 asm("sync"); 493 asm("nop"); 494 asm("lui $8, 0xb800"); 495 asm("li $9, 0x511e0000"); 496 asm("sw $9, 0x2180($8)"); 497 asm("sync"); 498 asm("nop"); 499 500 ephy_poll_phyaccess(); 501 502 /* ports 0-5 writes start */ 503 504 asm("li $10, 0"); 505 506 for (phy = 0; phy < 5; phy++) { 507 508 asm("sll $11, $10, 16"); 509 510 asm("li $9, 0x00900000"); 511 asm("or $9, $9, $10"); 512 asm("lui $8, 0xb800"); 513 asm("sw $9, 0x2188($8)"); 514 asm("sync"); 515 asm("nop"); 516 asm("li $9, 0x7f00008b"); 517 asm("or $9, $9, $11"); 518 asm("lui $8, 0xb800"); 519 asm("sw $9, 0x2180($8)"); 520 asm("sync"); 521 asm("nop"); 522 523 ephy_poll_phyaccess(); 524 525 asm("li $9, 0x00900000"); 526 asm("or $9, $9, $10"); 527 asm("lui $8, 0xb800"); 528 asm("sw $9, 0x2188($8)"); 529 asm("sync"); 530 asm("nop"); 531 asm("li $9, 0x74006000"); 532 asm("or $9, $9, $11"); 533 asm("lui $8, 0xb800"); 534 asm("sw $9, 0x2180($8)"); 535 asm("sync"); 536 asm("nop"); 537 538 ephy_poll_phyaccess(); 539 540 asm("li $9, 0x00900000"); 541 asm("or $9, $9, $10"); 542 asm("lui $8, 0xb800"); 543 asm("sw $9, 0x2188($8)"); 544 asm("sync"); 545 asm("nop"); 546 asm("li $9, 0x70000700"); 547 asm("or $9, $9, $11"); 548 asm("lui $8, 0xb800"); 549 asm("sw $9, 0x2180($8)"); 550 asm("sync"); 551 asm("nop"); 552 553 ephy_poll_phyaccess(); 554 555 asm("li $9, 0x00900000"); 556 asm("or $9, $9, $10"); 557 asm("lui $8, 0xb800"); 558 asm("sw $9, 0x2188($8)"); 559 asm("sync"); 560 asm("nop"); 561 asm("li $9, 0x71001000"); 562 asm("or $9, $9, $11"); 563 asm("lui $8, 0xb800"); 564 asm("sw $9, 0x2180($8)"); 565 asm("sync"); 566 asm("nop"); 567 568 ephy_poll_phyaccess(); 569 570 asm("li $9, 0x00900000"); 571 asm("or $9, $9, $10"); 572 asm("lui $8, 0xb800"); 573 asm("sw $9, 0x2188($8)"); 574 asm("sync"); 575 asm("nop"); 576 asm("li $9, 0x7f00000b"); 577 asm("or $9, $9, $11"); 578 asm("lui $8, 0xb800"); 579 asm("sw $9, 0x2180($8)"); 580 asm("sync"); 581 asm("nop"); 582 583 ephy_poll_phyaccess(); 584 585 asm("addi $10, $10, 1"); 586 } 587 588 coma_delay(); 589 /* ports 0-5 writes end */ 590 591 if (((CHIPID(sih->chip)) == BCM53572_CHIP_ID)) { 592 /* set ephy pll and bias power save through chipc registers */ 593 asm("lui $8, 0xb800"); 594 asm("li $9, 0x4"); 595 asm("sw $9, 0x0650($8)"); 596 asm("li $9, 0x8a60e001"); 597 asm("sw $9, 0x0654($8)"); 598 asm("sync"); 599 asm("nop"); 600 601 coma_delay(); 602 603 asm("lui $8, 0xb800"); 604 asm("li $9, 0x2"); 605 asm("sw $9, 0x0650($8)"); 606 asm("li $9, 0xcad0000f"); 607 asm("sw $9, 0x0654($8)"); 608 asm("sync"); 609 asm("nop"); 610 611 coma_delay(); 612 613 /* Clear the dmems ddrctrl reg */ 614 asm("lui $8, 0xb800"); 615 asm("li $9, 0x0"); 616 asm("sw $9, 0x41e4($8)"); 617 asm("sync"); 618 asm("nop"); 619 620 coma_delay(); 621 } 622 else { 623 /* A0 vs B0 steps */ 624 if (sih->chiprev == 0) { 625 626 /* set jtag user reg 3 = 0x60000 to turn off ephy pll and bias power */ 627 asm("lui $8, 0xb800"); 628 asm("li $9, 0xff33ff3a"); /* (16 + addr) << 20 | 0xfe03ff3a */ 629 asm("sw $9, 0x0034($8)"); 630 asm("li $9, 0x60000"); /* data */ 631 asm("sw $9, 0x0038($8)"); 632 asm("li $9, 0x80071f1f"); 633 asm("sw $9, 0x0030($8)"); 634 asm("sync"); 635 636 coma_delay(); 637 } else { 638 639 /* set ephy pll and bias power power save through chipc registers */ 640 asm("lui $8, 0xb800"); 641 asm("li $9, 0x4"); 642 asm("sw $9, 0x0650($8)"); 643 asm("li $9, 0x8a60e001"); 644 asm("sw $9, 0x0654($8)"); 645 asm("sync"); 646 asm("nop"); 647 648 coma_delay(); 649 650 asm("lui $8, 0xb800"); 651 asm("li $9, 0x2"); 652 asm("sw $9, 0x0650($8)"); 653 asm("li $9, 0xcad0000f"); 654 asm("sw $9, 0x0654($8)"); 655 asm("sync"); 656 asm("nop"); 657 658 coma_delay(); 659 } 660 } 661 662 /* set jtag user reg 7 = 0xc0 to turn off the pll and bias power of ephy */ 663 asm("lui $8, 0xb800"); 664 asm("li $9, 0xff73ff3a"); 665 asm("sw $9, 0x0034($8)"); 666 asm("li $9, 0xc0"); /* data */ 667 asm("sw $9, 0x0038($8)"); 668 asm("li $9, 0x80071f1f"); 669 asm("sw $9, 0x0030($8)"); 670 asm("sync"); 671 672 coma_delay(); 673 674 /* set gmac dmp io control = 0 */ 675 asm("lui $8, 0xb810"); 676 asm("li $9, 0x0"); 677 asm("sw $9, 0x2408($8)"); 678 asm("sync"); 679 asm("nop"); 680 681 coma_delay(); 682 683 if (((CHIPID(sih->chip)) == BCM53572_CHIP_ID)) { 684 /* set ddr dmp io control = 0 */ 685 asm("lui $8, 0xb810"); 686 asm("li $9, 0x0"); 687 asm("sw $9, 0x4408($8)"); 688 asm("sync"); 689 asm("nop"); 690 /* put dmems in reset */ 691 asm("li $9, 0x1"); 692 asm("sw $9, 0x4800($8)"); 693 asm("sync"); 694 asm("nop"); 695 } else { 696 /* set ddr dmp io control = 0 */ 697 asm("lui $8, 0xb810"); 698 asm("li $9, 0x0"); 699 asm("sw $9, 0x5408($8)"); 700 asm("sync"); 701 asm("nop"); 702 /* put dmemc in reset */ 703 asm("li $9, 0x1"); 704 asm("sw $9, 0x5800($8)"); 705 asm("sync"); 706 asm("nop"); 707 } 708 709 coma_delay(); 710 711 /* set PMU control = 1 */ 712 asm("lui $8, 0xb800"); 713 asm("li $9, 0x1"); 714 asm("sw $9, 0x0600($8)"); 715 asm("sync"); 716 asm("nop"); 717 718 coma_delay(); 719 720 if (((CHIPID(sih->chip)) != BCM53572_CHIP_ID)) { 721 /* Set switching freq of internal 12V regulator to 600kHz */ 722 asm("lui $8, 0xb800"); 723 asm("li $9, 0x1"); 724 asm("sw $9, 0x0658($8)"); 725 asm("sync"); 726 asm("nop"); 727 asm("lui $8, 0xb800"); 728 asm("li $9, 0x00018000"); 729 asm("sw $9, 0x065c($8)"); 730 asm("sync"); 731 asm("nop"); 732 733 coma_delay(); 734 } 735 736 /* set mips dmp io control = 0 */ 737 asm("lui $8, 0xb810"); 738 asm("li $9, 0x0"); 739 asm("sw $9, 0x3408($8)"); 740 asm("sync"); 741 asm("nop"); 742 743 /* wait for watch dog timer done */ 744 __asm__( 745 ".set\tmips3\n\t" 746 "sync\n\t" 747 "wait\n\t" 748 ".set\tmips0"); 749 750 asm("nop"); 751 asm("nop"); 752} 753 754static void __attribute__ ((__noinline__)) 755BCMINITFN(aftercoma)(void) 756{ 757 758} 759 760void 761si_router_coma(si_t *sih, int reset, int delay) 762{ 763 void *dmem = NULL; 764 chipcregs_t *cc; 765 uint ic_size, ic_lsize; 766 ulong start, end; 767 uint32 c0reg; 768 uint32 tmp; 769 int i; 770 osl_t *osh; 771 772 773 osh = si_osh(sih); 774 /* Disable interrupts */ 775 776 c0reg = MFC0(C0_STATUS, 0); 777 tmp = (c0reg & ~(ALLINTS | ST0_IE)); 778 MTC0(C0_STATUS, 0, tmp); 779 780 icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize); 781 782 /* Put coma routine into the icache */ 783 start = (ulong)&ephy_poll_phyaccess; 784 end = (ulong)&aftercoma; 785 for (i = 0; i < (end - start); i += ic_lsize) 786 cache_op(start + i, Fill_I); 787 788 /* Prepare JTAG registers */ 789 si_setcore(sih, CC_CORE_ID, 0); 790 cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX); 791 792 W_REG(osh, &cc->jtagctrl, 0x01); 793 W_REG(osh, &cc->jtagcmd, 0x80030000); 794 W_REG(osh, &cc->gpioouten, 0x0); 795 796 /* disable gpios */ 797 W_REG(osh, &cc->gpioouten, 0x0); 798 W_REG(osh, &cc->chipcontrol_addr, 0x2); 799 W_REG(osh, &cc->chipcontrol_data, 0x04000600); 800 801 /* Set the watchdog */ 802 if (((CHIPID(sih->chip)) == BCM5357_CHIP_ID) && (sih->chiprev == 0)) { 803 W_REG(osh, &cc->watchdog, reset*ILP_CLOCK); 804 } else { 805 si_watchdog_ms(sih, reset*1000); 806 } 807 808 if (((CHIPID(sih->chip)) == BCM53572_CHIP_ID)) 809 dmem = (void *)si_setcore(sih, DMEMS_CORE_ID, 0); 810 else 811 dmem = (void *)si_setcore(sih, DMEMC_CORE_ID, 0); 812 813 do_router_coma(sih, dmem, delay); 814} 815 816#define PLL_ENTRIES_4706 1 817static bool 818BCMINITFN(mips_pmu_setclock_4706)(si_t *sih, uint32 mipsclock, 819 uint32 ddrclock, uint32 axiclock) 820{ 821 chipcregs_t *cc = NULL; 822 osl_t *osh; 823 uint idx, i; 824 bool ret = TRUE, boolChanged = FALSE; 825 /* 25MHz table for 4706 */ 826 static uint32 BCMINITDATA(pll25mhz_table)[][3 + PLL_ENTRIES_4706] = { 827 /* cpu, ddr, axi, proc_PLL, */ 828 { 200, 100, 50, 0xc0011080, }, 829 { 300, 150, 75, 0xc00110c0, }, 830 { 400, 200, 100, 0xc0011100, }, 831 { 500, 250, 125, 0xc0011140, }, 832 { 600, 300, 150, 0xc0011180, }, 833 { 632, 316, 158, 0xc00157e8, }, 834 { 650, 325, 162, 0xc00111a0, }, 835 { 662, 331, 165, 0xc00111a8, }, 836 {0} 837 }; 838 static uint32 BCMINITDATA(pll25mhz_table_4706L)[][3 + PLL_ENTRIES_4706] = { 839 /* cpu, ddr, axi, proc_PLL, */ 840 { 200, 100, 50, 0xc0011100, }, 841 { 300, 150, 75, 0xc0011180, }, 842 { 400, 200, 100, 0xc0011200, }, 843 {0} 844 }; 845 uint32 (*pll_table)[4] = pll25mhz_table; 846 847 /* Since we already in 4706 specific routine, we no longer check the chip id 848 * The 4706L PLL m value is default to 4, thus the n value needs to be doubled 849 * And since it supports the max frequency is 400MHz, we replace the pll table 850 * here 851 */ 852 if (sih->chippkg == BCM4706L_PKG_ID) { 853 pll_table = pll25mhz_table_4706L; 854 } 855 856 osh = si_osh(sih); 857 858 /* get index of the current core */ 859 idx = si_coreidx(sih); 860 861 /* switch to chipc core */ 862 cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX); 863 ASSERT(cc); 864 865 mipsclock /= 1000000; 866 ddrclock /= 1000000; 867 axiclock /= 1000000; 868 869 for (idx = 0; pll_table[idx][0] != 0; idx++) { 870 if ((mipsclock <= pll_table[idx][0]) && 871 ((ddrclock == 0) || (ddrclock <= pll_table[idx][1])) && 872 ((axiclock == 0) || (axiclock <= pll_table[idx][2]))) 873 break; 874 } 875 876 if (pll_table[idx][0] == 0) { 877 ret = FALSE; 878 goto done; 879 } 880 881 for (i = 0; i < PLL_ENTRIES_4706; i++) { 882 W_REG(osh, &cc->pllcontrol_addr, PMU6_4706_PROCPLL_OFF + i); 883 (void)R_REG(osh, &cc->pllcontrol_addr); 884 if (R_REG(osh, &cc->pllcontrol_data) != pll_table[idx][i + 3]) { 885 W_REG(osh, &cc->pllcontrol_data, pll_table[idx][i + 3]); 886 boolChanged = TRUE; 887 } 888 } 889 890 if (boolChanged == FALSE) 891 goto done; 892 893 /* Wait for the last write */ 894 (void)R_REG(osh, &cc->pllcontrol_data); 895 896 /* And now do the pll update */ 897 W_REG(osh, &cc->pmucontrol, 898 R_REG(osh, &cc->pmucontrol) | PCTL_PLL_PLLCTL_UPD); 899 900 __asm__ __volatile__( 901 "nop\n" 902 "nop\n" 903 "nop\n" 904 "nop"); 905 906done: 907 si_setcoreidx(sih, idx); 908 return ret; 909} 910 911/* 912 * Set the MIPS, backplane and DDR clocks as closely as possible in chips 913 * with a PMU. So far that means 4716, 47162, 5357, and 5356 all of which share 914 * the same PLL controls. 915 */ 916static bool 917BCMINITFN(mips_pmu_setclock)(si_t *sih, uint32 mipsclock, uint32 ddrclock, uint32 axiclock) 918{ 919 osl_t *osh; 920 chipcregs_t *cc = NULL; 921 uint idx, i; 922 uint mainpll_pll0 = PMU4716_MAINPLL_PLL0; 923 bool ret = TRUE; 924 uint32 (*pll_table)[8]; 925 926 /* 20MHz table for 4716, 4717, 4718, 47162, 5357 */ 927 static uint32 BCMINITDATA(pll20mhz_table)[][8] = { 928 /* cpu, ddr, axi, pllctl12, pllctl13, pllctl14, pllctl15, pllctl16 */ 929 { 66, 66, 66, 0x11100070, 0x00121212, 0x03c00000, 0x20000000, 0x200005c0 }, 930 { 75, 75, 75, 0x11100070, 0x00101010, 0x03c00000, 0x20000000, 0x200005c0 }, 931 { 80, 80, 80, 0x11100070, 0x000a0a0a, 0x02800000, 0x20000000, 0x200005c0 }, 932 { 83, 83, 83, 0x11100070, 0x000c0c0c, 0x03200000, 0x20000000, 0x200005c0 }, 933 { 100, 66, 66, 0x11100070, 0x0012120c, 0x03c00000, 0x30000000, 0x200005c0 }, 934 { 100, 100, 100, 0x11100070, 0x000c0c0c, 0x03c00000, 0x20000000, 0x200005c0 }, 935 { 120, 60, 60, 0x11100070, 0x00101008, 0x03000000, 0x40000000, 0x200005c0 }, 936 { 120, 120, 120, 0x11100070, 0x00080808, 0x03000000, 0x20000000, 0x200005c0 }, 937 { 125, 83, 83, 0x11100070, 0x000c0c08, 0x03200000, 0x30000000, 0x200005c0 }, 938 { 133, 66, 66, 0x11100070, 0x0018180c, 0x05000000, 0x40000000, 0x200005c0 }, 939 { 133, 133, 133, 0x11100070, 0x000c0c0c, 0x05000000, 0x20000000, 0x200005c0 }, 940 { 148, 148, 74, 0x11100070, 0x00120909, 0x04300000, 0x28000000, 0x200005c0 }, 941 { 150, 75, 75, 0x11100070, 0x00101008, 0x03c00000, 0x40000000, 0x200005c0 }, 942 { 150, 100, 100, 0x11100070, 0x000c0c08, 0x03c00000, 0x30000000, 0x200005c0 }, 943 { 150, 150, 75, 0x11100070, 0x00100808, 0x03c00000, 0x28000000, 0x200005c0 }, 944 { 150, 150, 150, 0x11100070, 0x00080808, 0x03c00000, 0x20000000, 0x200005c0 }, 945 { 155, 155, 77, 0x11100070, 0x00120909, 0x04600000, 0x28000000, 0x200005c0 }, 946 { 155, 155, 155, 0x11100070, 0x00090909, 0x04600000, 0x20000000, 0x200005c0 }, 947 { 166, 83, 83, 0x11100070, 0x000c0c06, 0x03200000, 0x40000000, 0x200005c0 }, 948 { 166, 166, 83, 0x11100070, 0x000c0606, 0x03200000, 0x28000000, 0x200005c0 }, 949 { 166, 166, 166, 0x11100070, 0x00060606, 0x03200000, 0x20000000, 0x200005c0 }, 950 { 200, 200, 100, 0x11100070, 0x000c0606, 0x03c00000, 0x28000000, 0x200005c0 }, 951 { 223, 148, 74, 0x11100070, 0x00120906, 0x04300000, 0x38000000, 0x200005c0 }, 952 { 240, 120, 120, 0x11100070, 0x00080804, 0x03000000, 0x40000000, 0x200005c0 }, 953 { 240, 240, 120, 0x11100070, 0x00080404, 0x03000000, 0x28000000, 0x200005c0 }, 954 { 250, 166, 83, 0x11100070, 0x000c0604, 0x03200000, 0x38000000, 0x200005c0 }, 955 { 250, 166, 166, 0x11100070, 0x00060604, 0x03200000, 0x30000000, 0x200005c0 }, 956 { 266, 133, 133, 0x11100070, 0x000c0c06, 0x05000000, 0x40000000, 0x200005c0 }, 957 { 266, 266, 133, 0x11100070, 0x000c0606, 0x05000000, 0x28000000, 0x200005c0 }, 958 { 300, 100, 100, 0x11100070, 0x000c0c04, 0x03c00000, 0x60000000, 0x200005c0 }, 959 { 300, 150, 75, 0x11100070, 0x00100804, 0x03c00000, 0x48000000, 0x200005c0 }, 960 { 300, 150, 150, 0x11100070, 0x00080804, 0x03c00000, 0x40000000, 0x200005c0 }, 961 { 300, 200, 100, 0x11100070, 0x000c0604, 0x03c00000, 0x38000000, 0x200005c0 }, 962 { 320, 160, 80, 0x11100070, 0x00100804, 0x04000000, 0x48000000, 0x200005c0 }, 963 { 320, 213, 106, 0x11100070, 0x000c0604, 0x04000000, 0x38000000, 0x200005c0 }, 964 { 320, 240, 120, 0x11100070, 0x00080403, 0x03000000, 0x38000000, 0x200005c0 }, 965 { 320, 256, 128, 0x11100070, 0x000a0504, 0x04000000, 0x38000000, 0x200005c0 }, 966 { 330, 165, 82, 0x11100070, 0x00100804, 0x04200000, 0x48000000, 0x200005c0 }, 967 { 330, 165, 165, 0x11100070, 0x00080804, 0x04200000, 0x40000000, 0x200005c0 }, 968 { 333, 166, 83, 0x11100070, 0x000c0603, 0x03200000, 0x48000000, 0x200005c0 }, 969 { 333, 166, 166, 0x11100070, 0x00060603, 0x03200000, 0x40000000, 0x200005c0 }, 970 { 340, 226, 113, 0x11100070, 0x000c0604, 0x04400000, 0x38000000, 0x200005c0 }, 971 { 350, 175, 87, 0x11100070, 0x00100804, 0x04600000, 0x48000000, 0x200005c0 }, 972 { 353, 176, 88, 0x11100070, 0x000c0603, 0x03500000, 0x48000000, 0x200005c0 }, 973 { 360, 240, 120, 0x11100070, 0x000c0604, 0x04800000, 0x38000000, 0x200005c0 }, 974 { 370, 185, 92, 0x11100070, 0x00100804, 0x04a00000, 0x48000000, 0x200005c0 }, 975 { 370, 246, 123, 0x11100070, 0x000c0604, 0x04a00000, 0x38000000, 0x200005c0 }, 976 { 373, 186, 93, 0x11100070, 0x000c0603, 0x03800000, 0x48000000, 0x200005c0 }, 977 { 400, 133, 133, 0x11100070, 0x000c0c04, 0x05000000, 0x60000000, 0x200005c0 }, 978 { 400, 160, 80, 0x11100070, 0x00140a04, 0x05000000, 0x58000000, 0x200005c0 }, 979 { 400, 160, 160, 0x11100070, 0x000a0a04, 0x05000000, 0x50000000, 0x200005c0 }, 980 { 400, 200, 100, 0x11100070, 0x00100804, 0x05000000, 0x48000000, 0x200005c0 }, 981 { 400, 266, 133, 0x11100070, 0x000c0604, 0x05000000, 0x38000000, 0x200005c0 }, 982 { 426, 213, 106, 0x11100070, 0x000c0603, 0x04000000, 0x48000000, 0x200005c0 }, 983 { 440, 220, 110, 0x11100070, 0x000c0603, 0x04200000, 0x48000000, 0x200005c0 }, 984 { 446, 148, 74, 0x11100070, 0x00120903, 0x04300000, 0x68000000, 0x200005c0 }, 985 { 453, 226, 113, 0x11100070, 0x000c0603, 0x04400000, 0x48000000, 0x200005c0 }, 986 { 466, 233, 116, 0x11100070, 0x000c0603, 0x04600000, 0x48000000, 0x200005c0 }, 987 { 480, 137, 68, 0x11100070, 0x000e0702, 0x03000000, 0x78000000, 0x200005c0 }, 988 { 480, 137, 137, 0x11100070, 0x00070702, 0x03000000, 0x70000000, 0x200005c0 }, 989 { 480, 160, 80, 0x11100070, 0x000c0602, 0x03000000, 0x68000000, 0x200005c0 }, 990 { 480, 240, 120, 0x11100070, 0x00080402, 0x03000000, 0x48000000, 0x200005c0 }, 991 { 500, 100, 100, 0x11100070, 0x000a0a02, 0x03200000, 0xa0000000, 0x200005c0 }, 992 { 500, 166, 83, 0x11100070, 0x000c0602, 0x03200000, 0x68000000, 0x200005c0 }, 993 { 500, 166, 166, 0x11100070, 0x00060602, 0x03200000, 0x60000000, 0x200005c0 }, 994 { 500, 200, 100, 0x11100070, 0x000a0502, 0x03200000, 0x58000000, 0x200005c0 }, 995 { 500, 250, 125, 0x11100070, 0x00080402, 0x03200000, 0x48000000, 0x200005c0 }, 996 { 530, 176, 88, 0x11100070, 0x000c0602, 0x03500000, 0x68000000, 0x200005c0 }, 997 { 530, 176, 176, 0x11100070, 0x00060602, 0x03500000, 0x60000000, 0x200005c0 }, 998 { 530, 212, 106, 0x11100070, 0x000a0502, 0x03500000, 0x58000000, 0x200005c0 }, 999 { 530, 265, 132, 0x11100070, 0x00080402, 0x03500000, 0x48000000, 0x200005c0 }, 1000 { 533, 133, 133, 0x11100070, 0x000c0c03, 0x05000000, 0x80000000, 0x200005c0 }, 1001 { 533, 266, 133, 0x11100070, 0x000c0603, 0x05000000, 0x48000000, 0x200005c0 }, 1002 {0} 1003 }; 1004 1005 /* 25MHz table for 5356 */ 1006 static uint32 BCMINITDATA(pll25mhz_table)[][8] = { 1007 /* cpu, ddr, axi, pllctl12, pllctl13, pllctl14, pllctl15, pllctl16 */ 1008 { 66, 66, 66, 0x11100070, 0x00121212, 0x03000000, 0x20000000, 0x200005c0 }, 1009 { 75, 75, 75, 0x11100070, 0x00101010, 0x03000000, 0x20000000, 0x200005c0 }, 1010 { 80, 80, 80, 0x11100070, 0x000a0a0a, 0x02000000, 0x20000000, 0x200005c0 }, 1011 { 83, 83, 83, 0x11100070, 0x000c0c0c, 0x02800000, 0x20000000, 0x200005c0 }, 1012 { 100, 66, 66, 0x11100070, 0x0012120c, 0x03000000, 0x30000000, 0x200005c0 }, 1013 { 100, 100, 100, 0x11100070, 0x000c0c0c, 0x03000000, 0x20000000, 0x200005c0 }, 1014 { 125, 83, 83, 0x11100070, 0x000c0c08, 0x02800000, 0x30000000, 0x200005c0 }, 1015 { 133, 133, 133, 0x11100070, 0x000c0c0c, 0x04000000, 0x20000000, 0x200005c0 }, 1016 { 150, 75, 75, 0x11100070, 0x00101008, 0x03000000, 0x40000000, 0x200005c0 }, 1017 { 150, 100, 100, 0x11100070, 0x000c0c08, 0x03000000, 0x30000000, 0x200005c0 }, 1018 { 150, 150, 75, 0x11100070, 0x00100808, 0x03000000, 0x28000000, 0x200005c0 }, 1019 { 150, 150, 150, 0x11100070, 0x00080808, 0x03000000, 0x20000000, 0x200005c0 }, 1020 { 166, 83, 83, 0x11100070, 0x000c0c06, 0x02800000, 0x40000000, 0x200005c0 }, 1021 { 166, 166, 83, 0x11100070, 0x000c0606, 0x02800000, 0x28000000, 0x200005c0 }, 1022 { 166, 166, 166, 0x11100070, 0x00060606, 0x02800000, 0x20000000, 0x200005c0 }, 1023 { 200, 133, 133, 0x11100070, 0x000c0c08, 0x04000000, 0x30000000, 0x200005c0 }, 1024 { 200, 200, 100, 0x11100070, 0x000c0606, 0x03000000, 0x28000000, 0x200005c0 }, 1025 { 250, 166, 83, 0x11100070, 0x000c0604, 0x02800000, 0x38000000, 0x200005c0 }, 1026 { 250, 166, 166, 0x11100070, 0x00060604, 0x02800000, 0x30000000, 0x200005c0 }, 1027 { 293, 195, 97, 0x11100070, 0x000c0604, 0x02f00000, 0x38000000, 0x200005c0 }, 1028 { 300, 100, 100, 0x11100070, 0x000c0c04, 0x03000000, 0x60000000, 0x200005c0 }, 1029 { 300, 120, 120, 0x11100070, 0x000a0a04, 0x03000000, 0x50000000, 0x200005c0 }, 1030 { 300, 150, 75, 0x11100070, 0x00100804, 0x03000000, 0x48000000, 0x200005c0 }, 1031 { 300, 150, 150, 0x11100070, 0x00080804, 0x03000000, 0x40000000, 0x200005c0 }, 1032 { 300, 200, 100, 0x11100070, 0x000c0604, 0x03000000, 0x38000000, 0x200005c0 }, 1033 { 332, 110, 110, 0x11100070, 0x000c0c04, 0x03540000, 0x6047ae14, 0x202c2820 }, 1034 { 332, 133, 133, 0x11100070, 0x000a0a04, 0x03540000, 0x5047ae14, 0x202c2820 }, 1035 { 332, 166, 83, 0x11100070, 0x00100804, 0x03540000, 0x4847ae14, 0x202c2820 }, 1036 { 333, 111, 111, 0x11100070, 0x00090903, 0x02800000, 0x60000000, 0x200005c0 }, 1037 { 333, 133, 133, 0x11100070, 0x000f0f06, 0x05000000, 0x50000000, 0x38000700 }, 1038 { 333, 166, 83, 0x11100070, 0x000c0603, 0x02800000, 0x48000000, 0x200005c0 }, 1039 { 333, 166, 166, 0x11100070, 0x00060603, 0x02800000, 0x40000000, 0x200005c0 }, 1040 { 400, 133, 133, 0x11100070, 0x000c0c04, 0x04000000, 0x60000000, 0x200005c0 }, 1041 { 400, 200, 100, 0x11100070, 0x000c0603, 0x03000000, 0x48000000, 0x200005c0 }, 1042 { 400, 266, 133, 0x11100070, 0x000c0604, 0x04000000, 0x38000000, 0x200005c0 }, 1043 { 500, 166, 83, 0x11100070, 0x000c0602, 0x02800000, 0x68000000, 0x200005c0 }, 1044 { 500, 166, 166, 0x11100070, 0x00060602, 0x02800000, 0x60000000, 0x200005c0 }, 1045 { 500, 200, 100, 0x11100070, 0x000a0502, 0x02800000, 0x58000000, 0x200005c0 }, 1046 { 500, 250, 125, 0x11100070, 0x00080402, 0x02800000, 0x48000000, 0x200005c0 }, 1047 {0} 1048 }; 1049 1050 if (CHIPID(sih->chip) == BCM4706_CHIP_ID) 1051 return mips_pmu_setclock_4706(sih, mipsclock, ddrclock, axiclock); 1052 1053 /* By default use the 20MHz pll table */ 1054 pll_table = pll20mhz_table; 1055 1056 osh = si_osh(sih); 1057 1058 /* Adjust the mainpll_pll0 address and pll table for 5356 */ 1059 if (CHIPID(sih->chip) == BCM5356_CHIP_ID) { 1060 mainpll_pll0 = PMU5356_MAINPLL_PLL0; 1061 pll_table = pll25mhz_table; 1062 } 1063 /* Adjust the mainpll_pll0 address and pll table for 5357 */ 1064 if ((CHIPID(sih->chip) == BCM5357_CHIP_ID) || 1065 (CHIPID(sih->chip) == BCM4749_CHIP_ID)) { 1066 mainpll_pll0 = PMU5357_MAINPLL_PLL0; 1067 pll_table = pll20mhz_table; 1068 } 1069 1070 /* get index of the current core */ 1071 idx = si_coreidx(sih); 1072 1073 /* switch to chipc core */ 1074 cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX); 1075 ASSERT(cc); 1076 1077 mipsclock /= 1000000; 1078 ddrclock /= 1000000; 1079 axiclock /= 1000000; 1080 1081 HNDMIPS_NONE(("Looking for %d/%d/%d\n", mipsclock, ddrclock, axiclock)); 1082 1083 for (idx = 0; pll_table[idx][0] != 0; idx++) { 1084 uint16 chippkg; 1085 /* Bypass pll entries that are not allowed */ 1086 if ((((pll_table[idx][4] & 0xff) < 4) || 1087 (((pll_table[idx][5] >> 20) & 0x1ff) > 0x50)) && 1088 ((CHIPID(sih->chip) == BCM5357_CHIP_ID) || 1089 (CHIPID(sih->chip) == BCM4749_CHIP_ID)) && 1090 (((chippkg = R_REG(osh, &cc->sromotp[23])) & 0x80) == 0x80)) { 1091 continue; 1092 } 1093 if ((mipsclock <= pll_table[idx][0]) && 1094 ((ddrclock == 0) || (ddrclock <= pll_table[idx][1])) && 1095 ((axiclock == 0) || (axiclock <= pll_table[idx][2]))) 1096 break; 1097 } 1098 1099 if (pll_table[idx][0] == 0) { 1100 ret = FALSE; 1101 goto done; 1102 } 1103 1104 HNDMIPS_NONE(("Using entry %d: %d/%d/%d, 0x%08x, 0x%08x, 0x%08x, 0x%08x, %d\n", idx, 1105 pll_table[idx][0], pll_table[idx][1], pll_table[idx][2], 1106 pll_table[idx][3], pll_table[idx][4], pll_table[idx][5], 1107 pll_table[idx][6], pll_table[idx][7])); 1108 1109 for (i = PMU5_PLL_P1P2_OFF; i <= PMU5_PLL_FMAB_OFF; i++) { 1110 W_REG(osh, &cc->pllcontrol_addr, mainpll_pll0 + i); 1111 (void)R_REG(osh, &cc->pllcontrol_addr); 1112 if (R_REG(osh, &cc->pllcontrol_data) != pll_table[idx][i + 3]) 1113 break; 1114 } 1115 1116 /* All matched, no change needed */ 1117 if (i == (PMU5_PLL_FMAB_OFF + 1)) 1118 goto done; 1119 1120 /* Write new PLL settings */ 1121 for (i = PMU5_PLL_P1P2_OFF; i <= PMU5_PLL_PLLCTL_OFF; i++) { 1122 uint32 tmp; 1123 1124 W_REG(osh, &cc->pllcontrol_addr, mainpll_pll0 + i); 1125 (void)R_REG(osh, &cc->pllcontrol_addr); 1126 tmp = pll_table[idx][i + 3]; 1127 W_REG(osh, &cc->pllcontrol_data, tmp); 1128 } 1129 /* Wait for the last write */ 1130 (void)R_REG(osh, &cc->pllcontrol_data); 1131 1132 if (CHIPID(sih->chip) == BCM47162_CHIP_ID) { 1133 /* In 47162, clear min_res_mask */ 1134 W_REG(osh, &cc->min_res_mask, 1135 R_REG(osh, &cc->min_res_mask) & ~RES4716_PROC_HT_AVAIL); 1136 1137 /* Reset, use chipcommon's watchdog, not the PMU */ 1138 W_REG(osh, &cc->watchdog, 1000); 1139 1140 /* And now do the pll update */ 1141 W_REG(osh, &cc->pmucontrol, 1142 R_REG(osh, &cc->pmucontrol) | PCTL_PLL_PLLCTL_UPD); 1143 } else 1144 si_watchdog(sih, 100); 1145 1146 /* wait for timer interrupt */ 1147 while (1) 1148 __asm__ __volatile__( 1149 ".set\tmips3\n\t" 1150 "sync\n\t" 1151 "wait\n\t" 1152 ".set\tmips0"); 1153 1154done: 1155 /* switch back to previous core */ 1156 si_setcoreidx(sih, idx); 1157 1158 return ret; 1159} 1160 1161static void 1162BCMINITFN(handler)(void) 1163{ 1164 __asm__( 1165 ".set\tmips32\n\t" 1166 "ssnop\n\t" 1167 "ssnop\n\t" 1168 /* Disable interrupts */ 1169 /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */ 1170 "mfc0 $15, $12\n\t" 1171 /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */ 1172 "li $14, -31746\n\t" 1173 "and $15, $15, $14\n\t" 1174 "mtc0 $15, $12\n\t" 1175 "eret\n\t" 1176 "nop\n\t" 1177 "nop\n\t" 1178 ".set\tmips0"); 1179} 1180 1181/* The following MUST come right after handler() */ 1182static void 1183BCMINITFN(afterhandler)(void) 1184{ 1185} 1186 1187/* 1188 * Set the MIPS, backplane and PCI clocks as closely as possible. 1189 * 1190 * MIPS clocks synchronization function has been moved from PLL in chipcommon 1191 * core rev. 15 to a DLL inside the MIPS core in 4785. 1192 */ 1193bool 1194BCMINITFN(si_mips_setclock)(si_t *sih, uint32 mipsclock, uint32 siclock, uint32 pciclock) 1195{ 1196 osl_t *osh; 1197 chipcregs_t *cc = NULL; 1198 mips33regs_t *mipsr = NULL; 1199 volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, *clockcontrol_m2; 1200 uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, orig_ratio_cfg; 1201 uint32 pll_type, sync_mode; 1202 uint ic_size, ic_lsize; 1203 uint idx, i; 1204 1205 /* PLL configuration: type 3 */ 1206 typedef struct { 1207 uint32 mipsclock; 1208 uint16 n; 1209 uint32 m2; /* that is the clockcontrol_m2 */ 1210 } type3_table_t; 1211 static type3_table_t type3_table[] = { 1212 /* for 5350, mips clock is always double sb clock */ 1213 { 150000000, 0x311, 0x4020005 }, 1214 { 200000000, 0x311, 0x4020003 }, 1215 }; 1216 1217 /* PLL configuration: type 2, 4, 7 */ 1218 typedef struct { 1219 uint32 mipsclock; 1220 uint32 sbclock; 1221 uint32 pciclock; 1222 uint16 n; 1223 uint32 sb; 1224 uint32 pci33; 1225 uint32 m2; 1226 uint32 m3; 1227 uint32 ratio_cfg; 1228 uint32 ratio_parm; 1229 uint32 dll_r1; 1230 uint32 dll_r2; 1231 } n4m_table_t; 1232 static n4m_table_t BCMINITDATA(type2_table)[] = { 1233 { 120000000, 60000000, 32000000, 0x0303, 0x01000200, 0x01000600, 0x01000200, 1234 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1235 { 150000000, 75000000, 33333333, 0x0303, 0x01000100, 0x01000600, 0x01000100, 1236 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1237 { 180000000, 80000000, 30000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 1238 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 1239 { 180000000, 90000000, 30000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 1240 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1241 { 200000000, 100000000, 33333333, 0x0303, 0x02010000, 0x02040001, 0x02010000, 1242 0x06000001, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1243 { 211200000, 105600000, 30171428, 0x0902, 0x01000200, 0x01030400, 0x01000200, 1244 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1245 { 220800000, 110400000, 31542857, 0x1500, 0x01000200, 0x01030400, 0x01000200, 1246 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1247 { 230400000, 115200000, 32000000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 1248 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1249 { 234000000, 104000000, 31200000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 1250 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 1251 { 240000000, 120000000, 33333333, 0x0803, 0x01000200, 0x01020600, 0x01000200, 1252 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1253 { 252000000, 126000000, 33333333, 0x0504, 0x01000100, 0x01020500, 0x01000100, 1254 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1255 { 264000000, 132000000, 33000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 1256 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1257 { 270000000, 120000000, 30000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 1258 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 1259 { 276000000, 122666666, 31542857, 0x1500, 0x01010000, 0x01030400, 0x01020600, 1260 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 1261 { 280000000, 140000000, 31111111, 0x0503, 0x01000000, 0x01010600, 0x01000000, 1262 0x05000000, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1263 { 288000000, 128000000, 32914285, 0x0604, 0x01010000, 0x01030400, 0x01020600, 1264 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 1265 { 288000000, 144000000, 32000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 1266 0x05000000, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1267 { 300000000, 133333333, 33333333, 0x0803, 0x01010000, 0x01020600, 0x01010100, 1268 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 1269 { 300000000, 133333333, 37500000, 0x0803, 0x01010000, 0x01020500, 0x01010100, 1270 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 1271 { 300000000, 133333333, 42857142, 0x0803, 0x01010000, 0x01020400, 0x01010100, 1272 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 1273 { 300000000, 133333333, 50000000, 0x0803, 0x01010000, 0x01020300, 0x01010100, 1274 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 1275 { 300000000, 133333333, 60000000, 0x0803, 0x01010000, 0x01020200, 0x01010100, 1276 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 1277 { 300000000, 150000000, 33333333, 0x0803, 0x01000100, 0x01020600, 0x01010100, 1278 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1279 { 300000000, 150000000, 37500000, 0x0803, 0x01000100, 0x01020500, 0x01010100, 1280 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1281 { 300000000, 150000000, 42857142, 0x0803, 0x01000100, 0x01020400, 0x01010100, 1282 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1283 { 300000000, 150000000, 50000000, 0x0803, 0x01000100, 0x01020300, 0x01010100, 1284 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1285 { 300000000, 150000000, 60000000, 0x0803, 0x01000100, 0x01020200, 0x01010100, 1286 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 1287 { 330000000, 132000000, 33000000, 0x0903, 0x01000200, 0x00020200, 0x01010100, 1288 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 }, 1289 { 330000000, 146666666, 33000000, 0x0903, 0x01010000, 0x00020200, 0x01010100, 1290 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 }, 1291 { 330000000, 165000000, 33000000, 0x0903, 0x01000100, 0x00020200, 0x01010100, 1292 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 1293 { 330000000, 165000000, 41250000, 0x0903, 0x01000100, 0x00020100, 0x01010100, 1294 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 1295 { 330000000, 165000000, 55000000, 0x0903, 0x01000100, 0x00020000, 0x01010100, 1296 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 1297 { 360000000, 120000000, 32000000, 0x0a03, 0x01000300, 0x00010201, 0x01010200, 1298 0x05000100, 0, 0, 12 /* ratio 4/12 */, 0x04920492 }, 1299 { 360000000, 144000000, 32000000, 0x0a03, 0x01000200, 0x00010201, 0x01010200, 1300 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 }, 1301 { 360000000, 160000000, 32000000, 0x0a03, 0x01010000, 0x00010201, 0x01010200, 1302 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 }, 1303 { 360000000, 180000000, 32000000, 0x0a03, 0x01000100, 0x00010201, 0x01010200, 1304 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 1305 { 360000000, 180000000, 40000000, 0x0a03, 0x01000100, 0x00010101, 0x01010200, 1306 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 1307 { 360000000, 180000000, 53333333, 0x0a03, 0x01000100, 0x00010001, 0x01010200, 1308 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 1309 { 390000000, 130000000, 32500000, 0x0b03, 0x01010100, 0x00020101, 0x01020100, 1310 0x05000100, 0, 0, 12 /* ratio 4/12 */, 0x04920492 }, 1311 { 390000000, 156000000, 32500000, 0x0b03, 0x01000200, 0x00020101, 0x01020100, 1312 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 }, 1313 { 390000000, 173000000, 32500000, 0x0b03, 0x01010000, 0x00020101, 0x01020100, 1314 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 }, 1315 { 390000000, 195000000, 32500000, 0x0b03, 0x01000100, 0x00020101, 0x01020100, 1316 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 1317 }; 1318 static n4m_table_t BCMINITDATA(type4_table)[] = { 1319 { 120000000, 60000000, 0, 0x0009, 0x11020009, 0x01030203, 0x11020009, 0x04000009, 1320 11, 0x0aaa0555 }, 1321 { 150000000, 75000000, 0, 0x0009, 0x11050002, 0x01030203, 0x11050002, 0x04000005, 1322 11, 0x0aaa0555 }, 1323 { 192000000, 96000000, 0, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 1324 11, 0x0aaa0555 }, 1325 { 198000000, 99000000, 0, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005, 1326 11, 0x0aaa0555 }, 1327 { 200000000, 100000000, 0, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 1328 11, 0x0aaa0555 }, 1329 { 204000000, 102000000, 0, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 1330 11, 0x0aaa0555 }, 1331 { 208000000, 104000000, 0, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003, 1332 11, 0x0aaa0555 }, 1333 { 210000000, 105000000, 0, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 1334 11, 0x0aaa0555 }, 1335 { 216000000, 108000000, 0, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 1336 11, 0x0aaa0555 }, 1337 { 224000000, 112000000, 0, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003, 1338 11, 0x0aaa0555 }, 1339 { 228000000, 101333333, 0, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005, 1340 8, 0x012a00a9 }, 1341 { 228000000, 114000000, 0, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 1342 11, 0x0aaa0555 }, 1343 { 240000000, 102857143, 0, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003, 1344 13, 0x254a14a9 }, 1345 { 240000000, 120000000, 0, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 1346 11, 0x0aaa0555 }, 1347 { 252000000, 100800000, 0, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002, 1348 9, 0x02520129 }, 1349 { 252000000, 126000000, 0, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 1350 11, 0x0aaa0555 }, 1351 { 264000000, 132000000, 0, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 1352 11, 0x0aaa0555 }, 1353 { 272000000, 116571428, 0, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 1354 13, 0x254a14a9 }, 1355 { 280000000, 120000000, 0, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 1356 13, 0x254a14a9 }, 1357 { 288000000, 123428571, 0, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 1358 13, 0x254a14a9 }, 1359 { 300000000, 120000000, 0, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 1360 9, 0x02520129 }, 1361 { 300000000, 150000000, 0, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002, 1362 11, 0x0aaa0555 } 1363 }; 1364 static n4m_table_t BCMINITDATA(type7_table)[] = { 1365 { 183333333, 91666666, 0, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 1366 11, 0x0aaa0555 }, 1367 { 187500000, 93750000, 0, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 1368 11, 0x0aaa0555 }, 1369 { 196875000, 98437500, 0, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 1370 11, 0x0aaa0555 }, 1371 { 200000000, 100000000, 0, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003, 1372 11, 0x0aaa0555 }, 1373 { 200000000, 100000000, 0, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 1374 11, 0x0aaa0555 }, 1375 { 206250000, 103125000, 0, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 1376 11, 0x0aaa0555 }, 1377 { 212500000, 106250000, 0, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 1378 11, 0x0aaa0555 }, 1379 { 215625000, 107812500, 0, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005, 1380 11, 0x0aaa0555 }, 1381 { 216666666, 108333333, 0, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 1382 11, 0x0aaa0555 }, 1383 { 225000000, 112500000, 0, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 1384 11, 0x0aaa0555 }, 1385 { 233333333, 116666666, 0, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 1386 11, 0x0aaa0555 }, 1387 { 237500000, 118750000, 0, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 1388 11, 0x0aaa0555 }, 1389 { 240000000, 120000000, 0, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009, 1390 11, 0x0aaa0555 }, 1391 { 250000000, 125000000, 0, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003, 1392 11, 0x0aaa0555 } 1393 }; 1394 1395 ulong start, end, dst; 1396 bool ret = FALSE; 1397 1398 volatile uint32 *dll_ctrl = (volatile uint32 *)0xff400008; 1399 volatile uint32 *dll_r1 = (volatile uint32 *)0xff400010; 1400 volatile uint32 *dll_r2 = (volatile uint32 *)0xff400018; 1401 1402 /* 5354 chipcommon pll setting can't be changed. 1403 * The PMU on power up comes up with the default clk frequency 1404 * of 240MHz 1405 */ 1406 if ((CHIPID(sih->chip) == BCM5354_CHIP_ID) || (CHIPID(sih->chip) == BCM53572_CHIP_ID)) 1407 return TRUE; 1408 1409 if (sih->cccaps & CC_CAP_PMU) 1410 return mips_pmu_setclock(sih, mipsclock, siclock, pciclock); 1411 1412 osh = si_osh(sih); 1413 1414 /* get index of the current core */ 1415 idx = si_coreidx(sih); 1416 clockcontrol_m2 = NULL; 1417 1418 /* switch to chipc core */ 1419 cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX); 1420 ASSERT(cc); 1421 1422 pll_type = sih->cccaps & CC_CAP_PLL_MASK; 1423 if (pll_type == PLL_TYPE6) { 1424 clockcontrol_n = NULL; 1425 clockcontrol_sb = NULL; 1426 clockcontrol_pci = NULL; 1427 } else { 1428 clockcontrol_n = &cc->clockcontrol_n; 1429 clockcontrol_sb = &cc->clockcontrol_sb; 1430 clockcontrol_pci = &cc->clockcontrol_pci; 1431 clockcontrol_m2 = &cc->clockcontrol_m2; 1432 } 1433 1434 if (pll_type == PLL_TYPE6) { 1435 /* Silence compilers */ 1436 orig_n = orig_sb = orig_pci = 0; 1437 } else { 1438 /* Store the current clock register values */ 1439 orig_n = R_REG(osh, clockcontrol_n); 1440 orig_sb = R_REG(osh, clockcontrol_sb); 1441 orig_pci = R_REG(osh, clockcontrol_pci); 1442 } 1443 1444 if (pll_type == PLL_TYPE3) { 1445 /* 5350 */ 1446 if (CHIPID(sih->chip) != BCM5365_CHIP_ID) { 1447 /* 1448 * Search for the closest MIPS clock less than or equal to 1449 * a preferred value. 1450 */ 1451 for (i = 0; i < ARRAYSIZE(type3_table); i++) { 1452 if (type3_table[i].mipsclock > mipsclock) 1453 break; 1454 } 1455 if (i == 0) { 1456 ret = FALSE; 1457 goto done; 1458 } else { 1459 ret = TRUE; 1460 i--; 1461 } 1462 ASSERT(type3_table[i].mipsclock <= mipsclock); 1463 1464 /* No PLL change */ 1465 orig_m2 = R_REG(osh, &cc->clockcontrol_m2); 1466 if ((orig_n == type3_table[i].n) && 1467 (orig_m2 == type3_table[i].m2)) { 1468 goto done; 1469 } 1470 1471 /* Set the PLL controls */ 1472 W_REG(osh, clockcontrol_n, type3_table[i].n); 1473 W_REG(osh, clockcontrol_m2, type3_table[i].m2); 1474 1475 /* Reset */ 1476 si_watchdog(sih, 1); 1477 while (1); 1478 } 1479 } else if ((pll_type == PLL_TYPE2) || 1480 (pll_type == PLL_TYPE4) || 1481 (pll_type == PLL_TYPE6) || 1482 (pll_type == PLL_TYPE7)) { 1483 n4m_table_t *table = NULL, *te; 1484 uint tabsz = 0; 1485 1486 ASSERT(cc); 1487 1488 orig_mips = R_REG(osh, &cc->clockcontrol_m3); 1489 1490 switch (pll_type) { 1491 case PLL_TYPE6: { 1492 uint32 new_mips = 0; 1493 1494 ret = TRUE; 1495 if (mipsclock <= SB2MIPS_T6(CC_T6_M1)) 1496 new_mips = CC_T6_MMASK; 1497 1498 if (orig_mips == new_mips) 1499 goto done; 1500 1501 W_REG(osh, &cc->clockcontrol_m3, new_mips); 1502 goto end_fill; 1503 } 1504 case PLL_TYPE2: 1505 table = type2_table; 1506 tabsz = ARRAYSIZE(type2_table); 1507 break; 1508 case PLL_TYPE4: 1509 table = type4_table; 1510 tabsz = ARRAYSIZE(type4_table); 1511 break; 1512 case PLL_TYPE7: 1513 table = type7_table; 1514 tabsz = ARRAYSIZE(type7_table); 1515 break; 1516 default: 1517 ASSERT("No table for plltype" == NULL); 1518 break; 1519 } 1520 1521 /* Store the current clock register values */ 1522 orig_m2 = R_REG(osh, &cc->clockcontrol_m2); 1523 orig_ratio_parm = 0; 1524 orig_ratio_cfg = 0; 1525 1526 /* Look up current ratio */ 1527 for (i = 0; i < tabsz; i++) { 1528 if ((orig_n == table[i].n) && 1529 (orig_sb == table[i].sb) && 1530 (orig_pci == table[i].pci33) && 1531 (orig_m2 == table[i].m2) && 1532 (orig_mips == table[i].m3)) { 1533 orig_ratio_parm = table[i].ratio_parm; 1534 orig_ratio_cfg = table[i].ratio_cfg; 1535 break; 1536 } 1537 } 1538 1539 /* Search for the closest MIPS clock greater or equal to a preferred value */ 1540 for (i = 0; i < tabsz; i++) { 1541 ASSERT(table[i].mipsclock == 1542 si_clock_rate(pll_type, table[i].n, table[i].m3)); 1543 if ((mipsclock <= table[i].mipsclock) && 1544 ((siclock == 0) || (siclock <= table[i].sbclock)) && 1545 ((pciclock == 0) || (pciclock <= table[i].pciclock))) 1546 break; 1547 } 1548 if (i == tabsz) { 1549 ret = FALSE; 1550 goto done; 1551 } else { 1552 te = &table[i]; 1553 ret = TRUE; 1554 } 1555 1556 /* No PLL change */ 1557 if ((orig_n == te->n) && 1558 (orig_sb == te->sb) && 1559 (orig_pci == te->pci33) && 1560 (orig_m2 == te->m2) && 1561 (orig_mips == te->m3)) 1562 goto done; 1563 1564 /* Set the PLL controls */ 1565 W_REG(osh, clockcontrol_n, te->n); 1566 W_REG(osh, clockcontrol_sb, te->sb); 1567 W_REG(osh, clockcontrol_pci, te->pci33); 1568 W_REG(osh, &cc->clockcontrol_m2, te->m2); 1569 W_REG(osh, &cc->clockcontrol_m3, te->m3); 1570 1571 /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */ 1572 if ((pll_type == PLL_TYPE7) && (te->sb != te->m2) && 1573 (si_clock_rate(pll_type, te->n, te->m2) == 120000000)) 1574 W_REG(osh, &cc->chipcontrol, 1575 R_REG(osh, &cc->chipcontrol) | 0x100); 1576 1577 /* No ratio change */ 1578 if (CHIPID(sih->chip) != BCM4785_CHIP_ID) { 1579 if (orig_ratio_parm == te->ratio_parm) 1580 goto end_fill; 1581 } 1582 1583 /* Preload the code into the cache */ 1584 icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize); 1585 if (CHIPID(sih->chip) == BCM4785_CHIP_ID) { 1586 start = ((ulong) &&start_fill_4785) & ~(ic_lsize - 1); 1587 end = ((ulong) &&end_fill_4785 + (ic_lsize - 1)) & ~(ic_lsize - 1); 1588 } 1589 else { 1590 start = ((ulong) &&start_fill) & ~(ic_lsize - 1); 1591 end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1); 1592 } 1593 while (start < end) { 1594 cache_op(start, Fill_I); 1595 start += ic_lsize; 1596 } 1597 1598 /* 4785 clock freq change procedures */ 1599 if (CHIPID(sih->chip) == BCM4785_CHIP_ID) { 1600 start_fill_4785: 1601 /* Switch to async */ 1602 MTC0(C0_BROADCOM, 4, (1 << 22)); 1603 1604 /* Set clock ratio in MIPS */ 1605 *dll_r1 = (*dll_r1 & 0xfffffff0) | (te->dll_r1 - 1); 1606 *dll_r2 = te->dll_r2; 1607 1608 /* Enable new settings in MIPS */ 1609 *dll_r1 = *dll_r1 | 0xc0000000; 1610 1611 /* Set active cfg */ 1612 MTC0(C0_BROADCOM, 2, MFC0(C0_BROADCOM, 2) | (1 << 3) | 1); 1613 1614 /* Fake soft reset (clock cfg registers not reset) */ 1615 MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2)); 1616 1617 /* Clear active cfg */ 1618 MTC0(C0_BROADCOM, 2, MFC0(C0_BROADCOM, 2) & ~(1 << 3)); 1619 1620 /* set watchdog timer */ 1621 W_REG(osh, &cc->watchdog, 20); 1622 (void) R_REG(osh, &cc->chipid); 1623 1624 /* wait for timer interrupt */ 1625 __asm__ __volatile__( 1626 ".set\tmips3\n\t" 1627 "sync\n\t" 1628 "wait\n\t" 1629 ".set\tmips0"); 1630 end_fill_4785: 1631 while (1); 1632 } 1633 /* Generic clock freq change procedures */ 1634 else { 1635 /* Copy the handler */ 1636 start = (ulong) &handler; 1637 end = (ulong) &afterhandler; 1638 dst = KSEG1ADDR(0x180); 1639 for (i = 0; i < (end - start); i += 4) 1640 *((ulong *)(dst + i)) = *((ulong *)(start + i)); 1641 1642 /* Preload the handler into the cache one line at a time */ 1643 for (i = 0; i < (end - start); i += ic_lsize) 1644 cache_op(dst + i, Fill_I); 1645 1646 /* Clear BEV bit */ 1647 MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV); 1648 1649 /* Enable interrupts */ 1650 MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE)); 1651 1652 /* Enable MIPS timer interrupt */ 1653 mipsr = si_setcore(sih, MIPS33_CORE_ID, 0); 1654 ASSERT(mipsr); 1655 W_REG(osh, &mipsr->intmask, 1); 1656 1657 start_fill: 1658 /* step 1, set clock ratios */ 1659 MTC0(C0_BROADCOM, 3, te->ratio_parm); 1660 MTC0(C0_BROADCOM, 1, te->ratio_cfg); 1661 1662 /* step 2: program timer intr */ 1663 W_REG(osh, &mipsr->timer, 100); 1664 (void) R_REG(osh, &mipsr->timer); 1665 1666 /* step 3, switch to async */ 1667 sync_mode = MFC0(C0_BROADCOM, 4); 1668 MTC0(C0_BROADCOM, 4, 1 << 22); 1669 1670 /* step 4, set cfg active */ 1671 MTC0(C0_BROADCOM, 2, (1 << 3) | 1); 1672 1673 /* steps 5 & 6 */ 1674 __asm__ __volatile__( 1675 ".set\tmips3\n\t" 1676 "wait\n\t" 1677 ".set\tmips0"); 1678 1679 /* step 7, clear cfg active */ 1680 MTC0(C0_BROADCOM, 2, 0); 1681 1682 /* Additional Step: set back to orig sync mode */ 1683 MTC0(C0_BROADCOM, 4, sync_mode); 1684 1685 /* step 8, fake soft reset */ 1686 MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2)); 1687 1688 end_fill: 1689 /* set watchdog timer */ 1690 W_REG(osh, &cc->watchdog, 20); 1691 (void) R_REG(osh, &cc->chipid); 1692 1693 /* wait for timer interrupt */ 1694 __asm__ __volatile__( 1695 ".set\tmips3\n\t" 1696 "sync\n\t" 1697 "wait\n\t" 1698 ".set\tmips0"); 1699 while (1); 1700 } 1701 } 1702 1703done: 1704 /* Enable 4785 DLL */ 1705 if (CHIPID(sih->chip) == BCM4785_CHIP_ID) { 1706 uint32 tmp; 1707 1708 /* set mask to 1e, enable DLL (bit 0) */ 1709 *dll_ctrl |= 0x0041e021; 1710 1711 /* enable aggressive hardware mode */ 1712 *dll_ctrl |= 0x00000080; 1713 1714 /* wait for lock flag to clear */ 1715 while ((*dll_ctrl & 0x2) == 0); 1716 1717 /* clear sticky flags (clear on write 1) */ 1718 tmp = *dll_ctrl; 1719 *dll_ctrl = tmp; 1720 1721 /* set mask to 5b'10001 */ 1722 *dll_ctrl = (*dll_ctrl & 0xfffc1fff) | 0x00022000; 1723 1724 /* enable sync mode */ 1725 MTC0(C0_BROADCOM, 4, MFC0(C0_BROADCOM, 4) & 0xfe3fffff); 1726 (void)MFC0(C0_BROADCOM, 4); 1727 } 1728 1729 /* switch back to previous core */ 1730 si_setcoreidx(sih, idx); 1731 1732 return ret; 1733} 1734 1735void 1736BCMINITFN(enable_pfc)(uint32 mode) 1737{ 1738 uint32 prid; 1739 ulong start, end; 1740 uint ic_size, ic_lsize; 1741 1742 prid = MFC0(C0_PRID, 0); 1743 if (!BCM330X(prid)) 1744 return; 1745 1746 /* enable prefetch cache if available */ 1747 if (MFC0(C0_BROADCOM, 0) & BRCM_PFC_AVAIL) { 1748 /* If auto then choose the correct mode for this 1749 * platform, currently we only ever select one mode 1750 */ 1751 if (mode == PFC_AUTO) 1752 mode = PFC_INST; 1753 1754 icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize); 1755 1756 start = ((ulong) &&setpfc_start) & ~(ic_lsize - 1); 1757 end = ((ulong) &&setpfc_end + (ic_lsize - 1)) & ~(ic_lsize - 1); 1758 1759 /* Preload setpfc code into the cache one line at a time */ 1760 while (start < end) { 1761 cache_op(start, Fill_I); 1762 start += ic_lsize; 1763 } 1764 1765 /* Now set the pfc */ 1766 setpfc_start: 1767 /* write range */ 1768 *(volatile uint32 *)PFC_CR1 = 0xffff0000; 1769 1770 /* enable */ 1771 *(volatile uint32 *)PFC_CR0 = mode; 1772 setpfc_end: 1773 /* Compiler foder */ 1774 ic_size = 0; 1775 } 1776} 1777 1778/* returns the ncdl value to be programmed into sdram_ncdl for calibration */ 1779uint32 1780BCMINITFN(si_memc_get_ncdl)(si_t *sih) 1781{ 1782 osl_t *osh; 1783 sbmemcregs_t *memc; 1784 uint32 ret = 0; 1785 uint32 config, rd, wr, misc, dqsg, cd, sm, sd; 1786 uint idx, rev; 1787 1788 osh = si_osh(sih); 1789 1790 idx = si_coreidx(sih); 1791 1792 memc = (sbmemcregs_t *)si_setcore(sih, MEMC_CORE_ID, 0); 1793 if (memc == NULL) 1794 goto out; 1795 1796 rev = si_corerev(sih); 1797 1798 config = R_REG(osh, &memc->config); 1799 wr = R_REG(osh, &memc->wrncdlcor); 1800 rd = R_REG(osh, &memc->rdncdlcor); 1801 misc = R_REG(osh, &memc->miscdlyctl); 1802 dqsg = R_REG(osh, &memc->dqsgatencdl); 1803 1804 rd &= MEMC_RDNCDLCOR_RD_MASK; 1805 wr &= MEMC_WRNCDLCOR_WR_MASK; 1806 dqsg &= MEMC_DQSGATENCDL_G_MASK; 1807 1808 if (config & MEMC_CONFIG_DDR) { 1809 ret = (wr << 16) | (rd << 8) | dqsg; 1810 } else { 1811 if (rev > 0) 1812 cd = rd; 1813 else 1814 cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD); 1815 sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT; 1816 sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT; 1817 ret = (sm << 16) | (sd << 8) | cd; 1818 } 1819 1820out: 1821 /* switch back to previous core */ 1822 si_setcoreidx(sih, idx); 1823 1824 return ret; 1825} 1826 1827void 1828hnd_cpu_reset(si_t *sih) 1829{ 1830 if (CHIPID(sih->chip) == BCM4785_CHIP_ID) 1831 MTC0(C0_BROADCOM, 4, (1 << 22)); 1832 si_watchdog(sih, 1); 1833 if (CHIPID(sih->chip) == BCM4785_CHIP_ID) { 1834 __asm__ __volatile__( 1835 ".set\tmips3\n\t" 1836 "sync\n\t" 1837 "wait\n\t" 1838 ".set\tmips0"); 1839 } 1840 while (1); 1841} 1842 1843#if defined(BCMPERFSTATS) 1844/* 1845 * CP0 Register 25 supports 4 semi-independent 32bit performance counters. 1846 * $25 select 0, 1, 2, and 3 are the counters. The counters *decrement* (who thought this one up?) 1847 * $25 select 4 and 5 each contain 2-16bit control fields, one for each of the 4 counters 1848 * $25 select 6 is the global perf control register. 1849 */ 1850/* enable and start instruction counting */ 1851 1852void 1853hndmips_perf_cyclecount_enable(void) 1854{ 1855 MTC0(C0_PERFORMANCE, 6, 0x80000200); /* global enable perf counters */ 1856 MTC0(C0_PERFORMANCE, 4, 1857 0x8048 | MFC0(C0_PERFORMANCE, 4)); /* enable cycles counting for counter 0 */ 1858 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter zero */ 1859} 1860 1861void 1862hndmips_perf_instrcount_enable(void) 1863{ 1864 MTC0(C0_PERFORMANCE, 6, 0x80000200); /* global enable perf counters */ 1865 MTC0(C0_PERFORMANCE, 4, 1866 0x8044 | MFC0(C0_PERFORMANCE, 4)); /* enable instructions counting for counter 0 */ 1867 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter zero */ 1868} 1869 1870/* enable and start I$ hit and I$ miss counting */ 1871void 1872hndmips_perf_icachecount_enable(void) 1873{ 1874 MTC0(C0_PERFORMANCE, 6, 0x80000218); /* enable I$ counting */ 1875 MTC0(C0_PERFORMANCE, 4, 0x80148018); /* count I$ hits in cntr 0 and misses in cntr 1 */ 1876 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # I$ hits */ 1877 MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # I$ misses */ 1878} 1879 1880/* enable and start D$ hit and I$ miss counting */ 1881void 1882hndmips_perf_dcachecount_enable(void) 1883{ 1884 MTC0(C0_PERFORMANCE, 6, 0x80000211); /* enable D$ counting */ 1885 MTC0(C0_PERFORMANCE, 4, 0x80248028); /* count D$ hits in cntr 0 and misses in cntr 1 */ 1886 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # D$ hits */ 1887 MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # D$ misses */ 1888} 1889 1890void 1891hndmips_perf_icache_miss_enable() 1892{ 1893 MTC0(C0_PERFORMANCE, 4, 1894 0x80140000 | MFC0(C0_PERFORMANCE, 4)); /* enable cache misses counting for counter 1 */ 1895 MTC0(C0_PERFORMANCE, 1, 0); /* zero counter one */ 1896} 1897 1898 1899void 1900hndmips_perf_icache_hit_enable() 1901{ 1902 MTC0(C0_PERFORMANCE, 5, 0x8018 | MFC0(C0_PERFORMANCE, 5)); 1903 /* enable cache hits counting for counter 2 */ 1904 MTC0(C0_PERFORMANCE, 2, 0); /* zero counter 2 */ 1905} 1906 1907uint32 1908hndmips_perf_read_instrcount() 1909{ 1910 return -(long)(MFC0(C0_PERFORMANCE, 0)); 1911} 1912 1913uint32 1914hndmips_perf_read_cache_miss() 1915{ 1916 return -(long)(MFC0(C0_PERFORMANCE, 1)); 1917} 1918 1919uint32 1920hndmips_perf_read_cache_hit() 1921{ 1922 return -(long)(MFC0(C0_PERFORMANCE, 2)); 1923} 1924 1925#endif 1926