clock.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * linux/arch/unicore32/kernel/clock.c
  3. *
  4. * Code specific to PKUnity SoC and UniCore ISA
  5. *
  6. * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
  7. * Copyright (C) 2001-2010 Guan Xuetao
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. #include <linux/module.h>
  14. #include <linux/kernel.h>
  15. #include <linux/device.h>
  16. #include <linux/list.h>
  17. #include <linux/errno.h>
  18. #include <linux/err.h>
  19. #include <linux/string.h>
  20. #include <linux/clk.h>
  21. #include <linux/mutex.h>
  22. #include <linux/delay.h>
  23. #include <mach/hardware.h>
  24. /*
  25. * Very simple clock implementation
  26. */
  27. struct clk {
  28. struct list_head node;
  29. unsigned long rate;
  30. const char *name;
  31. };
  32. static struct clk clk_ost_clk = {
  33. .name = "OST_CLK",
  34. .rate = CLOCK_TICK_RATE,
  35. };
  36. static struct clk clk_mclk_clk = {
  37. .name = "MAIN_CLK",
  38. };
  39. static struct clk clk_bclk32_clk = {
  40. .name = "BUS32_CLK",
  41. };
  42. static struct clk clk_ddr_clk = {
  43. .name = "DDR_CLK",
  44. };
  45. static struct clk clk_vga_clk = {
  46. .name = "VGA_CLK",
  47. };
  48. static LIST_HEAD(clocks);
  49. static DEFINE_MUTEX(clocks_mutex);
  50. struct clk *clk_get(struct device *dev, const char *id)
  51. {
  52. struct clk *p, *clk = ERR_PTR(-ENOENT);
  53. mutex_lock(&clocks_mutex);
  54. list_for_each_entry(p, &clocks, node) {
  55. if (strcmp(id, p->name) == 0) {
  56. clk = p;
  57. break;
  58. }
  59. }
  60. mutex_unlock(&clocks_mutex);
  61. return clk;
  62. }
  63. EXPORT_SYMBOL(clk_get);
  64. void clk_put(struct clk *clk)
  65. {
  66. }
  67. EXPORT_SYMBOL(clk_put);
  68. int clk_enable(struct clk *clk)
  69. {
  70. return 0;
  71. }
  72. EXPORT_SYMBOL(clk_enable);
  73. void clk_disable(struct clk *clk)
  74. {
  75. }
  76. EXPORT_SYMBOL(clk_disable);
  77. unsigned long clk_get_rate(struct clk *clk)
  78. {
  79. return clk->rate;
  80. }
  81. EXPORT_SYMBOL(clk_get_rate);
  82. struct {
  83. unsigned long rate;
  84. unsigned long cfg;
  85. unsigned long div;
  86. } vga_clk_table[] = {
  87. {.rate = 25175000, .cfg = 0x00002001, .div = 0x9},
  88. {.rate = 31500000, .cfg = 0x00002001, .div = 0x7},
  89. {.rate = 40000000, .cfg = 0x00003801, .div = 0x9},
  90. {.rate = 49500000, .cfg = 0x00003801, .div = 0x7},
  91. {.rate = 65000000, .cfg = 0x00002c01, .div = 0x4},
  92. {.rate = 78750000, .cfg = 0x00002400, .div = 0x7},
  93. {.rate = 108000000, .cfg = 0x00002c01, .div = 0x2},
  94. {.rate = 106500000, .cfg = 0x00003c01, .div = 0x3},
  95. {.rate = 50650000, .cfg = 0x00106400, .div = 0x9},
  96. {.rate = 61500000, .cfg = 0x00106400, .div = 0xa},
  97. {.rate = 85500000, .cfg = 0x00002800, .div = 0x6},
  98. };
  99. struct {
  100. unsigned long mrate;
  101. unsigned long prate;
  102. } mclk_clk_table[] = {
  103. {.mrate = 500000000, .prate = 0x00109801},
  104. {.mrate = 525000000, .prate = 0x00104C00},
  105. {.mrate = 550000000, .prate = 0x00105000},
  106. {.mrate = 575000000, .prate = 0x00105400},
  107. {.mrate = 600000000, .prate = 0x00105800},
  108. {.mrate = 625000000, .prate = 0x00105C00},
  109. {.mrate = 650000000, .prate = 0x00106000},
  110. {.mrate = 675000000, .prate = 0x00106400},
  111. {.mrate = 700000000, .prate = 0x00106800},
  112. {.mrate = 725000000, .prate = 0x00106C00},
  113. {.mrate = 750000000, .prate = 0x00107000},
  114. {.mrate = 775000000, .prate = 0x00107400},
  115. {.mrate = 800000000, .prate = 0x00107800},
  116. };
  117. int clk_set_rate(struct clk *clk, unsigned long rate)
  118. {
  119. if (clk == &clk_vga_clk) {
  120. unsigned long pll_vgacfg, pll_vgadiv;
  121. int ret, i;
  122. /* lookup vga_clk_table */
  123. ret = -EINVAL;
  124. for (i = 0; i < ARRAY_SIZE(vga_clk_table); i++) {
  125. if (rate == vga_clk_table[i].rate) {
  126. pll_vgacfg = vga_clk_table[i].cfg;
  127. pll_vgadiv = vga_clk_table[i].div;
  128. ret = 0;
  129. break;
  130. }
  131. }
  132. if (ret)
  133. return ret;
  134. if (PM_PLLVGACFG == pll_vgacfg)
  135. return 0;
  136. /* set pll vga cfg reg. */
  137. PM_PLLVGACFG = pll_vgacfg;
  138. PM_PMCR = PM_PMCR_CFBVGA;
  139. while ((PM_PLLDFCDONE & PM_PLLDFCDONE_VGADFC)
  140. != PM_PLLDFCDONE_VGADFC)
  141. udelay(100); /* about 1ms */
  142. /* set div cfg reg. */
  143. PM_PCGR |= PM_PCGR_VGACLK;
  144. PM_DIVCFG = (PM_DIVCFG & ~PM_DIVCFG_VGACLK_MASK)
  145. | PM_DIVCFG_VGACLK(pll_vgadiv);
  146. PM_SWRESET |= PM_SWRESET_VGADIV;
  147. while ((PM_SWRESET & PM_SWRESET_VGADIV) == PM_SWRESET_VGADIV)
  148. udelay(100); /* 65536 bclk32, about 320us */
  149. PM_PCGR &= ~PM_PCGR_VGACLK;
  150. }
  151. #ifdef CONFIG_CPU_FREQ
  152. if (clk == &clk_mclk_clk) {
  153. u32 pll_rate, divstatus = PM_DIVSTATUS;
  154. int ret, i;
  155. /* lookup mclk_clk_table */
  156. ret = -EINVAL;
  157. for (i = 0; i < ARRAY_SIZE(mclk_clk_table); i++) {
  158. if (rate == mclk_clk_table[i].mrate) {
  159. pll_rate = mclk_clk_table[i].prate;
  160. clk_mclk_clk.rate = mclk_clk_table[i].mrate;
  161. ret = 0;
  162. break;
  163. }
  164. }
  165. if (ret)
  166. return ret;
  167. if (clk_mclk_clk.rate)
  168. clk_bclk32_clk.rate = clk_mclk_clk.rate
  169. / (((divstatus & 0x0000f000) >> 12) + 1);
  170. /* set pll sys cfg reg. */
  171. PM_PLLSYSCFG = pll_rate;
  172. PM_PMCR = PM_PMCR_CFBSYS;
  173. while ((PM_PLLDFCDONE & PM_PLLDFCDONE_SYSDFC)
  174. != PM_PLLDFCDONE_SYSDFC)
  175. udelay(100);
  176. /* about 1ms */
  177. }
  178. #endif
  179. return 0;
  180. }
  181. EXPORT_SYMBOL(clk_set_rate);
  182. int clk_register(struct clk *clk)
  183. {
  184. mutex_lock(&clocks_mutex);
  185. list_add(&clk->node, &clocks);
  186. mutex_unlock(&clocks_mutex);
  187. printk(KERN_DEFAULT "PKUnity PM: %s %lu.%02luM\n", clk->name,
  188. (clk->rate)/1000000, (clk->rate)/10000 % 100);
  189. return 0;
  190. }
  191. EXPORT_SYMBOL(clk_register);
  192. void clk_unregister(struct clk *clk)
  193. {
  194. mutex_lock(&clocks_mutex);
  195. list_del(&clk->node);
  196. mutex_unlock(&clocks_mutex);
  197. }
  198. EXPORT_SYMBOL(clk_unregister);
  199. struct {
  200. unsigned long prate;
  201. unsigned long rate;
  202. } pllrate_table[] = {
  203. {.prate = 0x00002001, .rate = 250000000},
  204. {.prate = 0x00104801, .rate = 250000000},
  205. {.prate = 0x00104C01, .rate = 262500000},
  206. {.prate = 0x00002401, .rate = 275000000},
  207. {.prate = 0x00105001, .rate = 275000000},
  208. {.prate = 0x00105401, .rate = 287500000},
  209. {.prate = 0x00002801, .rate = 300000000},
  210. {.prate = 0x00105801, .rate = 300000000},
  211. {.prate = 0x00105C01, .rate = 312500000},
  212. {.prate = 0x00002C01, .rate = 325000000},
  213. {.prate = 0x00106001, .rate = 325000000},
  214. {.prate = 0x00106401, .rate = 337500000},
  215. {.prate = 0x00003001, .rate = 350000000},
  216. {.prate = 0x00106801, .rate = 350000000},
  217. {.prate = 0x00106C01, .rate = 362500000},
  218. {.prate = 0x00003401, .rate = 375000000},
  219. {.prate = 0x00107001, .rate = 375000000},
  220. {.prate = 0x00107401, .rate = 387500000},
  221. {.prate = 0x00003801, .rate = 400000000},
  222. {.prate = 0x00107801, .rate = 400000000},
  223. {.prate = 0x00107C01, .rate = 412500000},
  224. {.prate = 0x00003C01, .rate = 425000000},
  225. {.prate = 0x00108001, .rate = 425000000},
  226. {.prate = 0x00108401, .rate = 437500000},
  227. {.prate = 0x00004001, .rate = 450000000},
  228. {.prate = 0x00108801, .rate = 450000000},
  229. {.prate = 0x00108C01, .rate = 462500000},
  230. {.prate = 0x00004401, .rate = 475000000},
  231. {.prate = 0x00109001, .rate = 475000000},
  232. {.prate = 0x00109401, .rate = 487500000},
  233. {.prate = 0x00004801, .rate = 500000000},
  234. {.prate = 0x00109801, .rate = 500000000},
  235. {.prate = 0x00104C00, .rate = 525000000},
  236. {.prate = 0x00002400, .rate = 550000000},
  237. {.prate = 0x00105000, .rate = 550000000},
  238. {.prate = 0x00105400, .rate = 575000000},
  239. {.prate = 0x00002800, .rate = 600000000},
  240. {.prate = 0x00105800, .rate = 600000000},
  241. {.prate = 0x00105C00, .rate = 625000000},
  242. {.prate = 0x00002C00, .rate = 650000000},
  243. {.prate = 0x00106000, .rate = 650000000},
  244. {.prate = 0x00106400, .rate = 675000000},
  245. {.prate = 0x00003000, .rate = 700000000},
  246. {.prate = 0x00106800, .rate = 700000000},
  247. {.prate = 0x00106C00, .rate = 725000000},
  248. {.prate = 0x00003400, .rate = 750000000},
  249. {.prate = 0x00107000, .rate = 750000000},
  250. {.prate = 0x00107400, .rate = 775000000},
  251. {.prate = 0x00003800, .rate = 800000000},
  252. {.prate = 0x00107800, .rate = 800000000},
  253. {.prate = 0x00107C00, .rate = 825000000},
  254. {.prate = 0x00003C00, .rate = 850000000},
  255. {.prate = 0x00108000, .rate = 850000000},
  256. {.prate = 0x00108400, .rate = 875000000},
  257. {.prate = 0x00004000, .rate = 900000000},
  258. {.prate = 0x00108800, .rate = 900000000},
  259. {.prate = 0x00108C00, .rate = 925000000},
  260. {.prate = 0x00004400, .rate = 950000000},
  261. {.prate = 0x00109000, .rate = 950000000},
  262. {.prate = 0x00109400, .rate = 975000000},
  263. {.prate = 0x00004800, .rate = 1000000000},
  264. {.prate = 0x00109800, .rate = 1000000000},
  265. };
  266. struct {
  267. unsigned long prate;
  268. unsigned long drate;
  269. } pddr_table[] = {
  270. {.prate = 0x00100800, .drate = 44236800},
  271. {.prate = 0x00100C00, .drate = 66355200},
  272. {.prate = 0x00101000, .drate = 88473600},
  273. {.prate = 0x00101400, .drate = 110592000},
  274. {.prate = 0x00101800, .drate = 132710400},
  275. {.prate = 0x00101C01, .drate = 154828800},
  276. {.prate = 0x00102001, .drate = 176947200},
  277. {.prate = 0x00102401, .drate = 199065600},
  278. {.prate = 0x00102801, .drate = 221184000},
  279. {.prate = 0x00102C01, .drate = 243302400},
  280. {.prate = 0x00103001, .drate = 265420800},
  281. {.prate = 0x00103401, .drate = 287539200},
  282. {.prate = 0x00103801, .drate = 309657600},
  283. {.prate = 0x00103C01, .drate = 331776000},
  284. {.prate = 0x00104001, .drate = 353894400},
  285. };
  286. static int __init clk_init(void)
  287. {
  288. #ifdef CONFIG_PUV3_PM
  289. u32 pllrate, divstatus = PM_DIVSTATUS;
  290. u32 pcgr_val = PM_PCGR;
  291. int i;
  292. pcgr_val |= PM_PCGR_BCLKMME | PM_PCGR_BCLKH264E | PM_PCGR_BCLKH264D
  293. | PM_PCGR_HECLK | PM_PCGR_HDCLK;
  294. PM_PCGR = pcgr_val;
  295. pllrate = PM_PLLSYSSTATUS;
  296. /* lookup pmclk_table */
  297. clk_mclk_clk.rate = 0;
  298. for (i = 0; i < ARRAY_SIZE(pllrate_table); i++) {
  299. if (pllrate == pllrate_table[i].prate) {
  300. clk_mclk_clk.rate = pllrate_table[i].rate;
  301. break;
  302. }
  303. }
  304. if (clk_mclk_clk.rate)
  305. clk_bclk32_clk.rate = clk_mclk_clk.rate /
  306. (((divstatus & 0x0000f000) >> 12) + 1);
  307. pllrate = PM_PLLDDRSTATUS;
  308. /* lookup pddr_table */
  309. clk_ddr_clk.rate = 0;
  310. for (i = 0; i < ARRAY_SIZE(pddr_table); i++) {
  311. if (pllrate == pddr_table[i].prate) {
  312. clk_ddr_clk.rate = pddr_table[i].drate;
  313. break;
  314. }
  315. }
  316. pllrate = PM_PLLVGASTATUS;
  317. /* lookup pvga_table */
  318. clk_vga_clk.rate = 0;
  319. for (i = 0; i < ARRAY_SIZE(pllrate_table); i++) {
  320. if (pllrate == pllrate_table[i].prate) {
  321. clk_vga_clk.rate = pllrate_table[i].rate;
  322. break;
  323. }
  324. }
  325. if (clk_vga_clk.rate)
  326. clk_vga_clk.rate = clk_vga_clk.rate /
  327. (((divstatus & 0x00f00000) >> 20) + 1);
  328. clk_register(&clk_vga_clk);
  329. #endif
  330. #ifdef CONFIG_ARCH_FPGA
  331. clk_ddr_clk.rate = 33000000;
  332. clk_mclk_clk.rate = 33000000;
  333. clk_bclk32_clk.rate = 33000000;
  334. #endif
  335. clk_register(&clk_ddr_clk);
  336. clk_register(&clk_mclk_clk);
  337. clk_register(&clk_bclk32_clk);
  338. clk_register(&clk_ost_clk);
  339. return 0;
  340. }
  341. core_initcall(clk_init);