clk-mux.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Copyright (c) 2015 MediaTek Inc.
  3. * Author: James Liao <jamesjj.liao@mediatek.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <linux/of.h>
  15. #include <linux/of_address.h>
  16. #include <linux/slab.h>
  17. #include "clk-mtk.h"
  18. #include "clk-mux.h"
  19. #define WORKAROUND_318_WARNING 1
  20. struct mtk_mux_upd_data {
  21. struct clk_hw hw;
  22. void __iomem *base;
  23. u32 mux_ofs;
  24. u32 upd_ofs;
  25. s8 mux_shift;
  26. s8 mux_width;
  27. s8 gate_shift;
  28. s8 upd_shift;
  29. spinlock_t *lock;
  30. };
  31. static inline struct mtk_mux_upd_data *to_mtk_mux_upd_data(struct clk_hw *hw)
  32. {
  33. return container_of(hw, struct mtk_mux_upd_data, hw);
  34. }
  35. static int mtk_mux_upd_enable(struct clk_hw *hw)
  36. {
  37. struct mtk_mux_upd_data *mux = to_mtk_mux_upd_data(hw);
  38. u32 val, orig;
  39. unsigned long flags = 0;
  40. if (mux->lock)
  41. spin_lock_irqsave(mux->lock, flags);
  42. val = clk_readl(mux->base + mux->mux_ofs);
  43. orig = val;
  44. val &= ~BIT(mux->gate_shift);
  45. if (val != orig) {
  46. clk_writel(val, mux->base + mux->mux_ofs);
  47. if (mux->upd_shift > 0)
  48. clk_writel(BIT(mux->upd_shift), mux->base + mux->upd_ofs);
  49. }
  50. if (mux->lock)
  51. spin_unlock_irqrestore(mux->lock, flags);
  52. return 0;
  53. }
  54. static void mtk_mux_upd_disable(struct clk_hw *hw)
  55. {
  56. struct mtk_mux_upd_data *mux = to_mtk_mux_upd_data(hw);
  57. u32 val, orig;
  58. unsigned long flags = 0;
  59. if (mux->lock)
  60. spin_lock_irqsave(mux->lock, flags);
  61. val = clk_readl(mux->base + mux->mux_ofs);
  62. orig = val;
  63. val |= BIT(mux->gate_shift);
  64. if (val != orig) {
  65. clk_writel(val, mux->base + mux->mux_ofs);
  66. if (mux->upd_shift > 0)
  67. clk_writel(BIT(mux->upd_shift), mux->base + mux->upd_ofs);
  68. }
  69. if (mux->lock)
  70. spin_unlock_irqrestore(mux->lock, flags);
  71. }
  72. static int mtk_mux_upd_is_enabled(struct clk_hw *hw)
  73. {
  74. struct mtk_mux_upd_data *mux = to_mtk_mux_upd_data(hw);
  75. if (mux->gate_shift < 0)
  76. return true;
  77. return (clk_readl(mux->base + mux->mux_ofs) & BIT(mux->gate_shift)) == 0;
  78. }
  79. static u8 mtk_mux_upd_get_parent(struct clk_hw *hw)
  80. {
  81. struct mtk_mux_upd_data *mux = to_mtk_mux_upd_data(hw);
  82. int num_parents = __clk_get_num_parents(hw->clk);
  83. u32 mask = GENMASK(mux->mux_width - 1, 0);
  84. u32 val;
  85. val = clk_readl(mux->base + mux->mux_ofs) >> mux->mux_shift;
  86. val &= mask;
  87. if (val >= num_parents)
  88. return -EINVAL;
  89. return val;
  90. }
  91. static int mtk_mux_upd_set_parent(struct clk_hw *hw, u8 index)
  92. {
  93. struct mtk_mux_upd_data *mux = to_mtk_mux_upd_data(hw);
  94. u32 mask = GENMASK(mux->mux_width - 1, 0);
  95. u32 val, orig;
  96. unsigned long flags = 0;
  97. if (mux->lock)
  98. spin_lock_irqsave(mux->lock, flags);
  99. val = clk_readl(mux->base + mux->mux_ofs);
  100. orig = val;
  101. val &= ~(mask << mux->mux_shift);
  102. val |= index << mux->mux_shift;
  103. if (val != orig) {
  104. clk_writel(val, mux->base + mux->mux_ofs);
  105. if (mux->upd_shift > 0)
  106. clk_writel(BIT(mux->upd_shift), mux->base + mux->upd_ofs);
  107. }
  108. if (mux->lock)
  109. spin_unlock_irqrestore(mux->lock, flags);
  110. return 0;
  111. }
  112. const struct clk_ops mtk_mux_upd_ops = {
  113. .is_enabled = mtk_mux_upd_is_enabled,
  114. .get_parent = mtk_mux_upd_get_parent,
  115. .set_parent = mtk_mux_upd_set_parent,
  116. };
  117. const struct clk_ops mtk_mux_upd_gate_ops = {
  118. .enable = mtk_mux_upd_enable,
  119. .disable = mtk_mux_upd_disable,
  120. .is_enabled = mtk_mux_upd_is_enabled,
  121. .get_parent = mtk_mux_upd_get_parent,
  122. .set_parent = mtk_mux_upd_set_parent,
  123. };
  124. struct clk * __init mtk_clk_register_mux_upd(const struct mtk_mux_upd *mu,
  125. void __iomem *base, spinlock_t *lock)
  126. {
  127. struct clk *clk;
  128. struct mtk_mux_upd_data *mux;
  129. struct clk_init_data init;
  130. mux = kzalloc(sizeof(*mux), GFP_KERNEL);
  131. if (!mux)
  132. return ERR_PTR(-ENOMEM);
  133. init.name = mu->name;
  134. init.flags = CLK_SET_RATE_PARENT;
  135. #if WORKAROUND_318_WARNING
  136. init.parent_names = (const char **)mu->parent_names;
  137. #else
  138. init.parent_names = mu->parent_names;
  139. #endif
  140. init.num_parents = mu->num_parents;
  141. if (mu->gate_shift < 0)
  142. init.ops = &mtk_mux_upd_ops;
  143. else
  144. init.ops = &mtk_mux_upd_gate_ops;
  145. mux->base = base;
  146. mux->mux_ofs = mu->mux_ofs;
  147. mux->upd_ofs = mu->upd_ofs;
  148. mux->mux_shift = mu->mux_shift;
  149. mux->mux_width = mu->mux_width;
  150. mux->gate_shift = mu->gate_shift;
  151. mux->upd_shift = mu->upd_shift;
  152. mux->lock = lock;
  153. mux->hw.init = &init;
  154. clk = clk_register(NULL, &mux->hw);
  155. if (IS_ERR(clk))
  156. kfree(mux);
  157. return clk;
  158. }
  159. void __init mtk_clk_register_mux_upds(const struct mtk_mux_upd *mus,
  160. int num, void __iomem *base, spinlock_t *lock,
  161. struct clk_onecell_data *clk_data)
  162. {
  163. struct clk *clk;
  164. int i;
  165. for (i = 0; i < num; i++) {
  166. const struct mtk_mux_upd *mu = &mus[i];
  167. clk = mtk_clk_register_mux_upd(mu, base, lock);
  168. if (IS_ERR(clk)) {
  169. pr_err("Failed to register clk %s: %ld\n",
  170. mu->name, PTR_ERR(clk));
  171. continue;
  172. }
  173. if (clk_data)
  174. clk_data->clks[mu->id] = clk;
  175. }
  176. }