clk-gate.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2014 MediaTek Inc.
  4. * Author: James Liao <jamesjj.liao@mediatek.com>
  5. */
  6. #include <linux/of.h>
  7. #include <linux/of_address.h>
  8. #include <linux/io.h>
  9. #include <linux/slab.h>
  10. #include <linux/delay.h>
  11. #include <linux/clkdev.h>
  12. #include "clk-mtk.h"
  13. #include "clk-gate.h"
  14. static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
  15. {
  16. struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
  17. u32 val;
  18. regmap_read(cg->regmap, cg->sta_ofs, &val);
  19. val &= BIT(cg->bit);
  20. return val == 0;
  21. }
  22. static int mtk_cg_bit_is_set(struct clk_hw *hw)
  23. {
  24. struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
  25. u32 val;
  26. regmap_read(cg->regmap, cg->sta_ofs, &val);
  27. val &= BIT(cg->bit);
  28. return val != 0;
  29. }
  30. static void mtk_cg_set_bit(struct clk_hw *hw)
  31. {
  32. struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
  33. regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit));
  34. }
  35. static void mtk_cg_clr_bit(struct clk_hw *hw)
  36. {
  37. struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
  38. regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
  39. }
  40. static void mtk_cg_set_bit_no_setclr(struct clk_hw *hw)
  41. {
  42. struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
  43. u32 cgbit = BIT(cg->bit);
  44. regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, cgbit);
  45. }
  46. static void mtk_cg_clr_bit_no_setclr(struct clk_hw *hw)
  47. {
  48. struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
  49. u32 cgbit = BIT(cg->bit);
  50. regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, 0);
  51. }
  52. static int mtk_cg_enable(struct clk_hw *hw)
  53. {
  54. mtk_cg_clr_bit(hw);
  55. return 0;
  56. }
  57. static void mtk_cg_disable(struct clk_hw *hw)
  58. {
  59. mtk_cg_set_bit(hw);
  60. }
  61. static int mtk_cg_enable_inv(struct clk_hw *hw)
  62. {
  63. mtk_cg_set_bit(hw);
  64. return 0;
  65. }
  66. static void mtk_cg_disable_inv(struct clk_hw *hw)
  67. {
  68. mtk_cg_clr_bit(hw);
  69. }
  70. static int mtk_cg_enable_no_setclr(struct clk_hw *hw)
  71. {
  72. mtk_cg_clr_bit_no_setclr(hw);
  73. return 0;
  74. }
  75. static void mtk_cg_disable_no_setclr(struct clk_hw *hw)
  76. {
  77. mtk_cg_set_bit_no_setclr(hw);
  78. }
  79. static int mtk_cg_enable_inv_no_setclr(struct clk_hw *hw)
  80. {
  81. mtk_cg_set_bit_no_setclr(hw);
  82. return 0;
  83. }
  84. static void mtk_cg_disable_inv_no_setclr(struct clk_hw *hw)
  85. {
  86. mtk_cg_clr_bit_no_setclr(hw);
  87. }
  88. const struct clk_ops mtk_clk_gate_ops_setclr = {
  89. .is_enabled = mtk_cg_bit_is_cleared,
  90. .enable = mtk_cg_enable,
  91. .disable = mtk_cg_disable,
  92. };
  93. const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
  94. .is_enabled = mtk_cg_bit_is_set,
  95. .enable = mtk_cg_enable_inv,
  96. .disable = mtk_cg_disable_inv,
  97. };
  98. const struct clk_ops mtk_clk_gate_ops_no_setclr = {
  99. .is_enabled = mtk_cg_bit_is_cleared,
  100. .enable = mtk_cg_enable_no_setclr,
  101. .disable = mtk_cg_disable_no_setclr,
  102. };
  103. const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = {
  104. .is_enabled = mtk_cg_bit_is_set,
  105. .enable = mtk_cg_enable_inv_no_setclr,
  106. .disable = mtk_cg_disable_inv_no_setclr,
  107. };
  108. struct clk *mtk_clk_register_gate(
  109. const char *name,
  110. const char *parent_name,
  111. struct regmap *regmap,
  112. int set_ofs,
  113. int clr_ofs,
  114. int sta_ofs,
  115. u8 bit,
  116. const struct clk_ops *ops,
  117. unsigned long flags,
  118. struct device *dev)
  119. {
  120. struct mtk_clk_gate *cg;
  121. struct clk *clk;
  122. struct clk_init_data init = {};
  123. cg = kzalloc(sizeof(*cg), GFP_KERNEL);
  124. if (!cg)
  125. return ERR_PTR(-ENOMEM);
  126. init.name = name;
  127. init.flags = flags | CLK_SET_RATE_PARENT;
  128. init.parent_names = parent_name ? &parent_name : NULL;
  129. init.num_parents = parent_name ? 1 : 0;
  130. init.ops = ops;
  131. cg->regmap = regmap;
  132. cg->set_ofs = set_ofs;
  133. cg->clr_ofs = clr_ofs;
  134. cg->sta_ofs = sta_ofs;
  135. cg->bit = bit;
  136. cg->hw.init = &init;
  137. clk = clk_register(dev, &cg->hw);
  138. if (IS_ERR(clk))
  139. kfree(cg);
  140. return clk;
  141. }