generic.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. /*
  2. * (C) Copyright 2007
  3. * Sascha Hauer, Pengutronix
  4. *
  5. * (C) Copyright 2008-2010 Freescale Semiconductor, Inc.
  6. *
  7. * See file CREDITS for list of people who contributed to this
  8. * project.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License as
  12. * published by the Free Software Foundation; either version 2 of
  13. * the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23. * MA 02111-1307 USA
  24. */
  25. #include <common.h>
  26. #include <asm/io.h>
  27. #include <asm/errno.h>
  28. #include <asm/arch/imx-regs.h>
  29. #include <asm/arch/crm_regs.h>
  30. #include <asm/arch/clock.h>
  31. #include <asm/arch/sys_proto.h>
  32. #ifdef CONFIG_FSL_ESDHC
  33. #include <fsl_esdhc.h>
  34. #endif
  35. #include <netdev.h>
  36. #define CLK_CODE(arm, ahb, sel) (((arm) << 16) + ((ahb) << 8) + (sel))
  37. #define CLK_CODE_ARM(c) (((c) >> 16) & 0xFF)
  38. #define CLK_CODE_AHB(c) (((c) >> 8) & 0xFF)
  39. #define CLK_CODE_PATH(c) ((c) & 0xFF)
  40. #define CCM_GET_DIVIDER(x, m, o) (((x) & (m)) >> (o))
  41. #ifdef CONFIG_FSL_ESDHC
  42. DECLARE_GLOBAL_DATA_PTR;
  43. #endif
  44. static int g_clk_mux_auto[8] = {
  45. CLK_CODE(1, 3, 0), CLK_CODE(1, 2, 1), CLK_CODE(2, 1, 1), -1,
  46. CLK_CODE(1, 6, 0), CLK_CODE(1, 4, 1), CLK_CODE(2, 2, 1), -1,
  47. };
  48. static int g_clk_mux_consumer[16] = {
  49. CLK_CODE(1, 4, 0), CLK_CODE(1, 3, 1), CLK_CODE(1, 3, 1), -1,
  50. -1, -1, CLK_CODE(4, 1, 0), CLK_CODE(1, 5, 0),
  51. CLK_CODE(1, 8, 1), CLK_CODE(1, 6, 1), CLK_CODE(2, 4, 0), -1,
  52. -1, -1, CLK_CODE(4, 2, 0), -1,
  53. };
  54. static int hsp_div_table[3][16] = {
  55. {4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1},
  56. {-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1},
  57. {3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1},
  58. };
  59. u32 get_cpu_rev(void)
  60. {
  61. int reg;
  62. struct iim_regs *iim =
  63. (struct iim_regs *)IIM_BASE_ADDR;
  64. reg = readl(&iim->iim_srev);
  65. if (!reg) {
  66. reg = readw(ROMPATCH_REV);
  67. reg <<= 4;
  68. } else {
  69. reg += CHIP_REV_1_0;
  70. }
  71. return 0x35000 + (reg & 0xFF);
  72. }
  73. static u32 get_arm_div(u32 pdr0, u32 *fi, u32 *fd)
  74. {
  75. int *pclk_mux;
  76. if (pdr0 & MXC_CCM_PDR0_AUTO_CON) {
  77. pclk_mux = g_clk_mux_consumer +
  78. ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >>
  79. MXC_CCM_PDR0_CON_MUX_DIV_OFFSET);
  80. } else {
  81. pclk_mux = g_clk_mux_auto +
  82. ((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >>
  83. MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET);
  84. }
  85. if ((*pclk_mux) == -1)
  86. return -1;
  87. if (fi && fd) {
  88. if (!CLK_CODE_PATH(*pclk_mux)) {
  89. *fi = *fd = 1;
  90. return CLK_CODE_ARM(*pclk_mux);
  91. }
  92. if (pdr0 & MXC_CCM_PDR0_AUTO_CON) {
  93. *fi = 3;
  94. *fd = 4;
  95. } else {
  96. *fi = 2;
  97. *fd = 3;
  98. }
  99. }
  100. return CLK_CODE_ARM(*pclk_mux);
  101. }
  102. static int get_ahb_div(u32 pdr0)
  103. {
  104. int *pclk_mux;
  105. pclk_mux = g_clk_mux_consumer +
  106. ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >>
  107. MXC_CCM_PDR0_CON_MUX_DIV_OFFSET);
  108. if ((*pclk_mux) == -1)
  109. return -1;
  110. return CLK_CODE_AHB(*pclk_mux);
  111. }
  112. static u32 decode_pll(u32 reg, u32 infreq)
  113. {
  114. u32 mfi = (reg >> 10) & 0xf;
  115. u32 mfn = reg & 0x3f;
  116. u32 mfd = (reg >> 16) & 0x3f;
  117. u32 pd = (reg >> 26) & 0xf;
  118. mfi = mfi <= 5 ? 5 : mfi;
  119. mfd += 1;
  120. pd += 1;
  121. return ((2 * (infreq / 1000) * (mfi * mfd + mfn)) / (mfd * pd)) * 1000;
  122. }
  123. static u32 get_mcu_main_clk(void)
  124. {
  125. u32 arm_div = 0, fi = 0, fd = 0;
  126. struct ccm_regs *ccm =
  127. (struct ccm_regs *)IMX_CCM_BASE;
  128. arm_div = get_arm_div(readl(&ccm->pdr0), &fi, &fd);
  129. fi *=
  130. decode_pll(readl(&ccm->mpctl),
  131. CONFIG_MX35_HCLK_FREQ);
  132. return fi / (arm_div * fd);
  133. }
  134. static u32 get_ipg_clk(void)
  135. {
  136. u32 freq = get_mcu_main_clk();
  137. struct ccm_regs *ccm =
  138. (struct ccm_regs *)IMX_CCM_BASE;
  139. u32 pdr0 = readl(&ccm->pdr0);
  140. return freq / (get_ahb_div(pdr0) * 2);
  141. }
  142. static u32 get_ipg_per_clk(void)
  143. {
  144. u32 freq = get_mcu_main_clk();
  145. struct ccm_regs *ccm =
  146. (struct ccm_regs *)IMX_CCM_BASE;
  147. u32 pdr0 = readl(&ccm->pdr0);
  148. u32 pdr4 = readl(&ccm->pdr4);
  149. u32 div;
  150. if (pdr0 & MXC_CCM_PDR0_PER_SEL) {
  151. div = (CCM_GET_DIVIDER(pdr4,
  152. MXC_CCM_PDR4_PER0_PRDF_MASK,
  153. MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1) *
  154. (CCM_GET_DIVIDER(pdr4,
  155. MXC_CCM_PDR4_PER0_PODF_MASK,
  156. MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1);
  157. } else {
  158. div = CCM_GET_DIVIDER(pdr0,
  159. MXC_CCM_PDR0_PER_PODF_MASK,
  160. MXC_CCM_PDR0_PER_PODF_OFFSET) + 1;
  161. freq /= get_ahb_div(pdr0);
  162. }
  163. return freq / div;
  164. }
  165. u32 imx_get_uartclk(void)
  166. {
  167. u32 freq;
  168. struct ccm_regs *ccm =
  169. (struct ccm_regs *)IMX_CCM_BASE;
  170. u32 pdr4 = readl(&ccm->pdr4);
  171. if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U) {
  172. freq = get_mcu_main_clk();
  173. } else {
  174. freq = decode_pll(readl(&ccm->ppctl),
  175. CONFIG_MX35_HCLK_FREQ);
  176. }
  177. freq /= ((CCM_GET_DIVIDER(pdr4,
  178. MXC_CCM_PDR4_UART_PRDF_MASK,
  179. MXC_CCM_PDR4_UART_PRDF_OFFSET) + 1) *
  180. (CCM_GET_DIVIDER(pdr4,
  181. MXC_CCM_PDR4_UART_PODF_MASK,
  182. MXC_CCM_PDR4_UART_PODF_OFFSET) + 1));
  183. return freq;
  184. }
  185. unsigned int mxc_get_main_clock(enum mxc_main_clocks clk)
  186. {
  187. u32 nfc_pdf, hsp_podf;
  188. u32 pll, ret_val = 0, usb_prdf, usb_podf;
  189. struct ccm_regs *ccm =
  190. (struct ccm_regs *)IMX_CCM_BASE;
  191. u32 reg = readl(&ccm->pdr0);
  192. u32 reg4 = readl(&ccm->pdr4);
  193. reg |= 0x1;
  194. switch (clk) {
  195. case CPU_CLK:
  196. ret_val = get_mcu_main_clk();
  197. break;
  198. case AHB_CLK:
  199. ret_val = get_mcu_main_clk();
  200. break;
  201. case HSP_CLK:
  202. if (reg & CLKMODE_CONSUMER) {
  203. hsp_podf = (reg >> 20) & 0x3;
  204. pll = get_mcu_main_clk();
  205. hsp_podf = hsp_div_table[hsp_podf][(reg>>16)&0xF];
  206. if (hsp_podf > 0) {
  207. ret_val = pll / hsp_podf;
  208. } else {
  209. puts("mismatch HSP with ARM clock setting\n");
  210. ret_val = 0;
  211. }
  212. } else {
  213. ret_val = get_mcu_main_clk();
  214. }
  215. break;
  216. case IPG_CLK:
  217. ret_val = get_ipg_clk();
  218. break;
  219. case IPG_PER_CLK:
  220. ret_val = get_ipg_per_clk();
  221. break;
  222. case NFC_CLK:
  223. nfc_pdf = (reg4 >> 28) & 0xF;
  224. pll = get_mcu_main_clk();
  225. /* AHB/nfc_pdf */
  226. ret_val = pll / (nfc_pdf + 1);
  227. break;
  228. case USB_CLK:
  229. usb_prdf = (reg4 >> 25) & 0x7;
  230. usb_podf = (reg4 >> 22) & 0x7;
  231. if (reg4 & 0x200) {
  232. pll = get_mcu_main_clk();
  233. } else {
  234. pll = decode_pll(readl(&ccm->ppctl),
  235. CONFIG_MX35_HCLK_FREQ);
  236. }
  237. ret_val = pll / ((usb_prdf + 1) * (usb_podf + 1));
  238. break;
  239. default:
  240. printf("Unknown clock: %d\n", clk);
  241. break;
  242. }
  243. return ret_val;
  244. }
  245. unsigned int mxc_get_peri_clock(enum mxc_peri_clocks clk)
  246. {
  247. u32 ret_val = 0, pdf, pre_pdf, clk_sel;
  248. struct ccm_regs *ccm =
  249. (struct ccm_regs *)IMX_CCM_BASE;
  250. u32 mpdr2 = readl(&ccm->pdr2);
  251. u32 mpdr3 = readl(&ccm->pdr3);
  252. u32 mpdr4 = readl(&ccm->pdr4);
  253. switch (clk) {
  254. case UART1_BAUD:
  255. case UART2_BAUD:
  256. case UART3_BAUD:
  257. clk_sel = mpdr3 & (1 << 14);
  258. pre_pdf = (mpdr4 >> 13) & 0x7;
  259. pdf = (mpdr4 >> 10) & 0x7;
  260. ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
  261. decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
  262. ((pre_pdf + 1) * (pdf + 1));
  263. break;
  264. case SSI1_BAUD:
  265. pre_pdf = (mpdr2 >> 24) & 0x7;
  266. pdf = mpdr2 & 0x3F;
  267. clk_sel = mpdr2 & (1 << 6);
  268. ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
  269. decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
  270. ((pre_pdf + 1) * (pdf + 1));
  271. break;
  272. case SSI2_BAUD:
  273. pre_pdf = (mpdr2 >> 27) & 0x7;
  274. pdf = (mpdr2 >> 8) & 0x3F;
  275. clk_sel = mpdr2 & (1 << 6);
  276. ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
  277. decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
  278. ((pre_pdf + 1) * (pdf + 1));
  279. break;
  280. case CSI_BAUD:
  281. clk_sel = mpdr2 & (1 << 7);
  282. pre_pdf = (mpdr2 >> 16) & 0x7;
  283. pdf = (mpdr2 >> 19) & 0x7;
  284. ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
  285. decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
  286. ((pre_pdf + 1) * (pdf + 1));
  287. break;
  288. case MSHC_CLK:
  289. pre_pdf = readl(&ccm->pdr1);
  290. clk_sel = (pre_pdf & 0x80);
  291. pdf = (pre_pdf >> 22) & 0x3F;
  292. pre_pdf = (pre_pdf >> 28) & 0x7;
  293. ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
  294. decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
  295. ((pre_pdf + 1) * (pdf + 1));
  296. break;
  297. case ESDHC1_CLK:
  298. clk_sel = mpdr3 & 0x40;
  299. pre_pdf = mpdr3 & 0x7;
  300. pdf = (mpdr3>>3) & 0x7;
  301. ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
  302. decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
  303. ((pre_pdf + 1) * (pdf + 1));
  304. break;
  305. case ESDHC2_CLK:
  306. clk_sel = mpdr3 & 0x40;
  307. pre_pdf = (mpdr3 >> 8) & 0x7;
  308. pdf = (mpdr3 >> 11) & 0x7;
  309. ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
  310. decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
  311. ((pre_pdf + 1) * (pdf + 1));
  312. break;
  313. case ESDHC3_CLK:
  314. clk_sel = mpdr3 & 0x40;
  315. pre_pdf = (mpdr3 >> 16) & 0x7;
  316. pdf = (mpdr3 >> 19) & 0x7;
  317. ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
  318. decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
  319. ((pre_pdf + 1) * (pdf + 1));
  320. break;
  321. case SPDIF_CLK:
  322. clk_sel = mpdr3 & 0x400000;
  323. pre_pdf = (mpdr3 >> 29) & 0x7;
  324. pdf = (mpdr3 >> 23) & 0x3F;
  325. ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) :
  326. decode_pll(readl(&ccm->ppctl), CONFIG_MX35_HCLK_FREQ)) /
  327. ((pre_pdf + 1) * (pdf + 1));
  328. break;
  329. default:
  330. printf("%s(): This clock: %d not supported yet\n",
  331. __func__, clk);
  332. break;
  333. }
  334. return ret_val;
  335. }
  336. unsigned int mxc_get_clock(enum mxc_clock clk)
  337. {
  338. switch (clk) {
  339. case MXC_ARM_CLK:
  340. return get_mcu_main_clk();
  341. case MXC_AHB_CLK:
  342. break;
  343. case MXC_IPG_CLK:
  344. return get_ipg_clk();
  345. case MXC_IPG_PERCLK:
  346. return get_ipg_per_clk();
  347. case MXC_UART_CLK:
  348. return imx_get_uartclk();
  349. case MXC_ESDHC_CLK:
  350. return mxc_get_peri_clock(ESDHC1_CLK);
  351. case MXC_USB_CLK:
  352. return mxc_get_main_clock(USB_CLK);
  353. case MXC_FEC_CLK:
  354. return get_ipg_clk();
  355. case MXC_CSPI_CLK:
  356. return get_ipg_clk();
  357. }
  358. return -1;
  359. }
  360. #ifdef CONFIG_FEC_MXC
  361. /*
  362. * The MX35 has no fuse for MAC, return a NULL MAC
  363. */
  364. void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
  365. {
  366. memset(mac, 0, 6);
  367. }
  368. u32 imx_get_fecclk(void)
  369. {
  370. return mxc_get_clock(MXC_IPG_CLK);
  371. }
  372. #endif
  373. int do_mx35_showclocks(cmd_tbl_t *cmdtp,
  374. int flag, int argc, char * const argv[])
  375. {
  376. u32 cpufreq = get_mcu_main_clk();
  377. printf("mx35 cpu clock: %dMHz\n", cpufreq / 1000000);
  378. printf("ipg clock : %dHz\n", get_ipg_clk());
  379. printf("ipg per clock : %dHz\n", get_ipg_per_clk());
  380. printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK));
  381. return 0;
  382. }
  383. U_BOOT_CMD(
  384. clocks, CONFIG_SYS_MAXARGS, 1, do_mx35_showclocks,
  385. "display clocks",
  386. ""
  387. );
  388. #if defined(CONFIG_DISPLAY_CPUINFO)
  389. static char *get_reset_cause(void)
  390. {
  391. /* read RCSR register from CCM module */
  392. struct ccm_regs *ccm =
  393. (struct ccm_regs *)IMX_CCM_BASE;
  394. u32 cause = readl(&ccm->rcsr) & 0x0F;
  395. switch (cause) {
  396. case 0x0000:
  397. return "POR";
  398. case 0x0002:
  399. return "JTAG";
  400. case 0x0004:
  401. return "RST";
  402. case 0x0008:
  403. return "WDOG";
  404. default:
  405. return "unknown reset";
  406. }
  407. }
  408. int print_cpuinfo(void)
  409. {
  410. u32 srev = get_cpu_rev();
  411. printf("CPU: Freescale i.MX35 rev %d.%d at %d MHz.\n",
  412. (srev & 0xF0) >> 4, (srev & 0x0F),
  413. get_mcu_main_clk() / 1000000);
  414. printf("Reset cause: %s\n", get_reset_cause());
  415. return 0;
  416. }
  417. #endif
  418. /*
  419. * Initializes on-chip ethernet controllers.
  420. * to override, implement board_eth_init()
  421. */
  422. int cpu_eth_init(bd_t *bis)
  423. {
  424. int rc = -ENODEV;
  425. #if defined(CONFIG_FEC_MXC)
  426. rc = fecmxc_initialize(bis);
  427. #endif
  428. return rc;
  429. }
  430. #ifdef CONFIG_FSL_ESDHC
  431. /*
  432. * Initializes on-chip MMC controllers.
  433. * to override, implement board_mmc_init()
  434. */
  435. int cpu_mmc_init(bd_t *bis)
  436. {
  437. return fsl_esdhc_mmc_init(bis);
  438. }
  439. #endif
  440. int get_clocks(void)
  441. {
  442. #ifdef CONFIG_FSL_ESDHC
  443. gd->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
  444. #endif
  445. return 0;
  446. }
  447. void reset_cpu(ulong addr)
  448. {
  449. struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR;
  450. writew(4, &wdog->wcr);
  451. }