clock.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. /*
  2. * Copyright (C) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. */
  18. #include <linux/kernel.h>
  19. #include <linux/init.h>
  20. #include <linux/math64.h>
  21. #include <linux/err.h>
  22. #include <linux/clk.h>
  23. #include <linux/io.h>
  24. #include <mach/clock.h>
  25. #include <mach/hardware.h>
  26. #include <mach/common.h>
  27. #include "crm_regs.h"
  28. static int _clk_enable(struct clk *clk)
  29. {
  30. unsigned int reg;
  31. reg = __raw_readl(clk->enable_reg);
  32. reg |= 1 << clk->enable_shift;
  33. __raw_writel(reg, clk->enable_reg);
  34. return 0;
  35. }
  36. static void _clk_disable(struct clk *clk)
  37. {
  38. unsigned int reg;
  39. reg = __raw_readl(clk->enable_reg);
  40. reg &= ~(1 << clk->enable_shift);
  41. __raw_writel(reg, clk->enable_reg);
  42. }
  43. static int _clk_can_use_parent(const struct clk *clk_arr[], unsigned int size,
  44. struct clk *parent)
  45. {
  46. int i;
  47. for (i = 0; i < size; i++)
  48. if (parent == clk_arr[i])
  49. return i;
  50. return -EINVAL;
  51. }
  52. static unsigned long
  53. _clk_simple_round_rate(struct clk *clk, unsigned long rate, unsigned int limit)
  54. {
  55. int div;
  56. unsigned long parent_rate;
  57. parent_rate = clk_get_rate(clk->parent);
  58. div = parent_rate / rate;
  59. if (parent_rate % rate)
  60. div++;
  61. if (div > limit)
  62. div = limit;
  63. return parent_rate / div;
  64. }
  65. static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
  66. {
  67. return clk->parent->round_rate(clk->parent, rate);
  68. }
  69. static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
  70. {
  71. return clk->parent->set_rate(clk->parent, rate);
  72. }
  73. static unsigned long clk16m_get_rate(struct clk *clk)
  74. {
  75. return 16000000;
  76. }
  77. static struct clk clk16m = {
  78. .name = "CLK16M",
  79. .get_rate = clk16m_get_rate,
  80. .enable = _clk_enable,
  81. .enable_reg = CCM_CSCR,
  82. .enable_shift = CCM_CSCR_OSC_EN_SHIFT,
  83. .disable = _clk_disable,
  84. };
  85. /* in Hz */
  86. static unsigned long clk32_rate;
  87. static unsigned long clk32_get_rate(struct clk *clk)
  88. {
  89. return clk32_rate;
  90. }
  91. static struct clk clk32 = {
  92. .name = "CLK32",
  93. .get_rate = clk32_get_rate,
  94. };
  95. static unsigned long clk32_premult_get_rate(struct clk *clk)
  96. {
  97. return clk_get_rate(clk->parent) * 512;
  98. }
  99. static struct clk clk32_premult = {
  100. .name = "CLK32_premultiplier",
  101. .parent = &clk32,
  102. .get_rate = clk32_premult_get_rate,
  103. };
  104. static const struct clk *prem_clk_clocks[] = {
  105. &clk32_premult,
  106. &clk16m,
  107. };
  108. static int prem_clk_set_parent(struct clk *clk, struct clk *parent)
  109. {
  110. int i;
  111. unsigned int reg = __raw_readl(CCM_CSCR);
  112. i = _clk_can_use_parent(prem_clk_clocks, ARRAY_SIZE(prem_clk_clocks),
  113. parent);
  114. switch (i) {
  115. case 0:
  116. reg &= ~CCM_CSCR_SYSTEM_SEL;
  117. break;
  118. case 1:
  119. reg |= CCM_CSCR_SYSTEM_SEL;
  120. break;
  121. default:
  122. return i;
  123. }
  124. __raw_writel(reg, CCM_CSCR);
  125. return 0;
  126. }
  127. static struct clk prem_clk = {
  128. .name = "prem_clk",
  129. .set_parent = prem_clk_set_parent,
  130. };
  131. static unsigned long system_clk_get_rate(struct clk *clk)
  132. {
  133. return mxc_decode_pll(__raw_readl(CCM_SPCTL0),
  134. clk_get_rate(clk->parent));
  135. }
  136. static struct clk system_clk = {
  137. .name = "system_clk",
  138. .parent = &prem_clk,
  139. .get_rate = system_clk_get_rate,
  140. };
  141. static unsigned long mcu_clk_get_rate(struct clk *clk)
  142. {
  143. return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
  144. clk_get_rate(clk->parent));
  145. }
  146. static struct clk mcu_clk = {
  147. .name = "mcu_clk",
  148. .parent = &clk32_premult,
  149. .get_rate = mcu_clk_get_rate,
  150. };
  151. static unsigned long fclk_get_rate(struct clk *clk)
  152. {
  153. unsigned long fclk = clk_get_rate(clk->parent);
  154. if (__raw_readl(CCM_CSCR) & CCM_CSCR_PRESC)
  155. fclk /= 2;
  156. return fclk;
  157. }
  158. static struct clk fclk = {
  159. .name = "fclk",
  160. .parent = &mcu_clk,
  161. .get_rate = fclk_get_rate,
  162. };
  163. /*
  164. * get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
  165. */
  166. static unsigned long hclk_get_rate(struct clk *clk)
  167. {
  168. return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) &
  169. CCM_CSCR_BCLK_MASK) >> CCM_CSCR_BCLK_OFFSET) + 1);
  170. }
  171. static unsigned long hclk_round_rate(struct clk *clk, unsigned long rate)
  172. {
  173. return _clk_simple_round_rate(clk, rate, 16);
  174. }
  175. static int hclk_set_rate(struct clk *clk, unsigned long rate)
  176. {
  177. unsigned int div;
  178. unsigned int reg;
  179. unsigned long parent_rate;
  180. parent_rate = clk_get_rate(clk->parent);
  181. div = parent_rate / rate;
  182. if (div > 16 || div < 1 || ((parent_rate / div) != rate))
  183. return -EINVAL;
  184. div--;
  185. reg = __raw_readl(CCM_CSCR);
  186. reg &= ~CCM_CSCR_BCLK_MASK;
  187. reg |= div << CCM_CSCR_BCLK_OFFSET;
  188. __raw_writel(reg, CCM_CSCR);
  189. return 0;
  190. }
  191. static struct clk hclk = {
  192. .name = "hclk",
  193. .parent = &system_clk,
  194. .get_rate = hclk_get_rate,
  195. .round_rate = hclk_round_rate,
  196. .set_rate = hclk_set_rate,
  197. };
  198. static unsigned long clk48m_get_rate(struct clk *clk)
  199. {
  200. return clk_get_rate(clk->parent) / (((__raw_readl(CCM_CSCR) &
  201. CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET) + 1);
  202. }
  203. static unsigned long clk48m_round_rate(struct clk *clk, unsigned long rate)
  204. {
  205. return _clk_simple_round_rate(clk, rate, 8);
  206. }
  207. static int clk48m_set_rate(struct clk *clk, unsigned long rate)
  208. {
  209. unsigned int div;
  210. unsigned int reg;
  211. unsigned long parent_rate;
  212. parent_rate = clk_get_rate(clk->parent);
  213. div = parent_rate / rate;
  214. if (div > 8 || div < 1 || ((parent_rate / div) != rate))
  215. return -EINVAL;
  216. div--;
  217. reg = __raw_readl(CCM_CSCR);
  218. reg &= ~CCM_CSCR_USB_MASK;
  219. reg |= div << CCM_CSCR_USB_OFFSET;
  220. __raw_writel(reg, CCM_CSCR);
  221. return 0;
  222. }
  223. static struct clk clk48m = {
  224. .name = "CLK48M",
  225. .parent = &system_clk,
  226. .get_rate = clk48m_get_rate,
  227. .round_rate = clk48m_round_rate,
  228. .set_rate = clk48m_set_rate,
  229. };
  230. /*
  231. * get peripheral clock 1 ( UART[12], Timer[12], PWM )
  232. */
  233. static unsigned long perclk1_get_rate(struct clk *clk)
  234. {
  235. return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
  236. CCM_PCDR_PCLK1_MASK) >> CCM_PCDR_PCLK1_OFFSET) + 1);
  237. }
  238. static unsigned long perclk1_round_rate(struct clk *clk, unsigned long rate)
  239. {
  240. return _clk_simple_round_rate(clk, rate, 16);
  241. }
  242. static int perclk1_set_rate(struct clk *clk, unsigned long rate)
  243. {
  244. unsigned int div;
  245. unsigned int reg;
  246. unsigned long parent_rate;
  247. parent_rate = clk_get_rate(clk->parent);
  248. div = parent_rate / rate;
  249. if (div > 16 || div < 1 || ((parent_rate / div) != rate))
  250. return -EINVAL;
  251. div--;
  252. reg = __raw_readl(CCM_PCDR);
  253. reg &= ~CCM_PCDR_PCLK1_MASK;
  254. reg |= div << CCM_PCDR_PCLK1_OFFSET;
  255. __raw_writel(reg, CCM_PCDR);
  256. return 0;
  257. }
  258. /*
  259. * get peripheral clock 2 ( LCD, SD, SPI[12] )
  260. */
  261. static unsigned long perclk2_get_rate(struct clk *clk)
  262. {
  263. return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
  264. CCM_PCDR_PCLK2_MASK) >> CCM_PCDR_PCLK2_OFFSET) + 1);
  265. }
  266. static unsigned long perclk2_round_rate(struct clk *clk, unsigned long rate)
  267. {
  268. return _clk_simple_round_rate(clk, rate, 16);
  269. }
  270. static int perclk2_set_rate(struct clk *clk, unsigned long rate)
  271. {
  272. unsigned int div;
  273. unsigned int reg;
  274. unsigned long parent_rate;
  275. parent_rate = clk_get_rate(clk->parent);
  276. div = parent_rate / rate;
  277. if (div > 16 || div < 1 || ((parent_rate / div) != rate))
  278. return -EINVAL;
  279. div--;
  280. reg = __raw_readl(CCM_PCDR);
  281. reg &= ~CCM_PCDR_PCLK2_MASK;
  282. reg |= div << CCM_PCDR_PCLK2_OFFSET;
  283. __raw_writel(reg, CCM_PCDR);
  284. return 0;
  285. }
  286. /*
  287. * get peripheral clock 3 ( SSI )
  288. */
  289. static unsigned long perclk3_get_rate(struct clk *clk)
  290. {
  291. return clk_get_rate(clk->parent) / (((__raw_readl(CCM_PCDR) &
  292. CCM_PCDR_PCLK3_MASK) >> CCM_PCDR_PCLK3_OFFSET) + 1);
  293. }
  294. static unsigned long perclk3_round_rate(struct clk *clk, unsigned long rate)
  295. {
  296. return _clk_simple_round_rate(clk, rate, 128);
  297. }
  298. static int perclk3_set_rate(struct clk *clk, unsigned long rate)
  299. {
  300. unsigned int div;
  301. unsigned int reg;
  302. unsigned long parent_rate;
  303. parent_rate = clk_get_rate(clk->parent);
  304. div = parent_rate / rate;
  305. if (div > 128 || div < 1 || ((parent_rate / div) != rate))
  306. return -EINVAL;
  307. div--;
  308. reg = __raw_readl(CCM_PCDR);
  309. reg &= ~CCM_PCDR_PCLK3_MASK;
  310. reg |= div << CCM_PCDR_PCLK3_OFFSET;
  311. __raw_writel(reg, CCM_PCDR);
  312. return 0;
  313. }
  314. static struct clk perclk[] = {
  315. {
  316. .name = "perclk",
  317. .id = 0,
  318. .parent = &system_clk,
  319. .get_rate = perclk1_get_rate,
  320. .round_rate = perclk1_round_rate,
  321. .set_rate = perclk1_set_rate,
  322. }, {
  323. .name = "perclk",
  324. .id = 1,
  325. .parent = &system_clk,
  326. .get_rate = perclk2_get_rate,
  327. .round_rate = perclk2_round_rate,
  328. .set_rate = perclk2_set_rate,
  329. }, {
  330. .name = "perclk",
  331. .id = 2,
  332. .parent = &system_clk,
  333. .get_rate = perclk3_get_rate,
  334. .round_rate = perclk3_round_rate,
  335. .set_rate = perclk3_set_rate,
  336. }
  337. };
  338. static const struct clk *clko_clocks[] = {
  339. &perclk[0],
  340. &hclk,
  341. &clk48m,
  342. &clk16m,
  343. &prem_clk,
  344. &fclk,
  345. };
  346. static int clko_set_parent(struct clk *clk, struct clk *parent)
  347. {
  348. int i;
  349. unsigned int reg;
  350. i = _clk_can_use_parent(clko_clocks, ARRAY_SIZE(clko_clocks), parent);
  351. if (i < 0)
  352. return i;
  353. reg = __raw_readl(CCM_CSCR) & ~CCM_CSCR_CLKO_MASK;
  354. reg |= i << CCM_CSCR_CLKO_OFFSET;
  355. __raw_writel(reg, CCM_CSCR);
  356. if (clko_clocks[i]->set_rate && clko_clocks[i]->round_rate) {
  357. clk->set_rate = _clk_parent_set_rate;
  358. clk->round_rate = _clk_parent_round_rate;
  359. } else {
  360. clk->set_rate = NULL;
  361. clk->round_rate = NULL;
  362. }
  363. return 0;
  364. }
  365. static struct clk clko_clk = {
  366. .name = "clko_clk",
  367. .set_parent = clko_set_parent,
  368. };
  369. static struct clk dma_clk = {
  370. .name = "dma",
  371. .parent = &hclk,
  372. .round_rate = _clk_parent_round_rate,
  373. .set_rate = _clk_parent_set_rate,
  374. .enable = _clk_enable,
  375. .enable_reg = SCM_GCCR,
  376. .enable_shift = SCM_GCCR_DMA_CLK_EN_OFFSET,
  377. .disable = _clk_disable,
  378. };
  379. static struct clk csi_clk = {
  380. .name = "csi_clk",
  381. .parent = &hclk,
  382. .round_rate = _clk_parent_round_rate,
  383. .set_rate = _clk_parent_set_rate,
  384. .enable = _clk_enable,
  385. .enable_reg = SCM_GCCR,
  386. .enable_shift = SCM_GCCR_CSI_CLK_EN_OFFSET,
  387. .disable = _clk_disable,
  388. };
  389. static struct clk mma_clk = {
  390. .name = "mma_clk",
  391. .parent = &hclk,
  392. .round_rate = _clk_parent_round_rate,
  393. .set_rate = _clk_parent_set_rate,
  394. .enable = _clk_enable,
  395. .enable_reg = SCM_GCCR,
  396. .enable_shift = SCM_GCCR_MMA_CLK_EN_OFFSET,
  397. .disable = _clk_disable,
  398. };
  399. static struct clk usbd_clk = {
  400. .name = "usbd_clk",
  401. .parent = &clk48m,
  402. .round_rate = _clk_parent_round_rate,
  403. .set_rate = _clk_parent_set_rate,
  404. .enable = _clk_enable,
  405. .enable_reg = SCM_GCCR,
  406. .enable_shift = SCM_GCCR_USBD_CLK_EN_OFFSET,
  407. .disable = _clk_disable,
  408. };
  409. static struct clk gpt_clk = {
  410. .name = "gpt_clk",
  411. .parent = &perclk[0],
  412. .round_rate = _clk_parent_round_rate,
  413. .set_rate = _clk_parent_set_rate,
  414. };
  415. static struct clk uart_clk = {
  416. .name = "uart",
  417. .parent = &perclk[0],
  418. .round_rate = _clk_parent_round_rate,
  419. .set_rate = _clk_parent_set_rate,
  420. };
  421. static struct clk i2c_clk = {
  422. .name = "i2c_clk",
  423. .parent = &hclk,
  424. .round_rate = _clk_parent_round_rate,
  425. .set_rate = _clk_parent_set_rate,
  426. };
  427. static struct clk spi_clk = {
  428. .name = "spi_clk",
  429. .parent = &perclk[1],
  430. .round_rate = _clk_parent_round_rate,
  431. .set_rate = _clk_parent_set_rate,
  432. };
  433. static struct clk sdhc_clk = {
  434. .name = "sdhc_clk",
  435. .parent = &perclk[1],
  436. .round_rate = _clk_parent_round_rate,
  437. .set_rate = _clk_parent_set_rate,
  438. };
  439. static struct clk lcdc_clk = {
  440. .name = "lcdc_clk",
  441. .parent = &perclk[1],
  442. .round_rate = _clk_parent_round_rate,
  443. .set_rate = _clk_parent_set_rate,
  444. };
  445. static struct clk mshc_clk = {
  446. .name = "mshc_clk",
  447. .parent = &hclk,
  448. .round_rate = _clk_parent_round_rate,
  449. .set_rate = _clk_parent_set_rate,
  450. };
  451. static struct clk ssi_clk = {
  452. .name = "ssi_clk",
  453. .parent = &perclk[2],
  454. .round_rate = _clk_parent_round_rate,
  455. .set_rate = _clk_parent_set_rate,
  456. };
  457. static struct clk rtc_clk = {
  458. .name = "rtc_clk",
  459. .parent = &clk32,
  460. };
  461. static struct clk *mxc_clks[] = {
  462. &clk16m,
  463. &clk32,
  464. &clk32_premult,
  465. &prem_clk,
  466. &system_clk,
  467. &mcu_clk,
  468. &fclk,
  469. &hclk,
  470. &clk48m,
  471. &perclk[0],
  472. &perclk[1],
  473. &perclk[2],
  474. &clko_clk,
  475. &dma_clk,
  476. &csi_clk,
  477. &mma_clk,
  478. &usbd_clk,
  479. &gpt_clk,
  480. &uart_clk,
  481. &i2c_clk,
  482. &spi_clk,
  483. &sdhc_clk,
  484. &lcdc_clk,
  485. &mshc_clk,
  486. &ssi_clk,
  487. &rtc_clk,
  488. };
  489. int __init mx1_clocks_init(unsigned long fref)
  490. {
  491. struct clk **clkp;
  492. unsigned int reg;
  493. /* disable clocks we are able to */
  494. __raw_writel(0, SCM_GCCR);
  495. clk32_rate = fref;
  496. reg = __raw_readl(CCM_CSCR);
  497. /* detect clock reference for system PLL */
  498. if (reg & CCM_CSCR_SYSTEM_SEL) {
  499. prem_clk.parent = &clk16m;
  500. } else {
  501. /* ensure that oscillator is disabled */
  502. reg &= ~(1 << CCM_CSCR_OSC_EN_SHIFT);
  503. __raw_writel(reg, CCM_CSCR);
  504. prem_clk.parent = &clk32_premult;
  505. }
  506. /* detect reference for CLKO */
  507. reg = (reg & CCM_CSCR_CLKO_MASK) >> CCM_CSCR_CLKO_OFFSET;
  508. clko_clk.parent = (struct clk *)clko_clocks[reg];
  509. for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
  510. clk_register(*clkp);
  511. clk_enable(&hclk);
  512. clk_enable(&fclk);
  513. mxc_timer_init(&gpt_clk);
  514. return 0;
  515. }