cpu_init.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. /*
  2. * (C) Copyright 2000-2007
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. #include <common.h>
  24. #include <watchdog.h>
  25. #include <ppc4xx_enet.h>
  26. #include <asm/processor.h>
  27. #include <asm/gpio.h>
  28. #include <ppc4xx.h>
  29. #if defined(CONFIG_405GP) || defined(CONFIG_405EP)
  30. DECLARE_GLOBAL_DATA_PTR;
  31. #endif
  32. #ifndef CONFIG_SYS_PLL_RECONFIG
  33. #define CONFIG_SYS_PLL_RECONFIG 0
  34. #endif
  35. void reconfigure_pll(u32 new_cpu_freq)
  36. {
  37. #if defined(CONFIG_440EPX)
  38. int reset_needed = 0;
  39. u32 reg, temp;
  40. u32 prbdv0, target_prbdv0, /* CLK_PRIMBD */
  41. fwdva, target_fwdva, fwdvb, target_fwdvb, /* CLK_PLLD */
  42. fbdv, target_fbdv, lfbdv, target_lfbdv,
  43. perdv0, target_perdv0, /* CLK_PERD */
  44. spcid0, target_spcid0; /* CLK_SPCID */
  45. /* Reconfigure clocks if necessary.
  46. * See PPC440EPx User's Manual, sections 8.2 and 14 */
  47. if (new_cpu_freq == 667) {
  48. target_prbdv0 = 2;
  49. target_fwdva = 2;
  50. target_fwdvb = 4;
  51. target_fbdv = 20;
  52. target_lfbdv = 1;
  53. target_perdv0 = 4;
  54. target_spcid0 = 4;
  55. mfcpr(CPR0_PRIMBD0, reg);
  56. temp = (reg & PRBDV_MASK) >> 24;
  57. prbdv0 = temp ? temp : 8;
  58. if (prbdv0 != target_prbdv0) {
  59. reg &= ~PRBDV_MASK;
  60. reg |= ((target_prbdv0 == 8 ? 0 : target_prbdv0) << 24);
  61. mtcpr(CPR0_PRIMBD0, reg);
  62. reset_needed = 1;
  63. }
  64. mfcpr(CPR0_PLLD, reg);
  65. temp = (reg & PLLD_FWDVA_MASK) >> 16;
  66. fwdva = temp ? temp : 16;
  67. temp = (reg & PLLD_FWDVB_MASK) >> 8;
  68. fwdvb = temp ? temp : 8;
  69. temp = (reg & PLLD_FBDV_MASK) >> 24;
  70. fbdv = temp ? temp : 32;
  71. temp = (reg & PLLD_LFBDV_MASK);
  72. lfbdv = temp ? temp : 64;
  73. if (fwdva != target_fwdva || fbdv != target_fbdv || lfbdv != target_lfbdv) {
  74. reg &= ~(PLLD_FWDVA_MASK | PLLD_FWDVB_MASK |
  75. PLLD_FBDV_MASK | PLLD_LFBDV_MASK);
  76. reg |= ((target_fwdva == 16 ? 0 : target_fwdva) << 16) |
  77. ((target_fwdvb == 8 ? 0 : target_fwdvb) << 8) |
  78. ((target_fbdv == 32 ? 0 : target_fbdv) << 24) |
  79. (target_lfbdv == 64 ? 0 : target_lfbdv);
  80. mtcpr(CPR0_PLLD, reg);
  81. reset_needed = 1;
  82. }
  83. mfcpr(CPR0_PERD, reg);
  84. perdv0 = (reg & CPR0_PERD_PERDV0_MASK) >> 24;
  85. if (perdv0 != target_perdv0) {
  86. reg &= ~CPR0_PERD_PERDV0_MASK;
  87. reg |= (target_perdv0 << 24);
  88. mtcpr(CPR0_PERD, reg);
  89. reset_needed = 1;
  90. }
  91. mfcpr(CPR0_SPCID, reg);
  92. temp = (reg & CPR0_SPCID_SPCIDV0_MASK) >> 24;
  93. spcid0 = temp ? temp : 4;
  94. if (spcid0 != target_spcid0) {
  95. reg &= ~CPR0_SPCID_SPCIDV0_MASK;
  96. reg |= ((target_spcid0 == 4 ? 0 : target_spcid0) << 24);
  97. mtcpr(CPR0_SPCID, reg);
  98. reset_needed = 1;
  99. }
  100. }
  101. /* Get current value of FWDVA.*/
  102. mfcpr(CPR0_PLLD, reg);
  103. temp = (reg & PLLD_FWDVA_MASK) >> 16;
  104. /*
  105. * Check to see if FWDVA has been set to value of 1. if it has we must
  106. * modify it.
  107. */
  108. if (temp == 1) {
  109. mfcpr(CPR0_PLLD, reg);
  110. /* Get current value of fbdv. */
  111. temp = (reg & PLLD_FBDV_MASK) >> 24;
  112. fbdv = temp ? temp : 32;
  113. /* Get current value of lfbdv. */
  114. temp = (reg & PLLD_LFBDV_MASK);
  115. lfbdv = temp ? temp : 64;
  116. /*
  117. * Load register that contains current boot strapping option.
  118. */
  119. mfcpr(CPR0_ICFG, reg);
  120. /* Shift strapping option into low 3 bits.*/
  121. reg = (reg >> 28);
  122. if ((reg == BOOT_STRAP_OPTION_A) || (reg == BOOT_STRAP_OPTION_B) ||
  123. (reg == BOOT_STRAP_OPTION_D) || (reg == BOOT_STRAP_OPTION_E)) {
  124. /*
  125. * Get current value of FWDVA. Assign current FWDVA to
  126. * new FWDVB.
  127. */
  128. mfcpr(CPR0_PLLD, reg);
  129. target_fwdvb = (reg & PLLD_FWDVA_MASK) >> 16;
  130. fwdvb = target_fwdvb ? target_fwdvb : 8;
  131. /*
  132. * Get current value of FWDVB. Assign current FWDVB to
  133. * new FWDVA.
  134. */
  135. target_fwdva = (reg & PLLD_FWDVB_MASK) >> 8;
  136. fwdva = target_fwdva ? target_fwdva : 16;
  137. /*
  138. * Update CPR0_PLLD with switched FWDVA and FWDVB.
  139. */
  140. reg &= ~(PLLD_FWDVA_MASK | PLLD_FWDVB_MASK |
  141. PLLD_FBDV_MASK | PLLD_LFBDV_MASK);
  142. reg |= ((fwdva == 16 ? 0 : fwdva) << 16) |
  143. ((fwdvb == 8 ? 0 : fwdvb) << 8) |
  144. ((fbdv == 32 ? 0 : fbdv) << 24) |
  145. (lfbdv == 64 ? 0 : lfbdv);
  146. mtcpr(CPR0_PLLD, reg);
  147. /* Acknowledge that a reset is required. */
  148. reset_needed = 1;
  149. }
  150. }
  151. if (reset_needed) {
  152. /*
  153. * Set reload inhibit so configuration will persist across
  154. * processor resets
  155. */
  156. mfcpr(CPR0_ICFG, reg);
  157. reg &= ~CPR0_ICFG_RLI_MASK;
  158. reg |= 1 << 31;
  159. mtcpr(CPR0_ICFG, reg);
  160. /* Reset processor if configuration changed */
  161. __asm__ __volatile__ ("sync; isync");
  162. mtspr(SPRN_DBCR0, 0x20000000);
  163. }
  164. #endif
  165. }
  166. /*
  167. * Breath some life into the CPU...
  168. *
  169. * Reconfigure PLL if necessary,
  170. * set up the memory map,
  171. * initialize a bunch of registers
  172. */
  173. void
  174. cpu_init_f (void)
  175. {
  176. #if defined(CONFIG_WATCHDOG) || defined(CONFIG_440GX) || defined(CONFIG_460EX)
  177. u32 val;
  178. #endif
  179. reconfigure_pll(CONFIG_SYS_PLL_RECONFIG);
  180. #if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && !defined(CONFIG_SYS_4xx_GPIO_TABLE)
  181. /*
  182. * GPIO0 setup (select GPIO or alternate function)
  183. */
  184. #if defined(CONFIG_SYS_GPIO0_OR)
  185. out32(GPIO0_OR, CONFIG_SYS_GPIO0_OR); /* set initial state of output pins */
  186. #endif
  187. #if defined(CONFIG_SYS_GPIO0_ODR)
  188. out32(GPIO0_ODR, CONFIG_SYS_GPIO0_ODR); /* open-drain select */
  189. #endif
  190. out32(GPIO0_OSRH, CONFIG_SYS_GPIO0_OSRH); /* output select */
  191. out32(GPIO0_OSRL, CONFIG_SYS_GPIO0_OSRL);
  192. out32(GPIO0_ISR1H, CONFIG_SYS_GPIO0_ISR1H); /* input select */
  193. out32(GPIO0_ISR1L, CONFIG_SYS_GPIO0_ISR1L);
  194. out32(GPIO0_TSRH, CONFIG_SYS_GPIO0_TSRH); /* three-state select */
  195. out32(GPIO0_TSRL, CONFIG_SYS_GPIO0_TSRL);
  196. #if defined(CONFIG_SYS_GPIO0_ISR2H)
  197. out32(GPIO0_ISR2H, CONFIG_SYS_GPIO0_ISR2H);
  198. out32(GPIO0_ISR2L, CONFIG_SYS_GPIO0_ISR2L);
  199. #endif
  200. #if defined (CONFIG_SYS_GPIO0_TCR)
  201. out32(GPIO0_TCR, CONFIG_SYS_GPIO0_TCR); /* enable output driver for outputs */
  202. #endif
  203. #endif /* CONFIG_405EP ... && !CONFIG_SYS_4xx_GPIO_TABLE */
  204. #if defined (CONFIG_405EP)
  205. /*
  206. * Set EMAC noise filter bits
  207. */
  208. mtdcr(CPC0_EPCTL, CPC0_EPRCSR_E0NFE | CPC0_EPRCSR_E1NFE);
  209. #endif /* CONFIG_405EP */
  210. #if defined(CONFIG_SYS_4xx_GPIO_TABLE)
  211. gpio_set_chip_configuration();
  212. #endif /* CONFIG_SYS_4xx_GPIO_TABLE */
  213. /*
  214. * External Bus Controller (EBC) Setup
  215. */
  216. #if (defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR))
  217. #if (defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
  218. defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
  219. defined(CONFIG_405EX) || defined(CONFIG_405))
  220. /*
  221. * Move the next instructions into icache, since these modify the flash
  222. * we are running from!
  223. */
  224. asm volatile(" bl 0f" ::: "lr");
  225. asm volatile("0: mflr 3" ::: "r3");
  226. asm volatile(" addi 4, 0, 14" ::: "r4");
  227. asm volatile(" mtctr 4" ::: "ctr");
  228. asm volatile("1: icbt 0, 3");
  229. asm volatile(" addi 3, 3, 32" ::: "r3");
  230. asm volatile(" bdnz 1b" ::: "ctr", "cr0");
  231. asm volatile(" addis 3, 0, 0x0" ::: "r3");
  232. asm volatile(" ori 3, 3, 0xA000" ::: "r3");
  233. asm volatile(" mtctr 3" ::: "ctr");
  234. asm volatile("2: bdnz 2b" ::: "ctr", "cr0");
  235. #endif
  236. mtebc(PB0AP, CONFIG_SYS_EBC_PB0AP);
  237. mtebc(PB0CR, CONFIG_SYS_EBC_PB0CR);
  238. #endif
  239. #if (defined(CONFIG_SYS_EBC_PB1AP) && defined(CONFIG_SYS_EBC_PB1CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 1))
  240. mtebc(PB1AP, CONFIG_SYS_EBC_PB1AP);
  241. mtebc(PB1CR, CONFIG_SYS_EBC_PB1CR);
  242. #endif
  243. #if (defined(CONFIG_SYS_EBC_PB2AP) && defined(CONFIG_SYS_EBC_PB2CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 2))
  244. mtebc(PB2AP, CONFIG_SYS_EBC_PB2AP);
  245. mtebc(PB2CR, CONFIG_SYS_EBC_PB2CR);
  246. #endif
  247. #if (defined(CONFIG_SYS_EBC_PB3AP) && defined(CONFIG_SYS_EBC_PB3CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 3))
  248. mtebc(PB3AP, CONFIG_SYS_EBC_PB3AP);
  249. mtebc(PB3CR, CONFIG_SYS_EBC_PB3CR);
  250. #endif
  251. #if (defined(CONFIG_SYS_EBC_PB4AP) && defined(CONFIG_SYS_EBC_PB4CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 4))
  252. mtebc(PB4AP, CONFIG_SYS_EBC_PB4AP);
  253. mtebc(PB4CR, CONFIG_SYS_EBC_PB4CR);
  254. #endif
  255. #if (defined(CONFIG_SYS_EBC_PB5AP) && defined(CONFIG_SYS_EBC_PB5CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 5))
  256. mtebc(PB5AP, CONFIG_SYS_EBC_PB5AP);
  257. mtebc(PB5CR, CONFIG_SYS_EBC_PB5CR);
  258. #endif
  259. #if (defined(CONFIG_SYS_EBC_PB6AP) && defined(CONFIG_SYS_EBC_PB6CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 6))
  260. mtebc(PB6AP, CONFIG_SYS_EBC_PB6AP);
  261. mtebc(PB6CR, CONFIG_SYS_EBC_PB6CR);
  262. #endif
  263. #if (defined(CONFIG_SYS_EBC_PB7AP) && defined(CONFIG_SYS_EBC_PB7CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 7))
  264. mtebc(PB7AP, CONFIG_SYS_EBC_PB7AP);
  265. mtebc(PB7CR, CONFIG_SYS_EBC_PB7CR);
  266. #endif
  267. #if defined (CONFIG_SYS_EBC_CFG)
  268. mtebc(EBC0_CFG, CONFIG_SYS_EBC_CFG);
  269. #endif
  270. #if defined(CONFIG_WATCHDOG)
  271. val = mfspr(tcr);
  272. #if defined(CONFIG_440EP) || defined(CONFIG_440GR)
  273. val |= 0xb8000000; /* generate system reset after 1.34 seconds */
  274. #elif defined(CONFIG_440EPX)
  275. val |= 0xb0000000; /* generate system reset after 1.34 seconds */
  276. #else
  277. val |= 0xf0000000; /* generate system reset after 2.684 seconds */
  278. #endif
  279. #if defined(CONFIG_SYS_4xx_RESET_TYPE)
  280. val &= ~0x30000000; /* clear WRC bits */
  281. val |= CONFIG_SYS_4xx_RESET_TYPE << 28; /* set board specific WRC type */
  282. #endif
  283. mtspr(tcr, val);
  284. val = mfspr(tsr);
  285. val |= 0x80000000; /* enable watchdog timer */
  286. mtspr(tsr, val);
  287. reset_4xx_watchdog();
  288. #endif /* CONFIG_WATCHDOG */
  289. #if defined(CONFIG_440GX)
  290. /* Take the GX out of compatibility mode
  291. * Travis Sawyer, 9 Mar 2004
  292. * NOTE: 440gx user manual inconsistency here
  293. * Compatibility mode and Ethernet Clock select are not
  294. * correct in the manual
  295. */
  296. mfsdr(SDR0_MFR, val);
  297. val &= ~0x10000000;
  298. mtsdr(SDR0_MFR,val);
  299. #endif /* CONFIG_440GX */
  300. #if defined(CONFIG_460EX)
  301. /*
  302. * Set SDR0_AHB_CFG[A2P_INCR4] (bit 24) and
  303. * clear SDR0_AHB_CFG[A2P_PROT2] (bit 25) for a new 460EX errata
  304. * regarding concurrent use of AHB USB OTG, USB 2.0 host and SATA
  305. */
  306. mfsdr(SDR0_AHB_CFG, val);
  307. val |= 0x80;
  308. val &= ~0x40;
  309. mtsdr(SDR0_AHB_CFG, val);
  310. mfsdr(SDR0_USB2HOST_CFG, val);
  311. val &= ~0xf00;
  312. val |= 0x400;
  313. mtsdr(SDR0_USB2HOST_CFG, val);
  314. #endif /* CONFIG_460EX */
  315. #if defined(CONFIG_405EX) || \
  316. defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
  317. defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
  318. defined(CONFIG_460SX)
  319. /*
  320. * Set PLB4 arbiter (Segment 0 and 1) to 4 deep pipeline read
  321. */
  322. mtdcr(PLB0_ACR, (mfdcr(PLB0_ACR) & ~PLB0_ACR_RDP_MASK) |
  323. PLB0_ACR_RDP_4DEEP);
  324. mtdcr(PLB1_ACR, (mfdcr(PLB1_ACR) & ~PLB1_ACR_RDP_MASK) |
  325. PLB1_ACR_RDP_4DEEP);
  326. #endif /* CONFIG_440SP/SPE || CONFIG_460EX/GT || CONFIG_405EX */
  327. }
  328. /*
  329. * initialize higher level parts of CPU like time base and timers
  330. */
  331. int cpu_init_r (void)
  332. {
  333. #if defined(CONFIG_405GP)
  334. uint pvr = get_pvr();
  335. /*
  336. * Set edge conditioning circuitry on PPC405GPr
  337. * for compatibility to existing PPC405GP designs.
  338. */
  339. if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
  340. mtdcr(CPC0_ECR, 0x60606000);
  341. }
  342. #endif /* defined(CONFIG_405GP) */
  343. return 0;
  344. }
  345. #if defined(CONFIG_PCI) && \
  346. (defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
  347. defined(CONFIG_440GR) || defined(CONFIG_440GRX))
  348. /*
  349. * 440EP(x)/GR(x) PCI async/sync clocking restriction:
  350. *
  351. * In asynchronous PCI mode, the synchronous PCI clock must meet
  352. * certain requirements. The following equation describes the
  353. * relationship that must be maintained between the asynchronous PCI
  354. * clock and synchronous PCI clock. Select an appropriate PCI:PLB
  355. * ratio to maintain the relationship:
  356. *
  357. * AsyncPCIClk - 1MHz <= SyncPCIclock <= (2 * AsyncPCIClk) - 1MHz
  358. */
  359. static int ppc4xx_pci_sync_clock_ok(u32 sync, u32 async)
  360. {
  361. if (((async - 1000000) > sync) || (sync > ((2 * async) - 1000000)))
  362. return 0;
  363. else
  364. return 1;
  365. }
  366. int ppc4xx_pci_sync_clock_config(u32 async)
  367. {
  368. sys_info_t sys_info;
  369. u32 sync;
  370. int div;
  371. u32 reg;
  372. u32 spcid_val[] = {
  373. CPR0_SPCID_SPCIDV0_DIV1, CPR0_SPCID_SPCIDV0_DIV2,
  374. CPR0_SPCID_SPCIDV0_DIV3, CPR0_SPCID_SPCIDV0_DIV4 };
  375. get_sys_info(&sys_info);
  376. sync = sys_info.freqPCI;
  377. /*
  378. * First check if the equation above is met
  379. */
  380. if (!ppc4xx_pci_sync_clock_ok(sync, async)) {
  381. /*
  382. * Reconfigure PCI sync clock to meet the equation.
  383. * Start with highest possible PCI sync frequency
  384. * (divider 1).
  385. */
  386. for (div = 1; div <= 4; div++) {
  387. sync = sys_info.freqPLB / div;
  388. if (ppc4xx_pci_sync_clock_ok(sync, async))
  389. break;
  390. }
  391. if (div <= 4) {
  392. mtcpr(CPR0_SPCID, spcid_val[div]);
  393. mfcpr(CPR0_ICFG, reg);
  394. reg |= CPR0_ICFG_RLI_MASK;
  395. mtcpr(CPR0_ICFG, reg);
  396. /* do chip reset */
  397. mtspr(SPRN_DBCR0, 0x20000000);
  398. } else {
  399. /* Impossible to configure the PCI sync clock */
  400. return -1;
  401. }
  402. }
  403. return 0;
  404. }
  405. #endif