clk-generic.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Generic clock support for AT91 architectures.
  4. *
  5. * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
  6. *
  7. * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
  8. *
  9. * Based on drivers/clk/at91/clk-generated.c from Linux.
  10. */
  11. #include <common.h>
  12. #include <clk-uclass.h>
  13. #include <dm.h>
  14. #include <linux/io.h>
  15. #include <linux/clk-provider.h>
  16. #include <linux/clk/at91_pmc.h>
  17. #include "pmc.h"
  18. #define UBOOT_DM_CLK_AT91_GCK "at91-gck-clk"
  19. #define GENERATED_MAX_DIV 255
  20. struct clk_gck {
  21. void __iomem *base;
  22. const u32 *clk_mux_table;
  23. const u32 *mux_table;
  24. const struct clk_pcr_layout *layout;
  25. struct clk_range range;
  26. struct clk clk;
  27. u32 num_parents;
  28. u32 id;
  29. };
  30. #define to_clk_gck(_c) container_of(_c, struct clk_gck, clk)
  31. static int clk_gck_enable(struct clk *clk)
  32. {
  33. struct clk_gck *gck = to_clk_gck(clk);
  34. pmc_write(gck->base, gck->layout->offset,
  35. (gck->id & gck->layout->pid_mask));
  36. pmc_update_bits(gck->base, gck->layout->offset,
  37. gck->layout->cmd | AT91_PMC_PCR_GCKEN,
  38. gck->layout->cmd | AT91_PMC_PCR_GCKEN);
  39. return 0;
  40. }
  41. static int clk_gck_disable(struct clk *clk)
  42. {
  43. struct clk_gck *gck = to_clk_gck(clk);
  44. pmc_write(gck->base, gck->layout->offset,
  45. (gck->id & gck->layout->pid_mask));
  46. pmc_update_bits(gck->base, gck->layout->offset,
  47. gck->layout->cmd | AT91_PMC_PCR_GCKEN,
  48. gck->layout->cmd);
  49. return 0;
  50. }
  51. static int clk_gck_set_parent(struct clk *clk, struct clk *parent)
  52. {
  53. struct clk_gck *gck = to_clk_gck(clk);
  54. int index;
  55. index = at91_clk_mux_val_to_index(gck->clk_mux_table, gck->num_parents,
  56. parent->id);
  57. if (index < 0)
  58. return index;
  59. index = at91_clk_mux_index_to_val(gck->mux_table, gck->num_parents,
  60. index);
  61. if (index < 0)
  62. return index;
  63. pmc_write(gck->base, gck->layout->offset,
  64. (gck->id & gck->layout->pid_mask));
  65. pmc_update_bits(gck->base, gck->layout->offset,
  66. gck->layout->gckcss_mask | gck->layout->cmd,
  67. (index << (ffs(gck->layout->gckcss_mask) - 1)) |
  68. gck->layout->cmd);
  69. return 0;
  70. }
  71. static ulong clk_gck_set_rate(struct clk *clk, ulong rate)
  72. {
  73. struct clk_gck *gck = to_clk_gck(clk);
  74. ulong parent_rate = clk_get_parent_rate(clk);
  75. u32 div;
  76. if (!rate || !parent_rate)
  77. return 0;
  78. if (gck->range.max && rate > gck->range.max)
  79. return 0;
  80. div = DIV_ROUND_CLOSEST(parent_rate, rate);
  81. if (div > GENERATED_MAX_DIV + 1 || !div)
  82. return 0;
  83. pmc_write(gck->base, gck->layout->offset,
  84. (gck->id & gck->layout->pid_mask));
  85. pmc_update_bits(gck->base, gck->layout->offset,
  86. AT91_PMC_PCR_GCKDIV_MASK | gck->layout->cmd,
  87. ((div - 1) << (ffs(AT91_PMC_PCR_GCKDIV_MASK) - 1)) |
  88. gck->layout->cmd);
  89. return parent_rate / div;
  90. }
  91. static ulong clk_gck_get_rate(struct clk *clk)
  92. {
  93. struct clk_gck *gck = to_clk_gck(clk);
  94. ulong parent_rate = clk_get_parent_rate(clk);
  95. u32 val, div;
  96. if (!parent_rate)
  97. return 0;
  98. pmc_write(gck->base, gck->layout->offset,
  99. (gck->id & gck->layout->pid_mask));
  100. pmc_read(gck->base, gck->layout->offset, &val);
  101. div = (val & AT91_PMC_PCR_GCKDIV_MASK) >>
  102. (ffs(AT91_PMC_PCR_GCKDIV_MASK) - 1);
  103. return parent_rate / (div + 1);
  104. }
  105. static const struct clk_ops gck_ops = {
  106. .enable = clk_gck_enable,
  107. .disable = clk_gck_disable,
  108. .set_parent = clk_gck_set_parent,
  109. .set_rate = clk_gck_set_rate,
  110. .get_rate = clk_gck_get_rate,
  111. };
  112. struct clk *
  113. at91_clk_register_generic(void __iomem *base,
  114. const struct clk_pcr_layout *layout,
  115. const char *name, const char * const *parent_names,
  116. const u32 *clk_mux_table, const u32 *mux_table,
  117. u8 num_parents, u8 id,
  118. const struct clk_range *range)
  119. {
  120. struct clk_gck *gck;
  121. struct clk *clk;
  122. int ret, index;
  123. u32 val;
  124. if (!base || !layout || !name || !parent_names || !num_parents ||
  125. !clk_mux_table || !mux_table || !range)
  126. return ERR_PTR(-EINVAL);
  127. gck = kzalloc(sizeof(*gck), GFP_KERNEL);
  128. if (!gck)
  129. return ERR_PTR(-ENOMEM);
  130. gck->id = id;
  131. gck->base = base;
  132. gck->range = *range;
  133. gck->layout = layout;
  134. gck->clk_mux_table = clk_mux_table;
  135. gck->mux_table = mux_table;
  136. gck->num_parents = num_parents;
  137. clk = &gck->clk;
  138. clk->flags = CLK_GET_RATE_NOCACHE;
  139. pmc_write(gck->base, gck->layout->offset,
  140. (gck->id & gck->layout->pid_mask));
  141. pmc_read(gck->base, gck->layout->offset, &val);
  142. val = (val & gck->layout->gckcss_mask) >>
  143. (ffs(gck->layout->gckcss_mask) - 1);
  144. index = at91_clk_mux_val_to_index(gck->mux_table, gck->num_parents,
  145. val);
  146. if (index < 0) {
  147. kfree(gck);
  148. return ERR_PTR(index);
  149. }
  150. ret = clk_register(clk, UBOOT_DM_CLK_AT91_GCK, name,
  151. parent_names[index]);
  152. if (ret) {
  153. kfree(gck);
  154. clk = ERR_PTR(ret);
  155. }
  156. return clk;
  157. }
  158. U_BOOT_DRIVER(at91_gck_clk) = {
  159. .name = UBOOT_DM_CLK_AT91_GCK,
  160. .id = UCLASS_CLK,
  161. .ops = &gck_ops,
  162. .flags = DM_FLAG_PRE_RELOC,
  163. };