clock.c 26 KB

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