clock.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * linux/arch/arm/mach-sa1100/clock.c
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/errno.h>
  7. #include <linux/err.h>
  8. #include <linux/clk.h>
  9. #include <linux/clkdev.h>
  10. #include <linux/clk-provider.h>
  11. #include <linux/io.h>
  12. #include <linux/spinlock.h>
  13. #include <mach/hardware.h>
  14. #include <mach/generic.h>
  15. static const char * const clk_tucr_parents[] = {
  16. "clk32768", "clk3686400",
  17. };
  18. static DEFINE_SPINLOCK(tucr_lock);
  19. static int clk_gpio27_enable(struct clk_hw *hw)
  20. {
  21. unsigned long flags;
  22. /*
  23. * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
  24. * (SA-1110 Developer's Manual, section 9.1.2.1)
  25. */
  26. local_irq_save(flags);
  27. GAFR |= GPIO_32_768kHz;
  28. GPDR |= GPIO_32_768kHz;
  29. local_irq_restore(flags);
  30. return 0;
  31. }
  32. static void clk_gpio27_disable(struct clk_hw *hw)
  33. {
  34. unsigned long flags;
  35. local_irq_save(flags);
  36. GPDR &= ~GPIO_32_768kHz;
  37. GAFR &= ~GPIO_32_768kHz;
  38. local_irq_restore(flags);
  39. }
  40. static const struct clk_ops clk_gpio27_ops = {
  41. .enable = clk_gpio27_enable,
  42. .disable = clk_gpio27_disable,
  43. };
  44. static const char * const clk_gpio27_parents[] = {
  45. "tucr-mux",
  46. };
  47. static const struct clk_init_data clk_gpio27_init_data __initconst = {
  48. .name = "gpio27",
  49. .ops = &clk_gpio27_ops,
  50. .parent_names = clk_gpio27_parents,
  51. .num_parents = ARRAY_SIZE(clk_gpio27_parents),
  52. };
  53. /*
  54. * Derived from the table 8-1 in the SA1110 manual, the MPLL appears to
  55. * multiply its input rate by 4 x (4 + PPCR). This calculation gives
  56. * the exact rate. The figures given in the table are the rates rounded
  57. * to 100kHz. Stick with sa11x0_getspeed() for the time being.
  58. */
  59. static unsigned long clk_mpll_recalc_rate(struct clk_hw *hw,
  60. unsigned long prate)
  61. {
  62. return sa11x0_getspeed(0) * 1000;
  63. }
  64. static const struct clk_ops clk_mpll_ops = {
  65. .recalc_rate = clk_mpll_recalc_rate,
  66. };
  67. static const char * const clk_mpll_parents[] = {
  68. "clk3686400",
  69. };
  70. static const struct clk_init_data clk_mpll_init_data __initconst = {
  71. .name = "mpll",
  72. .ops = &clk_mpll_ops,
  73. .parent_names = clk_mpll_parents,
  74. .num_parents = ARRAY_SIZE(clk_mpll_parents),
  75. .flags = CLK_GET_RATE_NOCACHE | CLK_IS_CRITICAL,
  76. };
  77. int __init sa11xx_clk_init(void)
  78. {
  79. struct clk_hw *hw;
  80. int ret;
  81. hw = clk_hw_register_fixed_rate(NULL, "clk32768", NULL, 0, 32768);
  82. if (IS_ERR(hw))
  83. return PTR_ERR(hw);
  84. clk_hw_register_clkdev(hw, NULL, "sa1100-rtc");
  85. hw = clk_hw_register_fixed_rate(NULL, "clk3686400", NULL, 0, 3686400);
  86. if (IS_ERR(hw))
  87. return PTR_ERR(hw);
  88. clk_hw_register_clkdev(hw, "OSTIMER0", NULL);
  89. hw = kzalloc(sizeof(*hw), GFP_KERNEL);
  90. if (!hw)
  91. return -ENOMEM;
  92. hw->init = &clk_mpll_init_data;
  93. ret = clk_hw_register(NULL, hw);
  94. if (ret) {
  95. kfree(hw);
  96. return ret;
  97. }
  98. clk_hw_register_clkdev(hw, NULL, "sa11x0-fb");
  99. clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia");
  100. clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia.0");
  101. clk_hw_register_clkdev(hw, NULL, "sa11x0-pcmcia.1");
  102. clk_hw_register_clkdev(hw, NULL, "1800");
  103. hw = clk_hw_register_mux(NULL, "tucr-mux", clk_tucr_parents,
  104. ARRAY_SIZE(clk_tucr_parents), 0,
  105. (void __iomem *)&TUCR, FShft(TUCR_TSEL),
  106. FAlnMsk(TUCR_TSEL), 0, &tucr_lock);
  107. clk_set_rate(hw->clk, 3686400);
  108. hw = kzalloc(sizeof(*hw), GFP_KERNEL);
  109. if (!hw)
  110. return -ENOMEM;
  111. hw->init = &clk_gpio27_init_data;
  112. ret = clk_hw_register(NULL, hw);
  113. if (ret) {
  114. kfree(hw);
  115. return ret;
  116. }
  117. clk_hw_register_clkdev(hw, NULL, "sa1111.0");
  118. return 0;
  119. }