cpu_init.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. /*
  2. * (C) Copyright 2000-2007
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <watchdog.h>
  9. #include <asm/ppc4xx-emac.h>
  10. #include <asm/processor.h>
  11. #include <asm/ppc4xx-gpio.h>
  12. #include <asm/ppc4xx.h>
  13. DECLARE_GLOBAL_DATA_PTR;
  14. #ifndef CONFIG_SYS_PLL_RECONFIG
  15. #define CONFIG_SYS_PLL_RECONFIG 0
  16. #endif
  17. #if defined(CONFIG_440EPX) || \
  18. defined(CONFIG_460EX) || defined(CONFIG_460GT)
  19. static void reset_with_rli(void)
  20. {
  21. u32 reg;
  22. /*
  23. * Set reload inhibit so configuration will persist across
  24. * processor resets
  25. */
  26. mfcpr(CPR0_ICFG, reg);
  27. reg |= CPR0_ICFG_RLI_MASK;
  28. mtcpr(CPR0_ICFG, reg);
  29. /* Reset processor if configuration changed */
  30. __asm__ __volatile__ ("sync; isync");
  31. mtspr(SPRN_DBCR0, 0x20000000);
  32. }
  33. #endif
  34. void reconfigure_pll(u32 new_cpu_freq)
  35. {
  36. #if defined(CONFIG_440EPX)
  37. int reset_needed = 0;
  38. u32 reg, temp;
  39. u32 prbdv0, target_prbdv0, /* CLK_PRIMBD */
  40. fwdva, target_fwdva, fwdvb, target_fwdvb, /* CLK_PLLD */
  41. fbdv, target_fbdv, lfbdv, target_lfbdv,
  42. perdv0, target_perdv0, /* CLK_PERD */
  43. spcid0, target_spcid0; /* CLK_SPCID */
  44. /* Reconfigure clocks if necessary.
  45. * See PPC440EPx User's Manual, sections 8.2 and 14 */
  46. if (new_cpu_freq == 667) {
  47. target_prbdv0 = 2;
  48. target_fwdva = 2;
  49. target_fwdvb = 4;
  50. target_fbdv = 20;
  51. target_lfbdv = 1;
  52. target_perdv0 = 4;
  53. target_spcid0 = 4;
  54. mfcpr(CPR0_PRIMBD0, reg);
  55. temp = (reg & PRBDV_MASK) >> 24;
  56. prbdv0 = temp ? temp : 8;
  57. if (prbdv0 != target_prbdv0) {
  58. reg &= ~PRBDV_MASK;
  59. reg |= ((target_prbdv0 == 8 ? 0 : target_prbdv0) << 24);
  60. mtcpr(CPR0_PRIMBD0, reg);
  61. reset_needed = 1;
  62. }
  63. mfcpr(CPR0_PLLD, reg);
  64. temp = (reg & PLLD_FWDVA_MASK) >> 16;
  65. fwdva = temp ? temp : 16;
  66. temp = (reg & PLLD_FWDVB_MASK) >> 8;
  67. fwdvb = temp ? temp : 8;
  68. temp = (reg & PLLD_FBDV_MASK) >> 24;
  69. fbdv = temp ? temp : 32;
  70. temp = (reg & PLLD_LFBDV_MASK);
  71. lfbdv = temp ? temp : 64;
  72. if (fwdva != target_fwdva || fbdv != target_fbdv || lfbdv != target_lfbdv) {
  73. reg &= ~(PLLD_FWDVA_MASK | PLLD_FWDVB_MASK |
  74. PLLD_FBDV_MASK | PLLD_LFBDV_MASK);
  75. reg |= ((target_fwdva == 16 ? 0 : target_fwdva) << 16) |
  76. ((target_fwdvb == 8 ? 0 : target_fwdvb) << 8) |
  77. ((target_fbdv == 32 ? 0 : target_fbdv) << 24) |
  78. (target_lfbdv == 64 ? 0 : target_lfbdv);
  79. mtcpr(CPR0_PLLD, reg);
  80. reset_needed = 1;
  81. }
  82. mfcpr(CPR0_PERD, reg);
  83. perdv0 = (reg & CPR0_PERD_PERDV0_MASK) >> 24;
  84. if (perdv0 != target_perdv0) {
  85. reg &= ~CPR0_PERD_PERDV0_MASK;
  86. reg |= (target_perdv0 << 24);
  87. mtcpr(CPR0_PERD, reg);
  88. reset_needed = 1;
  89. }
  90. mfcpr(CPR0_SPCID, reg);
  91. temp = (reg & CPR0_SPCID_SPCIDV0_MASK) >> 24;
  92. spcid0 = temp ? temp : 4;
  93. if (spcid0 != target_spcid0) {
  94. reg &= ~CPR0_SPCID_SPCIDV0_MASK;
  95. reg |= ((target_spcid0 == 4 ? 0 : target_spcid0) << 24);
  96. mtcpr(CPR0_SPCID, reg);
  97. reset_needed = 1;
  98. }
  99. }
  100. /* Get current value of FWDVA.*/
  101. mfcpr(CPR0_PLLD, reg);
  102. temp = (reg & PLLD_FWDVA_MASK) >> 16;
  103. /*
  104. * Check to see if FWDVA has been set to value of 1. if it has we must
  105. * modify it.
  106. */
  107. if (temp == 1) {
  108. /*
  109. * Load register that contains current boot strapping option.
  110. */
  111. mfcpr(CPR0_ICFG, reg);
  112. /*
  113. * Strapping option bits (ICS) are already in correct position,
  114. * only masking needed.
  115. */
  116. reg &= CPR0_ICFG_ICS_MASK;
  117. if ((reg == BOOT_STRAP_OPTION_A) || (reg == BOOT_STRAP_OPTION_B) ||
  118. (reg == BOOT_STRAP_OPTION_D) || (reg == BOOT_STRAP_OPTION_E)) {
  119. mfcpr(CPR0_PLLD, reg);
  120. /* Get current value of fbdv. */
  121. temp = (reg & PLLD_FBDV_MASK) >> 24;
  122. fbdv = temp ? temp : 32;
  123. /* Get current value of lfbdv. */
  124. temp = (reg & PLLD_LFBDV_MASK);
  125. lfbdv = temp ? temp : 64;
  126. /*
  127. * Get current value of FWDVA. Assign current FWDVA to
  128. * new FWDVB.
  129. */
  130. mfcpr(CPR0_PLLD, reg);
  131. target_fwdvb = (reg & PLLD_FWDVA_MASK) >> 16;
  132. fwdvb = target_fwdvb ? target_fwdvb : 8;
  133. /*
  134. * Get current value of FWDVB. Assign current FWDVB to
  135. * new FWDVA.
  136. */
  137. target_fwdva = (reg & PLLD_FWDVB_MASK) >> 8;
  138. fwdva = target_fwdva ? target_fwdva : 16;
  139. /*
  140. * Update CPR0_PLLD with switched FWDVA and FWDVB.
  141. */
  142. reg &= ~(PLLD_FWDVA_MASK | PLLD_FWDVB_MASK |
  143. PLLD_FBDV_MASK | PLLD_LFBDV_MASK);
  144. reg |= ((fwdva == 16 ? 0 : fwdva) << 16) |
  145. ((fwdvb == 8 ? 0 : fwdvb) << 8) |
  146. ((fbdv == 32 ? 0 : fbdv) << 24) |
  147. (lfbdv == 64 ? 0 : lfbdv);
  148. mtcpr(CPR0_PLLD, reg);
  149. /* Acknowledge that a reset is required. */
  150. reset_needed = 1;
  151. }
  152. }
  153. /* Now reset the CPU if needed */
  154. if (reset_needed)
  155. reset_with_rli();
  156. #endif
  157. #if defined(CONFIG_460EX) || defined(CONFIG_460GT)
  158. u32 reg;
  159. /*
  160. * See "9.2.1.1 Booting with Option E" in the 460EX/GT
  161. * users manual
  162. */
  163. mfcpr(CPR0_PLLC, reg);
  164. if ((reg & (CPR0_PLLC_RST | CPR0_PLLC_ENG)) == CPR0_PLLC_RST) {
  165. /*
  166. * Set engage bit
  167. */
  168. reg = (reg & ~CPR0_PLLC_RST) | CPR0_PLLC_ENG;
  169. mtcpr(CPR0_PLLC, reg);
  170. /* Now reset the CPU */
  171. reset_with_rli();
  172. }
  173. #endif
  174. }
  175. #ifdef CONFIG_SYS_4xx_CHIP_21_ERRATA
  176. void
  177. chip_21_errata(void)
  178. {
  179. /*
  180. * See rev 1.09 of the 405EX/405EXr errata. CHIP_21 says that
  181. * sometimes reading the PVR and/or SDR0_ECID results in incorrect
  182. * values. Since the rev-D chip uses the SDR0_ECID bits to control
  183. * internal features, that means the second PCIe or ethernet of an EX
  184. * variant could fail to work. Also, security features of both EX and
  185. * EXr might be incorrectly disabled.
  186. *
  187. * The suggested workaround is as follows (covering rev-C and rev-D):
  188. *
  189. * 1.Read the PVR and SDR0_ECID3.
  190. *
  191. * 2.If the PVR matches an expected Revision C PVR value AND if
  192. * SDR0_ECID3[12:15] is different from PVR[28:31], then processor is
  193. * Revision C: continue executing the initialization code (no reset
  194. * required). else go to step 3.
  195. *
  196. * 3.If the PVR matches an expected Revision D PVR value AND if
  197. * SDR0_ECID3[10:11] matches its expected value, then continue
  198. * executing initialization code, no reset required. else write
  199. * DBCR0[RST] = 0b11 to generate a SysReset.
  200. */
  201. u32 pvr;
  202. u32 pvr_28_31;
  203. u32 ecid3;
  204. u32 ecid3_10_11;
  205. u32 ecid3_12_15;
  206. /* Step 1: */
  207. pvr = get_pvr();
  208. mfsdr(SDR0_ECID3, ecid3);
  209. /* Step 2: */
  210. pvr_28_31 = pvr & 0xf;
  211. ecid3_10_11 = (ecid3 >> 20) & 0x3;
  212. ecid3_12_15 = (ecid3 >> 16) & 0xf;
  213. if ((pvr == CONFIG_405EX_CHIP21_PVR_REV_C) &&
  214. (pvr_28_31 != ecid3_12_15)) {
  215. /* No reset required. */
  216. return;
  217. }
  218. /* Step 3: */
  219. if ((pvr == CONFIG_405EX_CHIP21_PVR_REV_D) &&
  220. (ecid3_10_11 == CONFIG_405EX_CHIP21_ECID3_REV_D)) {
  221. /* No reset required. */
  222. return;
  223. }
  224. /* Reset required. */
  225. __asm__ __volatile__ ("sync; isync");
  226. mtspr(SPRN_DBCR0, 0x30000000);
  227. }
  228. #endif
  229. /*
  230. * Breath some life into the CPU...
  231. *
  232. * Reconfigure PLL if necessary,
  233. * set up the memory map,
  234. * initialize a bunch of registers
  235. */
  236. void
  237. cpu_init_f (void)
  238. {
  239. #if defined(CONFIG_WATCHDOG) || defined(CONFIG_440GX) || defined(CONFIG_460EX)
  240. u32 val;
  241. #endif
  242. #ifdef CONFIG_SYS_4xx_CHIP_21_ERRATA
  243. chip_21_errata();
  244. #endif
  245. reconfigure_pll(CONFIG_SYS_PLL_RECONFIG);
  246. #if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && \
  247. !defined(CONFIG_SYS_4xx_GPIO_TABLE)
  248. /*
  249. * GPIO0 setup (select GPIO or alternate function)
  250. */
  251. #if defined(CONFIG_SYS_GPIO0_OR)
  252. out32(GPIO0_OR, CONFIG_SYS_GPIO0_OR); /* set initial state of output pins */
  253. #endif
  254. #if defined(CONFIG_SYS_GPIO0_ODR)
  255. out32(GPIO0_ODR, CONFIG_SYS_GPIO0_ODR); /* open-drain select */
  256. #endif
  257. out32(GPIO0_OSRH, CONFIG_SYS_GPIO0_OSRH); /* output select */
  258. out32(GPIO0_OSRL, CONFIG_SYS_GPIO0_OSRL);
  259. out32(GPIO0_ISR1H, CONFIG_SYS_GPIO0_ISR1H); /* input select */
  260. out32(GPIO0_ISR1L, CONFIG_SYS_GPIO0_ISR1L);
  261. out32(GPIO0_TSRH, CONFIG_SYS_GPIO0_TSRH); /* three-state select */
  262. out32(GPIO0_TSRL, CONFIG_SYS_GPIO0_TSRL);
  263. #if defined(CONFIG_SYS_GPIO0_ISR2H)
  264. out32(GPIO0_ISR2H, CONFIG_SYS_GPIO0_ISR2H);
  265. out32(GPIO0_ISR2L, CONFIG_SYS_GPIO0_ISR2L);
  266. #endif
  267. #if defined (CONFIG_SYS_GPIO0_TCR)
  268. out32(GPIO0_TCR, CONFIG_SYS_GPIO0_TCR); /* enable output driver for outputs */
  269. #endif
  270. #endif /* CONFIG_405EP ... && !CONFIG_SYS_4xx_GPIO_TABLE */
  271. #if defined (CONFIG_405EP)
  272. /*
  273. * Set EMAC noise filter bits
  274. */
  275. mtdcr(CPC0_EPCTL, CPC0_EPCTL_E0NFE | CPC0_EPCTL_E1NFE);
  276. #endif /* CONFIG_405EP */
  277. #if defined(CONFIG_SYS_4xx_GPIO_TABLE)
  278. gpio_set_chip_configuration();
  279. #endif /* CONFIG_SYS_4xx_GPIO_TABLE */
  280. /*
  281. * External Bus Controller (EBC) Setup
  282. */
  283. #if (defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR))
  284. #if (defined(CONFIG_405GP) || \
  285. defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
  286. defined(CONFIG_405EX) || defined(CONFIG_405))
  287. /*
  288. * Move the next instructions into icache, since these modify the flash
  289. * we are running from!
  290. */
  291. asm volatile(" bl 0f" ::: "lr");
  292. asm volatile("0: mflr 3" ::: "r3");
  293. asm volatile(" addi 4, 0, 14" ::: "r4");
  294. asm volatile(" mtctr 4" ::: "ctr");
  295. asm volatile("1: icbt 0, 3");
  296. asm volatile(" addi 3, 3, 32" ::: "r3");
  297. asm volatile(" bdnz 1b" ::: "ctr", "cr0");
  298. asm volatile(" addis 3, 0, 0x0" ::: "r3");
  299. asm volatile(" ori 3, 3, 0xA000" ::: "r3");
  300. asm volatile(" mtctr 3" ::: "ctr");
  301. asm volatile("2: bdnz 2b" ::: "ctr", "cr0");
  302. #endif
  303. mtebc(PB0AP, CONFIG_SYS_EBC_PB0AP);
  304. mtebc(PB0CR, CONFIG_SYS_EBC_PB0CR);
  305. #endif
  306. #if (defined(CONFIG_SYS_EBC_PB1AP) && defined(CONFIG_SYS_EBC_PB1CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 1))
  307. mtebc(PB1AP, CONFIG_SYS_EBC_PB1AP);
  308. mtebc(PB1CR, CONFIG_SYS_EBC_PB1CR);
  309. #endif
  310. #if (defined(CONFIG_SYS_EBC_PB2AP) && defined(CONFIG_SYS_EBC_PB2CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 2))
  311. mtebc(PB2AP, CONFIG_SYS_EBC_PB2AP);
  312. mtebc(PB2CR, CONFIG_SYS_EBC_PB2CR);
  313. #endif
  314. #if (defined(CONFIG_SYS_EBC_PB3AP) && defined(CONFIG_SYS_EBC_PB3CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 3))
  315. mtebc(PB3AP, CONFIG_SYS_EBC_PB3AP);
  316. mtebc(PB3CR, CONFIG_SYS_EBC_PB3CR);
  317. #endif
  318. #if (defined(CONFIG_SYS_EBC_PB4AP) && defined(CONFIG_SYS_EBC_PB4CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 4))
  319. mtebc(PB4AP, CONFIG_SYS_EBC_PB4AP);
  320. mtebc(PB4CR, CONFIG_SYS_EBC_PB4CR);
  321. #endif
  322. #if (defined(CONFIG_SYS_EBC_PB5AP) && defined(CONFIG_SYS_EBC_PB5CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 5))
  323. mtebc(PB5AP, CONFIG_SYS_EBC_PB5AP);
  324. mtebc(PB5CR, CONFIG_SYS_EBC_PB5CR);
  325. #endif
  326. #if (defined(CONFIG_SYS_EBC_PB6AP) && defined(CONFIG_SYS_EBC_PB6CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 6))
  327. mtebc(PB6AP, CONFIG_SYS_EBC_PB6AP);
  328. mtebc(PB6CR, CONFIG_SYS_EBC_PB6CR);
  329. #endif
  330. #if (defined(CONFIG_SYS_EBC_PB7AP) && defined(CONFIG_SYS_EBC_PB7CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 7))
  331. mtebc(PB7AP, CONFIG_SYS_EBC_PB7AP);
  332. mtebc(PB7CR, CONFIG_SYS_EBC_PB7CR);
  333. #endif
  334. #if defined (CONFIG_SYS_EBC_CFG)
  335. mtebc(EBC0_CFG, CONFIG_SYS_EBC_CFG);
  336. #endif
  337. #if defined(CONFIG_WATCHDOG)
  338. val = mfspr(SPRN_TCR);
  339. #if defined(CONFIG_440EP) || defined(CONFIG_440GR)
  340. val |= 0xb8000000; /* generate system reset after 1.34 seconds */
  341. #elif defined(CONFIG_440EPX)
  342. val |= 0xb0000000; /* generate system reset after 1.34 seconds */
  343. #else
  344. val |= 0xf0000000; /* generate system reset after 2.684 seconds */
  345. #endif
  346. #if defined(CONFIG_SYS_4xx_RESET_TYPE)
  347. val &= ~0x30000000; /* clear WRC bits */
  348. val |= CONFIG_SYS_4xx_RESET_TYPE << 28; /* set board specific WRC type */
  349. #endif
  350. mtspr(SPRN_TCR, val);
  351. val = mfspr(SPRN_TSR);
  352. val |= 0x80000000; /* enable watchdog timer */
  353. mtspr(SPRN_TSR, val);
  354. reset_4xx_watchdog();
  355. #endif /* CONFIG_WATCHDOG */
  356. #if defined(CONFIG_440GX)
  357. /* Take the GX out of compatibility mode
  358. * Travis Sawyer, 9 Mar 2004
  359. * NOTE: 440gx user manual inconsistency here
  360. * Compatibility mode and Ethernet Clock select are not
  361. * correct in the manual
  362. */
  363. mfsdr(SDR0_MFR, val);
  364. val &= ~0x10000000;
  365. mtsdr(SDR0_MFR,val);
  366. #endif /* CONFIG_440GX */
  367. #if defined(CONFIG_460EX)
  368. /*
  369. * Set SDR0_AHB_CFG[A2P_INCR4] (bit 24) and
  370. * clear SDR0_AHB_CFG[A2P_PROT2] (bit 25) for a new 460EX errata
  371. * regarding concurrent use of AHB USB OTG, USB 2.0 host and SATA
  372. */
  373. mfsdr(SDR0_AHB_CFG, val);
  374. val |= 0x80;
  375. val &= ~0x40;
  376. mtsdr(SDR0_AHB_CFG, val);
  377. mfsdr(SDR0_USB2HOST_CFG, val);
  378. val &= ~0xf00;
  379. val |= 0x400;
  380. mtsdr(SDR0_USB2HOST_CFG, val);
  381. #endif /* CONFIG_460EX */
  382. #if defined(CONFIG_405EX) || \
  383. defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
  384. defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
  385. defined(CONFIG_460SX)
  386. /*
  387. * Set PLB4 arbiter (Segment 0 and 1) to 4 deep pipeline read
  388. */
  389. mtdcr(PLB4A0_ACR, (mfdcr(PLB4A0_ACR) & ~PLB4Ax_ACR_RDP_MASK) |
  390. PLB4Ax_ACR_RDP_4DEEP);
  391. mtdcr(PLB4A1_ACR, (mfdcr(PLB4A1_ACR) & ~PLB4Ax_ACR_RDP_MASK) |
  392. PLB4Ax_ACR_RDP_4DEEP);
  393. #endif /* CONFIG_440SP/SPE || CONFIG_460EX/GT || CONFIG_405EX */
  394. gd = (gd_t *)(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
  395. /* Clear initial global data */
  396. memset((void *)gd, 0, sizeof(gd_t));
  397. }
  398. /*
  399. * initialize higher level parts of CPU like time base and timers
  400. */
  401. int cpu_init_r (void)
  402. {
  403. #if defined(CONFIG_405GP)
  404. uint pvr = get_pvr();
  405. /*
  406. * Set edge conditioning circuitry on PPC405GPr
  407. * for compatibility to existing PPC405GP designs.
  408. */
  409. if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
  410. mtdcr(CPC0_ECR, 0x60606000);
  411. }
  412. #endif /* defined(CONFIG_405GP) */
  413. return 0;
  414. }
  415. #if defined(CONFIG_PCI) && \
  416. (defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
  417. defined(CONFIG_440GR) || defined(CONFIG_440GRX))
  418. /*
  419. * 440EP(x)/GR(x) PCI async/sync clocking restriction:
  420. *
  421. * In asynchronous PCI mode, the synchronous PCI clock must meet
  422. * certain requirements. The following equation describes the
  423. * relationship that must be maintained between the asynchronous PCI
  424. * clock and synchronous PCI clock. Select an appropriate PCI:PLB
  425. * ratio to maintain the relationship:
  426. *
  427. * AsyncPCIClk - 1MHz <= SyncPCIclock <= (2 * AsyncPCIClk) - 1MHz
  428. */
  429. static int ppc4xx_pci_sync_clock_ok(u32 sync, u32 async)
  430. {
  431. if (((async - 1000000) > sync) || (sync > ((2 * async) - 1000000)))
  432. return 0;
  433. else
  434. return 1;
  435. }
  436. int ppc4xx_pci_sync_clock_config(u32 async)
  437. {
  438. sys_info_t sys_info;
  439. u32 sync;
  440. int div;
  441. u32 reg;
  442. u32 spcid_val[] = {
  443. CPR0_SPCID_SPCIDV0_DIV1, CPR0_SPCID_SPCIDV0_DIV2,
  444. CPR0_SPCID_SPCIDV0_DIV3, CPR0_SPCID_SPCIDV0_DIV4 };
  445. get_sys_info(&sys_info);
  446. sync = sys_info.freqPCI;
  447. /*
  448. * First check if the equation above is met
  449. */
  450. if (!ppc4xx_pci_sync_clock_ok(sync, async)) {
  451. /*
  452. * Reconfigure PCI sync clock to meet the equation.
  453. * Start with highest possible PCI sync frequency
  454. * (divider 1).
  455. */
  456. for (div = 1; div <= 4; div++) {
  457. sync = sys_info.freqPLB / div;
  458. if (ppc4xx_pci_sync_clock_ok(sync, async))
  459. break;
  460. }
  461. if (div <= 4) {
  462. mtcpr(CPR0_SPCID, spcid_val[div]);
  463. mfcpr(CPR0_ICFG, reg);
  464. reg |= CPR0_ICFG_RLI_MASK;
  465. mtcpr(CPR0_ICFG, reg);
  466. /* do chip reset */
  467. mtspr(SPRN_DBCR0, 0x20000000);
  468. } else {
  469. /* Impossible to configure the PCI sync clock */
  470. return -1;
  471. }
  472. }
  473. return 0;
  474. }
  475. #endif