clock.c 10 KB

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