1/* 2 * BCM47XX Sonics SiliconBackplane MIPS core routines 3 * 4 * Copyright 2007, Broadcom Corporation 5 * All Rights Reserved. 6 * 7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY 8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM 9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS 10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. 11 * 12 * $Id: hndmips.c,v 1.1.1.1 2008/10/15 03:31:34 james26_jang Exp $ 13 */ 14 15#include <typedefs.h> 16#include <bcmdefs.h> 17#include <osl.h> 18#include <bcmutils.h> 19#include <sbutils.h> 20#include <bcmdevs.h> 21#include <bcmnvram.h> 22#include <sbconfig.h> 23#include <sbchipc.h> 24#include <sbmemc.h> 25#include <mipsinc.h> 26#include <sbhndmips.h> 27#include <hndcpu.h> 28#include <hndmips.h> 29 30/* sbipsflag register format, indexed by irq. */ 31static const uint32 sbips_int_mask[] = { 32 0, /* placeholder */ 33 SBIPS_INT1_MASK, 34 SBIPS_INT2_MASK, 35 SBIPS_INT3_MASK, 36 SBIPS_INT4_MASK 37}; 38 39static const uint32 sbips_int_shift[] = { 40 0, /* placeholder */ 41 SBIPS_INT1_SHIFT, 42 SBIPS_INT2_SHIFT, 43 SBIPS_INT3_SHIFT, 44 SBIPS_INT4_SHIFT 45}; 46 47/* 48 * Map SB cores sharing the MIPS hardware IRQ0 to virtual dedicated OS IRQs. 49 * Per-port BSP code is required to provide necessary translations between 50 * the shared MIPS IRQ and the virtual OS IRQs based on SB core flag. 51 * 52 * See sb_irq() for the mapping. 53 */ 54static uint shirq_map_base = 0; 55 56/* 57 * Returns the MIPS IRQ assignment of the current core. If unassigned, 58 * 0 is returned. 59 */ 60static uint 61sb_getirq(sb_t *sbh) 62{ 63 osl_t *osh; 64 uint idx; 65 void *regs; 66 sbconfig_t *sb; 67 uint32 flag, sbipsflag; 68 uint irq = 0; 69 70 osh = sb_osh(sbh); 71 flag = sb_flag(sbh); 72 73 idx = sb_coreidx(sbh); 74 75 if ((regs = sb_setcore(sbh, SB_MIPS33, 0)) != NULL) { 76 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); 77 78 /* sbipsflag specifies which core is routed to interrupts 1 to 4 */ 79 sbipsflag = R_REG(osh, &sb->sbipsflag); 80 for (irq = 1; irq <= 4; irq++) { 81 if (((sbipsflag & sbips_int_mask[irq]) >> sbips_int_shift[irq]) == flag) 82 break; 83 } 84 if (irq == 5) 85 irq = 0; 86 } 87 88 sb_setcoreidx(sbh, idx); 89 90 return irq; 91} 92 93/* 94 * Return the MIPS IRQ assignment of the current core. If necessary 95 * map cores sharing the MIPS hw IRQ0 to virtual dedicated OS IRQs. 96 */ 97uint 98sb_irq(sb_t *sbh) 99{ 100 uint irq = sb_getirq(sbh); 101 if (irq == 0 && shirq_map_base) 102 irq = sb_flag(sbh) + shirq_map_base; 103 return irq; 104} 105 106/* Clears the specified MIPS IRQ. */ 107static void 108BCMINITFN(sb_clearirq)(sb_t *sbh, uint irq) 109{ 110 osl_t *osh; 111 void *regs; 112 sbconfig_t *sb; 113 114 osh = sb_osh(sbh); 115 116 regs = sb_setcore(sbh, SB_MIPS33, 0); 117 ASSERT(regs); 118 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); 119 120 if (irq == 0) 121 W_REG(osh, &sb->sbintvec, 0); 122 else 123 OR_REG(osh, &sb->sbipsflag, sbips_int_mask[irq]); 124} 125 126/* 127 * Assigns the specified MIPS IRQ to the specified core. Shared MIPS 128 * IRQ 0 may be assigned more than once. 129 * 130 * The old assignment to the specified core is removed first. 131 */ 132static void 133BCMINITFN(sb_setirq)(sb_t *sbh, uint irq, uint coreid, uint coreunit) 134{ 135 osl_t *osh; 136 void *regs; 137 sbconfig_t *sb; 138 uint32 flag; 139 uint oldirq; 140 141 osh = sb_osh(sbh); 142 143 regs = sb_setcore(sbh, coreid, coreunit); 144 ASSERT(regs); 145 flag = sb_flag(sbh); 146 oldirq = sb_getirq(sbh); 147 if (oldirq) 148 sb_clearirq(sbh, oldirq); 149 150 regs = sb_setcore(sbh, SB_MIPS33, 0); 151 ASSERT(regs); 152 sb = (sbconfig_t *)((ulong) regs + SBCONFIGOFF); 153 154 if (!oldirq) 155 AND_REG(osh, &sb->sbintvec, ~(1 << flag)); 156 157 if (irq == 0) 158 OR_REG(osh, &sb->sbintvec, 1 << flag); 159 else { 160 flag <<= sbips_int_shift[irq]; 161 ASSERT(!(flag & ~sbips_int_mask[irq])); 162 flag |= R_REG(osh, &sb->sbipsflag) & ~sbips_int_mask[irq]; 163 W_REG(osh, &sb->sbipsflag, flag); 164 } 165} 166 167/* 168 * Initializes clocks and interrupts. SB and NVRAM access must be 169 * initialized prior to calling. 170 * 171 * 'shirqmap' enables virtual dedicated OS IRQ mapping if non-zero. 172 */ 173void 174BCMINITFN(sb_mips_init)(sb_t *sbh, uint shirqmap) 175{ 176 osl_t *osh; 177 ulong hz, ns, tmp; 178 chipcregs_t *cc; 179 uint irq; 180 181 osh = sb_osh(sbh); 182 183 /* Figure out current SB clock speed */ 184 if ((hz = sb_clock(sbh)) == 0) 185 hz = 100000000; 186 ns = 1000000000 / hz; 187 188 /* Setup external interface timing */ 189 cc = sb_setcore(sbh, SB_CC, 0); 190 ASSERT(cc); 191 192 /* Set timing for the flash */ 193 tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */ 194 tmp |= CEIL(10, ns) << FW_W1_SHIFT; /* W1 = 10nS */ 195 tmp |= CEIL(120, ns); /* W0 = 120nS */ 196 if (sbh->ccrev < 9) 197 W_REG(osh, &cc->flash_waitcount, tmp); 198 199 if ((sbh->ccrev < 9) || 200 ((sb_chip(sbh) == BCM5350_CHIP_ID) && sb_chiprev(sbh) == 0)) { 201 W_REG(osh, &cc->pcmcia_memwait, tmp); 202 } 203 204 /* Save shared IRQ mapping base */ 205 shirq_map_base = shirqmap; 206 207 /* Chip specific initialization */ 208 switch (sb_chip(sbh)) { 209 case BCM5350_CHIP_ID: 210 /* Clear interrupt map */ 211 for (irq = 0; irq <= 4; irq++) 212 sb_clearirq(sbh, irq); 213 sb_setirq(sbh, 0, SB_CC, 0); 214 sb_setirq(sbh, 0, SB_MIPS33, 0); 215 sb_setirq(sbh, 1, SB_D11, 0); 216 sb_setirq(sbh, 2, SB_ENET, 0); 217 sb_setirq(sbh, 3, SB_PCI, 0); 218 sb_setirq(sbh, 4, SB_USB, 0); 219 break; 220 case BCM4785_CHIP_ID: 221 /* Reassign PCI to irq 4 */ 222 sb_setirq(sbh, 4, SB_PCI, 0); 223 break; 224 } 225} 226 227/* Do any setup necessary to run a new image and jump to it. */ 228void 229hnd_cpu_jumpto(void *addr) 230{ 231 void (*jumpto)(void) = addr; 232 233 (jumpto)(); 234} 235 236uint32 237BCMINITFN(sb_cpu_clock)(sb_t *sbh) 238{ 239 chipcregs_t *cc; 240 uint32 n, m; 241 uint idx; 242 uint32 pll_type, rate = 0; 243 244 /* get index of the current core */ 245 idx = sb_coreidx(sbh); 246 pll_type = PLL_TYPE1; 247 248 /* switch to chipc core */ 249 cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0); 250 ASSERT(cc); 251 252 /* 5354 chip uses a non programmable PLL of frequency 240MHz */ 253 if (sb_chip(sbh) == BCM5354_CHIP_ID) { 254 //rate = 240000000; 255 rate = 200000000; 256 goto out; 257 } 258 259 pll_type = sbh->cccaps & CC_CAP_PLL_MASK; 260 n = R_REG(osh, &cc->clockcontrol_n); 261 if ((pll_type == PLL_TYPE2) || 262 (pll_type == PLL_TYPE4) || 263 (pll_type == PLL_TYPE6) || 264 (pll_type == PLL_TYPE7)) 265 m = R_REG(osh, &cc->clockcontrol_m3); 266 else if (pll_type == PLL_TYPE5) { 267 rate = 200000000; 268 goto out; 269 } else if (pll_type == PLL_TYPE3) { 270 if (sb_chip(sbh) == BCM5365_CHIP_ID) { 271 rate = 200000000; 272 goto out; 273 } 274 /* 5350 uses m2 to control mips */ 275 else 276 m = R_REG(osh, &cc->clockcontrol_m2); 277 } else 278 m = R_REG(osh, &cc->clockcontrol_sb); 279 280 /* calculate rate */ 281 rate = sb_clock_rate(pll_type, n, m); 282 283 if (pll_type == PLL_TYPE6) 284 rate = SB2MIPS_T6(rate); 285 286out: 287 /* switch back to previous core */ 288 sb_setcoreidx(sbh, idx); 289 290 return rate; 291} 292 293#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4) 294 295static void 296BCMINITFN(handler)(void) 297{ 298 __asm__( 299 ".set\tmips32\n\t" 300 "ssnop\n\t" 301 "ssnop\n\t" 302 /* Disable interrupts */ 303 /* MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~(ALLINTS | STO_IE)); */ 304 "mfc0 $15, $12\n\t" 305 /* Just a Hack to not to use reg 'at' which was causing problems on 4704 A2 */ 306 "li $14, -31746\n\t" 307 "and $15, $15, $14\n\t" 308 "mtc0 $15, $12\n\t" 309 "eret\n\t" 310 "nop\n\t" 311 "nop\n\t" 312 ".set\tmips0"); 313} 314 315/* The following MUST come right after handler() */ 316static void 317BCMINITFN(afterhandler)(void) 318{ 319} 320 321/* 322 * Set the MIPS, backplane and PCI clocks as closely as possible. 323 * 324 * MIPS clocks synchronization function has been moved from PLL in chipcommon 325 * core rev. 15 to a DLL inside the MIPS core in 4785. 326 */ 327bool 328BCMINITFN(sb_mips_setclock)(sb_t *sbh, uint32 mipsclock, uint32 sbclock, uint32 pciclock) 329{ 330 chipcregs_t *cc = NULL; 331 mipsregs_t *mipsr = NULL; 332 volatile uint32 *clockcontrol_n, *clockcontrol_sb, *clockcontrol_pci, *clockcontrol_m2; 333 uint32 orig_n, orig_sb, orig_pci, orig_m2, orig_mips, orig_ratio_parm, orig_ratio_cfg; 334 uint32 pll_type, sync_mode; 335 uint ic_size, ic_lsize; 336 uint idx, i; 337 338 /* PLL configuration: type 1 */ 339 typedef struct { 340 uint32 mipsclock; 341 uint16 n; 342 uint32 sb; 343 uint32 pci33; 344 uint32 pci25; 345 } n3m_table_t; 346 static n3m_table_t BCMINITDATA(type1_table)[] = { 347 /* 96.000 32.000 24.000 */ 348 { 96000000, 0x0303, 0x04020011, 0x11030011, 0x11050011 }, 349 /* 100.000 33.333 25.000 */ 350 { 100000000, 0x0009, 0x04020011, 0x11030011, 0x11050011 }, 351 /* 104.000 31.200 24.960 */ 352 { 104000000, 0x0802, 0x04020011, 0x11050009, 0x11090009 }, 353 /* 108.000 32.400 24.923 */ 354 { 108000000, 0x0403, 0x04020011, 0x11050009, 0x02000802 }, 355 /* 112.000 32.000 24.889 */ 356 { 112000000, 0x0205, 0x04020011, 0x11030021, 0x02000403 }, 357 /* 115.200 32.000 24.000 */ 358 { 115200000, 0x0303, 0x04020009, 0x11030011, 0x11050011 }, 359 /* 120.000 30.000 24.000 */ 360 { 120000000, 0x0011, 0x04020011, 0x11050011, 0x11090011 }, 361 /* 124.800 31.200 24.960 */ 362 { 124800000, 0x0802, 0x04020009, 0x11050009, 0x11090009 }, 363 /* 128.000 32.000 24.000 */ 364 { 128000000, 0x0305, 0x04020011, 0x11050011, 0x02000305 }, 365 /* 132.000 33.000 24.750 */ 366 { 132000000, 0x0603, 0x04020011, 0x11050011, 0x02000305 }, 367 /* 136.000 32.640 24.727 */ 368 { 136000000, 0x0c02, 0x04020011, 0x11090009, 0x02000603 }, 369 /* 140.000 30.000 24.706 */ 370 { 140000000, 0x0021, 0x04020011, 0x11050021, 0x02000c02 }, 371 /* 144.000 30.857 24.686 */ 372 { 144000000, 0x0405, 0x04020011, 0x01020202, 0x11090021 }, 373 /* 150.857 33.000 24.000 */ 374 { 150857142, 0x0605, 0x04020021, 0x02000305, 0x02000605 }, 375 /* 152.000 32.571 24.000 */ 376 { 152000000, 0x0e02, 0x04020011, 0x11050021, 0x02000e02 }, 377 /* 156.000 31.200 24.960 */ 378 { 156000000, 0x0802, 0x04020005, 0x11050009, 0x11090009 }, 379 /* 160.000 32.000 24.000 */ 380 { 160000000, 0x0309, 0x04020011, 0x11090011, 0x02000309 }, 381 /* 163.200 32.640 24.727 */ 382 { 163200000, 0x0c02, 0x04020009, 0x11090009, 0x02000603 }, 383 /* 168.000 32.000 24.889 */ 384 { 168000000, 0x0205, 0x04020005, 0x11030021, 0x02000403 }, 385 /* 176.000 33.000 24.000 */ 386 { 176000000, 0x0602, 0x04020003, 0x11050005, 0x02000602 }, 387 }; 388 389 /* PLL configuration: type 3 */ 390 typedef struct { 391 uint32 mipsclock; 392 uint16 n; 393 uint32 m2; /* that is the clockcontrol_m2 */ 394 } type3_table_t; 395 static type3_table_t type3_table[] = { 396 /* for 5350, mips clock is always double sb clock */ 397 { 150000000, 0x311, 0x4020005 }, 398 { 200000000, 0x311, 0x4020003 }, 399 }; 400 401 /* PLL configuration: type 2, 4, 7 */ 402 typedef struct { 403 uint32 mipsclock; 404 uint32 sbclock; 405 uint32 pciclock; 406 uint16 n; 407 uint32 sb; 408 uint32 pci33; 409 uint32 m2; 410 uint32 m3; 411 uint32 ratio_cfg; 412 uint32 ratio_parm; 413 uint32 d11_r1; 414 uint32 d11_r2; 415 } n4m_table_t; 416 static n4m_table_t BCMINITDATA(type2_table)[] = { 417 { 120000000, 60000000, 32000000, 0x0303, 0x01000200, 0x01000600, 0x01000200, 418 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 419 { 150000000, 75000000, 33333333, 0x0303, 0x01000100, 0x01000600, 0x01000100, 420 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 421 { 180000000, 80000000, 30000000, 0x0403, 0x01010000, 0x01020300, 0x01020600, 422 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 423 { 180000000, 90000000, 30000000, 0x0403, 0x01000100, 0x01020300, 0x01000100, 424 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 425 { 200000000, 100000000, 33333333, 0x0303, 0x02010000, 0x02040001, 0x02010000, 426 0x06000001, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 427 { 211200000, 105600000, 30171428, 0x0902, 0x01000200, 0x01030400, 0x01000200, 428 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 429 { 220800000, 110400000, 31542857, 0x1500, 0x01000200, 0x01030400, 0x01000200, 430 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 431 { 230400000, 115200000, 32000000, 0x0604, 0x01000200, 0x01020600, 0x01000200, 432 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 433 { 234000000, 104000000, 31200000, 0x0b01, 0x01010000, 0x01010700, 0x01020600, 434 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 435 { 240000000, 120000000, 33333333, 0x0803, 0x01000200, 0x01020600, 0x01000200, 436 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 437 { 252000000, 126000000, 33333333, 0x0504, 0x01000100, 0x01020500, 0x01000100, 438 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 439 { 264000000, 132000000, 33000000, 0x0903, 0x01000200, 0x01020700, 0x01000200, 440 0x05000200, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 441 { 270000000, 120000000, 30000000, 0x0703, 0x01010000, 0x01030400, 0x01020600, 442 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 443 { 276000000, 122666666, 31542857, 0x1500, 0x01010000, 0x01030400, 0x01020600, 444 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 445 { 280000000, 140000000, 31111111, 0x0503, 0x01000000, 0x01010600, 0x01000000, 446 0x05000000, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 447 { 288000000, 128000000, 32914285, 0x0604, 0x01010000, 0x01030400, 0x01020600, 448 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 449 { 288000000, 144000000, 32000000, 0x0404, 0x01000000, 0x01010600, 0x01000000, 450 0x05000000, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 451 { 300000000, 133333333, 33333333, 0x0803, 0x01010000, 0x01020600, 0x01010100, 452 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 453 { 300000000, 133333333, 37500000, 0x0803, 0x01010000, 0x01020500, 0x01010100, 454 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 455 { 300000000, 133333333, 42857142, 0x0803, 0x01010000, 0x01020400, 0x01010100, 456 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 457 { 300000000, 133333333, 50000000, 0x0803, 0x01010000, 0x01020300, 0x01010100, 458 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 459 { 300000000, 133333333, 60000000, 0x0803, 0x01010000, 0x01020200, 0x01010100, 460 0x05000100, 8, 0x012a00a9, 9 /* ratio 4/9 */, 0x012a00a9 }, 461 { 300000000, 150000000, 33333333, 0x0803, 0x01000100, 0x01020600, 0x01010100, 462 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 463 { 300000000, 150000000, 37500000, 0x0803, 0x01000100, 0x01020500, 0x01010100, 464 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 465 { 300000000, 150000000, 42857142, 0x0803, 0x01000100, 0x01020400, 0x01010100, 466 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 467 { 300000000, 150000000, 50000000, 0x0803, 0x01000100, 0x01020300, 0x01010100, 468 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 469 { 300000000, 150000000, 60000000, 0x0803, 0x01000100, 0x01020200, 0x01010100, 470 0x05000100, 11, 0x0aaa0555, 8 /* ratio 4/8 */, 0x00aa0055 }, 471 { 330000000, 132000000, 33000000, 0x0903, 0x01000200, 0x00020200, 0x01010100, 472 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 }, 473 { 330000000, 146666666, 33000000, 0x0903, 0x01010000, 0x00020200, 0x01010100, 474 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 }, 475 { 330000000, 165000000, 33000000, 0x0903, 0x01000100, 0x00020200, 0x01010100, 476 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 477 { 330000000, 165000000, 41250000, 0x0903, 0x01000100, 0x00020100, 0x01010100, 478 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 479 { 330000000, 165000000, 55000000, 0x0903, 0x01000100, 0x00020000, 0x01010100, 480 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 481 { 360000000, 120000000, 32000000, 0x0a03, 0x01000300, 0x00010201, 0x01010200, 482 0x05000100, 0, 0, 12 /* ratio 4/12 */, 0x04920492 }, 483 { 360000000, 144000000, 32000000, 0x0a03, 0x01000200, 0x00010201, 0x01010200, 484 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 }, 485 { 360000000, 160000000, 32000000, 0x0a03, 0x01010000, 0x00010201, 0x01010200, 486 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 }, 487 { 360000000, 180000000, 32000000, 0x0a03, 0x01000100, 0x00010201, 0x01010200, 488 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 489 { 360000000, 180000000, 40000000, 0x0a03, 0x01000100, 0x00010101, 0x01010200, 490 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 491 { 360000000, 180000000, 53333333, 0x0a03, 0x01000100, 0x00010001, 0x01010200, 492 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 493 { 390000000, 130000000, 32500000, 0x0b03, 0x01010100, 0x00020101, 0x01020100, 494 0x05000100, 0, 0, 12 /* ratio 4/12 */, 0x04920492 }, 495 { 390000000, 156000000, 32500000, 0x0b03, 0x01000200, 0x00020101, 0x01020100, 496 0x05000100, 0, 0, 10 /* ratio 4/10 */, 0x02520129 }, 497 { 390000000, 173000000, 32500000, 0x0b03, 0x01010000, 0x00020101, 0x01020100, 498 0x05000100, 0, 0, 9 /* ratio 4/9 */, 0x012a00a9 }, 499 { 390000000, 195000000, 32500000, 0x0b03, 0x01000100, 0x00020101, 0x01020100, 500 0x05000100, 0, 0, 8 /* ratio 4/8 */, 0x00aa0055 }, 501 }; 502 static n4m_table_t BCMINITDATA(type4_table)[] = { 503 { 120000000, 60000000, 0, 0x0009, 0x11020009, 0x01030203, 0x11020009, 0x04000009, 504 11, 0x0aaa0555 }, 505 { 150000000, 75000000, 0, 0x0009, 0x11050002, 0x01030203, 0x11050002, 0x04000005, 506 11, 0x0aaa0555 }, 507 { 192000000, 96000000, 0, 0x0702, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 508 11, 0x0aaa0555 }, 509 { 198000000, 99000000, 0, 0x0603, 0x11020005, 0x11030011, 0x11020005, 0x04000005, 510 11, 0x0aaa0555 }, 511 { 200000000, 100000000, 0, 0x0009, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 512 11, 0x0aaa0555 }, 513 { 204000000, 102000000, 0, 0x0c02, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 514 11, 0x0aaa0555 }, 515 { 208000000, 104000000, 0, 0x0802, 0x11030002, 0x11090005, 0x11030002, 0x04000003, 516 11, 0x0aaa0555 }, 517 { 210000000, 105000000, 0, 0x0209, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 518 11, 0x0aaa0555 }, 519 { 216000000, 108000000, 0, 0x0111, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 520 11, 0x0aaa0555 }, 521 { 224000000, 112000000, 0, 0x0205, 0x11030002, 0x02002103, 0x11030002, 0x04000003, 522 11, 0x0aaa0555 }, 523 { 228000000, 101333333, 0, 0x0e02, 0x11030003, 0x11210005, 0x01030305, 0x04000005, 524 8, 0x012a00a9 }, 525 { 228000000, 114000000, 0, 0x0e02, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 526 11, 0x0aaa0555 }, 527 { 240000000, 102857143, 0, 0x0109, 0x04000021, 0x01050203, 0x11030021, 0x04000003, 528 13, 0x254a14a9 }, 529 { 240000000, 120000000, 0, 0x0109, 0x11030002, 0x01050203, 0x11030002, 0x04000003, 530 11, 0x0aaa0555 }, 531 { 252000000, 100800000, 0, 0x0203, 0x04000009, 0x11050005, 0x02000209, 0x04000002, 532 9, 0x02520129 }, 533 { 252000000, 126000000, 0, 0x0203, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 534 11, 0x0aaa0555 }, 535 { 264000000, 132000000, 0, 0x0602, 0x04000005, 0x11050005, 0x04000005, 0x04000002, 536 11, 0x0aaa0555 }, 537 { 272000000, 116571428, 0, 0x0c02, 0x04000021, 0x02000909, 0x02000221, 0x04000003, 538 13, 0x254a14a9 }, 539 { 280000000, 120000000, 0, 0x0209, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 540 13, 0x254a14a9 }, 541 { 288000000, 123428571, 0, 0x0111, 0x04000021, 0x01030303, 0x02000221, 0x04000003, 542 13, 0x254a14a9 }, 543 { 300000000, 120000000, 0, 0x0009, 0x04000009, 0x01030203, 0x02000902, 0x04000002, 544 9, 0x02520129 }, 545 { 300000000, 150000000, 0, 0x0009, 0x04000005, 0x01030203, 0x04000005, 0x04000002, 546 11, 0x0aaa0555 } 547 }; 548 static n4m_table_t BCMINITDATA(type7_table)[] = { 549 { 183333333, 91666666, 0, 0x0605, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 550 11, 0x0aaa0555 }, 551 { 187500000, 93750000, 0, 0x0a03, 0x04000011, 0x11030011, 0x04000011, 0x04000003, 552 11, 0x0aaa0555 }, 553 { 196875000, 98437500, 0, 0x1003, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 554 11, 0x0aaa0555 }, 555 { 200000000, 100000000, 0, 0x0311, 0x04000011, 0x11030011, 0x04000009, 0x04000003, 556 11, 0x0aaa0555 }, 557 { 200000000, 100000000, 0, 0x0311, 0x04020011, 0x11030011, 0x04020011, 0x04020003, 558 11, 0x0aaa0555 }, 559 { 206250000, 103125000, 0, 0x1103, 0x11020005, 0x11050011, 0x11020005, 0x04000005, 560 11, 0x0aaa0555 }, 561 { 212500000, 106250000, 0, 0x0c05, 0x11020005, 0x01030303, 0x11020005, 0x04000005, 562 11, 0x0aaa0555 }, 563 { 215625000, 107812500, 0, 0x1203, 0x11090009, 0x11050005, 0x11020005, 0x04000005, 564 11, 0x0aaa0555 }, 565 { 216666666, 108333333, 0, 0x0805, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 566 11, 0x0aaa0555 }, 567 { 225000000, 112500000, 0, 0x0d03, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 568 11, 0x0aaa0555 }, 569 { 233333333, 116666666, 0, 0x0905, 0x11020003, 0x11030011, 0x11020003, 0x04000003, 570 11, 0x0aaa0555 }, 571 { 237500000, 118750000, 0, 0x0e05, 0x11020005, 0x11210005, 0x11020005, 0x04000005, 572 11, 0x0aaa0555 }, 573 { 240000000, 120000000, 0, 0x0b11, 0x11020009, 0x11210009, 0x11020009, 0x04000009, 574 11, 0x0aaa0555 }, 575 { 250000000, 125000000, 0, 0x0f03, 0x11020003, 0x11210003, 0x11020003, 0x04000003, 576 11, 0x0aaa0555 } 577 }; 578 579 ulong start, end, dst; 580 bool ret = FALSE; 581 582 volatile uint32 *dll_ctrl = (volatile uint32 *)0xff400008; 583 volatile uint32 *dll_r1 = (volatile uint32 *)0xff400010; 584 volatile uint32 *dll_r2 = (volatile uint32 *)0xff400018; 585 586 /* get index of the current core */ 587 idx = sb_coreidx(sbh); 588 clockcontrol_m2 = NULL; 589 590 /* switch to chipc core */ 591 cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0); 592 ASSERT(cc); 593 594 /* 5354 chipcommon pll setting can't be changed. 595 * The PMU on power up comes up with the default clk frequency 596 * of 240MHz 597 */ 598 if (sb_chip(sbh) == BCM5354_CHIP_ID) { 599 ret = TRUE; 600 goto done; 601 } 602 603 pll_type = sbh->cccaps & CC_CAP_PLL_MASK; 604 if (pll_type == PLL_TYPE6) { 605 clockcontrol_n = NULL; 606 clockcontrol_sb = NULL; 607 clockcontrol_pci = NULL; 608 } else { 609 clockcontrol_n = &cc->clockcontrol_n; 610 clockcontrol_sb = &cc->clockcontrol_sb; 611 clockcontrol_pci = &cc->clockcontrol_pci; 612 clockcontrol_m2 = &cc->clockcontrol_m2; 613 } 614 615 if (pll_type == PLL_TYPE6) { 616 /* Silence compilers */ 617 orig_n = orig_sb = orig_pci = 0; 618 } else { 619 /* Store the current clock register values */ 620 orig_n = R_REG(osh, clockcontrol_n); 621 orig_sb = R_REG(osh, clockcontrol_sb); 622 orig_pci = R_REG(osh, clockcontrol_pci); 623 } 624 625 if (pll_type == PLL_TYPE1) { 626 /* Keep the current PCI clock if not specified */ 627 if (pciclock == 0) { 628 pciclock = sb_clock_rate(pll_type, R_REG(osh, clockcontrol_n), 629 R_REG(osh, clockcontrol_pci)); 630 pciclock = (pciclock <= 25000000) ? 25000000 : 33000000; 631 } 632 633 /* Search for the closest MIPS clock less than or equal to a preferred value */ 634 for (i = 0; i < ARRAYSIZE(type1_table); i++) { 635 ASSERT(type1_table[i].mipsclock == 636 sb_clock_rate(pll_type, type1_table[i].n, 637 type1_table[i].sb)); 638 if (type1_table[i].mipsclock > mipsclock) 639 break; 640 } 641 if (i == 0) { 642 ret = FALSE; 643 goto done; 644 } else { 645 ret = TRUE; 646 i--; 647 } 648 ASSERT(type1_table[i].mipsclock <= mipsclock); 649 650 /* No PLL change */ 651 if ((orig_n == type1_table[i].n) && 652 (orig_sb == type1_table[i].sb) && 653 (orig_pci == type1_table[i].pci33)) 654 goto done; 655 656 /* Set the PLL controls */ 657 W_REG(osh, clockcontrol_n, type1_table[i].n); 658 W_REG(osh, clockcontrol_sb, type1_table[i].sb); 659 if (pciclock == 25000000) 660 W_REG(osh, clockcontrol_pci, type1_table[i].pci25); 661 else 662 W_REG(osh, clockcontrol_pci, type1_table[i].pci33); 663 664 /* Reset */ 665 sb_watchdog(sbh, 1); 666 while (1); 667 } else if (pll_type == PLL_TYPE3) { 668 /* 5350 */ 669 if (sb_chip(sbh) != BCM5365_CHIP_ID) { 670 /* 671 * Search for the closest MIPS clock less than or equal to 672 * a preferred value. 673 */ 674 for (i = 0; i < ARRAYSIZE(type3_table); i++) { 675 if (type3_table[i].mipsclock > mipsclock) 676 break; 677 } 678 if (i == 0) { 679 ret = FALSE; 680 goto done; 681 } else { 682 ret = TRUE; 683 i--; 684 } 685 ASSERT(type3_table[i].mipsclock <= mipsclock); 686 687 /* No PLL change */ 688 orig_m2 = R_REG(osh, &cc->clockcontrol_m2); 689 if ((orig_n == type3_table[i].n) && 690 (orig_m2 == type3_table[i].m2)) { 691 goto done; 692 } 693 694 /* Set the PLL controls */ 695 W_REG(osh, clockcontrol_n, type3_table[i].n); 696 W_REG(osh, clockcontrol_m2, type3_table[i].m2); 697 698 /* Reset */ 699 sb_watchdog(sbh, 1); 700 while (1); 701 } 702 } else if ((pll_type == PLL_TYPE2) || 703 (pll_type == PLL_TYPE4) || 704 (pll_type == PLL_TYPE6) || 705 (pll_type == PLL_TYPE7)) { 706 n4m_table_t *table = NULL, *te; 707 uint tabsz = 0; 708 709 ASSERT(cc); 710 711 orig_mips = R_REG(osh, &cc->clockcontrol_m3); 712 713 switch (pll_type) { 714 case PLL_TYPE6: { 715 uint32 new_mips = 0; 716 717 ret = TRUE; 718 if (mipsclock <= SB2MIPS_T6(CC_T6_M1)) 719 new_mips = CC_T6_MMASK; 720 721 if (orig_mips == new_mips) 722 goto done; 723 724 W_REG(osh, &cc->clockcontrol_m3, new_mips); 725 goto end_fill; 726 } 727 case PLL_TYPE2: 728 table = type2_table; 729 tabsz = ARRAYSIZE(type2_table); 730 break; 731 case PLL_TYPE4: 732 table = type4_table; 733 tabsz = ARRAYSIZE(type4_table); 734 break; 735 case PLL_TYPE7: 736 table = type7_table; 737 tabsz = ARRAYSIZE(type7_table); 738 break; 739 default: 740 ASSERT("No table for plltype" == NULL); 741 break; 742 } 743 744 /* Store the current clock register values */ 745 orig_m2 = R_REG(osh, &cc->clockcontrol_m2); 746 orig_ratio_parm = 0; 747 orig_ratio_cfg = 0; 748 749 /* Look up current ratio */ 750 for (i = 0; i < tabsz; i++) { 751 if ((orig_n == table[i].n) && 752 (orig_sb == table[i].sb) && 753 (orig_pci == table[i].pci33) && 754 (orig_m2 == table[i].m2) && 755 (orig_mips == table[i].m3)) { 756 orig_ratio_parm = table[i].ratio_parm; 757 orig_ratio_cfg = table[i].ratio_cfg; 758 break; 759 } 760 } 761 762 /* Search for the closest MIPS clock greater or equal to a preferred value */ 763 for (i = 0; i < tabsz; i++) { 764 ASSERT(table[i].mipsclock == 765 sb_clock_rate(pll_type, table[i].n, table[i].m3)); 766 if ((mipsclock <= table[i].mipsclock) && 767 ((sbclock == 0) || (sbclock <= table[i].sbclock)) && 768 ((pciclock == 0) || (pciclock <= table[i].pciclock))) 769 break; 770 } 771 if (i == tabsz) { 772 ret = FALSE; 773 goto done; 774 } else { 775 te = &table[i]; 776 ret = TRUE; 777 } 778 779 /* No PLL change */ 780 if ((orig_n == te->n) && 781 (orig_sb == te->sb) && 782 (orig_pci == te->pci33) && 783 (orig_m2 == te->m2) && 784 (orig_mips == te->m3)) 785 goto done; 786 787 /* Set the PLL controls */ 788 W_REG(osh, clockcontrol_n, te->n); 789 W_REG(osh, clockcontrol_sb, te->sb); 790 W_REG(osh, clockcontrol_pci, te->pci33); 791 W_REG(osh, &cc->clockcontrol_m2, te->m2); 792 W_REG(osh, &cc->clockcontrol_m3, te->m3); 793 794 /* Set the chipcontrol bit to change mipsref to the backplane divider if needed */ 795 if ((pll_type == PLL_TYPE7) && (te->sb != te->m2) && 796 (sb_clock_rate(pll_type, te->n, te->m2) == 120000000)) 797 W_REG(osh, &cc->chipcontrol, 798 R_REG(osh, &cc->chipcontrol) | 0x100); 799 800 /* No ratio change */ 801 if (sb_chip(sbh) != BCM4785_CHIP_ID) { 802 if (orig_ratio_parm == te->ratio_parm) 803 goto end_fill; 804 } 805 806 /* Preload the code into the cache */ 807 icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize); 808 if (sb_chip(sbh) == BCM4785_CHIP_ID) { 809 start = ((ulong) &&start_fill_4785) & ~(ic_lsize - 1); 810 end = ((ulong) &&end_fill_4785 + (ic_lsize - 1)) & ~(ic_lsize - 1); 811 } 812 else { 813 start = ((ulong) &&start_fill) & ~(ic_lsize - 1); 814 end = ((ulong) &&end_fill + (ic_lsize - 1)) & ~(ic_lsize - 1); 815 } 816 while (start < end) { 817 cache_op(start, Fill_I); 818 start += ic_lsize; 819 } 820 821 /* 4785 clock freq change procedures */ 822 if (sb_chip(sbh) == BCM4785_CHIP_ID) { 823 start_fill_4785: 824 /* Switch to async */ 825 MTC0(C0_BROADCOM, 4, (1 << 22)); 826 827 /* Set clock ratio in MIPS */ 828 *dll_r1 = (*dll_r1 & 0xfffffff0) | (te->d11_r1 - 1); 829 *dll_r2 = te->d11_r2; 830 831 /* Enable new settings in MIPS */ 832 *dll_r1 = *dll_r1 | 0xc0000000; 833 834 /* Set active cfg */ 835 MTC0(C0_BROADCOM, 2, MFC0(C0_BROADCOM, 2) | (1 << 3) | 1); 836 837 /* Fake soft reset (clock cfg registers not reset) */ 838 MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2)); 839 840 /* Clear active cfg */ 841 MTC0(C0_BROADCOM, 2, MFC0(C0_BROADCOM, 2) & ~(1 << 3)); 842 843 /* set watchdog timer */ 844 W_REG(osh, &cc->watchdog, 20); 845 (void) R_REG(osh, &cc->chipid); 846 847 /* wait for timer interrupt */ 848 __asm__ __volatile__( 849 ".set\tmips3\n\t" 850 "sync\n\t" 851 "wait\n\t" 852 ".set\tmips0"); 853 end_fill_4785: 854 while (1); 855 } 856 /* Generic clock freq change procedures */ 857 else { 858 /* Copy the handler */ 859 start = (ulong) &handler; 860 end = (ulong) &afterhandler; 861 dst = KSEG1ADDR(0x180); 862 for (i = 0; i < (end - start); i += 4) 863 *((ulong *)(dst + i)) = *((ulong *)(start + i)); 864 865 /* Preload the handler into the cache one line at a time */ 866 for (i = 0; i < (end - start); i += ic_lsize) 867 cache_op(dst + i, Fill_I); 868 869 /* Clear BEV bit */ 870 MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) & ~ST0_BEV); 871 872 /* Enable interrupts */ 873 MTC0(C0_STATUS, 0, MFC0(C0_STATUS, 0) | (ALLINTS | ST0_IE)); 874 875 /* Enable MIPS timer interrupt */ 876 mipsr = sb_setcore(sbh, SB_MIPS33, 0); 877 ASSERT(mipsr); 878 W_REG(osh, &mipsr->intmask, 1); 879 880 start_fill: 881 /* step 1, set clock ratios */ 882 MTC0(C0_BROADCOM, 3, te->ratio_parm); 883 MTC0(C0_BROADCOM, 1, te->ratio_cfg); 884 885 /* step 2: program timer intr */ 886 W_REG(osh, &mipsr->timer, 100); 887 (void) R_REG(osh, &mipsr->timer); 888 889 /* step 3, switch to async */ 890 sync_mode = MFC0(C0_BROADCOM, 4); 891 MTC0(C0_BROADCOM, 4, 1 << 22); 892 893 /* step 4, set cfg active */ 894 MTC0(C0_BROADCOM, 2, (1 << 3) | 1); 895 896 /* steps 5 & 6 */ 897 __asm__ __volatile__( 898 ".set\tmips3\n\t" 899 "wait\n\t" 900 ".set\tmips0"); 901 902 /* step 7, clear cfg active */ 903 MTC0(C0_BROADCOM, 2, 0); 904 905 /* Additional Step: set back to orig sync mode */ 906 MTC0(C0_BROADCOM, 4, sync_mode); 907 908 /* step 8, fake soft reset */ 909 MTC0(C0_BROADCOM, 5, MFC0(C0_BROADCOM, 5) | (1 << 2)); 910 911 end_fill: 912 /* set watchdog timer */ 913 W_REG(osh, &cc->watchdog, 20); 914 (void) R_REG(osh, &cc->chipid); 915 916 /* wait for timer interrupt */ 917 __asm__ __volatile__( 918 ".set\tmips3\n\t" 919 "sync\n\t" 920 "wait\n\t" 921 ".set\tmips0"); 922 while (1); 923 } 924 } 925 926done: 927 /* Enable 4785 DLL */ 928 if (sb_chip(sbh) == BCM4785_CHIP_ID) { 929 uint32 tmp; 930 931 /* set mask to 1e, enable DLL (bit 0) */ 932 *dll_ctrl |= 0x0041e021; 933 934 /* enable aggressive hardware mode */ 935 *dll_ctrl |= 0x00000080; 936 937 /* wait for lock flag to clear */ 938 while ((*dll_ctrl & 0x2) == 0); 939 940 /* clear sticky flags (clear on write 1) */ 941 tmp = *dll_ctrl; 942 *dll_ctrl = tmp; 943 944 /* set mask to 5b'10001 */ 945 *dll_ctrl = (*dll_ctrl & 0xfffc1fff) | 0x00022000; 946 947 /* enable sync mode */ 948 MTC0(C0_BROADCOM, 4, MFC0(C0_BROADCOM, 4) & 0xfe3fffff); 949 (void)MFC0(C0_BROADCOM, 4); 950 } 951 952 /* switch back to previous core */ 953 sb_setcoreidx(sbh, idx); 954 955 return ret; 956} 957 958void 959BCMINITFN(enable_pfc)(uint32 mode) 960{ 961 ulong start, end; 962 uint ic_size, ic_lsize; 963 964 /* If auto then choose the correct mode for this 965 * platform, currently we only ever select one mode 966 */ 967 if (mode == PFC_AUTO) 968 mode = PFC_INST; 969 970 icache_probe(MFC0(C0_CONFIG, 1), &ic_size, &ic_lsize); 971 972 /* enable prefetch cache if available */ 973 if (MFC0(C0_BROADCOM, 0) & BRCM_PFC_AVAIL) { 974 start = ((ulong) &&setpfc_start) & ~(ic_lsize - 1); 975 end = ((ulong) &&setpfc_end + (ic_lsize - 1)) & ~(ic_lsize - 1); 976 977 /* Preload setpfc code into the cache one line at a time */ 978 while (start < end) { 979 cache_op(start, Fill_I); 980 start += ic_lsize; 981 } 982 983 /* Now set the pfc */ 984 setpfc_start: 985 /* write range */ 986 *(volatile uint32 *)PFC_CR1 = 0xffff0000; 987 988 /* enable */ 989 *(volatile uint32 *)PFC_CR0 = mode; 990 setpfc_end: 991 /* Compiler foder */ 992 ic_size = 0; 993 } 994} 995 996/* returns the ncdl value to be programmed into sdram_ncdl for calibration */ 997uint32 998BCMINITFN(sb_memc_get_ncdl)(sb_t *sbh) 999{ 1000 osl_t *osh; 1001 sbmemcregs_t *memc; 1002 uint32 ret = 0; 1003 uint32 config, rd, wr, misc, dqsg, cd, sm, sd; 1004 uint idx, rev; 1005 1006 osh = sb_osh(sbh); 1007 1008 idx = sb_coreidx(sbh); 1009 1010 memc = (sbmemcregs_t *)sb_setcore(sbh, SB_MEMC, 0); 1011 if (memc == 0) 1012 goto out; 1013 1014 rev = sb_corerev(sbh); 1015 1016 config = R_REG(osh, &memc->config); 1017 wr = R_REG(osh, &memc->wrncdlcor); 1018 rd = R_REG(osh, &memc->rdncdlcor); 1019 misc = R_REG(osh, &memc->miscdlyctl); 1020 dqsg = R_REG(osh, &memc->dqsgatencdl); 1021 1022 rd &= MEMC_RDNCDLCOR_RD_MASK; 1023 wr &= MEMC_WRNCDLCOR_WR_MASK; 1024 dqsg &= MEMC_DQSGATENCDL_G_MASK; 1025 1026 if (config & MEMC_CONFIG_DDR) { 1027 ret = (wr << 16) | (rd << 8) | dqsg; 1028 } else { 1029 if (rev > 0) 1030 cd = rd; 1031 else 1032 cd = (rd == MEMC_CD_THRESHOLD) ? rd : (wr + MEMC_CD_THRESHOLD); 1033 sm = (misc & MEMC_MISC_SM_MASK) >> MEMC_MISC_SM_SHIFT; 1034 sd = (misc & MEMC_MISC_SD_MASK) >> MEMC_MISC_SD_SHIFT; 1035 ret = (sm << 16) | (sd << 8) | cd; 1036 } 1037 1038out: 1039 /* switch back to previous core */ 1040 sb_setcoreidx(sbh, idx); 1041 1042 return ret; 1043} 1044 1045void 1046hnd_cpu_reset(sb_t *sbh) 1047{ 1048 if (sb_chip(sbh) == BCM4785_CHIP_ID) 1049 MTC0(C0_BROADCOM, 4, (1 << 22)); 1050 sb_watchdog(sbh, 1); 1051 if (sb_chip(sbh) == BCM4785_CHIP_ID) { 1052 __asm__ __volatile__( 1053 ".set\tmips3\n\t" 1054 "sync\n\t" 1055 "wait\n\t" 1056 ".set\tmips0"); 1057 } 1058 while (1); 1059} 1060 1061#if defined(BCMPERFSTATS) 1062/* 1063 * CP0 Register 25 supports 4 semi-independent 32bit performance counters. 1064 * $25 select 0, 1, 2, and 3 are the counters. The counters *decrement* (who thought this one up?) 1065 * $25 select 4 and 5 each contain 2-16bit control fields, one for each of the 4 counters 1066 * $25 select 6 is the global perf control register. 1067 */ 1068/* enable and start instruction counting */ 1069 1070void 1071hndmips_perf_cyclecount_enable(void) 1072{ 1073 MTC0(C0_PERFORMANCE, 6, 0x80000200); /* global enable perf counters */ 1074 MTC0(C0_PERFORMANCE, 4, 1075 0x8048 | MFC0(C0_PERFORMANCE, 4)); /* enable cycles counting for counter 0 */ 1076 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter zero */ 1077} 1078 1079void 1080hndmips_perf_instrcount_enable(void) 1081{ 1082 MTC0(C0_PERFORMANCE, 6, 0x80000200); /* global enable perf counters */ 1083 MTC0(C0_PERFORMANCE, 4, 1084 0x8044 | MFC0(C0_PERFORMANCE, 4)); /* enable instructions counting for counter 0 */ 1085 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter zero */ 1086} 1087 1088/* enable and start I$ hit and I$ miss counting */ 1089void 1090hndmips_perf_icachecount_enable(void) 1091{ 1092 MTC0(C0_PERFORMANCE, 6, 0x80000218); /* enable I$ counting */ 1093 MTC0(C0_PERFORMANCE, 4, 0x80148018); /* count I$ hits in cntr 0 and misses in cntr 1 */ 1094 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # I$ hits */ 1095 MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # I$ misses */ 1096} 1097 1098/* enable and start D$ hit and I$ miss counting */ 1099void 1100hndmips_perf_dcachecount_enable(void) 1101{ 1102 MTC0(C0_PERFORMANCE, 6, 0x80000211); /* enable D$ counting */ 1103 MTC0(C0_PERFORMANCE, 4, 0x80248028); /* count D$ hits in cntr 0 and misses in cntr 1 */ 1104 MTC0(C0_PERFORMANCE, 0, 0); /* zero counter 0 - # D$ hits */ 1105 MTC0(C0_PERFORMANCE, 1, 0); /* zero counter 1 - # D$ misses */ 1106} 1107 1108void 1109hndmips_perf_icache_miss_enable() 1110{ 1111 MTC0(C0_PERFORMANCE, 4, 1112 0x80140000 | MFC0(C0_PERFORMANCE, 4)); /* enable cache misses counting for counter 1 */ 1113 MTC0(C0_PERFORMANCE, 1, 0); /* zero counter one */ 1114} 1115 1116 1117void 1118hndmips_perf_icache_hit_enable() 1119{ 1120 MTC0(C0_PERFORMANCE, 5, 0x8018 | MFC0(C0_PERFORMANCE, 5)); 1121 /* enable cache hits counting for counter 2 */ 1122 MTC0(C0_PERFORMANCE, 2, 0); /* zero counter 2 */ 1123} 1124 1125uint32 1126hndmips_perf_read_instrcount() 1127{ 1128 return -(long)(MFC0(C0_PERFORMANCE, 0)); 1129} 1130 1131uint32 1132hndmips_perf_read_cache_miss() 1133{ 1134 return -(long)(MFC0(C0_PERFORMANCE, 1)); 1135} 1136 1137uint32 1138hndmips_perf_read_cache_hit() 1139{ 1140 return -(long)(MFC0(C0_PERFORMANCE, 2)); 1141} 1142 1143#endif 1144