clock.c 26 KB

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