clock.c 18 KB

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