clkc.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Toshiba Visconti clock controller
  4. *
  5. * Copyright (c) 2021 TOSHIBA CORPORATION
  6. * Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation
  7. *
  8. * Nobuhiro Iwamatsu <[email protected]>
  9. */
  10. #include <linux/clk-provider.h>
  11. #include <linux/delay.h>
  12. #include <linux/device.h>
  13. #include <linux/io.h>
  14. #include <linux/of.h>
  15. #include <linux/of_address.h>
  16. #include <linux/regmap.h>
  17. #include <linux/slab.h>
  18. #include <linux/string.h>
  19. #include "clkc.h"
  20. static inline struct visconti_clk_gate *to_visconti_clk_gate(struct clk_hw *hw)
  21. {
  22. return container_of(hw, struct visconti_clk_gate, hw);
  23. }
  24. static int visconti_gate_clk_is_enabled(struct clk_hw *hw)
  25. {
  26. struct visconti_clk_gate *gate = to_visconti_clk_gate(hw);
  27. u32 clk = BIT(gate->ck_idx);
  28. u32 val;
  29. regmap_read(gate->regmap, gate->ckon_offset, &val);
  30. return (val & clk) ? 1 : 0;
  31. }
  32. static void visconti_gate_clk_disable(struct clk_hw *hw)
  33. {
  34. struct visconti_clk_gate *gate = to_visconti_clk_gate(hw);
  35. u32 clk = BIT(gate->ck_idx);
  36. unsigned long flags;
  37. spin_lock_irqsave(gate->lock, flags);
  38. if (!visconti_gate_clk_is_enabled(hw)) {
  39. spin_unlock_irqrestore(gate->lock, flags);
  40. return;
  41. }
  42. regmap_update_bits(gate->regmap, gate->ckoff_offset, clk, clk);
  43. spin_unlock_irqrestore(gate->lock, flags);
  44. }
  45. static int visconti_gate_clk_enable(struct clk_hw *hw)
  46. {
  47. struct visconti_clk_gate *gate = to_visconti_clk_gate(hw);
  48. u32 clk = BIT(gate->ck_idx);
  49. unsigned long flags;
  50. spin_lock_irqsave(gate->lock, flags);
  51. regmap_update_bits(gate->regmap, gate->ckon_offset, clk, clk);
  52. spin_unlock_irqrestore(gate->lock, flags);
  53. return 0;
  54. }
  55. static const struct clk_ops visconti_clk_gate_ops = {
  56. .enable = visconti_gate_clk_enable,
  57. .disable = visconti_gate_clk_disable,
  58. .is_enabled = visconti_gate_clk_is_enabled,
  59. };
  60. static struct clk_hw *visconti_clk_register_gate(struct device *dev,
  61. const char *name,
  62. const char *parent_name,
  63. struct regmap *regmap,
  64. const struct visconti_clk_gate_table *clks,
  65. u32 rson_offset,
  66. u32 rsoff_offset,
  67. u8 rs_idx,
  68. spinlock_t *lock)
  69. {
  70. struct visconti_clk_gate *gate;
  71. struct clk_parent_data *pdata;
  72. struct clk_init_data init;
  73. struct clk_hw *hw;
  74. int ret;
  75. pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
  76. if (!pdata)
  77. return ERR_PTR(-ENOMEM);
  78. pdata->name = pdata->fw_name = parent_name;
  79. gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
  80. if (!gate)
  81. return ERR_PTR(-ENOMEM);
  82. init.name = name;
  83. init.ops = &visconti_clk_gate_ops;
  84. init.flags = clks->flags;
  85. init.parent_data = pdata;
  86. init.num_parents = 1;
  87. gate->regmap = regmap;
  88. gate->ckon_offset = clks->ckon_offset;
  89. gate->ckoff_offset = clks->ckoff_offset;
  90. gate->ck_idx = clks->ck_idx;
  91. gate->rson_offset = rson_offset;
  92. gate->rsoff_offset = rsoff_offset;
  93. gate->rs_idx = rs_idx;
  94. gate->lock = lock;
  95. gate->hw.init = &init;
  96. hw = &gate->hw;
  97. ret = devm_clk_hw_register(dev, hw);
  98. if (ret)
  99. hw = ERR_PTR(ret);
  100. return hw;
  101. }
  102. int visconti_clk_register_gates(struct visconti_clk_provider *ctx,
  103. const struct visconti_clk_gate_table *clks,
  104. int num_gate,
  105. const struct visconti_reset_data *reset,
  106. spinlock_t *lock)
  107. {
  108. struct device *dev = ctx->dev;
  109. int i;
  110. for (i = 0; i < num_gate; i++) {
  111. const char *parent_div_name = clks[i].parent_data[0].name;
  112. struct clk_parent_data *pdata;
  113. u32 rson_offset, rsoff_offset;
  114. struct clk_hw *gate_clk;
  115. struct clk_hw *div_clk;
  116. char *dev_name;
  117. u8 rs_idx;
  118. pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
  119. if (!pdata)
  120. return -ENOMEM;
  121. dev_name = devm_kasprintf(dev, GFP_KERNEL, "%s_div", clks[i].name);
  122. if (!dev_name)
  123. return -ENOMEM;
  124. if (clks[i].rs_id != NO_RESET) {
  125. rson_offset = reset[clks[i].rs_id].rson_offset;
  126. rsoff_offset = reset[clks[i].rs_id].rsoff_offset;
  127. rs_idx = reset[clks[i].rs_id].rs_idx;
  128. } else {
  129. rson_offset = rsoff_offset = rs_idx = -1;
  130. }
  131. div_clk = devm_clk_hw_register_fixed_factor(dev,
  132. dev_name,
  133. parent_div_name,
  134. 0, 1,
  135. clks[i].div);
  136. if (IS_ERR(div_clk))
  137. return PTR_ERR(div_clk);
  138. gate_clk = visconti_clk_register_gate(dev,
  139. clks[i].name,
  140. dev_name,
  141. ctx->regmap,
  142. &clks[i],
  143. rson_offset,
  144. rsoff_offset,
  145. rs_idx,
  146. lock);
  147. if (IS_ERR(gate_clk)) {
  148. dev_err(dev, "%s: failed to register clock %s\n",
  149. __func__, clks[i].name);
  150. return PTR_ERR(gate_clk);
  151. }
  152. ctx->clk_data.hws[clks[i].id] = gate_clk;
  153. }
  154. return 0;
  155. }
  156. struct visconti_clk_provider *visconti_init_clk(struct device *dev,
  157. struct regmap *regmap,
  158. unsigned long nr_clks)
  159. {
  160. struct visconti_clk_provider *ctx;
  161. int i;
  162. ctx = devm_kzalloc(dev, struct_size(ctx, clk_data.hws, nr_clks), GFP_KERNEL);
  163. if (!ctx)
  164. return ERR_PTR(-ENOMEM);
  165. for (i = 0; i < nr_clks; ++i)
  166. ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
  167. ctx->clk_data.num = nr_clks;
  168. ctx->dev = dev;
  169. ctx->regmap = regmap;
  170. return ctx;
  171. }