clock.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright (C) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. */
  18. #include <linux/kernel.h>
  19. #include <linux/device.h>
  20. #include <linux/list.h>
  21. #include <linux/math64.h>
  22. #include <linux/err.h>
  23. #include <linux/io.h>
  24. #include <mach/hardware.h>
  25. /*
  26. * Very simple approach: We can't disable clocks, so we do
  27. * not need refcounting
  28. */
  29. struct clk {
  30. struct list_head node;
  31. const char *name;
  32. unsigned long (*get_rate)(void);
  33. };
  34. /*
  35. * get the system pll clock in Hz
  36. *
  37. * mfi + mfn / (mfd +1)
  38. * f = 2 * f_ref * --------------------
  39. * pd + 1
  40. */
  41. static unsigned long imx_decode_pll(unsigned int pll, u32 f_ref)
  42. {
  43. unsigned long long ll;
  44. unsigned long quot;
  45. u32 mfi = (pll >> 10) & 0xf;
  46. u32 mfn = pll & 0x3ff;
  47. u32 mfd = (pll >> 16) & 0x3ff;
  48. u32 pd = (pll >> 26) & 0xf;
  49. mfi = mfi <= 5 ? 5 : mfi;
  50. ll = 2 * (unsigned long long)f_ref *
  51. ((mfi << 16) + (mfn << 16) / (mfd + 1));
  52. quot = (pd + 1) * (1 << 16);
  53. ll += quot / 2;
  54. do_div(ll, quot);
  55. return (unsigned long)ll;
  56. }
  57. static unsigned long imx_get_system_clk(void)
  58. {
  59. u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512);
  60. return imx_decode_pll(SPCTL0, f_ref);
  61. }
  62. static unsigned long imx_get_mcu_clk(void)
  63. {
  64. return imx_decode_pll(MPCTL0, CLK32 * 512);
  65. }
  66. /*
  67. * get peripheral clock 1 ( UART[12], Timer[12], PWM )
  68. */
  69. static unsigned long imx_get_perclk1(void)
  70. {
  71. return imx_get_system_clk() / (((PCDR) & 0xf)+1);
  72. }
  73. /*
  74. * get peripheral clock 2 ( LCD, SD, SPI[12] )
  75. */
  76. static unsigned long imx_get_perclk2(void)
  77. {
  78. return imx_get_system_clk() / (((PCDR>>4) & 0xf)+1);
  79. }
  80. /*
  81. * get peripheral clock 3 ( SSI )
  82. */
  83. static unsigned long imx_get_perclk3(void)
  84. {
  85. return imx_get_system_clk() / (((PCDR>>16) & 0x7f)+1);
  86. }
  87. /*
  88. * get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
  89. */
  90. static unsigned long imx_get_hclk(void)
  91. {
  92. return imx_get_system_clk() / (((CSCR>>10) & 0xf)+1);
  93. }
  94. static struct clk clk_system_clk = {
  95. .name = "system_clk",
  96. .get_rate = imx_get_system_clk,
  97. };
  98. static struct clk clk_hclk = {
  99. .name = "hclk",
  100. .get_rate = imx_get_hclk,
  101. };
  102. static struct clk clk_mcu_clk = {
  103. .name = "mcu_clk",
  104. .get_rate = imx_get_mcu_clk,
  105. };
  106. static struct clk clk_perclk1 = {
  107. .name = "perclk1",
  108. .get_rate = imx_get_perclk1,
  109. };
  110. static struct clk clk_uart_clk = {
  111. .name = "uart_clk",
  112. .get_rate = imx_get_perclk1,
  113. };
  114. static struct clk clk_perclk2 = {
  115. .name = "perclk2",
  116. .get_rate = imx_get_perclk2,
  117. };
  118. static struct clk clk_perclk3 = {
  119. .name = "perclk3",
  120. .get_rate = imx_get_perclk3,
  121. };
  122. static struct clk *clks[] = {
  123. &clk_perclk1,
  124. &clk_perclk2,
  125. &clk_perclk3,
  126. &clk_system_clk,
  127. &clk_hclk,
  128. &clk_mcu_clk,
  129. &clk_uart_clk,
  130. };
  131. static LIST_HEAD(clocks);
  132. static DEFINE_MUTEX(clocks_mutex);
  133. struct clk *clk_get(struct device *dev, const char *id)
  134. {
  135. struct clk *p, *clk = ERR_PTR(-ENOENT);
  136. mutex_lock(&clocks_mutex);
  137. list_for_each_entry(p, &clocks, node) {
  138. if (!strcmp(p->name, id)) {
  139. clk = p;
  140. goto found;
  141. }
  142. }
  143. found:
  144. mutex_unlock(&clocks_mutex);
  145. return clk;
  146. }
  147. EXPORT_SYMBOL(clk_get);
  148. void clk_put(struct clk *clk)
  149. {
  150. }
  151. EXPORT_SYMBOL(clk_put);
  152. int clk_enable(struct clk *clk)
  153. {
  154. return 0;
  155. }
  156. EXPORT_SYMBOL(clk_enable);
  157. void clk_disable(struct clk *clk)
  158. {
  159. }
  160. EXPORT_SYMBOL(clk_disable);
  161. unsigned long clk_get_rate(struct clk *clk)
  162. {
  163. return clk->get_rate();
  164. }
  165. EXPORT_SYMBOL(clk_get_rate);
  166. int imx_clocks_init(void)
  167. {
  168. int i;
  169. mutex_lock(&clocks_mutex);
  170. for (i = 0; i < ARRAY_SIZE(clks); i++)
  171. list_add(&clks[i]->node, &clocks);
  172. mutex_unlock(&clocks_mutex);
  173. return 0;
  174. }