clock.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology
  3. * Author: Yanhua, yanh@lemote.com
  4. *
  5. * This file is subject to the terms and conditions of the GNU General Public
  6. * License. See the file "COPYING" in the main directory of this archive
  7. * for more details.
  8. */
  9. #include <linux/clk.h>
  10. #include <linux/cpufreq.h>
  11. #include <linux/errno.h>
  12. #include <linux/export.h>
  13. #include <linux/init.h>
  14. #include <linux/list.h>
  15. #include <linux/mutex.h>
  16. #include <linux/spinlock.h>
  17. #include <asm/clock.h>
  18. #include <asm/mach-loongson/loongson.h>
  19. static LIST_HEAD(clock_list);
  20. static DEFINE_SPINLOCK(clock_lock);
  21. static DEFINE_MUTEX(clock_list_sem);
  22. /* Minimum CLK support */
  23. enum {
  24. DC_ZERO, DC_25PT = 2, DC_37PT, DC_50PT, DC_62PT, DC_75PT,
  25. DC_87PT, DC_DISABLE, DC_RESV
  26. };
  27. struct cpufreq_frequency_table loongson2_clockmod_table[] = {
  28. {DC_RESV, CPUFREQ_ENTRY_INVALID},
  29. {DC_ZERO, CPUFREQ_ENTRY_INVALID},
  30. {DC_25PT, 0},
  31. {DC_37PT, 0},
  32. {DC_50PT, 0},
  33. {DC_62PT, 0},
  34. {DC_75PT, 0},
  35. {DC_87PT, 0},
  36. {DC_DISABLE, 0},
  37. {DC_RESV, CPUFREQ_TABLE_END},
  38. };
  39. EXPORT_SYMBOL_GPL(loongson2_clockmod_table);
  40. static struct clk cpu_clk = {
  41. .name = "cpu_clk",
  42. .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
  43. .rate = 800000000,
  44. };
  45. struct clk *clk_get(struct device *dev, const char *id)
  46. {
  47. return &cpu_clk;
  48. }
  49. EXPORT_SYMBOL(clk_get);
  50. static void propagate_rate(struct clk *clk)
  51. {
  52. struct clk *clkp;
  53. list_for_each_entry(clkp, &clock_list, node) {
  54. if (likely(clkp->parent != clk))
  55. continue;
  56. if (likely(clkp->ops && clkp->ops->recalc))
  57. clkp->ops->recalc(clkp);
  58. if (unlikely(clkp->flags & CLK_RATE_PROPAGATES))
  59. propagate_rate(clkp);
  60. }
  61. }
  62. int clk_enable(struct clk *clk)
  63. {
  64. return 0;
  65. }
  66. EXPORT_SYMBOL(clk_enable);
  67. void clk_disable(struct clk *clk)
  68. {
  69. }
  70. EXPORT_SYMBOL(clk_disable);
  71. unsigned long clk_get_rate(struct clk *clk)
  72. {
  73. return (unsigned long)clk->rate;
  74. }
  75. EXPORT_SYMBOL(clk_get_rate);
  76. void clk_put(struct clk *clk)
  77. {
  78. }
  79. EXPORT_SYMBOL(clk_put);
  80. int clk_set_rate(struct clk *clk, unsigned long rate)
  81. {
  82. int ret = 0;
  83. int regval;
  84. int i;
  85. if (likely(clk->ops && clk->ops->set_rate)) {
  86. unsigned long flags;
  87. spin_lock_irqsave(&clock_lock, flags);
  88. ret = clk->ops->set_rate(clk, rate, 0);
  89. spin_unlock_irqrestore(&clock_lock, flags);
  90. }
  91. if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
  92. propagate_rate(clk);
  93. for (i = 0; loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END;
  94. i++) {
  95. if (loongson2_clockmod_table[i].frequency ==
  96. CPUFREQ_ENTRY_INVALID)
  97. continue;
  98. if (rate == loongson2_clockmod_table[i].frequency)
  99. break;
  100. }
  101. if (rate != loongson2_clockmod_table[i].frequency)
  102. return -ENOTSUPP;
  103. clk->rate = rate;
  104. regval = LOONGSON_CHIPCFG0;
  105. regval = (regval & ~0x7) | (loongson2_clockmod_table[i].index - 1);
  106. LOONGSON_CHIPCFG0 = regval;
  107. return ret;
  108. }
  109. EXPORT_SYMBOL_GPL(clk_set_rate);
  110. long clk_round_rate(struct clk *clk, unsigned long rate)
  111. {
  112. if (likely(clk->ops && clk->ops->round_rate)) {
  113. unsigned long flags, rounded;
  114. spin_lock_irqsave(&clock_lock, flags);
  115. rounded = clk->ops->round_rate(clk, rate);
  116. spin_unlock_irqrestore(&clock_lock, flags);
  117. return rounded;
  118. }
  119. return rate;
  120. }
  121. EXPORT_SYMBOL_GPL(clk_round_rate);