r7s9210-cpg-mssr.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * R7S9210 Clock Pulse Generator / Module Standby
  4. *
  5. * Based on r8a7795-cpg-mssr.c
  6. *
  7. * Copyright (C) 2018 Chris Brandt
  8. * Copyright (C) 2018 Renesas Electronics Corp.
  9. *
  10. */
  11. #include <linux/clk.h>
  12. #include <linux/clk-provider.h>
  13. #include <dt-bindings/clock/r7s9210-cpg-mssr.h>
  14. #include "renesas-cpg-mssr.h"
  15. #define CPG_FRQCR 0x00
  16. static u8 cpg_mode;
  17. /* Internal Clock ratio table */
  18. static const struct {
  19. unsigned int i;
  20. unsigned int g;
  21. unsigned int b;
  22. unsigned int p1;
  23. /* p0 is always 32 */;
  24. } ratio_tab[5] = { /* I, G, B, P1 */
  25. { 2, 4, 8, 16}, /* FRQCR = 0x012 */
  26. { 4, 4, 8, 16}, /* FRQCR = 0x112 */
  27. { 8, 4, 8, 16}, /* FRQCR = 0x212 */
  28. { 16, 8, 16, 16}, /* FRQCR = 0x322 */
  29. { 16, 16, 32, 32}, /* FRQCR = 0x333 */
  30. };
  31. enum rz_clk_types {
  32. CLK_TYPE_RZA_MAIN = CLK_TYPE_CUSTOM,
  33. CLK_TYPE_RZA_PLL,
  34. };
  35. enum clk_ids {
  36. /* Core Clock Outputs exported to DT */
  37. LAST_DT_CORE_CLK = R7S9210_CLK_P0,
  38. /* External Input Clocks */
  39. CLK_EXTAL,
  40. /* Internal Core Clocks */
  41. CLK_MAIN,
  42. CLK_PLL,
  43. /* Module Clocks */
  44. MOD_CLK_BASE
  45. };
  46. static struct cpg_core_clk r7s9210_early_core_clks[] = {
  47. /* External Clock Inputs */
  48. DEF_INPUT("extal", CLK_EXTAL),
  49. /* Internal Core Clocks */
  50. DEF_BASE(".main", CLK_MAIN, CLK_TYPE_RZA_MAIN, CLK_EXTAL),
  51. DEF_BASE(".pll", CLK_PLL, CLK_TYPE_RZA_PLL, CLK_MAIN),
  52. /* Core Clock Outputs */
  53. DEF_FIXED("p1c", R7S9210_CLK_P1C, CLK_PLL, 16, 1),
  54. };
  55. static const struct mssr_mod_clk r7s9210_early_mod_clks[] __initconst = {
  56. DEF_MOD_STB("ostm2", 34, R7S9210_CLK_P1C),
  57. DEF_MOD_STB("ostm1", 35, R7S9210_CLK_P1C),
  58. DEF_MOD_STB("ostm0", 36, R7S9210_CLK_P1C),
  59. };
  60. static struct cpg_core_clk r7s9210_core_clks[] = {
  61. /* Core Clock Outputs */
  62. DEF_FIXED("i", R7S9210_CLK_I, CLK_PLL, 2, 1),
  63. DEF_FIXED("g", R7S9210_CLK_G, CLK_PLL, 4, 1),
  64. DEF_FIXED("b", R7S9210_CLK_B, CLK_PLL, 8, 1),
  65. DEF_FIXED("p1", R7S9210_CLK_P1, CLK_PLL, 16, 1),
  66. DEF_FIXED("p0", R7S9210_CLK_P0, CLK_PLL, 32, 1),
  67. };
  68. static const struct mssr_mod_clk r7s9210_mod_clks[] __initconst = {
  69. DEF_MOD_STB("scif4", 43, R7S9210_CLK_P1C),
  70. DEF_MOD_STB("scif3", 44, R7S9210_CLK_P1C),
  71. DEF_MOD_STB("scif2", 45, R7S9210_CLK_P1C),
  72. DEF_MOD_STB("scif1", 46, R7S9210_CLK_P1C),
  73. DEF_MOD_STB("scif0", 47, R7S9210_CLK_P1C),
  74. DEF_MOD_STB("ether1", 64, R7S9210_CLK_B),
  75. DEF_MOD_STB("ether0", 65, R7S9210_CLK_B),
  76. DEF_MOD_STB("i2c3", 84, R7S9210_CLK_P1),
  77. DEF_MOD_STB("i2c2", 85, R7S9210_CLK_P1),
  78. DEF_MOD_STB("i2c1", 86, R7S9210_CLK_P1),
  79. DEF_MOD_STB("i2c0", 87, R7S9210_CLK_P1),
  80. DEF_MOD_STB("spi2", 95, R7S9210_CLK_P1),
  81. DEF_MOD_STB("spi1", 96, R7S9210_CLK_P1),
  82. DEF_MOD_STB("spi0", 97, R7S9210_CLK_P1),
  83. };
  84. /* The clock dividers in the table vary based on DT and register settings */
  85. static void __init r7s9210_update_clk_table(struct clk *extal_clk,
  86. void __iomem *base)
  87. {
  88. int i;
  89. u16 frqcr;
  90. u8 index;
  91. /* If EXTAL is above 12MHz, then we know it is Mode 1 */
  92. if (clk_get_rate(extal_clk) > 12000000)
  93. cpg_mode = 1;
  94. frqcr = clk_readl(base + CPG_FRQCR) & 0xFFF;
  95. if (frqcr == 0x012)
  96. index = 0;
  97. else if (frqcr == 0x112)
  98. index = 1;
  99. else if (frqcr == 0x212)
  100. index = 2;
  101. else if (frqcr == 0x322)
  102. index = 3;
  103. else if (frqcr == 0x333)
  104. index = 4;
  105. else
  106. BUG_ON(1); /* Illegal FRQCR value */
  107. for (i = 0; i < ARRAY_SIZE(r7s9210_core_clks); i++) {
  108. switch (r7s9210_core_clks[i].id) {
  109. case R7S9210_CLK_I:
  110. r7s9210_core_clks[i].div = ratio_tab[index].i;
  111. break;
  112. case R7S9210_CLK_G:
  113. r7s9210_core_clks[i].div = ratio_tab[index].g;
  114. break;
  115. case R7S9210_CLK_B:
  116. r7s9210_core_clks[i].div = ratio_tab[index].b;
  117. break;
  118. case R7S9210_CLK_P1:
  119. case R7S9210_CLK_P1C:
  120. r7s9210_core_clks[i].div = ratio_tab[index].p1;
  121. break;
  122. case R7S9210_CLK_P0:
  123. r7s9210_core_clks[i].div = 32;
  124. break;
  125. }
  126. }
  127. }
  128. struct clk * __init rza2_cpg_clk_register(struct device *dev,
  129. const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
  130. struct clk **clks, void __iomem *base,
  131. struct raw_notifier_head *notifiers)
  132. {
  133. struct clk *parent;
  134. unsigned int mult = 1;
  135. unsigned int div = 1;
  136. parent = clks[core->parent];
  137. if (IS_ERR(parent))
  138. return ERR_CAST(parent);
  139. switch (core->id) {
  140. case CLK_MAIN:
  141. break;
  142. case CLK_PLL:
  143. if (cpg_mode)
  144. mult = 44; /* Divider 1 is 1/2 */
  145. else
  146. mult = 88; /* Divider 1 is 1 */
  147. break;
  148. default:
  149. return ERR_PTR(-EINVAL);
  150. }
  151. if (core->id == CLK_MAIN)
  152. r7s9210_update_clk_table(parent, base);
  153. return clk_register_fixed_factor(NULL, core->name,
  154. __clk_get_name(parent), 0, mult, div);
  155. }
  156. const struct cpg_mssr_info r7s9210_cpg_mssr_info __initconst = {
  157. /* Early Clocks */
  158. .early_core_clks = r7s9210_early_core_clks,
  159. .num_early_core_clks = ARRAY_SIZE(r7s9210_early_core_clks),
  160. .early_mod_clks = r7s9210_early_mod_clks,
  161. .num_early_mod_clks = ARRAY_SIZE(r7s9210_early_mod_clks),
  162. /* Core Clocks */
  163. .core_clks = r7s9210_core_clks,
  164. .num_core_clks = ARRAY_SIZE(r7s9210_core_clks),
  165. .last_dt_core_clk = LAST_DT_CORE_CLK,
  166. .num_total_core_clks = MOD_CLK_BASE,
  167. /* Module Clocks */
  168. .mod_clks = r7s9210_mod_clks,
  169. .num_mod_clks = ARRAY_SIZE(r7s9210_mod_clks),
  170. .num_hw_mod_clks = 11 * 32, /* includes STBCR0 which doesn't exist */
  171. /* Callbacks */
  172. .cpg_clk_register = rza2_cpg_clk_register,
  173. /* RZ/A2 has Standby Control Registers */
  174. .stbyctrl = true,
  175. };
  176. static void __init r7s9210_cpg_mssr_early_init(struct device_node *np)
  177. {
  178. cpg_mssr_early_init(np, &r7s9210_cpg_mssr_info);
  179. }
  180. CLK_OF_DECLARE_DRIVER(cpg_mstp_clks, "renesas,r7s9210-cpg-mssr",
  181. r7s9210_cpg_mssr_early_init);