clock.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. /* linux/arch/arm/mach-s3c2443/clock.c
  2. *
  3. * Copyright (c) 2007,2010 Simtec Electronics
  4. * Ben Dooks <ben@simtec.co.uk>
  5. *
  6. * S3C2443 Clock control support
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */
  22. #include <linux/init.h>
  23. #include <linux/module.h>
  24. #include <linux/kernel.h>
  25. #include <linux/list.h>
  26. #include <linux/errno.h>
  27. #include <linux/err.h>
  28. #include <linux/sysdev.h>
  29. #include <linux/clk.h>
  30. #include <linux/mutex.h>
  31. #include <linux/serial_core.h>
  32. #include <linux/io.h>
  33. #include <asm/mach/map.h>
  34. #include <mach/hardware.h>
  35. #include <mach/regs-s3c2443-clock.h>
  36. #include <plat/cpu-freq.h>
  37. #include <plat/s3c2443.h>
  38. #include <plat/clock.h>
  39. #include <plat/clock-clksrc.h>
  40. #include <plat/cpu.h>
  41. /* We currently have to assume that the system is running
  42. * from the XTPll input, and that all ***REFCLKs are being
  43. * fed from it, as we cannot read the state of OM[4] from
  44. * software.
  45. *
  46. * It would be possible for each board initialisation to
  47. * set the correct muxing at initialisation
  48. */
  49. static int s3c2443_gate(void __iomem *reg, struct clk *clk, int enable)
  50. {
  51. u32 ctrlbit = clk->ctrlbit;
  52. u32 con = __raw_readl(reg);
  53. if (enable)
  54. con |= ctrlbit;
  55. else
  56. con &= ~ctrlbit;
  57. __raw_writel(con, reg);
  58. return 0;
  59. }
  60. static int s3c2443_clkcon_enable_h(struct clk *clk, int enable)
  61. {
  62. return s3c2443_gate(S3C2443_HCLKCON, clk, enable);
  63. }
  64. static int s3c2443_clkcon_enable_p(struct clk *clk, int enable)
  65. {
  66. return s3c2443_gate(S3C2443_PCLKCON, clk, enable);
  67. }
  68. static int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
  69. {
  70. return s3c2443_gate(S3C2443_SCLKCON, clk, enable);
  71. }
  72. /* s3c2443_roundate_clksrc is close enough to s3c_roundate_clksrc */
  73. /* clock selections */
  74. static struct clk clk_mpllref = {
  75. .name = "mpllref",
  76. .parent = &clk_xtal,
  77. .id = -1,
  78. };
  79. #if 0
  80. static struct clk clk_mpll = {
  81. .name = "mpll",
  82. .parent = &clk_mpllref,
  83. .id = -1,
  84. };
  85. #endif
  86. static struct clk clk_i2s_ext = {
  87. .name = "i2s-ext",
  88. .id = -1,
  89. };
  90. static struct clk *clk_epllref_sources[] = {
  91. [0] = &clk_mpllref,
  92. [1] = &clk_mpllref,
  93. [2] = &clk_xtal,
  94. [3] = &clk_ext,
  95. };
  96. static struct clksrc_clk clk_epllref = {
  97. .clk = {
  98. .name = "epllref",
  99. .id = -1,
  100. },
  101. .sources = &(struct clksrc_sources) {
  102. .sources = clk_epllref_sources,
  103. .nr_sources = ARRAY_SIZE(clk_epllref_sources),
  104. },
  105. .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 7 },
  106. };
  107. static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
  108. {
  109. unsigned long parent_rate = clk_get_rate(clk->parent);
  110. unsigned long div = __raw_readl(S3C2443_CLKDIV0);
  111. div &= S3C2443_CLKDIV0_EXTDIV_MASK;
  112. div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1); /* x2 */
  113. return parent_rate / (div + 1);
  114. }
  115. static struct clk clk_mdivclk = {
  116. .name = "mdivclk",
  117. .parent = &clk_mpllref,
  118. .id = -1,
  119. .ops = &(struct clk_ops) {
  120. .get_rate = s3c2443_getrate_mdivclk,
  121. },
  122. };
  123. static int s3c2443_setparent_msysclk(struct clk *clk, struct clk *parent)
  124. {
  125. unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
  126. clksrc &= ~(S3C2443_CLKSRC_MSYSCLK_MPLL |
  127. S3C2443_CLKSRC_EXTCLK_DIV);
  128. if (parent == &clk_mpll)
  129. clksrc |= S3C2443_CLKSRC_MSYSCLK_MPLL;
  130. else if (parent == &clk_mdivclk)
  131. clksrc |= S3C2443_CLKSRC_EXTCLK_DIV;
  132. else if (parent != &clk_mpllref)
  133. return -EINVAL;
  134. __raw_writel(clksrc, S3C2443_CLKSRC);
  135. clk->parent = parent;
  136. return 0;
  137. }
  138. static struct clk clk_msysclk = {
  139. .name = "msysclk",
  140. .parent = &clk_xtal,
  141. .id = -1,
  142. .ops = &(struct clk_ops) {
  143. .set_parent = s3c2443_setparent_msysclk,
  144. },
  145. };
  146. /* armdiv
  147. *
  148. * this clock is sourced from msysclk and can have a number of
  149. * divider values applied to it to then be fed into armclk.
  150. */
  151. static struct clk clk_armdiv = {
  152. .name = "armdiv",
  153. .id = -1,
  154. .parent = &clk_msysclk,
  155. };
  156. /* armclk
  157. *
  158. * this is the clock fed into the ARM core itself, either from
  159. * armdiv or from hclk.
  160. */
  161. static int s3c2443_setparent_armclk(struct clk *clk, struct clk *parent)
  162. {
  163. unsigned long clkdiv0;
  164. clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
  165. if (parent == &clk_armdiv)
  166. clkdiv0 &= ~S3C2443_CLKDIV0_DVS;
  167. else if (parent == &clk_h)
  168. clkdiv0 |= S3C2443_CLKDIV0_DVS;
  169. else
  170. return -EINVAL;
  171. __raw_writel(clkdiv0, S3C2443_CLKDIV0);
  172. return 0;
  173. }
  174. static struct clk clk_arm = {
  175. .name = "armclk",
  176. .id = -1,
  177. .ops = &(struct clk_ops) {
  178. .set_parent = s3c2443_setparent_armclk,
  179. },
  180. };
  181. /* esysclk
  182. *
  183. * this is sourced from either the EPLL or the EPLLref clock
  184. */
  185. static int s3c2443_setparent_esysclk(struct clk *clk, struct clk *parent)
  186. {
  187. unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
  188. if (parent == &clk_epll)
  189. clksrc |= S3C2443_CLKSRC_ESYSCLK_EPLL;
  190. else if (parent == &clk_epllref.clk)
  191. clksrc &= ~S3C2443_CLKSRC_ESYSCLK_EPLL;
  192. else
  193. return -EINVAL;
  194. __raw_writel(clksrc, S3C2443_CLKSRC);
  195. clk->parent = parent;
  196. return 0;
  197. }
  198. static struct clk clk_esysclk = {
  199. .name = "esysclk",
  200. .parent = &clk_epll,
  201. .id = -1,
  202. .ops = &(struct clk_ops) {
  203. .set_parent = s3c2443_setparent_esysclk,
  204. },
  205. };
  206. /* uartclk
  207. *
  208. * UART baud-rate clock sourced from esysclk via a divisor
  209. */
  210. static struct clksrc_clk clk_uart = {
  211. .clk = {
  212. .name = "uartclk",
  213. .id = -1,
  214. .parent = &clk_esysclk,
  215. },
  216. .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 },
  217. };
  218. /* hsspi
  219. *
  220. * high-speed spi clock, sourced from esysclk
  221. */
  222. static struct clksrc_clk clk_hsspi = {
  223. .clk = {
  224. .name = "hsspi",
  225. .id = -1,
  226. .parent = &clk_esysclk,
  227. .ctrlbit = S3C2443_SCLKCON_HSSPICLK,
  228. .enable = s3c2443_clkcon_enable_s,
  229. },
  230. .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 },
  231. };
  232. /* usbhost
  233. *
  234. * usb host bus-clock, usually 48MHz to provide USB bus clock timing
  235. */
  236. static struct clksrc_clk clk_usb_bus_host = {
  237. .clk = {
  238. .name = "usb-bus-host-parent",
  239. .id = -1,
  240. .parent = &clk_esysclk,
  241. .ctrlbit = S3C2443_SCLKCON_USBHOST,
  242. .enable = s3c2443_clkcon_enable_s,
  243. },
  244. .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 },
  245. };
  246. /* clk_hsmcc_div
  247. *
  248. * this clock is sourced from epll, and is fed through a divider,
  249. * to a mux controlled by sclkcon where either it or a extclk can
  250. * be fed to the hsmmc block
  251. */
  252. static struct clksrc_clk clk_hsmmc_div = {
  253. .clk = {
  254. .name = "hsmmc-div",
  255. .id = -1,
  256. .parent = &clk_esysclk,
  257. },
  258. .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
  259. };
  260. static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
  261. {
  262. unsigned long clksrc = __raw_readl(S3C2443_SCLKCON);
  263. clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT |
  264. S3C2443_SCLKCON_HSMMCCLK_EPLL);
  265. if (parent == &clk_epll)
  266. clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL;
  267. else if (parent == &clk_ext)
  268. clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT;
  269. else
  270. return -EINVAL;
  271. if (clk->usage > 0) {
  272. __raw_writel(clksrc, S3C2443_SCLKCON);
  273. }
  274. clk->parent = parent;
  275. return 0;
  276. }
  277. static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
  278. {
  279. return s3c2443_setparent_hsmmc(clk, clk->parent);
  280. }
  281. static struct clk clk_hsmmc = {
  282. .name = "hsmmc-if",
  283. .id = -1,
  284. .parent = &clk_hsmmc_div.clk,
  285. .enable = s3c2443_enable_hsmmc,
  286. .ops = &(struct clk_ops) {
  287. .set_parent = s3c2443_setparent_hsmmc,
  288. },
  289. };
  290. /* i2s_eplldiv
  291. *
  292. * This clock is the output from the I2S divisor of ESYSCLK, and is seperate
  293. * from the mux that comes after it (cannot merge into one single clock)
  294. */
  295. static struct clksrc_clk clk_i2s_eplldiv = {
  296. .clk = {
  297. .name = "i2s-eplldiv",
  298. .id = -1,
  299. .parent = &clk_esysclk,
  300. },
  301. .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
  302. };
  303. /* i2s-ref
  304. *
  305. * i2s bus reference clock, selectable from external, esysclk or epllref
  306. *
  307. * Note, this used to be two clocks, but was compressed into one.
  308. */
  309. struct clk *clk_i2s_srclist[] = {
  310. [0] = &clk_i2s_eplldiv.clk,
  311. [1] = &clk_i2s_ext,
  312. [2] = &clk_epllref.clk,
  313. [3] = &clk_epllref.clk,
  314. };
  315. static struct clksrc_clk clk_i2s = {
  316. .clk = {
  317. .name = "i2s-if",
  318. .id = -1,
  319. .ctrlbit = S3C2443_SCLKCON_I2SCLK,
  320. .enable = s3c2443_clkcon_enable_s,
  321. },
  322. .sources = &(struct clksrc_sources) {
  323. .sources = clk_i2s_srclist,
  324. .nr_sources = ARRAY_SIZE(clk_i2s_srclist),
  325. },
  326. .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
  327. };
  328. /* cam-if
  329. *
  330. * camera interface bus-clock, divided down from esysclk
  331. */
  332. static struct clksrc_clk clk_cam = {
  333. .clk = {
  334. .name = "camif-upll", /* same as 2440 name */
  335. .id = -1,
  336. .parent = &clk_esysclk,
  337. .ctrlbit = S3C2443_SCLKCON_CAMCLK,
  338. .enable = s3c2443_clkcon_enable_s,
  339. },
  340. .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 26 },
  341. };
  342. /* display-if
  343. *
  344. * display interface clock, divided from esysclk
  345. */
  346. static struct clksrc_clk clk_display = {
  347. .clk = {
  348. .name = "display-if",
  349. .id = -1,
  350. .parent = &clk_esysclk,
  351. .ctrlbit = S3C2443_SCLKCON_DISPCLK,
  352. .enable = s3c2443_clkcon_enable_s,
  353. },
  354. .reg_div = { .reg = S3C2443_CLKDIV1, .size = 8, .shift = 16 },
  355. };
  356. /* prediv
  357. *
  358. * this divides the msysclk down to pass to h/p/etc.
  359. */
  360. static unsigned long s3c2443_prediv_getrate(struct clk *clk)
  361. {
  362. unsigned long rate = clk_get_rate(clk->parent);
  363. unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
  364. clkdiv0 &= S3C2443_CLKDIV0_PREDIV_MASK;
  365. clkdiv0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT;
  366. return rate / (clkdiv0 + 1);
  367. }
  368. static struct clk clk_prediv = {
  369. .name = "prediv",
  370. .id = -1,
  371. .parent = &clk_msysclk,
  372. .ops = &(struct clk_ops) {
  373. .get_rate = s3c2443_prediv_getrate,
  374. },
  375. };
  376. /* standard clock definitions */
  377. static struct clk init_clocks_disable[] = {
  378. {
  379. .name = "nand",
  380. .id = -1,
  381. .parent = &clk_h,
  382. }, {
  383. .name = "sdi",
  384. .id = -1,
  385. .parent = &clk_p,
  386. .enable = s3c2443_clkcon_enable_p,
  387. .ctrlbit = S3C2443_PCLKCON_SDI,
  388. }, {
  389. .name = "adc",
  390. .id = -1,
  391. .parent = &clk_p,
  392. .enable = s3c2443_clkcon_enable_p,
  393. .ctrlbit = S3C2443_PCLKCON_ADC,
  394. }, {
  395. .name = "i2c",
  396. .id = -1,
  397. .parent = &clk_p,
  398. .enable = s3c2443_clkcon_enable_p,
  399. .ctrlbit = S3C2443_PCLKCON_IIC,
  400. }, {
  401. .name = "iis",
  402. .id = -1,
  403. .parent = &clk_p,
  404. .enable = s3c2443_clkcon_enable_p,
  405. .ctrlbit = S3C2443_PCLKCON_IIS,
  406. }, {
  407. .name = "spi",
  408. .id = 0,
  409. .parent = &clk_p,
  410. .enable = s3c2443_clkcon_enable_p,
  411. .ctrlbit = S3C2443_PCLKCON_SPI0,
  412. }, {
  413. .name = "spi",
  414. .id = 1,
  415. .parent = &clk_p,
  416. .enable = s3c2443_clkcon_enable_p,
  417. .ctrlbit = S3C2443_PCLKCON_SPI1,
  418. }
  419. };
  420. static struct clk init_clocks[] = {
  421. {
  422. .name = "dma",
  423. .id = 0,
  424. .parent = &clk_h,
  425. .enable = s3c2443_clkcon_enable_h,
  426. .ctrlbit = S3C2443_HCLKCON_DMA0,
  427. }, {
  428. .name = "dma",
  429. .id = 1,
  430. .parent = &clk_h,
  431. .enable = s3c2443_clkcon_enable_h,
  432. .ctrlbit = S3C2443_HCLKCON_DMA1,
  433. }, {
  434. .name = "dma",
  435. .id = 2,
  436. .parent = &clk_h,
  437. .enable = s3c2443_clkcon_enable_h,
  438. .ctrlbit = S3C2443_HCLKCON_DMA2,
  439. }, {
  440. .name = "dma",
  441. .id = 3,
  442. .parent = &clk_h,
  443. .enable = s3c2443_clkcon_enable_h,
  444. .ctrlbit = S3C2443_HCLKCON_DMA3,
  445. }, {
  446. .name = "dma",
  447. .id = 4,
  448. .parent = &clk_h,
  449. .enable = s3c2443_clkcon_enable_h,
  450. .ctrlbit = S3C2443_HCLKCON_DMA4,
  451. }, {
  452. .name = "dma",
  453. .id = 5,
  454. .parent = &clk_h,
  455. .enable = s3c2443_clkcon_enable_h,
  456. .ctrlbit = S3C2443_HCLKCON_DMA5,
  457. }, {
  458. .name = "lcd",
  459. .id = -1,
  460. .parent = &clk_h,
  461. .enable = s3c2443_clkcon_enable_h,
  462. .ctrlbit = S3C2443_HCLKCON_LCDC,
  463. }, {
  464. .name = "gpio",
  465. .id = -1,
  466. .parent = &clk_p,
  467. .enable = s3c2443_clkcon_enable_p,
  468. .ctrlbit = S3C2443_PCLKCON_GPIO,
  469. }, {
  470. .name = "usb-host",
  471. .id = -1,
  472. .parent = &clk_h,
  473. .enable = s3c2443_clkcon_enable_h,
  474. .ctrlbit = S3C2443_HCLKCON_USBH,
  475. }, {
  476. .name = "usb-device",
  477. .id = -1,
  478. .parent = &clk_h,
  479. .enable = s3c2443_clkcon_enable_h,
  480. .ctrlbit = S3C2443_HCLKCON_USBD,
  481. }, {
  482. .name = "hsmmc",
  483. .id = -1,
  484. .parent = &clk_h,
  485. .enable = s3c2443_clkcon_enable_h,
  486. .ctrlbit = S3C2443_HCLKCON_HSMMC,
  487. }, {
  488. .name = "cfc",
  489. .id = -1,
  490. .parent = &clk_h,
  491. .enable = s3c2443_clkcon_enable_h,
  492. .ctrlbit = S3C2443_HCLKCON_CFC,
  493. }, {
  494. .name = "ssmc",
  495. .id = -1,
  496. .parent = &clk_h,
  497. .enable = s3c2443_clkcon_enable_h,
  498. .ctrlbit = S3C2443_HCLKCON_SSMC,
  499. }, {
  500. .name = "timers",
  501. .id = -1,
  502. .parent = &clk_p,
  503. .enable = s3c2443_clkcon_enable_p,
  504. .ctrlbit = S3C2443_PCLKCON_PWMT,
  505. }, {
  506. .name = "uart",
  507. .id = 0,
  508. .parent = &clk_p,
  509. .enable = s3c2443_clkcon_enable_p,
  510. .ctrlbit = S3C2443_PCLKCON_UART0,
  511. }, {
  512. .name = "uart",
  513. .id = 1,
  514. .parent = &clk_p,
  515. .enable = s3c2443_clkcon_enable_p,
  516. .ctrlbit = S3C2443_PCLKCON_UART1,
  517. }, {
  518. .name = "uart",
  519. .id = 2,
  520. .parent = &clk_p,
  521. .enable = s3c2443_clkcon_enable_p,
  522. .ctrlbit = S3C2443_PCLKCON_UART2,
  523. }, {
  524. .name = "uart",
  525. .id = 3,
  526. .parent = &clk_p,
  527. .enable = s3c2443_clkcon_enable_p,
  528. .ctrlbit = S3C2443_PCLKCON_UART3,
  529. }, {
  530. .name = "rtc",
  531. .id = -1,
  532. .parent = &clk_p,
  533. .enable = s3c2443_clkcon_enable_p,
  534. .ctrlbit = S3C2443_PCLKCON_RTC,
  535. }, {
  536. .name = "watchdog",
  537. .id = -1,
  538. .parent = &clk_p,
  539. .ctrlbit = S3C2443_PCLKCON_WDT,
  540. }, {
  541. .name = "usb-bus-host",
  542. .id = -1,
  543. .parent = &clk_usb_bus_host.clk,
  544. }, {
  545. .name = "ac97",
  546. .id = -1,
  547. .parent = &clk_p,
  548. .ctrlbit = S3C2443_PCLKCON_AC97,
  549. }
  550. };
  551. /* clocks to add where we need to check their parentage */
  552. /* s3c2443_clk_initparents
  553. *
  554. * Initialise the parents for the clocks that we get at start-time
  555. */
  556. static int __init clk_init_set_parent(struct clk *clk, struct clk *parent)
  557. {
  558. printk(KERN_DEBUG "clock %s: parent %s\n", clk->name, parent->name);
  559. return clk_set_parent(clk, parent);
  560. }
  561. static struct clksrc_clk __initdata *init_list[] = {
  562. &clk_epllref, /* should be first */
  563. &clk_i2s_eplldiv,
  564. &clk_i2s,
  565. &clk_cam,
  566. &clk_uart,
  567. &clk_display,
  568. &clk_hsmmc_div,
  569. &clk_usb_bus_host,
  570. };
  571. static void __init s3c2443_clk_initparents(void)
  572. {
  573. unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
  574. struct clk *parent;
  575. int ptr;
  576. /* esysclk source */
  577. parent = (clksrc & S3C2443_CLKSRC_ESYSCLK_EPLL) ?
  578. &clk_epll : &clk_epllref.clk;
  579. clk_init_set_parent(&clk_esysclk, parent);
  580. /* msysclk source */
  581. if (clksrc & S3C2443_CLKSRC_MSYSCLK_MPLL) {
  582. parent = &clk_mpll;
  583. } else {
  584. parent = (clksrc & S3C2443_CLKSRC_EXTCLK_DIV) ?
  585. &clk_mdivclk : &clk_mpllref;
  586. }
  587. clk_init_set_parent(&clk_msysclk, parent);
  588. /* arm */
  589. if (__raw_readl(S3C2443_CLKDIV0) & S3C2443_CLKDIV0_DVS)
  590. parent = &clk_h;
  591. else
  592. parent = &clk_armdiv;
  593. clk_init_set_parent(&clk_arm, parent);
  594. for (ptr = 0; ptr < ARRAY_SIZE(init_list); ptr++)
  595. s3c_set_clksrc(init_list[ptr], false);
  596. }
  597. /* armdiv divisor table */
  598. static unsigned int armdiv[16] = {
  599. [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 1,
  600. [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 2,
  601. [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 3,
  602. [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 4,
  603. [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 6,
  604. [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 8,
  605. [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 12,
  606. [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 16,
  607. };
  608. static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
  609. {
  610. clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
  611. return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
  612. }
  613. static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0)
  614. {
  615. clkcon0 &= S3C2443_CLKDIV0_HCLKDIV_MASK;
  616. return clkcon0 + 1;
  617. }
  618. /* clocks to add straight away */
  619. static struct clksrc_clk *clksrcs[] __initdata = {
  620. &clk_usb_bus_host,
  621. &clk_epllref,
  622. &clk_uart,
  623. &clk_display,
  624. &clk_cam,
  625. &clk_i2s_eplldiv,
  626. &clk_i2s,
  627. &clk_hsspi,
  628. &clk_hsmmc_div,
  629. };
  630. static struct clk *clks[] __initdata = {
  631. &clk_ext,
  632. &clk_epll,
  633. &clk_usb_bus,
  634. &clk_esysclk,
  635. &clk_mpllref,
  636. &clk_msysclk,
  637. &clk_hsmmc,
  638. &clk_armdiv,
  639. &clk_arm,
  640. &clk_prediv,
  641. };
  642. void __init_or_cpufreq s3c2443_setup_clocks(void)
  643. {
  644. unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
  645. unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
  646. struct clk *xtal_clk;
  647. unsigned long xtal;
  648. unsigned long pll;
  649. unsigned long fclk;
  650. unsigned long hclk;
  651. unsigned long pclk;
  652. xtal_clk = clk_get(NULL, "xtal");
  653. xtal = clk_get_rate(xtal_clk);
  654. clk_put(xtal_clk);
  655. pll = s3c2443_get_mpll(mpllcon, xtal);
  656. clk_msysclk.rate = pll;
  657. fclk = pll / s3c2443_fclk_div(clkdiv0);
  658. hclk = s3c2443_prediv_getrate(&clk_prediv);
  659. hclk /= s3c2443_get_hdiv(clkdiv0);
  660. pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);
  661. s3c24xx_setup_clocks(fclk, hclk, pclk);
  662. printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n",
  663. (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on",
  664. print_mhz(pll), print_mhz(fclk),
  665. print_mhz(hclk), print_mhz(pclk));
  666. s3c24xx_setup_clocks(fclk, hclk, pclk);
  667. }
  668. void __init s3c2443_init_clocks(int xtal)
  669. {
  670. struct clk *clkp;
  671. unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
  672. int ret;
  673. int ptr;
  674. /* s3c2443 parents h and p clocks from prediv */
  675. clk_h.parent = &clk_prediv;
  676. clk_p.parent = &clk_prediv;
  677. s3c24xx_register_baseclocks(xtal);
  678. s3c2443_setup_clocks();
  679. s3c2443_clk_initparents();
  680. for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
  681. clkp = clks[ptr];
  682. ret = s3c24xx_register_clock(clkp);
  683. if (ret < 0) {
  684. printk(KERN_ERR "Failed to register clock %s (%d)\n",
  685. clkp->name, ret);
  686. }
  687. }
  688. for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
  689. s3c_register_clksrc(clksrcs[ptr], 1);
  690. clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
  691. clk_epll.parent = &clk_epllref.clk;
  692. clk_usb_bus.parent = &clk_usb_bus_host.clk;
  693. /* ensure usb bus clock is within correct rate of 48MHz */
  694. if (clk_get_rate(&clk_usb_bus_host.clk) != (48 * 1000 * 1000)) {
  695. printk(KERN_INFO "Warning: USB host bus not at 48MHz\n");
  696. clk_set_rate(&clk_usb_bus_host.clk, 48*1000*1000);
  697. }
  698. printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
  699. (epllcon & S3C2443_PLLCON_OFF) ? "off":"on",
  700. print_mhz(clk_get_rate(&clk_epll)),
  701. print_mhz(clk_get_rate(&clk_usb_bus)));
  702. /* register clocks from clock array */
  703. s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
  704. /* We must be careful disabling the clocks we are not intending to
  705. * be using at boot time, as subsystems such as the LCD which do
  706. * their own DMA requests to the bus can cause the system to lockup
  707. * if they where in the middle of requesting bus access.
  708. *
  709. * Disabling the LCD clock if the LCD is active is very dangerous,
  710. * and therefore the bootloader should be careful to not enable
  711. * the LCD clock if it is not needed.
  712. */
  713. /* install (and disable) the clocks we do not need immediately */
  714. clkp = init_clocks_disable;
  715. for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
  716. ret = s3c24xx_register_clock(clkp);
  717. if (ret < 0) {
  718. printk(KERN_ERR "Failed to register clock %s (%d)\n",
  719. clkp->name, ret);
  720. }
  721. (clkp->enable)(clkp, 0);
  722. }
  723. s3c_pwmclk_init();
  724. }