clock.c 19 KB

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