clk.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * This program is free software; you can redistribute it and/or modify it
  3. * under the terms of the GNU General Public License version 2 as published
  4. * by the Free Software Foundation.
  5. *
  6. * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
  7. * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  8. */
  9. #include <linux/io.h>
  10. #include <linux/export.h>
  11. #include <linux/init.h>
  12. #include <linux/kernel.h>
  13. #include <linux/types.h>
  14. #include <linux/clk.h>
  15. #include <linux/clkdev.h>
  16. #include <linux/err.h>
  17. #include <linux/list.h>
  18. #include <asm/time.h>
  19. #include <asm/irq.h>
  20. #include <asm/div64.h>
  21. #include <lantiq_soc.h>
  22. #include "clk.h"
  23. #include "prom.h"
  24. /* lantiq socs have 3 static clocks */
  25. static struct clk cpu_clk_generic[3];
  26. void clkdev_add_static(unsigned long cpu, unsigned long fpi, unsigned long io)
  27. {
  28. cpu_clk_generic[0].rate = cpu;
  29. cpu_clk_generic[1].rate = fpi;
  30. cpu_clk_generic[2].rate = io;
  31. }
  32. struct clk *clk_get_cpu(void)
  33. {
  34. return &cpu_clk_generic[0];
  35. }
  36. struct clk *clk_get_fpi(void)
  37. {
  38. return &cpu_clk_generic[1];
  39. }
  40. EXPORT_SYMBOL_GPL(clk_get_fpi);
  41. struct clk *clk_get_io(void)
  42. {
  43. return &cpu_clk_generic[2];
  44. }
  45. static inline int clk_good(struct clk *clk)
  46. {
  47. return clk && !IS_ERR(clk);
  48. }
  49. unsigned long clk_get_rate(struct clk *clk)
  50. {
  51. if (unlikely(!clk_good(clk)))
  52. return 0;
  53. if (clk->rate != 0)
  54. return clk->rate;
  55. if (clk->get_rate != NULL)
  56. return clk->get_rate();
  57. return 0;
  58. }
  59. EXPORT_SYMBOL(clk_get_rate);
  60. int clk_set_rate(struct clk *clk, unsigned long rate)
  61. {
  62. if (unlikely(!clk_good(clk)))
  63. return 0;
  64. if (clk->rates && *clk->rates) {
  65. unsigned long *r = clk->rates;
  66. while (*r && (*r != rate))
  67. r++;
  68. if (!*r) {
  69. pr_err("clk %s.%s: trying to set invalid rate %ld\n",
  70. clk->cl.dev_id, clk->cl.con_id, rate);
  71. return -1;
  72. }
  73. }
  74. clk->rate = rate;
  75. return 0;
  76. }
  77. EXPORT_SYMBOL(clk_set_rate);
  78. int clk_enable(struct clk *clk)
  79. {
  80. if (unlikely(!clk_good(clk)))
  81. return -1;
  82. if (clk->enable)
  83. return clk->enable(clk);
  84. return -1;
  85. }
  86. EXPORT_SYMBOL(clk_enable);
  87. void clk_disable(struct clk *clk)
  88. {
  89. if (unlikely(!clk_good(clk)))
  90. return;
  91. if (clk->disable)
  92. clk->disable(clk);
  93. }
  94. EXPORT_SYMBOL(clk_disable);
  95. int clk_activate(struct clk *clk)
  96. {
  97. if (unlikely(!clk_good(clk)))
  98. return -1;
  99. if (clk->activate)
  100. return clk->activate(clk);
  101. return -1;
  102. }
  103. EXPORT_SYMBOL(clk_activate);
  104. void clk_deactivate(struct clk *clk)
  105. {
  106. if (unlikely(!clk_good(clk)))
  107. return;
  108. if (clk->deactivate)
  109. clk->deactivate(clk);
  110. }
  111. EXPORT_SYMBOL(clk_deactivate);
  112. struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
  113. {
  114. return NULL;
  115. }
  116. static inline u32 get_counter_resolution(void)
  117. {
  118. u32 res;
  119. __asm__ __volatile__(
  120. ".set push\n"
  121. ".set mips32r2\n"
  122. "rdhwr %0, $3\n"
  123. ".set pop\n"
  124. : "=&r" (res)
  125. : /* no input */
  126. : "memory");
  127. return res;
  128. }
  129. void __init plat_time_init(void)
  130. {
  131. struct clk *clk;
  132. ltq_soc_init();
  133. clk = clk_get_cpu();
  134. mips_hpt_frequency = clk_get_rate(clk) / get_counter_resolution();
  135. write_c0_compare(read_c0_count());
  136. pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
  137. clk_put(clk);
  138. }