cpu_init.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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 CFG_PLL_RECONFIG
  33. #define CFG_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(clk_primbd, 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(clk_primbd, reg);
  62. reset_needed = 1;
  63. }
  64. mfcpr(clk_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(clk_plld, reg);
  81. reset_needed = 1;
  82. }
  83. mfcpr(clk_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(clk_perd, reg);
  89. reset_needed = 1;
  90. }
  91. mfcpr(clk_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(clk_spcid, reg);
  98. reset_needed = 1;
  99. }
  100. /* Set reload inhibit so configuration will persist across
  101. * processor resets */
  102. mfcpr(clk_icfg, reg);
  103. reg &= ~CPR0_ICFG_RLI_MASK;
  104. reg |= 1 << 31;
  105. mtcpr(clk_icfg, reg);
  106. }
  107. /* Reset processor if configuration changed */
  108. if (reset_needed) {
  109. __asm__ __volatile__ ("sync; isync");
  110. mtspr(dbcr0, 0x20000000);
  111. }
  112. #endif
  113. }
  114. /*
  115. * Breath some life into the CPU...
  116. *
  117. * Reconfigure PLL if necessary,
  118. * set up the memory map,
  119. * initialize a bunch of registers
  120. */
  121. void
  122. cpu_init_f (void)
  123. {
  124. #if defined(CONFIG_WATCHDOG)
  125. unsigned long val;
  126. #endif
  127. reconfigure_pll(CFG_PLL_RECONFIG);
  128. #if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && !defined(CFG_4xx_GPIO_TABLE)
  129. /*
  130. * GPIO0 setup (select GPIO or alternate function)
  131. */
  132. #if defined(CFG_GPIO0_OR)
  133. out32(GPIO0_OR, CFG_GPIO0_OR); /* set initial state of output pins */
  134. #endif
  135. #if defined(CFG_GPIO0_ODR)
  136. out32(GPIO0_ODR, CFG_GPIO0_ODR); /* open-drain select */
  137. #endif
  138. out32(GPIO0_OSRH, CFG_GPIO0_OSRH); /* output select */
  139. out32(GPIO0_OSRL, CFG_GPIO0_OSRL);
  140. out32(GPIO0_ISR1H, CFG_GPIO0_ISR1H); /* input select */
  141. out32(GPIO0_ISR1L, CFG_GPIO0_ISR1L);
  142. out32(GPIO0_TSRH, CFG_GPIO0_TSRH); /* three-state select */
  143. out32(GPIO0_TSRL, CFG_GPIO0_TSRL);
  144. #if defined(CFG_GPIO0_ISR2H)
  145. out32(GPIO0_ISR2H, CFG_GPIO0_ISR2H);
  146. out32(GPIO0_ISR2L, CFG_GPIO0_ISR2L);
  147. #endif
  148. #if defined (CFG_GPIO0_TCR)
  149. out32(GPIO0_TCR, CFG_GPIO0_TCR); /* enable output driver for outputs */
  150. #endif
  151. #endif /* CONFIG_405EP ... && !CFG_4xx_GPIO_TABLE */
  152. #if defined (CONFIG_405EP)
  153. /*
  154. * Set EMAC noise filter bits
  155. */
  156. mtdcr(cpc0_epctl, CPC0_EPRCSR_E0NFE | CPC0_EPRCSR_E1NFE);
  157. /*
  158. * Enable the internal PCI arbiter
  159. */
  160. mtdcr(cpc0_pci, mfdcr(cpc0_pci) | CPC0_PCI_HOST_CFG_EN | CPC0_PCI_ARBIT_EN);
  161. #endif /* CONFIG_405EP */
  162. #if defined(CFG_4xx_GPIO_TABLE)
  163. gpio_set_chip_configuration();
  164. #endif /* CFG_4xx_GPIO_TABLE */
  165. /*
  166. * External Bus Controller (EBC) Setup
  167. */
  168. #if (defined(CFG_EBC_PB0AP) && defined(CFG_EBC_PB0CR))
  169. #if (defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
  170. defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
  171. defined(CONFIG_405EX) || defined(CONFIG_405))
  172. /*
  173. * Move the next instructions into icache, since these modify the flash
  174. * we are running from!
  175. */
  176. asm volatile(" bl 0f" ::: "lr");
  177. asm volatile("0: mflr 3" ::: "r3");
  178. asm volatile(" addi 4, 0, 14" ::: "r4");
  179. asm volatile(" mtctr 4" ::: "ctr");
  180. asm volatile("1: icbt 0, 3");
  181. asm volatile(" addi 3, 3, 32" ::: "r3");
  182. asm volatile(" bdnz 1b" ::: "ctr", "cr0");
  183. asm volatile(" addis 3, 0, 0x0" ::: "r3");
  184. asm volatile(" ori 3, 3, 0xA000" ::: "r3");
  185. asm volatile(" mtctr 3" ::: "ctr");
  186. asm volatile("2: bdnz 2b" ::: "ctr", "cr0");
  187. #endif
  188. mtebc(pb0ap, CFG_EBC_PB0AP);
  189. mtebc(pb0cr, CFG_EBC_PB0CR);
  190. #endif
  191. #if (defined(CFG_EBC_PB1AP) && defined(CFG_EBC_PB1CR) && !(CFG_INIT_DCACHE_CS == 1))
  192. mtebc(pb1ap, CFG_EBC_PB1AP);
  193. mtebc(pb1cr, CFG_EBC_PB1CR);
  194. #endif
  195. #if (defined(CFG_EBC_PB2AP) && defined(CFG_EBC_PB2CR) && !(CFG_INIT_DCACHE_CS == 2))
  196. mtebc(pb2ap, CFG_EBC_PB2AP);
  197. mtebc(pb2cr, CFG_EBC_PB2CR);
  198. #endif
  199. #if (defined(CFG_EBC_PB3AP) && defined(CFG_EBC_PB3CR) && !(CFG_INIT_DCACHE_CS == 3))
  200. mtebc(pb3ap, CFG_EBC_PB3AP);
  201. mtebc(pb3cr, CFG_EBC_PB3CR);
  202. #endif
  203. #if (defined(CFG_EBC_PB4AP) && defined(CFG_EBC_PB4CR) && !(CFG_INIT_DCACHE_CS == 4))
  204. mtebc(pb4ap, CFG_EBC_PB4AP);
  205. mtebc(pb4cr, CFG_EBC_PB4CR);
  206. #endif
  207. #if (defined(CFG_EBC_PB5AP) && defined(CFG_EBC_PB5CR) && !(CFG_INIT_DCACHE_CS == 5))
  208. mtebc(pb5ap, CFG_EBC_PB5AP);
  209. mtebc(pb5cr, CFG_EBC_PB5CR);
  210. #endif
  211. #if (defined(CFG_EBC_PB6AP) && defined(CFG_EBC_PB6CR) && !(CFG_INIT_DCACHE_CS == 6))
  212. mtebc(pb6ap, CFG_EBC_PB6AP);
  213. mtebc(pb6cr, CFG_EBC_PB6CR);
  214. #endif
  215. #if (defined(CFG_EBC_PB7AP) && defined(CFG_EBC_PB7CR) && !(CFG_INIT_DCACHE_CS == 7))
  216. mtebc(pb7ap, CFG_EBC_PB7AP);
  217. mtebc(pb7cr, CFG_EBC_PB7CR);
  218. #endif
  219. #if defined (CFG_EBC_CFG)
  220. mtebc(EBC0_CFG, CFG_EBC_CFG);
  221. #endif
  222. #if defined(CONFIG_WATCHDOG)
  223. val = mfspr(tcr);
  224. #if defined(CONFIG_440EP) || defined(CONFIG_440GR)
  225. val |= 0xb8000000; /* generate system reset after 1.34 seconds */
  226. #elif defined(CONFIG_440EPX)
  227. val |= 0xb0000000; /* generate system reset after 1.34 seconds */
  228. #else
  229. val |= 0xf0000000; /* generate system reset after 2.684 seconds */
  230. #endif
  231. #if defined(CFG_4xx_RESET_TYPE)
  232. val &= ~0x30000000; /* clear WRC bits */
  233. val |= CFG_4xx_RESET_TYPE << 28; /* set board specific WRC type */
  234. #endif
  235. mtspr(tcr, val);
  236. val = mfspr(tsr);
  237. val |= 0x80000000; /* enable watchdog timer */
  238. mtspr(tsr, val);
  239. reset_4xx_watchdog();
  240. #endif /* CONFIG_WATCHDOG */
  241. }
  242. /*
  243. * initialize higher level parts of CPU like time base and timers
  244. */
  245. int cpu_init_r (void)
  246. {
  247. #if defined(CONFIG_405GP) || defined(CONFIG_405EP)
  248. bd_t *bd = gd->bd;
  249. unsigned long reg;
  250. #if defined(CONFIG_405GP)
  251. uint pvr = get_pvr();
  252. #endif
  253. /*
  254. * Write Ethernetaddress into on-chip register
  255. */
  256. reg = 0x00000000;
  257. reg |= bd->bi_enetaddr[0]; /* set high address */
  258. reg = reg << 8;
  259. reg |= bd->bi_enetaddr[1];
  260. out32 (EMAC_IAH, reg);
  261. reg = 0x00000000;
  262. reg |= bd->bi_enetaddr[2]; /* set low address */
  263. reg = reg << 8;
  264. reg |= bd->bi_enetaddr[3];
  265. reg = reg << 8;
  266. reg |= bd->bi_enetaddr[4];
  267. reg = reg << 8;
  268. reg |= bd->bi_enetaddr[5];
  269. out32 (EMAC_IAL, reg);
  270. #if defined(CONFIG_405GP)
  271. /*
  272. * Set edge conditioning circuitry on PPC405GPr
  273. * for compatibility to existing PPC405GP designs.
  274. */
  275. if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
  276. mtdcr(ecr, 0x60606000);
  277. }
  278. #endif /* defined(CONFIG_405GP) */
  279. #endif /* defined(CONFIG_405GP) || defined(CONFIG_405EP) */
  280. return (0);
  281. }