clock-sh7343.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * arch/sh/kernel/cpu/sh4/clock-sh7343.c
  3. *
  4. * SH7343/SH7722 support for the clock framework
  5. *
  6. * Copyright (C) 2006 Paul Mundt
  7. *
  8. * This file is subject to the terms and conditions of the GNU General Public
  9. * License. See the file "COPYING" in the main directory of this archive
  10. * for more details.
  11. */
  12. #include <linux/init.h>
  13. #include <linux/kernel.h>
  14. #include <linux/io.h>
  15. #include <asm/clock.h>
  16. #include <asm/freq.h>
  17. /*
  18. * SH7343/SH7722 uses a common set of multipliers and divisors, so this
  19. * is quite simple..
  20. */
  21. static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
  22. static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
  23. #define pll_calc() (((ctrl_inl(FRQCR) >> 24) & 0x1f) + 1)
  24. static void master_clk_init(struct clk *clk)
  25. {
  26. clk->parent = clk_get(NULL, "cpu_clk");
  27. }
  28. static void master_clk_recalc(struct clk *clk)
  29. {
  30. int idx = (ctrl_inl(FRQCR) & 0x000f);
  31. clk->rate *= clk->parent->rate * multipliers[idx] / divisors[idx];
  32. }
  33. static struct clk_ops sh7343_master_clk_ops = {
  34. .init = master_clk_init,
  35. .recalc = master_clk_recalc,
  36. };
  37. static void module_clk_init(struct clk *clk)
  38. {
  39. clk->parent = NULL;
  40. clk->rate = CONFIG_SH_PCLK_FREQ;
  41. }
  42. static struct clk_ops sh7343_module_clk_ops = {
  43. .init = module_clk_init,
  44. };
  45. static void bus_clk_init(struct clk *clk)
  46. {
  47. clk->parent = clk_get(NULL, "cpu_clk");
  48. }
  49. static void bus_clk_recalc(struct clk *clk)
  50. {
  51. int idx = (ctrl_inl(FRQCR) >> 8) & 0x000f;
  52. clk->rate = clk->parent->rate * multipliers[idx] / divisors[idx];
  53. }
  54. static struct clk_ops sh7343_bus_clk_ops = {
  55. .init = bus_clk_init,
  56. .recalc = bus_clk_recalc,
  57. };
  58. static void cpu_clk_init(struct clk *clk)
  59. {
  60. clk->parent = clk_get(NULL, "module_clk");
  61. clk->flags |= CLK_RATE_PROPAGATES;
  62. clk_set_rate(clk, clk_get_rate(clk));
  63. }
  64. static void cpu_clk_recalc(struct clk *clk)
  65. {
  66. int idx = (ctrl_inl(FRQCR) >> 20) & 0x000f;
  67. clk->rate = clk->parent->rate * pll_calc() *
  68. multipliers[idx] / divisors[idx];
  69. }
  70. static struct clk_ops sh7343_cpu_clk_ops = {
  71. .init = cpu_clk_init,
  72. .recalc = cpu_clk_recalc,
  73. };
  74. static struct clk_ops *sh7343_clk_ops[] = {
  75. &sh7343_master_clk_ops,
  76. &sh7343_module_clk_ops,
  77. &sh7343_bus_clk_ops,
  78. &sh7343_cpu_clk_ops,
  79. };
  80. void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
  81. {
  82. if (idx < ARRAY_SIZE(sh7343_clk_ops))
  83. *ops = sh7343_clk_ops[idx];
  84. }