s3c6400-clock.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. /* linux/arch/arm/plat-s3c64xx/s3c6400-clock.c
  2. *
  3. * Copyright 2008 Openmoko, Inc.
  4. * Copyright 2008 Simtec Electronics
  5. * Ben Dooks <ben@simtec.co.uk>
  6. * http://armlinux.simtec.co.uk/
  7. *
  8. * S3C6400 based common clock support
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. */
  14. #include <linux/init.h>
  15. #include <linux/module.h>
  16. #include <linux/kernel.h>
  17. #include <linux/list.h>
  18. #include <linux/errno.h>
  19. #include <linux/err.h>
  20. #include <linux/clk.h>
  21. #include <linux/sysdev.h>
  22. #include <linux/io.h>
  23. #include <mach/hardware.h>
  24. #include <mach/map.h>
  25. #include <plat/cpu-freq.h>
  26. #include <plat/regs-clock.h>
  27. #include <plat/clock.h>
  28. #include <plat/cpu.h>
  29. #include <plat/pll.h>
  30. /* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
  31. * ext_xtal_mux for want of an actual name from the manual.
  32. */
  33. static struct clk clk_ext_xtal_mux = {
  34. .name = "ext_xtal",
  35. .id = -1,
  36. };
  37. #define clk_fin_apll clk_ext_xtal_mux
  38. #define clk_fin_mpll clk_ext_xtal_mux
  39. #define clk_fin_epll clk_ext_xtal_mux
  40. #define clk_fout_mpll clk_mpll
  41. struct clk_sources {
  42. unsigned int nr_sources;
  43. struct clk **sources;
  44. };
  45. struct clksrc_clk {
  46. struct clk clk;
  47. unsigned int mask;
  48. unsigned int shift;
  49. struct clk_sources *sources;
  50. unsigned int divider_shift;
  51. void __iomem *reg_divider;
  52. };
  53. static struct clk clk_fout_apll = {
  54. .name = "fout_apll",
  55. .id = -1,
  56. };
  57. static struct clk *clk_src_apll_list[] = {
  58. [0] = &clk_fin_apll,
  59. [1] = &clk_fout_apll,
  60. };
  61. static struct clk_sources clk_src_apll = {
  62. .sources = clk_src_apll_list,
  63. .nr_sources = ARRAY_SIZE(clk_src_apll_list),
  64. };
  65. static struct clksrc_clk clk_mout_apll = {
  66. .clk = {
  67. .name = "mout_apll",
  68. .id = -1,
  69. },
  70. .shift = S3C6400_CLKSRC_APLL_MOUT_SHIFT,
  71. .mask = S3C6400_CLKSRC_APLL_MOUT,
  72. .sources = &clk_src_apll,
  73. };
  74. static struct clk clk_fout_epll = {
  75. .name = "fout_epll",
  76. .id = -1,
  77. };
  78. static struct clk *clk_src_epll_list[] = {
  79. [0] = &clk_fin_epll,
  80. [1] = &clk_fout_epll,
  81. };
  82. static struct clk_sources clk_src_epll = {
  83. .sources = clk_src_epll_list,
  84. .nr_sources = ARRAY_SIZE(clk_src_epll_list),
  85. };
  86. static struct clksrc_clk clk_mout_epll = {
  87. .clk = {
  88. .name = "mout_epll",
  89. .id = -1,
  90. },
  91. .shift = S3C6400_CLKSRC_EPLL_MOUT_SHIFT,
  92. .mask = S3C6400_CLKSRC_EPLL_MOUT,
  93. .sources = &clk_src_epll,
  94. };
  95. static struct clk *clk_src_mpll_list[] = {
  96. [0] = &clk_fin_mpll,
  97. [1] = &clk_fout_mpll,
  98. };
  99. static struct clk_sources clk_src_mpll = {
  100. .sources = clk_src_mpll_list,
  101. .nr_sources = ARRAY_SIZE(clk_src_mpll_list),
  102. };
  103. static struct clksrc_clk clk_mout_mpll = {
  104. .clk = {
  105. .name = "mout_mpll",
  106. .id = -1,
  107. },
  108. .shift = S3C6400_CLKSRC_MPLL_MOUT_SHIFT,
  109. .mask = S3C6400_CLKSRC_MPLL_MOUT,
  110. .sources = &clk_src_mpll,
  111. };
  112. static unsigned int armclk_mask;
  113. static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
  114. {
  115. unsigned long rate = clk_get_rate(clk->parent);
  116. u32 clkdiv;
  117. /* divisor mask starts at bit0, so no need to shift */
  118. clkdiv = __raw_readl(S3C_CLK_DIV0) & armclk_mask;
  119. return rate / (clkdiv + 1);
  120. }
  121. static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
  122. unsigned long rate)
  123. {
  124. unsigned long parent = clk_get_rate(clk->parent);
  125. u32 div;
  126. if (parent < rate)
  127. return parent;
  128. div = (parent / rate) - 1;
  129. if (div > armclk_mask)
  130. div = armclk_mask;
  131. return parent / (div + 1);
  132. }
  133. static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
  134. {
  135. unsigned long parent = clk_get_rate(clk->parent);
  136. u32 div;
  137. u32 val;
  138. if (rate < parent / (armclk_mask + 1))
  139. return -EINVAL;
  140. rate = clk_round_rate(clk, rate);
  141. div = clk_get_rate(clk->parent) / rate;
  142. val = __raw_readl(S3C_CLK_DIV0);
  143. val &= ~armclk_mask;
  144. val |= (div - 1);
  145. __raw_writel(val, S3C_CLK_DIV0);
  146. return 0;
  147. }
  148. static struct clk clk_arm = {
  149. .name = "armclk",
  150. .id = -1,
  151. .parent = &clk_mout_apll.clk,
  152. .get_rate = s3c64xx_clk_arm_get_rate,
  153. .set_rate = s3c64xx_clk_arm_set_rate,
  154. .round_rate = s3c64xx_clk_arm_round_rate,
  155. };
  156. static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
  157. {
  158. unsigned long rate = clk_get_rate(clk->parent);
  159. printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
  160. if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK)
  161. rate /= 2;
  162. return rate;
  163. }
  164. static struct clk clk_dout_mpll = {
  165. .name = "dout_mpll",
  166. .id = -1,
  167. .parent = &clk_mout_mpll.clk,
  168. .get_rate = s3c64xx_clk_doutmpll_get_rate,
  169. };
  170. static struct clk *clkset_spi_mmc_list[] = {
  171. &clk_mout_epll.clk,
  172. &clk_dout_mpll,
  173. &clk_fin_epll,
  174. &clk_27m,
  175. };
  176. static struct clk_sources clkset_spi_mmc = {
  177. .sources = clkset_spi_mmc_list,
  178. .nr_sources = ARRAY_SIZE(clkset_spi_mmc_list),
  179. };
  180. static struct clk *clkset_irda_list[] = {
  181. &clk_mout_epll.clk,
  182. &clk_dout_mpll,
  183. NULL,
  184. &clk_27m,
  185. };
  186. static struct clk_sources clkset_irda = {
  187. .sources = clkset_irda_list,
  188. .nr_sources = ARRAY_SIZE(clkset_irda_list),
  189. };
  190. static struct clk *clkset_uart_list[] = {
  191. &clk_mout_epll.clk,
  192. &clk_dout_mpll,
  193. NULL,
  194. NULL
  195. };
  196. static struct clk_sources clkset_uart = {
  197. .sources = clkset_uart_list,
  198. .nr_sources = ARRAY_SIZE(clkset_uart_list),
  199. };
  200. static struct clk *clkset_uhost_list[] = {
  201. &clk_48m,
  202. &clk_mout_epll.clk,
  203. &clk_dout_mpll,
  204. &clk_fin_epll,
  205. };
  206. static struct clk_sources clkset_uhost = {
  207. .sources = clkset_uhost_list,
  208. .nr_sources = ARRAY_SIZE(clkset_uhost_list),
  209. };
  210. /* The peripheral clocks are all controlled via clocksource followed
  211. * by an optional divider and gate stage. We currently roll this into
  212. * one clock which hides the intermediate clock from the mux.
  213. *
  214. * Note, the JPEG clock can only be an even divider...
  215. *
  216. * The scaler and LCD clocks depend on the S3C64XX version, and also
  217. * have a common parent divisor so are not included here.
  218. */
  219. static inline struct clksrc_clk *to_clksrc(struct clk *clk)
  220. {
  221. return container_of(clk, struct clksrc_clk, clk);
  222. }
  223. static unsigned long s3c64xx_getrate_clksrc(struct clk *clk)
  224. {
  225. struct clksrc_clk *sclk = to_clksrc(clk);
  226. unsigned long rate = clk_get_rate(clk->parent);
  227. u32 clkdiv = __raw_readl(sclk->reg_divider);
  228. clkdiv >>= sclk->divider_shift;
  229. clkdiv &= 0xf;
  230. clkdiv++;
  231. rate /= clkdiv;
  232. return rate;
  233. }
  234. static int s3c64xx_setrate_clksrc(struct clk *clk, unsigned long rate)
  235. {
  236. struct clksrc_clk *sclk = to_clksrc(clk);
  237. void __iomem *reg = sclk->reg_divider;
  238. unsigned int div;
  239. u32 val;
  240. rate = clk_round_rate(clk, rate);
  241. div = clk_get_rate(clk->parent) / rate;
  242. if (div > 16)
  243. return -EINVAL;
  244. val = __raw_readl(reg);
  245. val &= ~(0xf << sclk->divider_shift);
  246. val |= (div - 1) << sclk->divider_shift;
  247. __raw_writel(val, reg);
  248. return 0;
  249. }
  250. static int s3c64xx_setparent_clksrc(struct clk *clk, struct clk *parent)
  251. {
  252. struct clksrc_clk *sclk = to_clksrc(clk);
  253. struct clk_sources *srcs = sclk->sources;
  254. u32 clksrc = __raw_readl(S3C_CLK_SRC);
  255. int src_nr = -1;
  256. int ptr;
  257. for (ptr = 0; ptr < srcs->nr_sources; ptr++)
  258. if (srcs->sources[ptr] == parent) {
  259. src_nr = ptr;
  260. break;
  261. }
  262. if (src_nr >= 0) {
  263. clksrc &= ~sclk->mask;
  264. clksrc |= src_nr << sclk->shift;
  265. __raw_writel(clksrc, S3C_CLK_SRC);
  266. clk->parent = parent;
  267. return 0;
  268. }
  269. return -EINVAL;
  270. }
  271. static unsigned long s3c64xx_roundrate_clksrc(struct clk *clk,
  272. unsigned long rate)
  273. {
  274. unsigned long parent_rate = clk_get_rate(clk->parent);
  275. int div;
  276. if (rate > parent_rate)
  277. rate = parent_rate;
  278. else {
  279. div = parent_rate / rate;
  280. if (div == 0)
  281. div = 1;
  282. if (div > 16)
  283. div = 16;
  284. rate = parent_rate / div;
  285. }
  286. return rate;
  287. }
  288. static struct clksrc_clk clk_mmc0 = {
  289. .clk = {
  290. .name = "mmc_bus",
  291. .id = 0,
  292. .ctrlbit = S3C_CLKCON_SCLK_MMC0,
  293. .enable = s3c64xx_sclk_ctrl,
  294. .set_parent = s3c64xx_setparent_clksrc,
  295. .get_rate = s3c64xx_getrate_clksrc,
  296. .set_rate = s3c64xx_setrate_clksrc,
  297. .round_rate = s3c64xx_roundrate_clksrc,
  298. },
  299. .shift = S3C6400_CLKSRC_MMC0_SHIFT,
  300. .mask = S3C6400_CLKSRC_MMC0_MASK,
  301. .sources = &clkset_spi_mmc,
  302. .divider_shift = S3C6400_CLKDIV1_MMC0_SHIFT,
  303. .reg_divider = S3C_CLK_DIV1,
  304. };
  305. static struct clksrc_clk clk_mmc1 = {
  306. .clk = {
  307. .name = "mmc_bus",
  308. .id = 1,
  309. .ctrlbit = S3C_CLKCON_SCLK_MMC1,
  310. .enable = s3c64xx_sclk_ctrl,
  311. .get_rate = s3c64xx_getrate_clksrc,
  312. .set_rate = s3c64xx_setrate_clksrc,
  313. .set_parent = s3c64xx_setparent_clksrc,
  314. .round_rate = s3c64xx_roundrate_clksrc,
  315. },
  316. .shift = S3C6400_CLKSRC_MMC1_SHIFT,
  317. .mask = S3C6400_CLKSRC_MMC1_MASK,
  318. .sources = &clkset_spi_mmc,
  319. .divider_shift = S3C6400_CLKDIV1_MMC1_SHIFT,
  320. .reg_divider = S3C_CLK_DIV1,
  321. };
  322. static struct clksrc_clk clk_mmc2 = {
  323. .clk = {
  324. .name = "mmc_bus",
  325. .id = 2,
  326. .ctrlbit = S3C_CLKCON_SCLK_MMC2,
  327. .enable = s3c64xx_sclk_ctrl,
  328. .get_rate = s3c64xx_getrate_clksrc,
  329. .set_rate = s3c64xx_setrate_clksrc,
  330. .set_parent = s3c64xx_setparent_clksrc,
  331. .round_rate = s3c64xx_roundrate_clksrc,
  332. },
  333. .shift = S3C6400_CLKSRC_MMC2_SHIFT,
  334. .mask = S3C6400_CLKSRC_MMC2_MASK,
  335. .sources = &clkset_spi_mmc,
  336. .divider_shift = S3C6400_CLKDIV1_MMC2_SHIFT,
  337. .reg_divider = S3C_CLK_DIV1,
  338. };
  339. static struct clksrc_clk clk_usbhost = {
  340. .clk = {
  341. .name = "usb-bus-host",
  342. .id = -1,
  343. .ctrlbit = S3C_CLKCON_SCLK_UHOST,
  344. .enable = s3c64xx_sclk_ctrl,
  345. .set_parent = s3c64xx_setparent_clksrc,
  346. .get_rate = s3c64xx_getrate_clksrc,
  347. .set_rate = s3c64xx_setrate_clksrc,
  348. .round_rate = s3c64xx_roundrate_clksrc,
  349. },
  350. .shift = S3C6400_CLKSRC_UHOST_SHIFT,
  351. .mask = S3C6400_CLKSRC_UHOST_MASK,
  352. .sources = &clkset_uhost,
  353. .divider_shift = S3C6400_CLKDIV1_UHOST_SHIFT,
  354. .reg_divider = S3C_CLK_DIV1,
  355. };
  356. static struct clksrc_clk clk_uart_uclk1 = {
  357. .clk = {
  358. .name = "uclk1",
  359. .id = -1,
  360. .ctrlbit = S3C_CLKCON_SCLK_UART,
  361. .enable = s3c64xx_sclk_ctrl,
  362. .set_parent = s3c64xx_setparent_clksrc,
  363. .get_rate = s3c64xx_getrate_clksrc,
  364. .set_rate = s3c64xx_setrate_clksrc,
  365. .round_rate = s3c64xx_roundrate_clksrc,
  366. },
  367. .shift = S3C6400_CLKSRC_UART_SHIFT,
  368. .mask = S3C6400_CLKSRC_UART_MASK,
  369. .sources = &clkset_uart,
  370. .divider_shift = S3C6400_CLKDIV2_UART_SHIFT,
  371. .reg_divider = S3C_CLK_DIV2,
  372. };
  373. /* Where does UCLK0 come from? */
  374. static struct clksrc_clk clk_spi0 = {
  375. .clk = {
  376. .name = "spi-bus",
  377. .id = 0,
  378. .ctrlbit = S3C_CLKCON_SCLK_SPI0,
  379. .enable = s3c64xx_sclk_ctrl,
  380. .set_parent = s3c64xx_setparent_clksrc,
  381. .get_rate = s3c64xx_getrate_clksrc,
  382. .set_rate = s3c64xx_setrate_clksrc,
  383. .round_rate = s3c64xx_roundrate_clksrc,
  384. },
  385. .shift = S3C6400_CLKSRC_SPI0_SHIFT,
  386. .mask = S3C6400_CLKSRC_SPI0_MASK,
  387. .sources = &clkset_spi_mmc,
  388. .divider_shift = S3C6400_CLKDIV2_SPI0_SHIFT,
  389. .reg_divider = S3C_CLK_DIV2,
  390. };
  391. static struct clksrc_clk clk_spi1 = {
  392. .clk = {
  393. .name = "spi-bus",
  394. .id = 1,
  395. .ctrlbit = S3C_CLKCON_SCLK_SPI1,
  396. .enable = s3c64xx_sclk_ctrl,
  397. .set_parent = s3c64xx_setparent_clksrc,
  398. .get_rate = s3c64xx_getrate_clksrc,
  399. .set_rate = s3c64xx_setrate_clksrc,
  400. .round_rate = s3c64xx_roundrate_clksrc,
  401. },
  402. .shift = S3C6400_CLKSRC_SPI1_SHIFT,
  403. .mask = S3C6400_CLKSRC_SPI1_MASK,
  404. .sources = &clkset_spi_mmc,
  405. .divider_shift = S3C6400_CLKDIV2_SPI1_SHIFT,
  406. .reg_divider = S3C_CLK_DIV2,
  407. };
  408. static struct clk clk_iis_cd0 = {
  409. .name = "iis_cdclk0",
  410. .id = -1,
  411. };
  412. static struct clk clk_iis_cd1 = {
  413. .name = "iis_cdclk1",
  414. .id = -1,
  415. };
  416. static struct clk clk_pcm_cd = {
  417. .name = "pcm_cdclk",
  418. .id = -1,
  419. };
  420. static struct clk *clkset_audio0_list[] = {
  421. [0] = &clk_mout_epll.clk,
  422. [1] = &clk_dout_mpll,
  423. [2] = &clk_fin_epll,
  424. [3] = &clk_iis_cd0,
  425. [4] = &clk_pcm_cd,
  426. };
  427. static struct clk_sources clkset_audio0 = {
  428. .sources = clkset_audio0_list,
  429. .nr_sources = ARRAY_SIZE(clkset_audio0_list),
  430. };
  431. static struct clksrc_clk clk_audio0 = {
  432. .clk = {
  433. .name = "audio-bus",
  434. .id = 0,
  435. .ctrlbit = S3C_CLKCON_SCLK_AUDIO0,
  436. .enable = s3c64xx_sclk_ctrl,
  437. .set_parent = s3c64xx_setparent_clksrc,
  438. .get_rate = s3c64xx_getrate_clksrc,
  439. .set_rate = s3c64xx_setrate_clksrc,
  440. .round_rate = s3c64xx_roundrate_clksrc,
  441. },
  442. .shift = S3C6400_CLKSRC_AUDIO0_SHIFT,
  443. .mask = S3C6400_CLKSRC_AUDIO0_MASK,
  444. .sources = &clkset_audio0,
  445. .divider_shift = S3C6400_CLKDIV2_AUDIO0_SHIFT,
  446. .reg_divider = S3C_CLK_DIV2,
  447. };
  448. static struct clk *clkset_audio1_list[] = {
  449. [0] = &clk_mout_epll.clk,
  450. [1] = &clk_dout_mpll,
  451. [2] = &clk_fin_epll,
  452. [3] = &clk_iis_cd1,
  453. [4] = &clk_pcm_cd,
  454. };
  455. static struct clk_sources clkset_audio1 = {
  456. .sources = clkset_audio1_list,
  457. .nr_sources = ARRAY_SIZE(clkset_audio1_list),
  458. };
  459. static struct clksrc_clk clk_audio1 = {
  460. .clk = {
  461. .name = "audio-bus",
  462. .id = 1,
  463. .ctrlbit = S3C_CLKCON_SCLK_AUDIO1,
  464. .enable = s3c64xx_sclk_ctrl,
  465. .set_parent = s3c64xx_setparent_clksrc,
  466. .get_rate = s3c64xx_getrate_clksrc,
  467. .set_rate = s3c64xx_setrate_clksrc,
  468. .round_rate = s3c64xx_roundrate_clksrc,
  469. },
  470. .shift = S3C6400_CLKSRC_AUDIO1_SHIFT,
  471. .mask = S3C6400_CLKSRC_AUDIO1_MASK,
  472. .sources = &clkset_audio1,
  473. .divider_shift = S3C6400_CLKDIV2_AUDIO1_SHIFT,
  474. .reg_divider = S3C_CLK_DIV2,
  475. };
  476. static struct clksrc_clk clk_irda = {
  477. .clk = {
  478. .name = "irda-bus",
  479. .id = 0,
  480. .ctrlbit = S3C_CLKCON_SCLK_IRDA,
  481. .enable = s3c64xx_sclk_ctrl,
  482. .set_parent = s3c64xx_setparent_clksrc,
  483. .get_rate = s3c64xx_getrate_clksrc,
  484. .set_rate = s3c64xx_setrate_clksrc,
  485. .round_rate = s3c64xx_roundrate_clksrc,
  486. },
  487. .shift = S3C6400_CLKSRC_IRDA_SHIFT,
  488. .mask = S3C6400_CLKSRC_IRDA_MASK,
  489. .sources = &clkset_irda,
  490. .divider_shift = S3C6400_CLKDIV2_IRDA_SHIFT,
  491. .reg_divider = S3C_CLK_DIV2,
  492. };
  493. static struct clk *clkset_camif_list[] = {
  494. &clk_h2,
  495. };
  496. static struct clk_sources clkset_camif = {
  497. .sources = clkset_camif_list,
  498. .nr_sources = ARRAY_SIZE(clkset_camif_list),
  499. };
  500. static struct clksrc_clk clk_camif = {
  501. .clk = {
  502. .name = "camera",
  503. .id = -1,
  504. .ctrlbit = S3C_CLKCON_SCLK_CAM,
  505. .enable = s3c64xx_sclk_ctrl,
  506. .set_parent = s3c64xx_setparent_clksrc,
  507. .get_rate = s3c64xx_getrate_clksrc,
  508. .set_rate = s3c64xx_setrate_clksrc,
  509. .round_rate = s3c64xx_roundrate_clksrc,
  510. },
  511. .shift = 0,
  512. .mask = 0,
  513. .sources = &clkset_camif,
  514. .divider_shift = S3C6400_CLKDIV0_CAM_SHIFT,
  515. .reg_divider = S3C_CLK_DIV0,
  516. };
  517. /* Clock initialisation code */
  518. static struct clksrc_clk *init_parents[] = {
  519. &clk_mout_apll,
  520. &clk_mout_epll,
  521. &clk_mout_mpll,
  522. &clk_mmc0,
  523. &clk_mmc1,
  524. &clk_mmc2,
  525. &clk_usbhost,
  526. &clk_uart_uclk1,
  527. &clk_spi0,
  528. &clk_spi1,
  529. &clk_audio0,
  530. &clk_audio1,
  531. &clk_irda,
  532. &clk_camif,
  533. };
  534. static void __init_or_cpufreq s3c6400_set_clksrc(struct clksrc_clk *clk)
  535. {
  536. struct clk_sources *srcs = clk->sources;
  537. u32 clksrc = __raw_readl(S3C_CLK_SRC);
  538. clksrc &= clk->mask;
  539. clksrc >>= clk->shift;
  540. if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) {
  541. printk(KERN_ERR "%s: bad source %d\n",
  542. clk->clk.name, clksrc);
  543. return;
  544. }
  545. clk->clk.parent = srcs->sources[clksrc];
  546. printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n",
  547. clk->clk.name, clk->clk.parent->name, clksrc,
  548. clk_get_rate(&clk->clk));
  549. }
  550. #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
  551. void __init_or_cpufreq s3c6400_setup_clocks(void)
  552. {
  553. struct clk *xtal_clk;
  554. unsigned long xtal;
  555. unsigned long fclk;
  556. unsigned long hclk;
  557. unsigned long hclk2;
  558. unsigned long pclk;
  559. unsigned long epll;
  560. unsigned long apll;
  561. unsigned long mpll;
  562. unsigned int ptr;
  563. u32 clkdiv0;
  564. printk(KERN_DEBUG "%s: registering clocks\n", __func__);
  565. clkdiv0 = __raw_readl(S3C_CLK_DIV0);
  566. printk(KERN_DEBUG "%s: clkdiv0 = %08x\n", __func__, clkdiv0);
  567. xtal_clk = clk_get(NULL, "xtal");
  568. BUG_ON(IS_ERR(xtal_clk));
  569. xtal = clk_get_rate(xtal_clk);
  570. clk_put(xtal_clk);
  571. printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
  572. /* For now assume the mux always selects the crystal */
  573. clk_ext_xtal_mux.parent = xtal_clk;
  574. epll = s3c6400_get_epll(xtal);
  575. mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
  576. apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
  577. fclk = mpll;
  578. printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
  579. apll, mpll, epll);
  580. hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
  581. hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
  582. pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
  583. printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n",
  584. hclk2, hclk, pclk);
  585. clk_fout_mpll.rate = mpll;
  586. clk_fout_epll.rate = epll;
  587. clk_fout_apll.rate = apll;
  588. clk_h2.rate = hclk2;
  589. clk_h.rate = hclk;
  590. clk_p.rate = pclk;
  591. clk_f.rate = fclk;
  592. for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
  593. s3c6400_set_clksrc(init_parents[ptr]);
  594. }
  595. static struct clk *clks[] __initdata = {
  596. &clk_ext_xtal_mux,
  597. &clk_iis_cd0,
  598. &clk_iis_cd1,
  599. &clk_pcm_cd,
  600. &clk_mout_epll.clk,
  601. &clk_fout_epll,
  602. &clk_mout_mpll.clk,
  603. &clk_dout_mpll,
  604. &clk_mmc0.clk,
  605. &clk_mmc1.clk,
  606. &clk_mmc2.clk,
  607. &clk_usbhost.clk,
  608. &clk_uart_uclk1.clk,
  609. &clk_spi0.clk,
  610. &clk_spi1.clk,
  611. &clk_audio0.clk,
  612. &clk_audio1.clk,
  613. &clk_irda.clk,
  614. &clk_camif.clk,
  615. &clk_arm,
  616. };
  617. /**
  618. * s3c6400_register_clocks - register clocks for s3c6400 and above
  619. * @armclk_divlimit: Divisor mask for ARMCLK
  620. *
  621. * Register the clocks for the S3C6400 and above SoC range, such
  622. * as ARMCLK and the clocks which have divider chains attached.
  623. *
  624. * This call does not setup the clocks, which is left to the
  625. * s3c6400_setup_clocks() call which may be needed by the cpufreq
  626. * or resume code to re-set the clocks if the bootloader has changed
  627. * them.
  628. */
  629. void __init s3c6400_register_clocks(unsigned armclk_divlimit)
  630. {
  631. struct clk *clkp;
  632. int ret;
  633. int ptr;
  634. armclk_mask = armclk_divlimit;
  635. for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
  636. clkp = clks[ptr];
  637. ret = s3c24xx_register_clock(clkp);
  638. if (ret < 0) {
  639. printk(KERN_ERR "Failed to register clock %s (%d)\n",
  640. clkp->name, ret);
  641. }
  642. }
  643. clk_mpll.parent = &clk_mout_mpll.clk;
  644. clk_epll.parent = &clk_mout_epll.clk;
  645. }