clock.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. #include <linux/clk.h>
  2. #include <linux/kernel.h>
  3. #include <linux/init.h>
  4. #include <linux/io.h>
  5. #include <mach/clock.h>
  6. #include <mach/hardware.h>
  7. #include <mach/common.h>
  8. #include <asm/clkdev.h>
  9. #include <asm/bug.h>
  10. #include <asm/div64.h>
  11. #include "crm_regs.h"
  12. #define CRM_SMALL_DIVIDER(base, name) \
  13. crm_small_divider(base, \
  14. base ## _ ## name ## _OFFSET, \
  15. base ## _ ## name ## _MASK)
  16. #define CRM_1DIVIDER(base, name) \
  17. crm_divider(base, \
  18. base ## _ ## name ## _OFFSET, \
  19. base ## _ ## name ## _MASK, 1)
  20. #define CRM_16DIVIDER(base, name) \
  21. crm_divider(base, \
  22. base ## _ ## name ## _OFFSET, \
  23. base ## _ ## name ## _MASK, 16)
  24. static u32 crm_small_divider(void __iomem *reg, u8 offset, u32 mask)
  25. {
  26. static const u32 crm_small_dividers[] = {
  27. 2, 3, 4, 5, 6, 8, 10, 12
  28. };
  29. u8 idx;
  30. idx = (__raw_readl(reg) & mask) >> offset;
  31. if (idx > 7)
  32. return 1;
  33. return crm_small_dividers[idx];
  34. }
  35. static u32 crm_divider(void __iomem *reg, u8 offset, u32 mask, u32 z)
  36. {
  37. u32 div;
  38. div = (__raw_readl(reg) & mask) >> offset;
  39. return div ? div : z;
  40. }
  41. static int _clk_1bit_enable(struct clk *clk)
  42. {
  43. u32 reg;
  44. reg = __raw_readl(clk->enable_reg);
  45. reg |= 1 << clk->enable_shift;
  46. __raw_writel(reg, clk->enable_reg);
  47. return 0;
  48. }
  49. static void _clk_1bit_disable(struct clk *clk)
  50. {
  51. u32 reg;
  52. reg = __raw_readl(clk->enable_reg);
  53. reg &= ~(1 << clk->enable_shift);
  54. __raw_writel(reg, clk->enable_reg);
  55. }
  56. static int _clk_3bit_enable(struct clk *clk)
  57. {
  58. u32 reg;
  59. reg = __raw_readl(clk->enable_reg);
  60. reg |= 0x7 << clk->enable_shift;
  61. __raw_writel(reg, clk->enable_reg);
  62. return 0;
  63. }
  64. static void _clk_3bit_disable(struct clk *clk)
  65. {
  66. u32 reg;
  67. reg = __raw_readl(clk->enable_reg);
  68. reg &= ~(0x7 << clk->enable_shift);
  69. __raw_writel(reg, clk->enable_reg);
  70. }
  71. static unsigned long ckih_rate;
  72. static unsigned long clk_ckih_get_rate(struct clk *clk)
  73. {
  74. return ckih_rate;
  75. }
  76. static struct clk ckih_clk = {
  77. .get_rate = clk_ckih_get_rate,
  78. };
  79. static unsigned long clk_ckih_x2_get_rate(struct clk *clk)
  80. {
  81. return 2 * clk_get_rate(clk->parent);
  82. }
  83. static struct clk ckih_x2_clk = {
  84. .parent = &ckih_clk,
  85. .get_rate = clk_ckih_x2_get_rate,
  86. };
  87. static unsigned long clk_ckil_get_rate(struct clk *clk)
  88. {
  89. return CKIL_CLK_FREQ;
  90. }
  91. static struct clk ckil_clk = {
  92. .get_rate = clk_ckil_get_rate,
  93. };
  94. /* plls stuff */
  95. static struct clk mcu_pll_clk;
  96. static struct clk dsp_pll_clk;
  97. static struct clk usb_pll_clk;
  98. static struct clk *pll_clk(u8 sel)
  99. {
  100. switch (sel) {
  101. case 0:
  102. return &mcu_pll_clk;
  103. case 1:
  104. return &dsp_pll_clk;
  105. case 2:
  106. return &usb_pll_clk;
  107. }
  108. BUG();
  109. }
  110. static void __iomem *pll_base(struct clk *clk)
  111. {
  112. if (clk == &mcu_pll_clk)
  113. return MXC_PLL0_BASE;
  114. else if (clk == &dsp_pll_clk)
  115. return MXC_PLL1_BASE;
  116. else if (clk == &usb_pll_clk)
  117. return MXC_PLL2_BASE;
  118. BUG();
  119. }
  120. static unsigned long clk_pll_get_rate(struct clk *clk)
  121. {
  122. const void __iomem *pllbase;
  123. unsigned long dp_op, dp_mfd, dp_mfn, pll_hfsm, ref_clk, mfi;
  124. long mfn, mfn_abs, mfd, pdf;
  125. s64 temp;
  126. pllbase = pll_base(clk);
  127. pll_hfsm = __raw_readl(pllbase + MXC_PLL_DP_CTL) & MXC_PLL_DP_CTL_HFSM;
  128. if (pll_hfsm == 0) {
  129. dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
  130. dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
  131. dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
  132. } else {
  133. dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
  134. dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
  135. dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
  136. }
  137. pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
  138. mfi = (dp_op >> MXC_PLL_DP_OP_MFI_OFFSET) & MXC_PLL_DP_OP_PDF_MASK;
  139. mfi = (mfi <= 5) ? 5 : mfi;
  140. mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
  141. mfn = dp_mfn & MXC_PLL_DP_MFN_MASK;
  142. mfn = (mfn <= 0x4000000) ? mfn : (mfn - 0x10000000);
  143. if (mfn < 0)
  144. mfn_abs = -mfn;
  145. else
  146. mfn_abs = mfn;
  147. /* XXX: actually this asumes that ckih is fed to pll, but spec says
  148. * that ckih_x2 is also possible. need to check this out.
  149. */
  150. ref_clk = clk_get_rate(&ckih_clk);
  151. ref_clk *= 2;
  152. ref_clk /= pdf + 1;
  153. temp = (u64) ref_clk * mfn_abs;
  154. do_div(temp, mfd);
  155. if (mfn < 0)
  156. temp = -temp;
  157. temp += ref_clk * mfi;
  158. return temp;
  159. }
  160. static int clk_pll_enable(struct clk *clk)
  161. {
  162. void __iomem *ctl;
  163. u32 reg;
  164. ctl = pll_base(clk);
  165. reg = __raw_readl(ctl);
  166. reg |= (MXC_PLL_DP_CTL_RST | MXC_PLL_DP_CTL_UPEN);
  167. __raw_writel(reg, ctl);
  168. do {
  169. reg = __raw_readl(ctl);
  170. } while ((reg & MXC_PLL_DP_CTL_LRF) != MXC_PLL_DP_CTL_LRF);
  171. return 0;
  172. }
  173. static void clk_pll_disable(struct clk *clk)
  174. {
  175. void __iomem *ctl;
  176. u32 reg;
  177. ctl = pll_base(clk);
  178. reg = __raw_readl(ctl);
  179. reg &= ~(MXC_PLL_DP_CTL_RST | MXC_PLL_DP_CTL_UPEN);
  180. __raw_writel(reg, ctl);
  181. }
  182. static struct clk mcu_pll_clk = {
  183. .parent = &ckih_clk,
  184. .get_rate = clk_pll_get_rate,
  185. .enable = clk_pll_enable,
  186. .disable = clk_pll_disable,
  187. };
  188. static struct clk dsp_pll_clk = {
  189. .parent = &ckih_clk,
  190. .get_rate = clk_pll_get_rate,
  191. .enable = clk_pll_enable,
  192. .disable = clk_pll_disable,
  193. };
  194. static struct clk usb_pll_clk = {
  195. .parent = &ckih_clk,
  196. .get_rate = clk_pll_get_rate,
  197. .enable = clk_pll_enable,
  198. .disable = clk_pll_disable,
  199. };
  200. /* plls stuff end */
  201. /* ap_ref_clk stuff */
  202. static struct clk ap_ref_clk;
  203. static unsigned long clk_ap_ref_get_rate(struct clk *clk)
  204. {
  205. u32 ascsr, acsr;
  206. u8 ap_pat_ref_div_2, ap_isel, acs, ads;
  207. ascsr = __raw_readl(MXC_CRMAP_ASCSR);
  208. acsr = __raw_readl(MXC_CRMAP_ACSR);
  209. /* 0 for ckih, 1 for ckih*2 */
  210. ap_isel = ascsr & MXC_CRMAP_ASCSR_APISEL;
  211. /* reg divider */
  212. ap_pat_ref_div_2 = (ascsr >> MXC_CRMAP_ASCSR_AP_PATDIV2_OFFSET) & 0x1;
  213. /* undocumented, 1 for disabling divider */
  214. ads = (acsr >> MXC_CRMAP_ACSR_ADS_OFFSET) & 0x1;
  215. /* 0 for pat_ref, 1 for divider out */
  216. acs = acsr & MXC_CRMAP_ACSR_ACS;
  217. if (acs & !ads)
  218. /* use divided clock */
  219. return clk_get_rate(clk->parent) / (ap_pat_ref_div_2 ? 2 : 1);
  220. return clk_get_rate(clk->parent) * (ap_isel ? 2 : 1);
  221. }
  222. static struct clk ap_ref_clk = {
  223. .parent = &ckih_clk,
  224. .get_rate = clk_ap_ref_get_rate,
  225. };
  226. /* ap_ref_clk stuff end */
  227. /* ap_pre_dfs_clk stuff */
  228. static struct clk ap_pre_dfs_clk;
  229. static unsigned long clk_ap_pre_dfs_get_rate(struct clk *clk)
  230. {
  231. u32 acsr, ascsr;
  232. acsr = __raw_readl(MXC_CRMAP_ACSR);
  233. ascsr = __raw_readl(MXC_CRMAP_ASCSR);
  234. if (acsr & MXC_CRMAP_ACSR_ACS) {
  235. u8 sel;
  236. sel = (ascsr & MXC_CRMAP_ASCSR_APSEL_MASK) >>
  237. MXC_CRMAP_ASCSR_APSEL_OFFSET;
  238. return clk_get_rate(pll_clk(sel)) /
  239. CRM_SMALL_DIVIDER(MXC_CRMAP_ACDR, ARMDIV);
  240. }
  241. return clk_get_rate(&ap_ref_clk);
  242. }
  243. static struct clk ap_pre_dfs_clk = {
  244. .get_rate = clk_ap_pre_dfs_get_rate,
  245. };
  246. /* ap_pre_dfs_clk stuff end */
  247. /* usb_clk stuff */
  248. static struct clk usb_clk;
  249. static struct clk *clk_usb_parent(struct clk *clk)
  250. {
  251. u32 acsr, ascsr;
  252. acsr = __raw_readl(MXC_CRMAP_ACSR);
  253. ascsr = __raw_readl(MXC_CRMAP_ASCSR);
  254. if (acsr & MXC_CRMAP_ACSR_ACS) {
  255. u8 sel;
  256. sel = (ascsr & MXC_CRMAP_ASCSR_USBSEL_MASK) >>
  257. MXC_CRMAP_ASCSR_USBSEL_OFFSET;
  258. return pll_clk(sel);
  259. }
  260. return &ap_ref_clk;
  261. }
  262. static unsigned long clk_usb_get_rate(struct clk *clk)
  263. {
  264. return clk_get_rate(clk->parent) /
  265. CRM_SMALL_DIVIDER(MXC_CRMAP_ACDER2, USBDIV);
  266. }
  267. static struct clk usb_clk = {
  268. .enable_reg = MXC_CRMAP_ACDER2,
  269. .enable_shift = MXC_CRMAP_ACDER2_USBEN_OFFSET,
  270. .get_rate = clk_usb_get_rate,
  271. .enable = _clk_1bit_enable,
  272. .disable = _clk_1bit_disable,
  273. };
  274. /* usb_clk stuff end */
  275. static unsigned long clk_ipg_get_rate(struct clk *clk)
  276. {
  277. return clk_get_rate(clk->parent) / CRM_16DIVIDER(MXC_CRMAP_ACDR, IPDIV);
  278. }
  279. static unsigned long clk_ahb_get_rate(struct clk *clk)
  280. {
  281. return clk_get_rate(clk->parent) /
  282. CRM_16DIVIDER(MXC_CRMAP_ACDR, AHBDIV);
  283. }
  284. static struct clk ipg_clk = {
  285. .parent = &ap_pre_dfs_clk,
  286. .get_rate = clk_ipg_get_rate,
  287. };
  288. static struct clk ahb_clk = {
  289. .parent = &ap_pre_dfs_clk,
  290. .get_rate = clk_ahb_get_rate,
  291. };
  292. /* perclk_clk stuff */
  293. static struct clk perclk_clk;
  294. static unsigned long clk_perclk_get_rate(struct clk *clk)
  295. {
  296. u32 acder2;
  297. acder2 = __raw_readl(MXC_CRMAP_ACDER2);
  298. if (acder2 & MXC_CRMAP_ACDER2_BAUD_ISEL_MASK)
  299. return 2 * clk_get_rate(clk->parent);
  300. return clk_get_rate(clk->parent);
  301. }
  302. static struct clk perclk_clk = {
  303. .parent = &ckih_clk,
  304. .get_rate = clk_perclk_get_rate,
  305. };
  306. /* perclk_clk stuff end */
  307. /* uart_clk stuff */
  308. static struct clk uart_clk[];
  309. static unsigned long clk_uart_get_rate(struct clk *clk)
  310. {
  311. u32 div;
  312. switch (clk->id) {
  313. case 0:
  314. case 1:
  315. div = CRM_SMALL_DIVIDER(MXC_CRMAP_ACDER2, BAUDDIV);
  316. break;
  317. case 2:
  318. div = CRM_SMALL_DIVIDER(MXC_CRMAP_APRA, UART3DIV);
  319. break;
  320. default:
  321. BUG();
  322. }
  323. return clk_get_rate(clk->parent) / div;
  324. }
  325. static struct clk uart_clk[] = {
  326. {
  327. .id = 0,
  328. .parent = &perclk_clk,
  329. .enable_reg = MXC_CRMAP_APRA,
  330. .enable_shift = MXC_CRMAP_APRA_UART1EN_OFFSET,
  331. .get_rate = clk_uart_get_rate,
  332. .enable = _clk_1bit_enable,
  333. .disable = _clk_1bit_disable,
  334. }, {
  335. .id = 1,
  336. .parent = &perclk_clk,
  337. .enable_reg = MXC_CRMAP_APRA,
  338. .enable_shift = MXC_CRMAP_APRA_UART2EN_OFFSET,
  339. .get_rate = clk_uart_get_rate,
  340. .enable = _clk_1bit_enable,
  341. .disable = _clk_1bit_disable,
  342. }, {
  343. .id = 2,
  344. .parent = &perclk_clk,
  345. .enable_reg = MXC_CRMAP_APRA,
  346. .enable_shift = MXC_CRMAP_APRA_UART3EN_OFFSET,
  347. .get_rate = clk_uart_get_rate,
  348. .enable = _clk_1bit_enable,
  349. .disable = _clk_1bit_disable,
  350. },
  351. };
  352. /* uart_clk stuff end */
  353. /* sdhc_clk stuff */
  354. static struct clk nfc_clk;
  355. static unsigned long clk_nfc_get_rate(struct clk *clk)
  356. {
  357. return clk_get_rate(clk->parent) /
  358. CRM_1DIVIDER(MXC_CRMAP_ACDER2, NFCDIV);
  359. }
  360. static struct clk nfc_clk = {
  361. .parent = &ahb_clk,
  362. .enable_reg = MXC_CRMAP_ACDER2,
  363. .enable_shift = MXC_CRMAP_ACDER2_NFCEN_OFFSET,
  364. .get_rate = clk_nfc_get_rate,
  365. .enable = _clk_1bit_enable,
  366. .disable = _clk_1bit_disable,
  367. };
  368. /* sdhc_clk stuff end */
  369. /* sdhc_clk stuff */
  370. static struct clk sdhc_clk[];
  371. static struct clk *clk_sdhc_parent(struct clk *clk)
  372. {
  373. u32 aprb;
  374. u8 sel;
  375. u32 mask;
  376. int offset;
  377. aprb = __raw_readl(MXC_CRMAP_APRB);
  378. switch (clk->id) {
  379. case 0:
  380. mask = MXC_CRMAP_APRB_SDHC1_ISEL_MASK;
  381. offset = MXC_CRMAP_APRB_SDHC1_ISEL_OFFSET;
  382. break;
  383. case 1:
  384. mask = MXC_CRMAP_APRB_SDHC2_ISEL_MASK;
  385. offset = MXC_CRMAP_APRB_SDHC2_ISEL_OFFSET;
  386. break;
  387. default:
  388. BUG();
  389. }
  390. sel = (aprb & mask) >> offset;
  391. switch (sel) {
  392. case 0:
  393. return &ckih_clk;
  394. case 1:
  395. return &ckih_x2_clk;
  396. }
  397. return &usb_clk;
  398. }
  399. static unsigned long clk_sdhc_get_rate(struct clk *clk)
  400. {
  401. u32 div;
  402. switch (clk->id) {
  403. case 0:
  404. div = CRM_SMALL_DIVIDER(MXC_CRMAP_APRB, SDHC1_DIV);
  405. break;
  406. case 1:
  407. div = CRM_SMALL_DIVIDER(MXC_CRMAP_APRB, SDHC2_DIV);
  408. break;
  409. default:
  410. BUG();
  411. }
  412. return clk_get_rate(clk->parent) / div;
  413. }
  414. static int clk_sdhc_enable(struct clk *clk)
  415. {
  416. u32 amlpmre1, aprb;
  417. amlpmre1 = __raw_readl(MXC_CRMAP_AMLPMRE1);
  418. aprb = __raw_readl(MXC_CRMAP_APRB);
  419. switch (clk->id) {
  420. case 0:
  421. amlpmre1 |= (0x7 << MXC_CRMAP_AMLPMRE1_MLPME4_OFFSET);
  422. aprb |= (0x1 << MXC_CRMAP_APRB_SDHC1EN_OFFSET);
  423. break;
  424. case 1:
  425. amlpmre1 |= (0x7 << MXC_CRMAP_AMLPMRE1_MLPME5_OFFSET);
  426. aprb |= (0x1 << MXC_CRMAP_APRB_SDHC2EN_OFFSET);
  427. break;
  428. }
  429. __raw_writel(amlpmre1, MXC_CRMAP_AMLPMRE1);
  430. __raw_writel(aprb, MXC_CRMAP_APRB);
  431. return 0;
  432. }
  433. static void clk_sdhc_disable(struct clk *clk)
  434. {
  435. u32 amlpmre1, aprb;
  436. amlpmre1 = __raw_readl(MXC_CRMAP_AMLPMRE1);
  437. aprb = __raw_readl(MXC_CRMAP_APRB);
  438. switch (clk->id) {
  439. case 0:
  440. amlpmre1 &= ~(0x7 << MXC_CRMAP_AMLPMRE1_MLPME4_OFFSET);
  441. aprb &= ~(0x1 << MXC_CRMAP_APRB_SDHC1EN_OFFSET);
  442. break;
  443. case 1:
  444. amlpmre1 &= ~(0x7 << MXC_CRMAP_AMLPMRE1_MLPME5_OFFSET);
  445. aprb &= ~(0x1 << MXC_CRMAP_APRB_SDHC2EN_OFFSET);
  446. break;
  447. }
  448. __raw_writel(amlpmre1, MXC_CRMAP_AMLPMRE1);
  449. __raw_writel(aprb, MXC_CRMAP_APRB);
  450. }
  451. static struct clk sdhc_clk[] = {
  452. {
  453. .id = 0,
  454. .get_rate = clk_sdhc_get_rate,
  455. .enable = clk_sdhc_enable,
  456. .disable = clk_sdhc_disable,
  457. }, {
  458. .id = 1,
  459. .get_rate = clk_sdhc_get_rate,
  460. .enable = clk_sdhc_enable,
  461. .disable = clk_sdhc_disable,
  462. },
  463. };
  464. /* sdhc_clk stuff end */
  465. /* wdog_clk stuff */
  466. static struct clk wdog_clk[] = {
  467. {
  468. .id = 0,
  469. .parent = &ipg_clk,
  470. .enable_reg = MXC_CRMAP_AMLPMRD,
  471. .enable_shift = MXC_CRMAP_AMLPMRD_MLPMD7_OFFSET,
  472. .enable = _clk_3bit_enable,
  473. .disable = _clk_3bit_disable,
  474. }, {
  475. .id = 1,
  476. .parent = &ipg_clk,
  477. .enable_reg = MXC_CRMAP_AMLPMRD,
  478. .enable_shift = MXC_CRMAP_AMLPMRD_MLPMD3_OFFSET,
  479. .enable = _clk_3bit_enable,
  480. .disable = _clk_3bit_disable,
  481. },
  482. };
  483. /* wdog_clk stuff end */
  484. /* gpt_clk stuff */
  485. static struct clk gpt_clk = {
  486. .parent = &ipg_clk,
  487. .enable_reg = MXC_CRMAP_AMLPMRC,
  488. .enable_shift = MXC_CRMAP_AMLPMRC_MLPMC4_OFFSET,
  489. .enable = _clk_3bit_enable,
  490. .disable = _clk_3bit_disable,
  491. };
  492. /* gpt_clk stuff end */
  493. /* cspi_clk stuff */
  494. static struct clk cspi_clk[] = {
  495. {
  496. .id = 0,
  497. .parent = &ipg_clk,
  498. .enable_reg = MXC_CRMAP_AMLPMRE2,
  499. .enable_shift = MXC_CRMAP_AMLPMRE2_MLPME0_OFFSET,
  500. .enable = _clk_3bit_enable,
  501. .disable = _clk_3bit_disable,
  502. }, {
  503. .id = 1,
  504. .parent = &ipg_clk,
  505. .enable_reg = MXC_CRMAP_AMLPMRE1,
  506. .enable_shift = MXC_CRMAP_AMLPMRE1_MLPME6_OFFSET,
  507. .enable = _clk_3bit_enable,
  508. .disable = _clk_3bit_disable,
  509. },
  510. };
  511. /* cspi_clk stuff end */
  512. #define _REGISTER_CLOCK(d, n, c) \
  513. { \
  514. .dev_id = d, \
  515. .con_id = n, \
  516. .clk = &c, \
  517. },
  518. static struct clk_lookup lookups[] = {
  519. _REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0])
  520. _REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[1])
  521. _REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[2])
  522. _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc_clk[0])
  523. _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc_clk[1])
  524. _REGISTER_CLOCK("mxc-wdt.0", NULL, wdog_clk[0])
  525. _REGISTER_CLOCK("spi_imx.0", NULL, cspi_clk[0])
  526. _REGISTER_CLOCK("spi_imx.1", NULL, cspi_clk[1])
  527. };
  528. int __init mxc91231_clocks_init(unsigned long fref)
  529. {
  530. void __iomem *gpt_base;
  531. int i;
  532. ckih_rate = fref;
  533. usb_clk.parent = clk_usb_parent(&usb_clk);
  534. sdhc_clk[0].parent = clk_sdhc_parent(&sdhc_clk[0]);
  535. sdhc_clk[1].parent = clk_sdhc_parent(&sdhc_clk[1]);
  536. for (i = 0; i < ARRAY_SIZE(lookups); i++)
  537. clkdev_add(&lookups[i]);
  538. gpt_base = MXC91231_IO_ADDRESS(MXC91231_GPT1_BASE_ADDR);
  539. mxc_timer_init(&gpt_clk, gpt_base, MXC91231_INT_GPT);
  540. return 0;
  541. }