clock_imx27.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626
  1. /*
  2. * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
  3. * Copyright 2008 Juergen Beisert, 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/clk.h>
  20. #include <linux/io.h>
  21. #include <linux/module.h>
  22. #include <linux/spinlock.h>
  23. #include <asm/arch/clock.h>
  24. #include <asm/arch/common.h>
  25. #include <asm/div64.h>
  26. #include <asm/mach-types.h>
  27. #include "crm_regs.h"
  28. static struct clk ckil_clk;
  29. static struct clk mpll_clk;
  30. static struct clk mpll_main_clk[];
  31. static struct clk spll_clk;
  32. static int _clk_enable(struct clk *clk)
  33. {
  34. unsigned long reg;
  35. reg = __raw_readl(clk->enable_reg);
  36. reg |= 1 << clk->enable_shift;
  37. __raw_writel(reg, clk->enable_reg);
  38. return 0;
  39. }
  40. static void _clk_disable(struct clk *clk)
  41. {
  42. unsigned long reg;
  43. reg = __raw_readl(clk->enable_reg);
  44. reg &= ~(1 << clk->enable_shift);
  45. __raw_writel(reg, clk->enable_reg);
  46. }
  47. static int _clk_spll_enable(struct clk *clk)
  48. {
  49. unsigned long reg;
  50. reg = __raw_readl(CCM_CSCR);
  51. reg |= CCM_CSCR_SPEN;
  52. __raw_writel(reg, CCM_CSCR);
  53. while ((__raw_readl(CCM_SPCTL1) & CCM_SPCTL1_LF) == 0)
  54. ;
  55. return 0;
  56. }
  57. static void _clk_spll_disable(struct clk *clk)
  58. {
  59. unsigned long reg;
  60. reg = __raw_readl(CCM_CSCR);
  61. reg &= ~CCM_CSCR_SPEN;
  62. __raw_writel(reg, CCM_CSCR);
  63. }
  64. static void _clk_pccr01_enable(unsigned long mask0, unsigned long mask1)
  65. {
  66. unsigned long reg;
  67. reg = __raw_readl(CCM_PCCR0);
  68. reg |= mask0;
  69. __raw_writel(reg, CCM_PCCR0);
  70. reg = __raw_readl(CCM_PCCR1);
  71. reg |= mask1;
  72. __raw_writel(reg, CCM_PCCR1);
  73. }
  74. static void _clk_pccr01_disable(unsigned long mask0, unsigned long mask1)
  75. {
  76. unsigned long reg;
  77. reg = __raw_readl(CCM_PCCR0);
  78. reg &= ~mask0;
  79. __raw_writel(reg, CCM_PCCR0);
  80. reg = __raw_readl(CCM_PCCR1);
  81. reg &= ~mask1;
  82. __raw_writel(reg, CCM_PCCR1);
  83. }
  84. static void _clk_pccr10_enable(unsigned long mask1, unsigned long mask0)
  85. {
  86. unsigned long reg;
  87. reg = __raw_readl(CCM_PCCR1);
  88. reg |= mask1;
  89. __raw_writel(reg, CCM_PCCR1);
  90. reg = __raw_readl(CCM_PCCR0);
  91. reg |= mask0;
  92. __raw_writel(reg, CCM_PCCR0);
  93. }
  94. static void _clk_pccr10_disable(unsigned long mask1, unsigned long mask0)
  95. {
  96. unsigned long reg;
  97. reg = __raw_readl(CCM_PCCR1);
  98. reg &= ~mask1;
  99. __raw_writel(reg, CCM_PCCR1);
  100. reg = __raw_readl(CCM_PCCR0);
  101. reg &= ~mask0;
  102. __raw_writel(reg, CCM_PCCR0);
  103. }
  104. static int _clk_dma_enable(struct clk *clk)
  105. {
  106. _clk_pccr01_enable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
  107. return 0;
  108. }
  109. static void _clk_dma_disable(struct clk *clk)
  110. {
  111. _clk_pccr01_disable(CCM_PCCR0_DMA_MASK, CCM_PCCR1_HCLK_DMA_MASK);
  112. }
  113. static int _clk_rtic_enable(struct clk *clk)
  114. {
  115. _clk_pccr01_enable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
  116. return 0;
  117. }
  118. static void _clk_rtic_disable(struct clk *clk)
  119. {
  120. _clk_pccr01_disable(CCM_PCCR0_RTIC_MASK, CCM_PCCR1_HCLK_RTIC_MASK);
  121. }
  122. static int _clk_emma_enable(struct clk *clk)
  123. {
  124. _clk_pccr01_enable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
  125. return 0;
  126. }
  127. static void _clk_emma_disable(struct clk *clk)
  128. {
  129. _clk_pccr01_disable(CCM_PCCR0_EMMA_MASK, CCM_PCCR1_HCLK_EMMA_MASK);
  130. }
  131. static int _clk_slcdc_enable(struct clk *clk)
  132. {
  133. _clk_pccr01_enable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
  134. return 0;
  135. }
  136. static void _clk_slcdc_disable(struct clk *clk)
  137. {
  138. _clk_pccr01_disable(CCM_PCCR0_SLCDC_MASK, CCM_PCCR1_HCLK_SLCDC_MASK);
  139. }
  140. static int _clk_fec_enable(struct clk *clk)
  141. {
  142. _clk_pccr01_enable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
  143. return 0;
  144. }
  145. static void _clk_fec_disable(struct clk *clk)
  146. {
  147. _clk_pccr01_disable(CCM_PCCR0_FEC_MASK, CCM_PCCR1_HCLK_FEC_MASK);
  148. }
  149. static int _clk_vpu_enable(struct clk *clk)
  150. {
  151. unsigned long reg;
  152. reg = __raw_readl(CCM_PCCR1);
  153. reg |= CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK;
  154. __raw_writel(reg, CCM_PCCR1);
  155. return 0;
  156. }
  157. static void _clk_vpu_disable(struct clk *clk)
  158. {
  159. unsigned long reg;
  160. reg = __raw_readl(CCM_PCCR1);
  161. reg &= ~(CCM_PCCR1_VPU_BAUD_MASK | CCM_PCCR1_HCLK_VPU_MASK);
  162. __raw_writel(reg, CCM_PCCR1);
  163. }
  164. static int _clk_sahara2_enable(struct clk *clk)
  165. {
  166. _clk_pccr01_enable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
  167. return 0;
  168. }
  169. static void _clk_sahara2_disable(struct clk *clk)
  170. {
  171. _clk_pccr01_disable(CCM_PCCR0_SAHARA_MASK, CCM_PCCR1_HCLK_SAHARA_MASK);
  172. }
  173. static int _clk_mstick1_enable(struct clk *clk)
  174. {
  175. _clk_pccr10_enable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
  176. return 0;
  177. }
  178. static void _clk_mstick1_disable(struct clk *clk)
  179. {
  180. _clk_pccr10_disable(CCM_PCCR1_MSHC_BAUD_MASK, CCM_PCCR0_MSHC_MASK);
  181. }
  182. #define CSCR() (__raw_readl(CCM_CSCR))
  183. #define PCDR0() (__raw_readl(CCM_PCDR0))
  184. #define PCDR1() (__raw_readl(CCM_PCDR1))
  185. static int _clk_cpu_set_parent(struct clk *clk, struct clk *parent)
  186. {
  187. int cscr = CSCR();
  188. if (clk->parent == parent)
  189. return 0;
  190. if (mx27_revision() >= CHIP_REV_2_0) {
  191. if (parent == &mpll_main_clk[0]) {
  192. cscr |= CCM_CSCR_ARM_SRC;
  193. } else {
  194. if (parent == &mpll_main_clk[1])
  195. cscr &= ~CCM_CSCR_ARM_SRC;
  196. else
  197. return -EINVAL;
  198. }
  199. __raw_writel(cscr, CCM_CSCR);
  200. } else
  201. return -ENODEV;
  202. clk->parent = parent;
  203. return 0;
  204. }
  205. static unsigned long _clk_cpu_round_rate(struct clk *clk, unsigned long rate)
  206. {
  207. int div;
  208. unsigned long parent_rate;
  209. parent_rate = clk_get_rate(clk->parent);
  210. div = parent_rate / rate;
  211. if (parent_rate % rate)
  212. div++;
  213. if (div > 4)
  214. div = 4;
  215. return parent_rate / div;
  216. }
  217. static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate)
  218. {
  219. unsigned int div;
  220. uint32_t reg;
  221. unsigned long parent_rate;
  222. parent_rate = clk_get_rate(clk->parent);
  223. div = parent_rate / rate;
  224. if (div > 4 || div < 1 || ((parent_rate / div) != rate))
  225. return -EINVAL;
  226. div--;
  227. reg = __raw_readl(CCM_CSCR);
  228. if (mx27_revision() >= CHIP_REV_2_0) {
  229. reg &= ~CCM_CSCR_ARM_MASK;
  230. reg |= div << CCM_CSCR_ARM_OFFSET;
  231. reg &= ~0x06;
  232. __raw_writel(reg | 0x80000000, CCM_CSCR);
  233. } else {
  234. printk(KERN_ERR "Cant set CPU frequency!\n");
  235. }
  236. return 0;
  237. }
  238. static unsigned long _clk_perclkx_round_rate(struct clk *clk,
  239. unsigned long rate)
  240. {
  241. u32 div;
  242. unsigned long parent_rate;
  243. parent_rate = clk_get_rate(clk->parent);
  244. div = parent_rate / rate;
  245. if (parent_rate % rate)
  246. div++;
  247. if (div > 64)
  248. div = 64;
  249. return parent_rate / div;
  250. }
  251. static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
  252. {
  253. u32 reg;
  254. u32 div;
  255. unsigned long parent_rate;
  256. parent_rate = clk_get_rate(clk->parent);
  257. if (clk->id < 0 || clk->id > 3)
  258. return -EINVAL;
  259. div = parent_rate / rate;
  260. if (div > 64 || div < 1 || ((parent_rate / div) != rate))
  261. return -EINVAL;
  262. div--;
  263. reg =
  264. __raw_readl(CCM_PCDR1) & ~(CCM_PCDR1_PERDIV1_MASK <<
  265. (clk->id << 3));
  266. reg |= div << (clk->id << 3);
  267. __raw_writel(reg, CCM_PCDR1);
  268. return 0;
  269. }
  270. static unsigned long _clk_usb_recalc(struct clk *clk)
  271. {
  272. unsigned long usb_pdf;
  273. unsigned long parent_rate;
  274. parent_rate = clk_get_rate(clk->parent);
  275. usb_pdf = (CSCR() & CCM_CSCR_USB_MASK) >> CCM_CSCR_USB_OFFSET;
  276. return parent_rate / (usb_pdf + 1U);
  277. }
  278. static unsigned long _clk_ssi1_recalc(struct clk *clk)
  279. {
  280. unsigned long ssi1_pdf;
  281. unsigned long parent_rate;
  282. parent_rate = clk_get_rate(clk->parent);
  283. ssi1_pdf = (PCDR0() & CCM_PCDR0_SSI1BAUDDIV_MASK) >>
  284. CCM_PCDR0_SSI1BAUDDIV_OFFSET;
  285. if (mx27_revision() >= CHIP_REV_2_0)
  286. ssi1_pdf += 4;
  287. else
  288. ssi1_pdf = (ssi1_pdf < 2) ? 124UL : ssi1_pdf;
  289. return 2UL * parent_rate / ssi1_pdf;
  290. }
  291. static unsigned long _clk_ssi2_recalc(struct clk *clk)
  292. {
  293. unsigned long ssi2_pdf;
  294. unsigned long parent_rate;
  295. parent_rate = clk_get_rate(clk->parent);
  296. ssi2_pdf = (PCDR0() & CCM_PCDR0_SSI2BAUDDIV_MASK) >>
  297. CCM_PCDR0_SSI2BAUDDIV_OFFSET;
  298. if (mx27_revision() >= CHIP_REV_2_0)
  299. ssi2_pdf += 4;
  300. else
  301. ssi2_pdf = (ssi2_pdf < 2) ? 124UL : ssi2_pdf;
  302. return 2UL * parent_rate / ssi2_pdf;
  303. }
  304. static unsigned long _clk_nfc_recalc(struct clk *clk)
  305. {
  306. unsigned long nfc_pdf;
  307. unsigned long parent_rate;
  308. parent_rate = clk_get_rate(clk->parent);
  309. if (mx27_revision() >= CHIP_REV_2_0) {
  310. nfc_pdf =
  311. (PCDR0() & CCM_PCDR0_NFCDIV2_MASK) >>
  312. CCM_PCDR0_NFCDIV2_OFFSET;
  313. } else {
  314. nfc_pdf =
  315. (PCDR0() & CCM_PCDR0_NFCDIV_MASK) >>
  316. CCM_PCDR0_NFCDIV_OFFSET;
  317. }
  318. return parent_rate / (nfc_pdf + 1);
  319. }
  320. static unsigned long _clk_vpu_recalc(struct clk *clk)
  321. {
  322. unsigned long vpu_pdf;
  323. unsigned long parent_rate;
  324. parent_rate = clk_get_rate(clk->parent);
  325. if (mx27_revision() >= CHIP_REV_2_0) {
  326. vpu_pdf =
  327. (PCDR0() & CCM_PCDR0_VPUDIV2_MASK) >>
  328. CCM_PCDR0_VPUDIV2_OFFSET;
  329. vpu_pdf += 4;
  330. } else {
  331. vpu_pdf =
  332. (PCDR0() & CCM_PCDR0_VPUDIV_MASK) >>
  333. CCM_PCDR0_VPUDIV_OFFSET;
  334. vpu_pdf = (vpu_pdf < 2) ? 124 : vpu_pdf;
  335. }
  336. return 2UL * parent_rate / vpu_pdf;
  337. }
  338. static unsigned long _clk_parent_round_rate(struct clk *clk, unsigned long rate)
  339. {
  340. return clk->parent->round_rate(clk->parent, rate);
  341. }
  342. static int _clk_parent_set_rate(struct clk *clk, unsigned long rate)
  343. {
  344. return clk->parent->set_rate(clk->parent, rate);
  345. }
  346. /* in Hz */
  347. static unsigned long external_high_reference = 26000000;
  348. static unsigned long get_high_reference_clock_rate(struct clk *clk)
  349. {
  350. return external_high_reference;
  351. }
  352. /*
  353. * the high frequency external clock reference
  354. * Default case is 26MHz. Could be changed at runtime
  355. * with a call to change_external_high_reference()
  356. */
  357. static struct clk ckih_clk = {
  358. .name = "ckih",
  359. .get_rate = get_high_reference_clock_rate,
  360. };
  361. /* in Hz */
  362. static unsigned long external_low_reference = 32768;
  363. static unsigned long get_low_reference_clock_rate(struct clk *clk)
  364. {
  365. return external_low_reference;
  366. }
  367. /*
  368. * the low frequency external clock reference
  369. * Default case is 32.768kHz Could be changed at runtime
  370. * with a call to change_external_low_reference()
  371. */
  372. static struct clk ckil_clk = {
  373. .name = "ckil",
  374. .get_rate = get_low_reference_clock_rate,
  375. };
  376. static unsigned long get_mpll_clk(struct clk *clk)
  377. {
  378. uint32_t reg;
  379. unsigned long ref_clk;
  380. unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
  381. unsigned long long temp;
  382. ref_clk = clk_get_rate(clk->parent);
  383. reg = __raw_readl(CCM_MPCTL0);
  384. pdf = (reg & CCM_MPCTL0_PD_MASK) >> CCM_MPCTL0_PD_OFFSET;
  385. mfd = (reg & CCM_MPCTL0_MFD_MASK) >> CCM_MPCTL0_MFD_OFFSET;
  386. mfi = (reg & CCM_MPCTL0_MFI_MASK) >> CCM_MPCTL0_MFI_OFFSET;
  387. mfn = (reg & CCM_MPCTL0_MFN_MASK) >> CCM_MPCTL0_MFN_OFFSET;
  388. mfi = (mfi <= 5) ? 5 : mfi;
  389. temp = 2LL * ref_clk * mfn;
  390. do_div(temp, mfd + 1);
  391. temp = 2LL * ref_clk * mfi + temp;
  392. do_div(temp, pdf + 1);
  393. return (unsigned long)temp;
  394. }
  395. static struct clk mpll_clk = {
  396. .name = "mpll",
  397. .parent = &ckih_clk,
  398. .get_rate = get_mpll_clk,
  399. };
  400. static unsigned long _clk_mpll_main_get_rate(struct clk *clk)
  401. {
  402. unsigned long parent_rate;
  403. parent_rate = clk_get_rate(clk->parent);
  404. /* i.MX27 TO2:
  405. * clk->id == 0: arm clock source path 1 which is from 2*MPLL/DIV_2
  406. * clk->id == 1: arm clock source path 2 which is from 2*MPLL/DIV_3
  407. */
  408. if (mx27_revision() >= CHIP_REV_2_0 && clk->id == 1)
  409. return 2UL * parent_rate / 3UL;
  410. return parent_rate;
  411. }
  412. static struct clk mpll_main_clk[] = {
  413. {
  414. /* For i.MX27 TO2, it is the MPLL path 1 of ARM core
  415. * It provide the clock source whose rate is same as MPLL
  416. */
  417. .name = "mpll_main",
  418. .id = 0,
  419. .parent = &mpll_clk,
  420. .get_rate = _clk_mpll_main_get_rate
  421. }, {
  422. /* For i.MX27 TO2, it is the MPLL path 2 of ARM core
  423. * It provide the clock source whose rate is same MPLL * 2/3
  424. */
  425. .name = "mpll_main",
  426. .id = 1,
  427. .parent = &mpll_clk,
  428. .get_rate = _clk_mpll_main_get_rate
  429. }
  430. };
  431. static unsigned long get_spll_clk(struct clk *clk)
  432. {
  433. uint32_t reg;
  434. unsigned long ref_clk;
  435. unsigned long mfi = 0, mfn = 0, mfd = 0, pdf = 0;
  436. unsigned long long temp;
  437. ref_clk = clk_get_rate(clk->parent);
  438. reg = __raw_readl(CCM_SPCTL0);
  439. /*TODO: This is TO2 Bug */
  440. if (mx27_revision() >= CHIP_REV_2_0)
  441. __raw_writel(reg, CCM_SPCTL0);
  442. pdf = (reg & CCM_SPCTL0_PD_MASK) >> CCM_SPCTL0_PD_OFFSET;
  443. mfd = (reg & CCM_SPCTL0_MFD_MASK) >> CCM_SPCTL0_MFD_OFFSET;
  444. mfi = (reg & CCM_SPCTL0_MFI_MASK) >> CCM_SPCTL0_MFI_OFFSET;
  445. mfn = (reg & CCM_SPCTL0_MFN_MASK) >> CCM_SPCTL0_MFN_OFFSET;
  446. mfi = (mfi <= 5) ? 5 : mfi;
  447. temp = 2LL * ref_clk * mfn;
  448. do_div(temp, mfd + 1);
  449. temp = 2LL * ref_clk * mfi + temp;
  450. do_div(temp, pdf + 1);
  451. return (unsigned long)temp;
  452. }
  453. static struct clk spll_clk = {
  454. .name = "spll",
  455. .parent = &ckih_clk,
  456. .get_rate = get_spll_clk,
  457. .enable = _clk_spll_enable,
  458. .disable = _clk_spll_disable,
  459. };
  460. static unsigned long get_cpu_clk(struct clk *clk)
  461. {
  462. u32 div;
  463. unsigned long rate;
  464. if (mx27_revision() >= CHIP_REV_2_0)
  465. div = (CSCR() & CCM_CSCR_ARM_MASK) >> CCM_CSCR_ARM_OFFSET;
  466. else
  467. div = (CSCR() & CCM_CSCR_PRESC_MASK) >> CCM_CSCR_PRESC_OFFSET;
  468. rate = clk_get_rate(clk->parent);
  469. return rate / (div + 1);
  470. }
  471. static struct clk cpu_clk = {
  472. .name = "cpu_clk",
  473. .parent = &mpll_main_clk[1],
  474. .set_parent = _clk_cpu_set_parent,
  475. .round_rate = _clk_cpu_round_rate,
  476. .get_rate = get_cpu_clk,
  477. .set_rate = _clk_cpu_set_rate,
  478. };
  479. static unsigned long get_ahb_clk(struct clk *clk)
  480. {
  481. unsigned long rate;
  482. unsigned long bclk_pdf;
  483. if (mx27_revision() >= CHIP_REV_2_0)
  484. bclk_pdf = (CSCR() & CCM_CSCR_AHB_MASK)
  485. >> CCM_CSCR_AHB_OFFSET;
  486. else
  487. bclk_pdf = (CSCR() & CCM_CSCR_BCLK_MASK)
  488. >> CCM_CSCR_BCLK_OFFSET;
  489. rate = clk_get_rate(clk->parent);
  490. return rate / (bclk_pdf + 1);
  491. }
  492. static struct clk ahb_clk = {
  493. .name = "ahb_clk",
  494. .parent = &mpll_main_clk[1],
  495. .get_rate = get_ahb_clk,
  496. };
  497. static unsigned long get_ipg_clk(struct clk *clk)
  498. {
  499. unsigned long rate;
  500. unsigned long ipg_pdf;
  501. if (mx27_revision() >= CHIP_REV_2_0)
  502. return clk_get_rate(clk->parent);
  503. else
  504. ipg_pdf = (CSCR() & CCM_CSCR_IPDIV) >> CCM_CSCR_IPDIV_OFFSET;
  505. rate = clk_get_rate(clk->parent);
  506. return rate / (ipg_pdf + 1);
  507. }
  508. static struct clk ipg_clk = {
  509. .name = "ipg_clk",
  510. .parent = &ahb_clk,
  511. .get_rate = get_ipg_clk,
  512. };
  513. static unsigned long _clk_perclkx_recalc(struct clk *clk)
  514. {
  515. unsigned long perclk_pdf;
  516. unsigned long parent_rate;
  517. parent_rate = clk_get_rate(clk->parent);
  518. if (clk->id < 0 || clk->id > 3)
  519. return 0;
  520. perclk_pdf = (PCDR1() >> (clk->id << 3)) & CCM_PCDR1_PERDIV1_MASK;
  521. return parent_rate / (perclk_pdf + 1);
  522. }
  523. static struct clk per_clk[] = {
  524. {
  525. .name = "per_clk",
  526. .id = 0,
  527. .parent = &mpll_main_clk[1],
  528. .get_rate = _clk_perclkx_recalc,
  529. .enable = _clk_enable,
  530. .enable_reg = CCM_PCCR1,
  531. .enable_shift = CCM_PCCR1_PERCLK1_OFFSET,
  532. .disable = _clk_disable,
  533. }, {
  534. .name = "per_clk",
  535. .id = 1,
  536. .parent = &mpll_main_clk[1],
  537. .get_rate = _clk_perclkx_recalc,
  538. .enable = _clk_enable,
  539. .enable_reg = CCM_PCCR1,
  540. .enable_shift = CCM_PCCR1_PERCLK2_OFFSET,
  541. .disable = _clk_disable,
  542. }, {
  543. .name = "per_clk",
  544. .id = 2,
  545. .parent = &mpll_main_clk[1],
  546. .round_rate = _clk_perclkx_round_rate,
  547. .set_rate = _clk_perclkx_set_rate,
  548. .get_rate = _clk_perclkx_recalc,
  549. .enable = _clk_enable,
  550. .enable_reg = CCM_PCCR1,
  551. .enable_shift = CCM_PCCR1_PERCLK3_OFFSET,
  552. .disable = _clk_disable,
  553. }, {
  554. .name = "per_clk",
  555. .id = 3,
  556. .parent = &mpll_main_clk[1],
  557. .round_rate = _clk_perclkx_round_rate,
  558. .set_rate = _clk_perclkx_set_rate,
  559. .get_rate = _clk_perclkx_recalc,
  560. .enable = _clk_enable,
  561. .enable_reg = CCM_PCCR1,
  562. .enable_shift = CCM_PCCR1_PERCLK4_OFFSET,
  563. .disable = _clk_disable,
  564. },
  565. };
  566. struct clk uart1_clk[] = {
  567. {
  568. .name = "uart_clk",
  569. .id = 0,
  570. .parent = &per_clk[0],
  571. .secondary = &uart1_clk[1],
  572. }, {
  573. .name = "uart_ipg_clk",
  574. .id = 0,
  575. .parent = &ipg_clk,
  576. .enable = _clk_enable,
  577. .enable_reg = CCM_PCCR1,
  578. .enable_shift = CCM_PCCR1_UART1_OFFSET,
  579. .disable = _clk_disable,
  580. },
  581. };
  582. struct clk uart2_clk[] = {
  583. {
  584. .name = "uart_clk",
  585. .id = 1,
  586. .parent = &per_clk[0],
  587. .secondary = &uart2_clk[1],
  588. }, {
  589. .name = "uart_ipg_clk",
  590. .id = 1,
  591. .parent = &ipg_clk,
  592. .enable = _clk_enable,
  593. .enable_reg = CCM_PCCR1,
  594. .enable_shift = CCM_PCCR1_UART2_OFFSET,
  595. .disable = _clk_disable,
  596. },
  597. };
  598. struct clk uart3_clk[] = {
  599. {
  600. .name = "uart_clk",
  601. .id = 2,
  602. .parent = &per_clk[0],
  603. .secondary = &uart3_clk[1],
  604. }, {
  605. .name = "uart_ipg_clk",
  606. .id = 2,
  607. .parent = &ipg_clk,
  608. .enable = _clk_enable,
  609. .enable_reg = CCM_PCCR1,
  610. .enable_shift = CCM_PCCR1_UART3_OFFSET,
  611. .disable = _clk_disable,
  612. },
  613. };
  614. struct clk uart4_clk[] = {
  615. {
  616. .name = "uart_clk",
  617. .id = 3,
  618. .parent = &per_clk[0],
  619. .secondary = &uart4_clk[1],
  620. }, {
  621. .name = "uart_ipg_clk",
  622. .id = 3,
  623. .parent = &ipg_clk,
  624. .enable = _clk_enable,
  625. .enable_reg = CCM_PCCR1,
  626. .enable_shift = CCM_PCCR1_UART4_OFFSET,
  627. .disable = _clk_disable,
  628. },
  629. };
  630. struct clk uart5_clk[] = {
  631. {
  632. .name = "uart_clk",
  633. .id = 4,
  634. .parent = &per_clk[0],
  635. .secondary = &uart5_clk[1],
  636. }, {
  637. .name = "uart_ipg_clk",
  638. .id = 4,
  639. .parent = &ipg_clk,
  640. .enable = _clk_enable,
  641. .enable_reg = CCM_PCCR1,
  642. .enable_shift = CCM_PCCR1_UART5_OFFSET,
  643. .disable = _clk_disable,
  644. },
  645. };
  646. struct clk uart6_clk[] = {
  647. {
  648. .name = "uart_clk",
  649. .id = 5,
  650. .parent = &per_clk[0],
  651. .secondary = &uart6_clk[1],
  652. }, {
  653. .name = "uart_ipg_clk",
  654. .id = 5,
  655. .parent = &ipg_clk,
  656. .enable = _clk_enable,
  657. .enable_reg = CCM_PCCR1,
  658. .enable_shift = CCM_PCCR1_UART6_OFFSET,
  659. .disable = _clk_disable,
  660. },
  661. };
  662. static struct clk gpt1_clk[] = {
  663. {
  664. .name = "gpt_clk",
  665. .id = 0,
  666. .parent = &per_clk[0],
  667. .secondary = &gpt1_clk[1],
  668. }, {
  669. .name = "gpt_ipg_clk",
  670. .id = 0,
  671. .parent = &ipg_clk,
  672. .enable = _clk_enable,
  673. .enable_reg = CCM_PCCR0,
  674. .enable_shift = CCM_PCCR0_GPT1_OFFSET,
  675. .disable = _clk_disable,
  676. },
  677. };
  678. static struct clk gpt2_clk[] = {
  679. {
  680. .name = "gpt_clk",
  681. .id = 1,
  682. .parent = &per_clk[0],
  683. .secondary = &gpt2_clk[1],
  684. }, {
  685. .name = "gpt_ipg_clk",
  686. .id = 1,
  687. .parent = &ipg_clk,
  688. .enable = _clk_enable,
  689. .enable_reg = CCM_PCCR0,
  690. .enable_shift = CCM_PCCR0_GPT2_OFFSET,
  691. .disable = _clk_disable,
  692. },
  693. };
  694. static struct clk gpt3_clk[] = {
  695. {
  696. .name = "gpt_clk",
  697. .id = 2,
  698. .parent = &per_clk[0],
  699. .secondary = &gpt3_clk[1],
  700. }, {
  701. .name = "gpt_ipg_clk",
  702. .id = 2,
  703. .parent = &ipg_clk,
  704. .enable = _clk_enable,
  705. .enable_reg = CCM_PCCR0,
  706. .enable_shift = CCM_PCCR0_GPT3_OFFSET,
  707. .disable = _clk_disable,
  708. },
  709. };
  710. static struct clk gpt4_clk[] = {
  711. {
  712. .name = "gpt_clk",
  713. .id = 3,
  714. .parent = &per_clk[0],
  715. .secondary = &gpt4_clk[1],
  716. }, {
  717. .name = "gpt_ipg_clk",
  718. .id = 3,
  719. .parent = &ipg_clk,
  720. .enable = _clk_enable,
  721. .enable_reg = CCM_PCCR0,
  722. .enable_shift = CCM_PCCR0_GPT4_OFFSET,
  723. .disable = _clk_disable,
  724. },
  725. };
  726. static struct clk gpt5_clk[] = {
  727. {
  728. .name = "gpt_clk",
  729. .id = 4,
  730. .parent = &per_clk[0],
  731. .secondary = &gpt5_clk[1],
  732. }, {
  733. .name = "gpt_ipg_clk",
  734. .id = 4,
  735. .parent = &ipg_clk,
  736. .enable = _clk_enable,
  737. .enable_reg = CCM_PCCR0,
  738. .enable_shift = CCM_PCCR0_GPT5_OFFSET,
  739. .disable = _clk_disable,
  740. },
  741. };
  742. static struct clk gpt6_clk[] = {
  743. {
  744. .name = "gpt_clk",
  745. .id = 5,
  746. .parent = &per_clk[0],
  747. .secondary = &gpt6_clk[1],
  748. }, {
  749. .name = "gpt_ipg_clk",
  750. .id = 5,
  751. .parent = &ipg_clk,
  752. .enable = _clk_enable,
  753. .enable_reg = CCM_PCCR0,
  754. .enable_shift = CCM_PCCR0_GPT6_OFFSET,
  755. .disable = _clk_disable,
  756. },
  757. };
  758. static struct clk pwm_clk[] = {
  759. {
  760. .name = "pwm_clk",
  761. .parent = &per_clk[0],
  762. .secondary = &pwm_clk[1],
  763. }, {
  764. .name = "pwm_clk",
  765. .parent = &ipg_clk,
  766. .enable = _clk_enable,
  767. .enable_reg = CCM_PCCR0,
  768. .enable_shift = CCM_PCCR0_PWM_OFFSET,
  769. .disable = _clk_disable,
  770. },
  771. };
  772. static struct clk sdhc1_clk[] = {
  773. {
  774. .name = "sdhc_clk",
  775. .id = 0,
  776. .parent = &per_clk[1],
  777. .secondary = &sdhc1_clk[1],
  778. }, {
  779. .name = "sdhc_ipg_clk",
  780. .id = 0,
  781. .parent = &ipg_clk,
  782. .enable = _clk_enable,
  783. .enable_reg = CCM_PCCR0,
  784. .enable_shift = CCM_PCCR0_SDHC1_OFFSET,
  785. .disable = _clk_disable,
  786. },
  787. };
  788. static struct clk sdhc2_clk[] = {
  789. {
  790. .name = "sdhc_clk",
  791. .id = 1,
  792. .parent = &per_clk[1],
  793. .secondary = &sdhc2_clk[1],
  794. }, {
  795. .name = "sdhc_ipg_clk",
  796. .id = 1,
  797. .parent = &ipg_clk,
  798. .enable = _clk_enable,
  799. .enable_reg = CCM_PCCR0,
  800. .enable_shift = CCM_PCCR0_SDHC2_OFFSET,
  801. .disable = _clk_disable,
  802. },
  803. };
  804. static struct clk sdhc3_clk[] = {
  805. {
  806. .name = "sdhc_clk",
  807. .id = 2,
  808. .parent = &per_clk[1],
  809. .secondary = &sdhc3_clk[1],
  810. }, {
  811. .name = "sdhc_ipg_clk",
  812. .id = 2,
  813. .parent = &ipg_clk,
  814. .enable = _clk_enable,
  815. .enable_reg = CCM_PCCR0,
  816. .enable_shift = CCM_PCCR0_SDHC3_OFFSET,
  817. .disable = _clk_disable,
  818. },
  819. };
  820. static struct clk cspi1_clk[] = {
  821. {
  822. .name = "cspi_clk",
  823. .id = 0,
  824. .parent = &per_clk[1],
  825. .secondary = &cspi1_clk[1],
  826. }, {
  827. .name = "cspi_ipg_clk",
  828. .id = 0,
  829. .parent = &ipg_clk,
  830. .enable = _clk_enable,
  831. .enable_reg = CCM_PCCR0,
  832. .enable_shift = CCM_PCCR0_CSPI1_OFFSET,
  833. .disable = _clk_disable,
  834. },
  835. };
  836. static struct clk cspi2_clk[] = {
  837. {
  838. .name = "cspi_clk",
  839. .id = 1,
  840. .parent = &per_clk[1],
  841. .secondary = &cspi2_clk[1],
  842. }, {
  843. .name = "cspi_ipg_clk",
  844. .id = 1,
  845. .parent = &ipg_clk,
  846. .enable = _clk_enable,
  847. .enable_reg = CCM_PCCR0,
  848. .enable_shift = CCM_PCCR0_CSPI2_OFFSET,
  849. .disable = _clk_disable,
  850. },
  851. };
  852. static struct clk cspi3_clk[] = {
  853. {
  854. .name = "cspi_clk",
  855. .id = 2,
  856. .parent = &per_clk[1],
  857. .secondary = &cspi3_clk[1],
  858. }, {
  859. .name = "cspi_ipg_clk",
  860. .id = 2,
  861. .parent = &ipg_clk,
  862. .enable = _clk_enable,
  863. .enable_reg = CCM_PCCR0,
  864. .enable_shift = CCM_PCCR0_CSPI3_OFFSET,
  865. .disable = _clk_disable,
  866. },
  867. };
  868. static struct clk lcdc_clk[] = {
  869. {
  870. .name = "lcdc_clk",
  871. .parent = &per_clk[2],
  872. .secondary = &lcdc_clk[1],
  873. .round_rate = _clk_parent_round_rate,
  874. .set_rate = _clk_parent_set_rate,
  875. }, {
  876. .name = "lcdc_ipg_clk",
  877. .parent = &ipg_clk,
  878. .secondary = &lcdc_clk[2],
  879. .enable = _clk_enable,
  880. .enable_reg = CCM_PCCR0,
  881. .enable_shift = CCM_PCCR0_LCDC_OFFSET,
  882. .disable = _clk_disable,
  883. }, {
  884. .name = "lcdc_ahb_clk",
  885. .parent = &ahb_clk,
  886. .enable = _clk_enable,
  887. .enable_reg = CCM_PCCR1,
  888. .enable_shift = CCM_PCCR1_HCLK_LCDC_OFFSET,
  889. .disable = _clk_disable,
  890. },
  891. };
  892. static struct clk csi_clk[] = {
  893. {
  894. .name = "csi_perclk",
  895. .parent = &per_clk[3],
  896. .secondary = &csi_clk[1],
  897. .round_rate = _clk_parent_round_rate,
  898. .set_rate = _clk_parent_set_rate,
  899. }, {
  900. .name = "csi_ahb_clk",
  901. .parent = &ahb_clk,
  902. .enable = _clk_enable,
  903. .enable_reg = CCM_PCCR1,
  904. .enable_shift = CCM_PCCR1_HCLK_CSI_OFFSET,
  905. .disable = _clk_disable,
  906. },
  907. };
  908. static struct clk usb_clk[] = {
  909. {
  910. .name = "usb_clk",
  911. .parent = &spll_clk,
  912. .get_rate = _clk_usb_recalc,
  913. .enable = _clk_enable,
  914. .enable_reg = CCM_PCCR1,
  915. .enable_shift = CCM_PCCR1_USBOTG_OFFSET,
  916. .disable = _clk_disable,
  917. }, {
  918. .name = "usb_ahb_clk",
  919. .parent = &ahb_clk,
  920. .enable = _clk_enable,
  921. .enable_reg = CCM_PCCR1,
  922. .enable_shift = CCM_PCCR1_HCLK_USBOTG_OFFSET,
  923. .disable = _clk_disable,
  924. }
  925. };
  926. static struct clk ssi1_clk[] = {
  927. {
  928. .name = "ssi_clk",
  929. .id = 0,
  930. .parent = &mpll_main_clk[1],
  931. .secondary = &ssi1_clk[1],
  932. .get_rate = _clk_ssi1_recalc,
  933. .enable = _clk_enable,
  934. .enable_reg = CCM_PCCR1,
  935. .enable_shift = CCM_PCCR1_SSI1_BAUD_OFFSET,
  936. .disable = _clk_disable,
  937. }, {
  938. .name = "ssi_ipg_clk",
  939. .id = 0,
  940. .parent = &ipg_clk,
  941. .enable = _clk_enable,
  942. .enable_reg = CCM_PCCR0,
  943. .enable_shift = CCM_PCCR0_SSI1_IPG_OFFSET,
  944. .disable = _clk_disable,
  945. },
  946. };
  947. static struct clk ssi2_clk[] = {
  948. {
  949. .name = "ssi_clk",
  950. .id = 1,
  951. .parent = &mpll_main_clk[1],
  952. .secondary = &ssi2_clk[1],
  953. .get_rate = _clk_ssi2_recalc,
  954. .enable = _clk_enable,
  955. .enable_reg = CCM_PCCR1,
  956. .enable_shift = CCM_PCCR1_SSI2_BAUD_OFFSET,
  957. .disable = _clk_disable,
  958. }, {
  959. .name = "ssi_ipg_clk",
  960. .id = 1,
  961. .parent = &ipg_clk,
  962. .enable = _clk_enable,
  963. .enable_reg = CCM_PCCR0,
  964. .enable_shift = CCM_PCCR0_SSI2_IPG_OFFSET,
  965. .disable = _clk_disable,
  966. },
  967. };
  968. static struct clk nfc_clk = {
  969. .name = "nfc_clk",
  970. .parent = &cpu_clk,
  971. .get_rate = _clk_nfc_recalc,
  972. .enable = _clk_enable,
  973. .enable_reg = CCM_PCCR1,
  974. .enable_shift = CCM_PCCR1_NFC_BAUD_OFFSET,
  975. .disable = _clk_disable,
  976. };
  977. static struct clk vpu_clk = {
  978. .name = "vpu_clk",
  979. .parent = &mpll_main_clk[1],
  980. .get_rate = _clk_vpu_recalc,
  981. .enable = _clk_vpu_enable,
  982. .disable = _clk_vpu_disable,
  983. };
  984. static struct clk dma_clk = {
  985. .name = "dma_clk",
  986. .parent = &ahb_clk,
  987. .enable = _clk_dma_enable,
  988. .disable = _clk_dma_disable,
  989. };
  990. static struct clk rtic_clk = {
  991. .name = "rtic_clk",
  992. .parent = &ahb_clk,
  993. .enable = _clk_rtic_enable,
  994. .disable = _clk_rtic_disable,
  995. };
  996. static struct clk brom_clk = {
  997. .name = "brom_clk",
  998. .parent = &ahb_clk,
  999. .enable = _clk_enable,
  1000. .enable_reg = CCM_PCCR1,
  1001. .enable_shift = CCM_PCCR1_HCLK_BROM_OFFSET,
  1002. .disable = _clk_disable,
  1003. };
  1004. static struct clk emma_clk = {
  1005. .name = "emma_clk",
  1006. .parent = &ahb_clk,
  1007. .enable = _clk_emma_enable,
  1008. .disable = _clk_emma_disable,
  1009. };
  1010. static struct clk slcdc_clk = {
  1011. .name = "slcdc_clk",
  1012. .parent = &ahb_clk,
  1013. .enable = _clk_slcdc_enable,
  1014. .disable = _clk_slcdc_disable,
  1015. };
  1016. static struct clk fec_clk = {
  1017. .name = "fec_clk",
  1018. .parent = &ahb_clk,
  1019. .enable = _clk_fec_enable,
  1020. .disable = _clk_fec_disable,
  1021. };
  1022. static struct clk emi_clk = {
  1023. .name = "emi_clk",
  1024. .parent = &ahb_clk,
  1025. .enable = _clk_enable,
  1026. .enable_reg = CCM_PCCR1,
  1027. .enable_shift = CCM_PCCR1_HCLK_EMI_OFFSET,
  1028. .disable = _clk_disable,
  1029. };
  1030. static struct clk sahara2_clk = {
  1031. .name = "sahara_clk",
  1032. .parent = &ahb_clk,
  1033. .enable = _clk_sahara2_enable,
  1034. .disable = _clk_sahara2_disable,
  1035. };
  1036. static struct clk ata_clk = {
  1037. .name = "ata_clk",
  1038. .parent = &ahb_clk,
  1039. .enable = _clk_enable,
  1040. .enable_reg = CCM_PCCR1,
  1041. .enable_shift = CCM_PCCR1_HCLK_ATA_OFFSET,
  1042. .disable = _clk_disable,
  1043. };
  1044. static struct clk mstick1_clk = {
  1045. .name = "mstick1_clk",
  1046. .parent = &ipg_clk,
  1047. .enable = _clk_mstick1_enable,
  1048. .disable = _clk_mstick1_disable,
  1049. };
  1050. static struct clk wdog_clk = {
  1051. .name = "wdog_clk",
  1052. .parent = &ipg_clk,
  1053. .enable = _clk_enable,
  1054. .enable_reg = CCM_PCCR1,
  1055. .enable_shift = CCM_PCCR1_WDT_OFFSET,
  1056. .disable = _clk_disable,
  1057. };
  1058. static struct clk gpio_clk = {
  1059. .name = "gpio_clk",
  1060. .parent = &ipg_clk,
  1061. .enable = _clk_enable,
  1062. .enable_reg = CCM_PCCR1,
  1063. .enable_shift = CCM_PCCR0_GPIO_OFFSET,
  1064. .disable = _clk_disable,
  1065. };
  1066. static struct clk i2c_clk[] = {
  1067. {
  1068. .name = "i2c_clk",
  1069. .id = 0,
  1070. .parent = &ipg_clk,
  1071. .enable = _clk_enable,
  1072. .enable_reg = CCM_PCCR0,
  1073. .enable_shift = CCM_PCCR0_I2C1_OFFSET,
  1074. .disable = _clk_disable,
  1075. }, {
  1076. .name = "i2c_clk",
  1077. .id = 1,
  1078. .parent = &ipg_clk,
  1079. .enable = _clk_enable,
  1080. .enable_reg = CCM_PCCR0,
  1081. .enable_shift = CCM_PCCR0_I2C2_OFFSET,
  1082. .disable = _clk_disable,
  1083. },
  1084. };
  1085. static struct clk iim_clk = {
  1086. .name = "iim_clk",
  1087. .parent = &ipg_clk,
  1088. .enable = _clk_enable,
  1089. .enable_reg = CCM_PCCR0,
  1090. .enable_shift = CCM_PCCR0_IIM_OFFSET,
  1091. .disable = _clk_disable,
  1092. };
  1093. static struct clk kpp_clk = {
  1094. .name = "kpp_clk",
  1095. .parent = &ipg_clk,
  1096. .enable = _clk_enable,
  1097. .enable_reg = CCM_PCCR0,
  1098. .enable_shift = CCM_PCCR0_KPP_OFFSET,
  1099. .disable = _clk_disable,
  1100. };
  1101. static struct clk owire_clk = {
  1102. .name = "owire_clk",
  1103. .parent = &ipg_clk,
  1104. .enable = _clk_enable,
  1105. .enable_reg = CCM_PCCR0,
  1106. .enable_shift = CCM_PCCR0_OWIRE_OFFSET,
  1107. .disable = _clk_disable,
  1108. };
  1109. static struct clk rtc_clk = {
  1110. .name = "rtc_clk",
  1111. .parent = &ipg_clk,
  1112. .enable = _clk_enable,
  1113. .enable_reg = CCM_PCCR0,
  1114. .enable_shift = CCM_PCCR0_RTC_OFFSET,
  1115. .disable = _clk_disable,
  1116. };
  1117. static struct clk scc_clk = {
  1118. .name = "scc_clk",
  1119. .parent = &ipg_clk,
  1120. .enable = _clk_enable,
  1121. .enable_reg = CCM_PCCR0,
  1122. .enable_shift = CCM_PCCR0_SCC_OFFSET,
  1123. .disable = _clk_disable,
  1124. };
  1125. static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
  1126. {
  1127. u32 div;
  1128. unsigned long parent_rate;
  1129. parent_rate = clk_get_rate(clk->parent);
  1130. div = parent_rate / rate;
  1131. if (parent_rate % rate)
  1132. div++;
  1133. if (div > 8)
  1134. div = 8;
  1135. return parent_rate / div;
  1136. }
  1137. static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
  1138. {
  1139. u32 reg;
  1140. u32 div;
  1141. unsigned long parent_rate;
  1142. parent_rate = clk_get_rate(clk->parent);
  1143. div = parent_rate / rate;
  1144. if (div > 8 || div < 1 || ((parent_rate / div) != rate))
  1145. return -EINVAL;
  1146. div--;
  1147. reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKODIV_MASK;
  1148. reg |= div << CCM_PCDR0_CLKODIV_OFFSET;
  1149. __raw_writel(reg, CCM_PCDR0);
  1150. return 0;
  1151. }
  1152. static unsigned long _clk_clko_recalc(struct clk *clk)
  1153. {
  1154. u32 div;
  1155. unsigned long parent_rate;
  1156. parent_rate = clk_get_rate(clk->parent);
  1157. div = __raw_readl(CCM_PCDR0) & CCM_PCDR0_CLKODIV_MASK >>
  1158. CCM_PCDR0_CLKODIV_OFFSET;
  1159. div++;
  1160. return parent_rate / div;
  1161. }
  1162. static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
  1163. {
  1164. u32 reg;
  1165. reg = __raw_readl(CCM_CCSR) & ~CCM_CCSR_CLKOSEL_MASK;
  1166. if (parent == &ckil_clk)
  1167. reg |= 0 << CCM_CCSR_CLKOSEL_OFFSET;
  1168. else if (parent == &ckih_clk)
  1169. reg |= 2 << CCM_CCSR_CLKOSEL_OFFSET;
  1170. else if (parent == mpll_clk.parent)
  1171. reg |= 3 << CCM_CCSR_CLKOSEL_OFFSET;
  1172. else if (parent == spll_clk.parent)
  1173. reg |= 4 << CCM_CCSR_CLKOSEL_OFFSET;
  1174. else if (parent == &mpll_clk)
  1175. reg |= 5 << CCM_CCSR_CLKOSEL_OFFSET;
  1176. else if (parent == &spll_clk)
  1177. reg |= 6 << CCM_CCSR_CLKOSEL_OFFSET;
  1178. else if (parent == &cpu_clk)
  1179. reg |= 7 << CCM_CCSR_CLKOSEL_OFFSET;
  1180. else if (parent == &ahb_clk)
  1181. reg |= 8 << CCM_CCSR_CLKOSEL_OFFSET;
  1182. else if (parent == &ipg_clk)
  1183. reg |= 9 << CCM_CCSR_CLKOSEL_OFFSET;
  1184. else if (parent == &per_clk[0])
  1185. reg |= 0xA << CCM_CCSR_CLKOSEL_OFFSET;
  1186. else if (parent == &per_clk[1])
  1187. reg |= 0xB << CCM_CCSR_CLKOSEL_OFFSET;
  1188. else if (parent == &per_clk[2])
  1189. reg |= 0xC << CCM_CCSR_CLKOSEL_OFFSET;
  1190. else if (parent == &per_clk[3])
  1191. reg |= 0xD << CCM_CCSR_CLKOSEL_OFFSET;
  1192. else if (parent == &ssi1_clk[0])
  1193. reg |= 0xE << CCM_CCSR_CLKOSEL_OFFSET;
  1194. else if (parent == &ssi2_clk[0])
  1195. reg |= 0xF << CCM_CCSR_CLKOSEL_OFFSET;
  1196. else if (parent == &nfc_clk)
  1197. reg |= 0x10 << CCM_CCSR_CLKOSEL_OFFSET;
  1198. else if (parent == &mstick1_clk)
  1199. reg |= 0x11 << CCM_CCSR_CLKOSEL_OFFSET;
  1200. else if (parent == &vpu_clk)
  1201. reg |= 0x12 << CCM_CCSR_CLKOSEL_OFFSET;
  1202. else if (parent == &usb_clk[0])
  1203. reg |= 0x15 << CCM_CCSR_CLKOSEL_OFFSET;
  1204. else
  1205. return -EINVAL;
  1206. __raw_writel(reg, CCM_CCSR);
  1207. return 0;
  1208. }
  1209. static int _clk_clko_enable(struct clk *clk)
  1210. {
  1211. u32 reg;
  1212. reg = __raw_readl(CCM_PCDR0) | CCM_PCDR0_CLKO_EN;
  1213. __raw_writel(reg, CCM_PCDR0);
  1214. return 0;
  1215. }
  1216. static void _clk_clko_disable(struct clk *clk)
  1217. {
  1218. u32 reg;
  1219. reg = __raw_readl(CCM_PCDR0) & ~CCM_PCDR0_CLKO_EN;
  1220. __raw_writel(reg, CCM_PCDR0);
  1221. }
  1222. static struct clk clko_clk = {
  1223. .name = "clko_clk",
  1224. .get_rate = _clk_clko_recalc,
  1225. .set_rate = _clk_clko_set_rate,
  1226. .round_rate = _clk_clko_round_rate,
  1227. .set_parent = _clk_clko_set_parent,
  1228. .enable = _clk_clko_enable,
  1229. .disable = _clk_clko_disable,
  1230. };
  1231. static struct clk *mxc_clks[] = {
  1232. &ckih_clk,
  1233. &ckil_clk,
  1234. &mpll_clk,
  1235. &mpll_main_clk[0],
  1236. &mpll_main_clk[1],
  1237. &spll_clk,
  1238. &cpu_clk,
  1239. &ahb_clk,
  1240. &ipg_clk,
  1241. &per_clk[0],
  1242. &per_clk[1],
  1243. &per_clk[2],
  1244. &per_clk[3],
  1245. &clko_clk,
  1246. &uart1_clk[0],
  1247. &uart1_clk[1],
  1248. &uart2_clk[0],
  1249. &uart2_clk[1],
  1250. &uart3_clk[0],
  1251. &uart3_clk[1],
  1252. &uart4_clk[0],
  1253. &uart4_clk[1],
  1254. &uart5_clk[0],
  1255. &uart5_clk[1],
  1256. &uart6_clk[0],
  1257. &uart6_clk[1],
  1258. &gpt1_clk[0],
  1259. &gpt1_clk[1],
  1260. &gpt2_clk[0],
  1261. &gpt2_clk[1],
  1262. &gpt3_clk[0],
  1263. &gpt3_clk[1],
  1264. &gpt4_clk[0],
  1265. &gpt4_clk[1],
  1266. &gpt5_clk[0],
  1267. &gpt5_clk[1],
  1268. &gpt6_clk[0],
  1269. &gpt6_clk[1],
  1270. &pwm_clk[0],
  1271. &pwm_clk[1],
  1272. &sdhc1_clk[0],
  1273. &sdhc1_clk[1],
  1274. &sdhc2_clk[0],
  1275. &sdhc2_clk[1],
  1276. &sdhc3_clk[0],
  1277. &sdhc3_clk[1],
  1278. &cspi1_clk[0],
  1279. &cspi1_clk[1],
  1280. &cspi2_clk[0],
  1281. &cspi2_clk[1],
  1282. &cspi3_clk[0],
  1283. &cspi3_clk[1],
  1284. &lcdc_clk[0],
  1285. &lcdc_clk[1],
  1286. &lcdc_clk[2],
  1287. &csi_clk[0],
  1288. &csi_clk[1],
  1289. &usb_clk[0],
  1290. &usb_clk[1],
  1291. &ssi1_clk[0],
  1292. &ssi1_clk[1],
  1293. &ssi2_clk[0],
  1294. &ssi2_clk[1],
  1295. &nfc_clk,
  1296. &vpu_clk,
  1297. &dma_clk,
  1298. &rtic_clk,
  1299. &brom_clk,
  1300. &emma_clk,
  1301. &slcdc_clk,
  1302. &fec_clk,
  1303. &emi_clk,
  1304. &sahara2_clk,
  1305. &ata_clk,
  1306. &mstick1_clk,
  1307. &wdog_clk,
  1308. &gpio_clk,
  1309. &i2c_clk[0],
  1310. &i2c_clk[1],
  1311. &iim_clk,
  1312. &kpp_clk,
  1313. &owire_clk,
  1314. &rtc_clk,
  1315. &scc_clk,
  1316. };
  1317. void __init change_external_low_reference(unsigned long new_ref)
  1318. {
  1319. external_low_reference = new_ref;
  1320. }
  1321. unsigned long __init clk_early_get_timer_rate(void)
  1322. {
  1323. return clk_get_rate(&per_clk[0]);
  1324. }
  1325. static void __init probe_mxc_clocks(void)
  1326. {
  1327. int i;
  1328. if (mx27_revision() >= CHIP_REV_2_0) {
  1329. if (CSCR() & 0x8000)
  1330. cpu_clk.parent = &mpll_main_clk[0];
  1331. if (!(CSCR() & 0x00800000))
  1332. ssi2_clk[0].parent = &spll_clk;
  1333. if (!(CSCR() & 0x00400000))
  1334. ssi1_clk[0].parent = &spll_clk;
  1335. if (!(CSCR() & 0x00200000))
  1336. vpu_clk.parent = &spll_clk;
  1337. } else {
  1338. cpu_clk.parent = &mpll_clk;
  1339. cpu_clk.set_parent = NULL;
  1340. cpu_clk.round_rate = NULL;
  1341. cpu_clk.set_rate = NULL;
  1342. ahb_clk.parent = &mpll_clk;
  1343. for (i = 0; i < sizeof(per_clk) / sizeof(per_clk[0]); i++)
  1344. per_clk[i].parent = &mpll_clk;
  1345. ssi1_clk[0].parent = &mpll_clk;
  1346. ssi2_clk[0].parent = &mpll_clk;
  1347. vpu_clk.parent = &mpll_clk;
  1348. }
  1349. }
  1350. /*
  1351. * must be called very early to get information about the
  1352. * available clock rate when the timer framework starts
  1353. */
  1354. int __init mxc_clocks_init(unsigned long fref)
  1355. {
  1356. u32 cscr;
  1357. struct clk **clkp;
  1358. external_high_reference = fref;
  1359. /* detect clock reference for both system PLL */
  1360. cscr = CSCR();
  1361. if (cscr & CCM_CSCR_MCU)
  1362. mpll_clk.parent = &ckih_clk;
  1363. else
  1364. mpll_clk.parent = &ckil_clk;
  1365. if (cscr & CCM_CSCR_SP)
  1366. spll_clk.parent = &ckih_clk;
  1367. else
  1368. spll_clk.parent = &ckil_clk;
  1369. probe_mxc_clocks();
  1370. per_clk[0].enable(&per_clk[0]);
  1371. gpt1_clk[1].enable(&gpt1_clk[1]);
  1372. for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
  1373. clk_register(*clkp);
  1374. /* Turn off all possible clocks */
  1375. __raw_writel(CCM_PCCR0_GPT1_MASK, CCM_PCCR0);
  1376. __raw_writel(CCM_PCCR1_PERCLK1_MASK | CCM_PCCR1_HCLK_EMI_MASK,
  1377. CCM_PCCR1);
  1378. spll_clk.disable(&spll_clk);
  1379. /* This will propagate to all children and init all the clock rates */
  1380. clk_enable(&emi_clk);
  1381. clk_enable(&gpio_clk);
  1382. clk_enable(&iim_clk);
  1383. clk_enable(&gpt1_clk[0]);
  1384. #ifdef CONFIG_DEBUG_LL_CONSOLE
  1385. clk_enable(&uart1_clk[0]);
  1386. #endif
  1387. return 0;
  1388. }