clock.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131
  1. /*
  2. * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
  3. * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation; either version 2
  8. * of the License, or (at your option) any later version.
  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., 51 Franklin Street, Fifth Floor, Boston,
  17. * MA 02110-1301, USA.
  18. */
  19. #include <linux/module.h>
  20. #include <linux/spinlock.h>
  21. #include <linux/delay.h>
  22. #include <linux/clk.h>
  23. #include <linux/err.h>
  24. #include <linux/io.h>
  25. #include <mach/clock.h>
  26. #include <mach/hardware.h>
  27. #include <mach/common.h>
  28. #include <asm/div64.h>
  29. #include "crm_regs.h"
  30. #define PRE_DIV_MIN_FREQ 10000000 /* Minimum Frequency after Predivider */
  31. static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
  32. {
  33. u32 min_pre, temp_pre, old_err, err;
  34. if (div >= 512) {
  35. *pre = 8;
  36. *post = 64;
  37. } else if (div >= 64) {
  38. min_pre = (div - 1) / 64 + 1;
  39. old_err = 8;
  40. for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
  41. err = div % temp_pre;
  42. if (err == 0) {
  43. *pre = temp_pre;
  44. break;
  45. }
  46. err = temp_pre - err;
  47. if (err < old_err) {
  48. old_err = err;
  49. *pre = temp_pre;
  50. }
  51. }
  52. *post = (div + *pre - 1) / *pre;
  53. } else if (div <= 8) {
  54. *pre = div;
  55. *post = 1;
  56. } else {
  57. *pre = 1;
  58. *post = div;
  59. }
  60. }
  61. static struct clk mcu_pll_clk;
  62. static struct clk mcu_main_clk;
  63. static struct clk usb_pll_clk;
  64. static struct clk serial_pll_clk;
  65. static struct clk ipg_clk;
  66. static struct clk ckih_clk;
  67. static struct clk ahb_clk;
  68. static int _clk_enable(struct clk *clk)
  69. {
  70. u32 reg;
  71. reg = __raw_readl(clk->enable_reg);
  72. reg |= 3 << clk->enable_shift;
  73. __raw_writel(reg, clk->enable_reg);
  74. return 0;
  75. }
  76. static void _clk_disable(struct clk *clk)
  77. {
  78. u32 reg;
  79. reg = __raw_readl(clk->enable_reg);
  80. reg &= ~(3 << clk->enable_shift);
  81. __raw_writel(reg, clk->enable_reg);
  82. }
  83. static void _clk_emi_disable(struct clk *clk)
  84. {
  85. u32 reg;
  86. reg = __raw_readl(clk->enable_reg);
  87. reg &= ~(3 << clk->enable_shift);
  88. reg |= (1 << clk->enable_shift);
  89. __raw_writel(reg, clk->enable_reg);
  90. }
  91. static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
  92. {
  93. u32 reg;
  94. signed long pd = 1; /* Pre-divider */
  95. signed long mfi; /* Multiplication Factor (Integer part) */
  96. signed long mfn; /* Multiplication Factor (Integer part) */
  97. signed long mfd; /* Multiplication Factor (Denominator Part) */
  98. signed long tmp;
  99. u32 ref_freq = clk_get_rate(clk->parent);
  100. while (((ref_freq / pd) * 10) > rate)
  101. pd++;
  102. if ((ref_freq / pd) < PRE_DIV_MIN_FREQ)
  103. return -EINVAL;
  104. /* the ref_freq/2 in the following is to round up */
  105. mfi = (((rate / 2) * pd) + (ref_freq / 2)) / ref_freq;
  106. if (mfi < 5 || mfi > 15)
  107. return -EINVAL;
  108. /* pick a mfd value that will work
  109. * then solve for mfn */
  110. mfd = ref_freq / 50000;
  111. /*
  112. * pll_freq * pd * mfd
  113. * mfn = -------------------- - (mfi * mfd)
  114. * 2 * ref_freq
  115. */
  116. /* the tmp/2 is for rounding */
  117. tmp = ref_freq / 10000;
  118. mfn =
  119. ((((((rate / 2) + (tmp / 2)) / tmp) * pd) * mfd) / 10000) -
  120. (mfi * mfd);
  121. mfn = mfn & 0x3ff;
  122. pd--;
  123. mfd--;
  124. /* Change the Pll value */
  125. reg = (mfi << MXC_CCM_PCTL_MFI_OFFSET) |
  126. (mfn << MXC_CCM_PCTL_MFN_OFFSET) |
  127. (mfd << MXC_CCM_PCTL_MFD_OFFSET) | (pd << MXC_CCM_PCTL_PD_OFFSET);
  128. if (clk == &mcu_pll_clk)
  129. __raw_writel(reg, MXC_CCM_MPCTL);
  130. else if (clk == &usb_pll_clk)
  131. __raw_writel(reg, MXC_CCM_UPCTL);
  132. else if (clk == &serial_pll_clk)
  133. __raw_writel(reg, MXC_CCM_SRPCTL);
  134. return 0;
  135. }
  136. static unsigned long _clk_pll_get_rate(struct clk *clk)
  137. {
  138. unsigned long reg, ccmr;
  139. unsigned int prcs, ref_clk;
  140. ccmr = __raw_readl(MXC_CCM_CCMR);
  141. prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET;
  142. if (prcs == 0x1)
  143. ref_clk = CKIL_CLK_FREQ * 1024;
  144. else
  145. ref_clk = clk_get_rate(&ckih_clk);
  146. if (clk == &mcu_pll_clk) {
  147. if ((ccmr & MXC_CCM_CCMR_MPE) == 0)
  148. return ref_clk;
  149. if ((ccmr & MXC_CCM_CCMR_MDS) != 0)
  150. return ref_clk;
  151. reg = __raw_readl(MXC_CCM_MPCTL);
  152. } else if (clk == &usb_pll_clk)
  153. reg = __raw_readl(MXC_CCM_UPCTL);
  154. else if (clk == &serial_pll_clk)
  155. reg = __raw_readl(MXC_CCM_SRPCTL);
  156. else {
  157. BUG();
  158. return 0;
  159. }
  160. return mxc_decode_pll(reg, ref_clk);
  161. }
  162. static int _clk_usb_pll_enable(struct clk *clk)
  163. {
  164. u32 reg;
  165. reg = __raw_readl(MXC_CCM_CCMR);
  166. reg |= MXC_CCM_CCMR_UPE;
  167. __raw_writel(reg, MXC_CCM_CCMR);
  168. /* No lock bit on MX31, so using max time from spec */
  169. udelay(80);
  170. return 0;
  171. }
  172. static void _clk_usb_pll_disable(struct clk *clk)
  173. {
  174. u32 reg;
  175. reg = __raw_readl(MXC_CCM_CCMR);
  176. reg &= ~MXC_CCM_CCMR_UPE;
  177. __raw_writel(reg, MXC_CCM_CCMR);
  178. }
  179. static int _clk_serial_pll_enable(struct clk *clk)
  180. {
  181. u32 reg;
  182. reg = __raw_readl(MXC_CCM_CCMR);
  183. reg |= MXC_CCM_CCMR_SPE;
  184. __raw_writel(reg, MXC_CCM_CCMR);
  185. /* No lock bit on MX31, so using max time from spec */
  186. udelay(80);
  187. return 0;
  188. }
  189. static void _clk_serial_pll_disable(struct clk *clk)
  190. {
  191. u32 reg;
  192. reg = __raw_readl(MXC_CCM_CCMR);
  193. reg &= ~MXC_CCM_CCMR_SPE;
  194. __raw_writel(reg, MXC_CCM_CCMR);
  195. }
  196. #define PDR0(mask, off) ((__raw_readl(MXC_CCM_PDR0) & mask) >> off)
  197. #define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off)
  198. #define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off)
  199. static unsigned long _clk_mcu_main_get_rate(struct clk *clk)
  200. {
  201. u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0);
  202. if ((pmcr0 & MXC_CCM_PMCR0_DFSUP1) == MXC_CCM_PMCR0_DFSUP1_SPLL)
  203. return clk_get_rate(&serial_pll_clk);
  204. else
  205. return clk_get_rate(&mcu_pll_clk);
  206. }
  207. static unsigned long _clk_hclk_get_rate(struct clk *clk)
  208. {
  209. unsigned long max_pdf;
  210. max_pdf = PDR0(MXC_CCM_PDR0_MAX_PODF_MASK,
  211. MXC_CCM_PDR0_MAX_PODF_OFFSET);
  212. return clk_get_rate(clk->parent) / (max_pdf + 1);
  213. }
  214. static unsigned long _clk_ipg_get_rate(struct clk *clk)
  215. {
  216. unsigned long ipg_pdf;
  217. ipg_pdf = PDR0(MXC_CCM_PDR0_IPG_PODF_MASK,
  218. MXC_CCM_PDR0_IPG_PODF_OFFSET);
  219. return clk_get_rate(clk->parent) / (ipg_pdf + 1);
  220. }
  221. static unsigned long _clk_nfc_get_rate(struct clk *clk)
  222. {
  223. unsigned long nfc_pdf;
  224. nfc_pdf = PDR0(MXC_CCM_PDR0_NFC_PODF_MASK,
  225. MXC_CCM_PDR0_NFC_PODF_OFFSET);
  226. return clk_get_rate(clk->parent) / (nfc_pdf + 1);
  227. }
  228. static unsigned long _clk_hsp_get_rate(struct clk *clk)
  229. {
  230. unsigned long hsp_pdf;
  231. hsp_pdf = PDR0(MXC_CCM_PDR0_HSP_PODF_MASK,
  232. MXC_CCM_PDR0_HSP_PODF_OFFSET);
  233. return clk_get_rate(clk->parent) / (hsp_pdf + 1);
  234. }
  235. static unsigned long _clk_usb_get_rate(struct clk *clk)
  236. {
  237. unsigned long usb_pdf, usb_prepdf;
  238. usb_pdf = PDR1(MXC_CCM_PDR1_USB_PODF_MASK,
  239. MXC_CCM_PDR1_USB_PODF_OFFSET);
  240. usb_prepdf = PDR1(MXC_CCM_PDR1_USB_PRDF_MASK,
  241. MXC_CCM_PDR1_USB_PRDF_OFFSET);
  242. return clk_get_rate(clk->parent) / (usb_prepdf + 1) / (usb_pdf + 1);
  243. }
  244. static unsigned long _clk_csi_get_rate(struct clk *clk)
  245. {
  246. u32 reg, pre, post;
  247. reg = __raw_readl(MXC_CCM_PDR0);
  248. pre = (reg & MXC_CCM_PDR0_CSI_PRDF_MASK) >>
  249. MXC_CCM_PDR0_CSI_PRDF_OFFSET;
  250. pre++;
  251. post = (reg & MXC_CCM_PDR0_CSI_PODF_MASK) >>
  252. MXC_CCM_PDR0_CSI_PODF_OFFSET;
  253. post++;
  254. return clk_get_rate(clk->parent) / (pre * post);
  255. }
  256. static unsigned long _clk_csi_round_rate(struct clk *clk, unsigned long rate)
  257. {
  258. u32 pre, post, parent = clk_get_rate(clk->parent);
  259. u32 div = parent / rate;
  260. if (parent % rate)
  261. div++;
  262. __calc_pre_post_dividers(div, &pre, &post);
  263. return parent / (pre * post);
  264. }
  265. static int _clk_csi_set_rate(struct clk *clk, unsigned long rate)
  266. {
  267. u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
  268. div = parent / rate;
  269. if ((parent / div) != rate)
  270. return -EINVAL;
  271. __calc_pre_post_dividers(div, &pre, &post);
  272. /* Set CSI clock divider */
  273. reg = __raw_readl(MXC_CCM_PDR0) &
  274. ~(MXC_CCM_PDR0_CSI_PODF_MASK | MXC_CCM_PDR0_CSI_PRDF_MASK);
  275. reg |= (post - 1) << MXC_CCM_PDR0_CSI_PODF_OFFSET;
  276. reg |= (pre - 1) << MXC_CCM_PDR0_CSI_PRDF_OFFSET;
  277. __raw_writel(reg, MXC_CCM_PDR0);
  278. return 0;
  279. }
  280. static unsigned long _clk_per_get_rate(struct clk *clk)
  281. {
  282. unsigned long per_pdf;
  283. per_pdf = PDR0(MXC_CCM_PDR0_PER_PODF_MASK,
  284. MXC_CCM_PDR0_PER_PODF_OFFSET);
  285. return clk_get_rate(clk->parent) / (per_pdf + 1);
  286. }
  287. static unsigned long _clk_ssi1_get_rate(struct clk *clk)
  288. {
  289. unsigned long ssi1_pdf, ssi1_prepdf;
  290. ssi1_pdf = PDR1(MXC_CCM_PDR1_SSI1_PODF_MASK,
  291. MXC_CCM_PDR1_SSI1_PODF_OFFSET);
  292. ssi1_prepdf = PDR1(MXC_CCM_PDR1_SSI1_PRE_PODF_MASK,
  293. MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET);
  294. return clk_get_rate(clk->parent) / (ssi1_prepdf + 1) / (ssi1_pdf + 1);
  295. }
  296. static unsigned long _clk_ssi2_get_rate(struct clk *clk)
  297. {
  298. unsigned long ssi2_pdf, ssi2_prepdf;
  299. ssi2_pdf = PDR1(MXC_CCM_PDR1_SSI2_PODF_MASK,
  300. MXC_CCM_PDR1_SSI2_PODF_OFFSET);
  301. ssi2_prepdf = PDR1(MXC_CCM_PDR1_SSI2_PRE_PODF_MASK,
  302. MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET);
  303. return clk_get_rate(clk->parent) / (ssi2_prepdf + 1) / (ssi2_pdf + 1);
  304. }
  305. static unsigned long _clk_firi_get_rate(struct clk *clk)
  306. {
  307. unsigned long firi_pdf, firi_prepdf;
  308. firi_pdf = PDR1(MXC_CCM_PDR1_FIRI_PODF_MASK,
  309. MXC_CCM_PDR1_FIRI_PODF_OFFSET);
  310. firi_prepdf = PDR1(MXC_CCM_PDR1_FIRI_PRE_PODF_MASK,
  311. MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET);
  312. return clk_get_rate(clk->parent) / (firi_prepdf + 1) / (firi_pdf + 1);
  313. }
  314. static unsigned long _clk_firi_round_rate(struct clk *clk, unsigned long rate)
  315. {
  316. u32 pre, post;
  317. u32 parent = clk_get_rate(clk->parent);
  318. u32 div = parent / rate;
  319. if (parent % rate)
  320. div++;
  321. __calc_pre_post_dividers(div, &pre, &post);
  322. return parent / (pre * post);
  323. }
  324. static int _clk_firi_set_rate(struct clk *clk, unsigned long rate)
  325. {
  326. u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
  327. div = parent / rate;
  328. if ((parent / div) != rate)
  329. return -EINVAL;
  330. __calc_pre_post_dividers(div, &pre, &post);
  331. /* Set FIRI clock divider */
  332. reg = __raw_readl(MXC_CCM_PDR1) &
  333. ~(MXC_CCM_PDR1_FIRI_PODF_MASK | MXC_CCM_PDR1_FIRI_PRE_PODF_MASK);
  334. reg |= (pre - 1) << MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET;
  335. reg |= (post - 1) << MXC_CCM_PDR1_FIRI_PODF_OFFSET;
  336. __raw_writel(reg, MXC_CCM_PDR1);
  337. return 0;
  338. }
  339. static unsigned long _clk_mbx_get_rate(struct clk *clk)
  340. {
  341. return clk_get_rate(clk->parent) / 2;
  342. }
  343. static unsigned long _clk_mstick1_get_rate(struct clk *clk)
  344. {
  345. unsigned long msti_pdf;
  346. msti_pdf = PDR2(MXC_CCM_PDR2_MST1_PDF_MASK,
  347. MXC_CCM_PDR2_MST1_PDF_OFFSET);
  348. return clk_get_rate(clk->parent) / (msti_pdf + 1);
  349. }
  350. static unsigned long _clk_mstick2_get_rate(struct clk *clk)
  351. {
  352. unsigned long msti_pdf;
  353. msti_pdf = PDR2(MXC_CCM_PDR2_MST2_PDF_MASK,
  354. MXC_CCM_PDR2_MST2_PDF_OFFSET);
  355. return clk_get_rate(clk->parent) / (msti_pdf + 1);
  356. }
  357. static unsigned long ckih_rate;
  358. static unsigned long clk_ckih_get_rate(struct clk *clk)
  359. {
  360. return ckih_rate;
  361. }
  362. static struct clk ckih_clk = {
  363. .name = "ckih",
  364. .get_rate = clk_ckih_get_rate,
  365. };
  366. static unsigned long clk_ckil_get_rate(struct clk *clk)
  367. {
  368. return CKIL_CLK_FREQ;
  369. }
  370. static struct clk ckil_clk = {
  371. .name = "ckil",
  372. .get_rate = clk_ckil_get_rate,
  373. };
  374. static struct clk mcu_pll_clk = {
  375. .name = "mcu_pll",
  376. .parent = &ckih_clk,
  377. .set_rate = _clk_pll_set_rate,
  378. .get_rate = _clk_pll_get_rate,
  379. };
  380. static struct clk mcu_main_clk = {
  381. .name = "mcu_main_clk",
  382. .parent = &mcu_pll_clk,
  383. .get_rate = _clk_mcu_main_get_rate,
  384. };
  385. static struct clk serial_pll_clk = {
  386. .name = "serial_pll",
  387. .parent = &ckih_clk,
  388. .set_rate = _clk_pll_set_rate,
  389. .get_rate = _clk_pll_get_rate,
  390. .enable = _clk_serial_pll_enable,
  391. .disable = _clk_serial_pll_disable,
  392. };
  393. static struct clk usb_pll_clk = {
  394. .name = "usb_pll",
  395. .parent = &ckih_clk,
  396. .set_rate = _clk_pll_set_rate,
  397. .get_rate = _clk_pll_get_rate,
  398. .enable = _clk_usb_pll_enable,
  399. .disable = _clk_usb_pll_disable,
  400. };
  401. static struct clk ahb_clk = {
  402. .name = "ahb_clk",
  403. .parent = &mcu_main_clk,
  404. .get_rate = _clk_hclk_get_rate,
  405. };
  406. static struct clk per_clk = {
  407. .name = "per_clk",
  408. .parent = &usb_pll_clk,
  409. .get_rate = _clk_per_get_rate,
  410. };
  411. static struct clk perclk_clk = {
  412. .name = "perclk_clk",
  413. .parent = &ipg_clk,
  414. };
  415. static struct clk cspi_clk[] = {
  416. {
  417. .name = "cspi_clk",
  418. .id = 0,
  419. .parent = &ipg_clk,
  420. .enable = _clk_enable,
  421. .enable_reg = MXC_CCM_CGR2,
  422. .enable_shift = MXC_CCM_CGR2_CSPI1_OFFSET,
  423. .disable = _clk_disable,},
  424. {
  425. .name = "cspi_clk",
  426. .id = 1,
  427. .parent = &ipg_clk,
  428. .enable = _clk_enable,
  429. .enable_reg = MXC_CCM_CGR2,
  430. .enable_shift = MXC_CCM_CGR2_CSPI2_OFFSET,
  431. .disable = _clk_disable,},
  432. {
  433. .name = "cspi_clk",
  434. .id = 2,
  435. .parent = &ipg_clk,
  436. .enable = _clk_enable,
  437. .enable_reg = MXC_CCM_CGR0,
  438. .enable_shift = MXC_CCM_CGR0_CSPI3_OFFSET,
  439. .disable = _clk_disable,},
  440. };
  441. static struct clk ipg_clk = {
  442. .name = "ipg_clk",
  443. .parent = &ahb_clk,
  444. .get_rate = _clk_ipg_get_rate,
  445. };
  446. static struct clk emi_clk = {
  447. .name = "emi_clk",
  448. .parent = &ahb_clk,
  449. .enable = _clk_enable,
  450. .enable_reg = MXC_CCM_CGR2,
  451. .enable_shift = MXC_CCM_CGR2_EMI_OFFSET,
  452. .disable = _clk_emi_disable,
  453. };
  454. static struct clk gpt_clk = {
  455. .name = "gpt_clk",
  456. .parent = &perclk_clk,
  457. .enable = _clk_enable,
  458. .enable_reg = MXC_CCM_CGR0,
  459. .enable_shift = MXC_CCM_CGR0_GPT_OFFSET,
  460. .disable = _clk_disable,
  461. };
  462. static struct clk pwm_clk = {
  463. .name = "pwm_clk",
  464. .parent = &perclk_clk,
  465. .enable = _clk_enable,
  466. .enable_reg = MXC_CCM_CGR0,
  467. .enable_shift = MXC_CCM_CGR1_PWM_OFFSET,
  468. .disable = _clk_disable,
  469. };
  470. static struct clk epit_clk[] = {
  471. {
  472. .name = "epit_clk",
  473. .id = 0,
  474. .parent = &perclk_clk,
  475. .enable = _clk_enable,
  476. .enable_reg = MXC_CCM_CGR0,
  477. .enable_shift = MXC_CCM_CGR0_EPIT1_OFFSET,
  478. .disable = _clk_disable,},
  479. {
  480. .name = "epit_clk",
  481. .id = 1,
  482. .parent = &perclk_clk,
  483. .enable = _clk_enable,
  484. .enable_reg = MXC_CCM_CGR0,
  485. .enable_shift = MXC_CCM_CGR0_EPIT2_OFFSET,
  486. .disable = _clk_disable,},
  487. };
  488. static struct clk nfc_clk = {
  489. .name = "nfc",
  490. .parent = &ahb_clk,
  491. .get_rate = _clk_nfc_get_rate,
  492. };
  493. static struct clk scc_clk = {
  494. .name = "scc_clk",
  495. .parent = &ipg_clk,
  496. };
  497. static struct clk ipu_clk = {
  498. .name = "ipu_clk",
  499. .parent = &mcu_main_clk,
  500. .get_rate = _clk_hsp_get_rate,
  501. .enable = _clk_enable,
  502. .enable_reg = MXC_CCM_CGR1,
  503. .enable_shift = MXC_CCM_CGR1_IPU_OFFSET,
  504. .disable = _clk_disable,
  505. };
  506. static struct clk kpp_clk = {
  507. .name = "kpp_clk",
  508. .parent = &ipg_clk,
  509. .enable = _clk_enable,
  510. .enable_reg = MXC_CCM_CGR1,
  511. .enable_shift = MXC_CCM_CGR1_KPP_OFFSET,
  512. .disable = _clk_disable,
  513. };
  514. static struct clk wdog_clk = {
  515. .name = "wdog_clk",
  516. .parent = &ipg_clk,
  517. .enable = _clk_enable,
  518. .enable_reg = MXC_CCM_CGR1,
  519. .enable_shift = MXC_CCM_CGR1_WDOG_OFFSET,
  520. .disable = _clk_disable,
  521. };
  522. static struct clk rtc_clk = {
  523. .name = "rtc_clk",
  524. .parent = &ipg_clk,
  525. .enable = _clk_enable,
  526. .enable_reg = MXC_CCM_CGR1,
  527. .enable_shift = MXC_CCM_CGR1_RTC_OFFSET,
  528. .disable = _clk_disable,
  529. };
  530. static struct clk usb_clk[] = {
  531. {
  532. .name = "usb_clk",
  533. .parent = &usb_pll_clk,
  534. .get_rate = _clk_usb_get_rate,},
  535. {
  536. .name = "usb_ahb_clk",
  537. .parent = &ahb_clk,
  538. .enable = _clk_enable,
  539. .enable_reg = MXC_CCM_CGR1,
  540. .enable_shift = MXC_CCM_CGR1_USBOTG_OFFSET,
  541. .disable = _clk_disable,},
  542. };
  543. static struct clk csi_clk = {
  544. .name = "csi_clk",
  545. .parent = &serial_pll_clk,
  546. .get_rate = _clk_csi_get_rate,
  547. .round_rate = _clk_csi_round_rate,
  548. .set_rate = _clk_csi_set_rate,
  549. .enable = _clk_enable,
  550. .enable_reg = MXC_CCM_CGR1,
  551. .enable_shift = MXC_CCM_CGR1_CSI_OFFSET,
  552. .disable = _clk_disable,
  553. };
  554. static struct clk uart_clk[] = {
  555. {
  556. .name = "uart",
  557. .id = 0,
  558. .parent = &perclk_clk,
  559. .enable = _clk_enable,
  560. .enable_reg = MXC_CCM_CGR0,
  561. .enable_shift = MXC_CCM_CGR0_UART1_OFFSET,
  562. .disable = _clk_disable,},
  563. {
  564. .name = "uart",
  565. .id = 1,
  566. .parent = &perclk_clk,
  567. .enable = _clk_enable,
  568. .enable_reg = MXC_CCM_CGR0,
  569. .enable_shift = MXC_CCM_CGR0_UART2_OFFSET,
  570. .disable = _clk_disable,},
  571. {
  572. .name = "uart",
  573. .id = 2,
  574. .parent = &perclk_clk,
  575. .enable = _clk_enable,
  576. .enable_reg = MXC_CCM_CGR1,
  577. .enable_shift = MXC_CCM_CGR1_UART3_OFFSET,
  578. .disable = _clk_disable,},
  579. {
  580. .name = "uart",
  581. .id = 3,
  582. .parent = &perclk_clk,
  583. .enable = _clk_enable,
  584. .enable_reg = MXC_CCM_CGR1,
  585. .enable_shift = MXC_CCM_CGR1_UART4_OFFSET,
  586. .disable = _clk_disable,},
  587. {
  588. .name = "uart",
  589. .id = 4,
  590. .parent = &perclk_clk,
  591. .enable = _clk_enable,
  592. .enable_reg = MXC_CCM_CGR1,
  593. .enable_shift = MXC_CCM_CGR1_UART5_OFFSET,
  594. .disable = _clk_disable,},
  595. };
  596. static struct clk i2c_clk[] = {
  597. {
  598. .name = "i2c_clk",
  599. .id = 0,
  600. .parent = &perclk_clk,
  601. .enable = _clk_enable,
  602. .enable_reg = MXC_CCM_CGR0,
  603. .enable_shift = MXC_CCM_CGR0_I2C1_OFFSET,
  604. .disable = _clk_disable,},
  605. {
  606. .name = "i2c_clk",
  607. .id = 1,
  608. .parent = &perclk_clk,
  609. .enable = _clk_enable,
  610. .enable_reg = MXC_CCM_CGR0,
  611. .enable_shift = MXC_CCM_CGR0_I2C2_OFFSET,
  612. .disable = _clk_disable,},
  613. {
  614. .name = "i2c_clk",
  615. .id = 2,
  616. .parent = &perclk_clk,
  617. .enable = _clk_enable,
  618. .enable_reg = MXC_CCM_CGR0,
  619. .enable_shift = MXC_CCM_CGR0_I2C3_OFFSET,
  620. .disable = _clk_disable,},
  621. };
  622. static struct clk owire_clk = {
  623. .name = "owire",
  624. .parent = &perclk_clk,
  625. .enable_reg = MXC_CCM_CGR1,
  626. .enable_shift = MXC_CCM_CGR1_OWIRE_OFFSET,
  627. .enable = _clk_enable,
  628. .disable = _clk_disable,
  629. };
  630. static struct clk sdhc_clk[] = {
  631. {
  632. .name = "sdhc_clk",
  633. .id = 0,
  634. .parent = &perclk_clk,
  635. .enable = _clk_enable,
  636. .enable_reg = MXC_CCM_CGR0,
  637. .enable_shift = MXC_CCM_CGR0_SD_MMC1_OFFSET,
  638. .disable = _clk_disable,},
  639. {
  640. .name = "sdhc_clk",
  641. .id = 1,
  642. .parent = &perclk_clk,
  643. .enable = _clk_enable,
  644. .enable_reg = MXC_CCM_CGR0,
  645. .enable_shift = MXC_CCM_CGR0_SD_MMC2_OFFSET,
  646. .disable = _clk_disable,},
  647. };
  648. static struct clk ssi_clk[] = {
  649. {
  650. .name = "ssi_clk",
  651. .parent = &serial_pll_clk,
  652. .get_rate = _clk_ssi1_get_rate,
  653. .enable = _clk_enable,
  654. .enable_reg = MXC_CCM_CGR0,
  655. .enable_shift = MXC_CCM_CGR0_SSI1_OFFSET,
  656. .disable = _clk_disable,},
  657. {
  658. .name = "ssi_clk",
  659. .id = 1,
  660. .parent = &serial_pll_clk,
  661. .get_rate = _clk_ssi2_get_rate,
  662. .enable = _clk_enable,
  663. .enable_reg = MXC_CCM_CGR2,
  664. .enable_shift = MXC_CCM_CGR2_SSI2_OFFSET,
  665. .disable = _clk_disable,},
  666. };
  667. static struct clk firi_clk = {
  668. .name = "firi_clk",
  669. .parent = &usb_pll_clk,
  670. .round_rate = _clk_firi_round_rate,
  671. .set_rate = _clk_firi_set_rate,
  672. .get_rate = _clk_firi_get_rate,
  673. .enable = _clk_enable,
  674. .enable_reg = MXC_CCM_CGR2,
  675. .enable_shift = MXC_CCM_CGR2_FIRI_OFFSET,
  676. .disable = _clk_disable,
  677. };
  678. static struct clk ata_clk = {
  679. .name = "ata_clk",
  680. .parent = &ipg_clk,
  681. .enable = _clk_enable,
  682. .enable_reg = MXC_CCM_CGR0,
  683. .enable_shift = MXC_CCM_CGR0_ATA_OFFSET,
  684. .disable = _clk_disable,
  685. };
  686. static struct clk mbx_clk = {
  687. .name = "mbx_clk",
  688. .parent = &ahb_clk,
  689. .enable = _clk_enable,
  690. .enable_reg = MXC_CCM_CGR2,
  691. .enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
  692. .get_rate = _clk_mbx_get_rate,
  693. };
  694. static struct clk vpu_clk = {
  695. .name = "vpu_clk",
  696. .parent = &ahb_clk,
  697. .enable = _clk_enable,
  698. .enable_reg = MXC_CCM_CGR2,
  699. .enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
  700. .get_rate = _clk_mbx_get_rate,
  701. };
  702. static struct clk rtic_clk = {
  703. .name = "rtic_clk",
  704. .parent = &ahb_clk,
  705. .enable = _clk_enable,
  706. .enable_reg = MXC_CCM_CGR2,
  707. .enable_shift = MXC_CCM_CGR2_RTIC_OFFSET,
  708. .disable = _clk_disable,
  709. };
  710. static struct clk rng_clk = {
  711. .name = "rng_clk",
  712. .parent = &ipg_clk,
  713. .enable = _clk_enable,
  714. .enable_reg = MXC_CCM_CGR0,
  715. .enable_shift = MXC_CCM_CGR0_RNG_OFFSET,
  716. .disable = _clk_disable,
  717. };
  718. static struct clk sdma_clk[] = {
  719. {
  720. .name = "sdma_ahb_clk",
  721. .parent = &ahb_clk,
  722. .enable = _clk_enable,
  723. .enable_reg = MXC_CCM_CGR0,
  724. .enable_shift = MXC_CCM_CGR0_SDMA_OFFSET,
  725. .disable = _clk_disable,},
  726. {
  727. .name = "sdma_ipg_clk",
  728. .parent = &ipg_clk,}
  729. };
  730. static struct clk mpeg4_clk = {
  731. .name = "mpeg4_clk",
  732. .parent = &ahb_clk,
  733. .enable = _clk_enable,
  734. .enable_reg = MXC_CCM_CGR1,
  735. .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
  736. .disable = _clk_disable,
  737. };
  738. static struct clk vl2cc_clk = {
  739. .name = "vl2cc_clk",
  740. .parent = &ahb_clk,
  741. .enable = _clk_enable,
  742. .enable_reg = MXC_CCM_CGR1,
  743. .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
  744. .disable = _clk_disable,
  745. };
  746. static struct clk mstick_clk[] = {
  747. {
  748. .name = "mstick_clk",
  749. .id = 0,
  750. .parent = &usb_pll_clk,
  751. .get_rate = _clk_mstick1_get_rate,
  752. .enable = _clk_enable,
  753. .enable_reg = MXC_CCM_CGR1,
  754. .enable_shift = MXC_CCM_CGR1_MEMSTICK1_OFFSET,
  755. .disable = _clk_disable,},
  756. {
  757. .name = "mstick_clk",
  758. .id = 1,
  759. .parent = &usb_pll_clk,
  760. .get_rate = _clk_mstick2_get_rate,
  761. .enable = _clk_enable,
  762. .enable_reg = MXC_CCM_CGR1,
  763. .enable_shift = MXC_CCM_CGR1_MEMSTICK2_OFFSET,
  764. .disable = _clk_disable,},
  765. };
  766. static struct clk iim_clk = {
  767. .name = "iim_clk",
  768. .parent = &ipg_clk,
  769. .enable = _clk_enable,
  770. .enable_reg = MXC_CCM_CGR0,
  771. .enable_shift = MXC_CCM_CGR0_IIM_OFFSET,
  772. .disable = _clk_disable,
  773. };
  774. static unsigned long _clk_cko1_round_rate(struct clk *clk, unsigned long rate)
  775. {
  776. u32 div, parent = clk_get_rate(clk->parent);
  777. div = parent / rate;
  778. if (parent % rate)
  779. div++;
  780. if (div > 8)
  781. div = 16;
  782. else if (div > 4)
  783. div = 8;
  784. else if (div > 2)
  785. div = 4;
  786. return parent / div;
  787. }
  788. static int _clk_cko1_set_rate(struct clk *clk, unsigned long rate)
  789. {
  790. u32 reg, div, parent = clk_get_rate(clk->parent);
  791. div = parent / rate;
  792. if (div == 16)
  793. div = 4;
  794. else if (div == 8)
  795. div = 3;
  796. else if (div == 4)
  797. div = 2;
  798. else if (div == 2)
  799. div = 1;
  800. else if (div == 1)
  801. div = 0;
  802. else
  803. return -EINVAL;
  804. reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOUTDIV_MASK;
  805. reg |= div << MXC_CCM_COSR_CLKOUTDIV_OFFSET;
  806. __raw_writel(reg, MXC_CCM_COSR);
  807. return 0;
  808. }
  809. static unsigned long _clk_cko1_get_rate(struct clk *clk)
  810. {
  811. u32 div;
  812. div = __raw_readl(MXC_CCM_COSR) & MXC_CCM_COSR_CLKOUTDIV_MASK >>
  813. MXC_CCM_COSR_CLKOUTDIV_OFFSET;
  814. return clk_get_rate(clk->parent) / (1 << div);
  815. }
  816. static int _clk_cko1_set_parent(struct clk *clk, struct clk *parent)
  817. {
  818. u32 reg;
  819. reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOSEL_MASK;
  820. if (parent == &mcu_main_clk)
  821. reg |= 0 << MXC_CCM_COSR_CLKOSEL_OFFSET;
  822. else if (parent == &ipg_clk)
  823. reg |= 1 << MXC_CCM_COSR_CLKOSEL_OFFSET;
  824. else if (parent == &usb_pll_clk)
  825. reg |= 2 << MXC_CCM_COSR_CLKOSEL_OFFSET;
  826. else if (parent == mcu_main_clk.parent)
  827. reg |= 3 << MXC_CCM_COSR_CLKOSEL_OFFSET;
  828. else if (parent == &ahb_clk)
  829. reg |= 5 << MXC_CCM_COSR_CLKOSEL_OFFSET;
  830. else if (parent == &serial_pll_clk)
  831. reg |= 7 << MXC_CCM_COSR_CLKOSEL_OFFSET;
  832. else if (parent == &ckih_clk)
  833. reg |= 8 << MXC_CCM_COSR_CLKOSEL_OFFSET;
  834. else if (parent == &emi_clk)
  835. reg |= 9 << MXC_CCM_COSR_CLKOSEL_OFFSET;
  836. else if (parent == &ipu_clk)
  837. reg |= 0xA << MXC_CCM_COSR_CLKOSEL_OFFSET;
  838. else if (parent == &nfc_clk)
  839. reg |= 0xB << MXC_CCM_COSR_CLKOSEL_OFFSET;
  840. else if (parent == &uart_clk[0])
  841. reg |= 0xC << MXC_CCM_COSR_CLKOSEL_OFFSET;
  842. else
  843. return -EINVAL;
  844. __raw_writel(reg, MXC_CCM_COSR);
  845. return 0;
  846. }
  847. static int _clk_cko1_enable(struct clk *clk)
  848. {
  849. u32 reg;
  850. reg = __raw_readl(MXC_CCM_COSR) | MXC_CCM_COSR_CLKOEN;
  851. __raw_writel(reg, MXC_CCM_COSR);
  852. return 0;
  853. }
  854. static void _clk_cko1_disable(struct clk *clk)
  855. {
  856. u32 reg;
  857. reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOEN;
  858. __raw_writel(reg, MXC_CCM_COSR);
  859. }
  860. static struct clk cko1_clk = {
  861. .name = "cko1_clk",
  862. .get_rate = _clk_cko1_get_rate,
  863. .set_rate = _clk_cko1_set_rate,
  864. .round_rate = _clk_cko1_round_rate,
  865. .set_parent = _clk_cko1_set_parent,
  866. .enable = _clk_cko1_enable,
  867. .disable = _clk_cko1_disable,
  868. };
  869. static struct clk *mxc_clks[] = {
  870. &ckih_clk,
  871. &ckil_clk,
  872. &mcu_pll_clk,
  873. &usb_pll_clk,
  874. &serial_pll_clk,
  875. &mcu_main_clk,
  876. &ahb_clk,
  877. &per_clk,
  878. &perclk_clk,
  879. &cko1_clk,
  880. &emi_clk,
  881. &cspi_clk[0],
  882. &cspi_clk[1],
  883. &cspi_clk[2],
  884. &ipg_clk,
  885. &gpt_clk,
  886. &pwm_clk,
  887. &wdog_clk,
  888. &rtc_clk,
  889. &epit_clk[0],
  890. &epit_clk[1],
  891. &nfc_clk,
  892. &ipu_clk,
  893. &kpp_clk,
  894. &usb_clk[0],
  895. &usb_clk[1],
  896. &csi_clk,
  897. &uart_clk[0],
  898. &uart_clk[1],
  899. &uart_clk[2],
  900. &uart_clk[3],
  901. &uart_clk[4],
  902. &i2c_clk[0],
  903. &i2c_clk[1],
  904. &i2c_clk[2],
  905. &owire_clk,
  906. &sdhc_clk[0],
  907. &sdhc_clk[1],
  908. &ssi_clk[0],
  909. &ssi_clk[1],
  910. &firi_clk,
  911. &ata_clk,
  912. &rtic_clk,
  913. &rng_clk,
  914. &sdma_clk[0],
  915. &sdma_clk[1],
  916. &mstick_clk[0],
  917. &mstick_clk[1],
  918. &scc_clk,
  919. &iim_clk,
  920. };
  921. int __init mx31_clocks_init(unsigned long fref)
  922. {
  923. u32 reg;
  924. struct clk **clkp;
  925. mxc_set_cpu_type(MXC_CPU_MX31);
  926. ckih_rate = fref;
  927. for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
  928. clk_register(*clkp);
  929. if (cpu_is_mx31()) {
  930. clk_register(&mpeg4_clk);
  931. clk_register(&mbx_clk);
  932. } else {
  933. clk_register(&vpu_clk);
  934. clk_register(&vl2cc_clk);
  935. }
  936. /* Turn off all possible clocks */
  937. __raw_writel(MXC_CCM_CGR0_GPT_MASK, MXC_CCM_CGR0);
  938. __raw_writel(0, MXC_CCM_CGR1);
  939. __raw_writel(MXC_CCM_CGR2_EMI_MASK |
  940. MXC_CCM_CGR2_IPMUX1_MASK |
  941. MXC_CCM_CGR2_IPMUX2_MASK |
  942. MXC_CCM_CGR2_MXCCLKENSEL_MASK | /* for MX32 */
  943. MXC_CCM_CGR2_CHIKCAMPEN_MASK | /* for MX32 */
  944. MXC_CCM_CGR2_OVRVPUBUSY_MASK | /* for MX32 */
  945. 1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for
  946. MX32, but still required to be set */
  947. MXC_CCM_CGR2);
  948. clk_disable(&cko1_clk);
  949. clk_disable(&usb_pll_clk);
  950. pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk));
  951. clk_enable(&gpt_clk);
  952. clk_enable(&emi_clk);
  953. clk_enable(&iim_clk);
  954. clk_enable(&serial_pll_clk);
  955. if (mx31_revision() >= CHIP_REV_2_0) {
  956. reg = __raw_readl(MXC_CCM_PMCR1);
  957. /* No PLL restart on DVFS switch; enable auto EMI handshake */
  958. reg |= MXC_CCM_PMCR1_PLLRDIS | MXC_CCM_PMCR1_EMIRQ_EN;
  959. __raw_writel(reg, MXC_CCM_PMCR1);
  960. }
  961. mxc_timer_init(&ipg_clk);
  962. return 0;
  963. }