clk-loongson1b.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /*
  2. * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation; either version 2 of the License, or (at your
  7. * option) any later version.
  8. */
  9. #include <linux/clkdev.h>
  10. #include <linux/clk-provider.h>
  11. #include <linux/io.h>
  12. #include <linux/err.h>
  13. #include <loongson1.h>
  14. #include "clk.h"
  15. #define OSC (33 * 1000000)
  16. #define DIV_APB 2
  17. static DEFINE_SPINLOCK(_lock);
  18. static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
  19. unsigned long parent_rate)
  20. {
  21. u32 pll, rate;
  22. pll = __raw_readl(LS1X_CLK_PLL_FREQ);
  23. rate = 12 + (pll & GENMASK(5, 0));
  24. rate *= OSC;
  25. rate >>= 1;
  26. return rate;
  27. }
  28. static const struct clk_ops ls1x_pll_clk_ops = {
  29. .recalc_rate = ls1x_pll_recalc_rate,
  30. };
  31. static const char *const cpu_parents[] = { "cpu_clk_div", "osc_clk", };
  32. static const char *const ahb_parents[] = { "ahb_clk_div", "osc_clk", };
  33. static const char *const dc_parents[] = { "dc_clk_div", "osc_clk", };
  34. void __init ls1x_clk_init(void)
  35. {
  36. struct clk_hw *hw;
  37. hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
  38. clk_hw_register_clkdev(hw, "osc_clk", NULL);
  39. /* clock derived from 33 MHz OSC clk */
  40. hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk",
  41. &ls1x_pll_clk_ops, 0);
  42. clk_hw_register_clkdev(hw, "pll_clk", NULL);
  43. /* clock derived from PLL clk */
  44. /* _____
  45. * _______________________| |
  46. * OSC ___/ | MUX |___ CPU CLK
  47. * \___ PLL ___ CPU DIV ___| |
  48. * |_____|
  49. */
  50. hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
  51. CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
  52. DIV_CPU_SHIFT, DIV_CPU_WIDTH,
  53. CLK_DIVIDER_ONE_BASED |
  54. CLK_DIVIDER_ROUND_CLOSEST, &_lock);
  55. clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
  56. hw = clk_hw_register_mux(NULL, "cpu_clk", cpu_parents,
  57. ARRAY_SIZE(cpu_parents),
  58. CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
  59. BYPASS_CPU_SHIFT, BYPASS_CPU_WIDTH, 0, &_lock);
  60. clk_hw_register_clkdev(hw, "cpu_clk", NULL);
  61. /* _____
  62. * _______________________| |
  63. * OSC ___/ | MUX |___ DC CLK
  64. * \___ PLL ___ DC DIV ___| |
  65. * |_____|
  66. */
  67. hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
  68. 0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
  69. DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
  70. clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
  71. hw = clk_hw_register_mux(NULL, "dc_clk", dc_parents,
  72. ARRAY_SIZE(dc_parents),
  73. CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
  74. BYPASS_DC_SHIFT, BYPASS_DC_WIDTH, 0, &_lock);
  75. clk_hw_register_clkdev(hw, "dc_clk", NULL);
  76. /* _____
  77. * _______________________| |
  78. * OSC ___/ | MUX |___ DDR CLK
  79. * \___ PLL ___ DDR DIV ___| |
  80. * |_____|
  81. */
  82. hw = clk_hw_register_divider(NULL, "ahb_clk_div", "pll_clk",
  83. 0, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT,
  84. DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED,
  85. &_lock);
  86. clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
  87. hw = clk_hw_register_mux(NULL, "ahb_clk", ahb_parents,
  88. ARRAY_SIZE(ahb_parents),
  89. CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
  90. BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock);
  91. clk_hw_register_clkdev(hw, "ahb_clk", NULL);
  92. clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
  93. clk_hw_register_clkdev(hw, "stmmaceth", NULL);
  94. /* clock derived from AHB clk */
  95. /* APB clk is always half of the AHB clk */
  96. hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
  97. DIV_APB);
  98. clk_hw_register_clkdev(hw, "apb_clk", NULL);
  99. clk_hw_register_clkdev(hw, "ls1x-ac97", NULL);
  100. clk_hw_register_clkdev(hw, "ls1x-i2c", NULL);
  101. clk_hw_register_clkdev(hw, "ls1x-nand", NULL);
  102. clk_hw_register_clkdev(hw, "ls1x-pwmtimer", NULL);
  103. clk_hw_register_clkdev(hw, "ls1x-spi", NULL);
  104. clk_hw_register_clkdev(hw, "ls1x-wdt", NULL);
  105. clk_hw_register_clkdev(hw, "serial8250", NULL);
  106. }