blob: 378c723a6dff71a52fb071d80c0b0ce1334e093f [file] [log] [blame]
xjb04a4022021-11-25 15:01:52 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018 MediaTek Inc.
4 * Author: Owen Chen <owen.chen@mediatek.com>
5 */
6#include <linux/of.h>
7#include <linux/of_address.h>
8#include <linux/slab.h>
9#include <linux/mfd/syscon.h>
10#include "clk-mtk.h"
11#include "clk-mux.h"
12static inline struct mtk_clk_mux *to_mtk_clk_mux(struct clk_hw *hw)
13{
14 return container_of(hw, struct mtk_clk_mux, hw);
15}
16static int mtk_mux_enable(struct clk_hw *hw)
17{
18 struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
19 u32 mask = BIT(mux->gate_shift);
20 unsigned long flags = 0;
21 int ret = 0;
22 if (mux->lock)
23 spin_lock_irqsave(mux->lock, flags);
24 else
25 __acquire(mux->lock);
26 ret = regmap_update_bits(mux->regmap, mux->mux_ofs, mask, 0);
27 if (mux->lock)
28 spin_unlock_irqrestore(mux->lock, flags);
29 else
30 __release(mux->lock);
31 return ret;
32}
33static void mtk_mux_disable(struct clk_hw *hw)
34{
35 struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
36 u32 mask = BIT(mux->gate_shift);
37 unsigned long flags = 0;
38 if (mux->lock)
39 spin_lock_irqsave(mux->lock, flags);
40 else
41 __acquire(mux->lock);
42 regmap_update_bits(mux->regmap, mux->mux_ofs, mask, mask);
43 if (mux->lock)
44 spin_unlock_irqrestore(mux->lock, flags);
45 else
46 __release(mux->lock);
47}
48static int mtk_mux_enable_setclr(struct clk_hw *hw)
49{
50 struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
51 u32 val = 0;
52 unsigned long flags = 0;
53 if (mux->lock)
54 spin_lock_irqsave(mux->lock, flags);
55 else
56 __acquire(mux->lock);
57 val = BIT(mux->gate_shift);
58 regmap_write(mux->regmap, mux->clr_ofs,
59 val);
60 if (mux->lock)
61 spin_unlock_irqrestore(mux->lock, flags);
62 else
63 __release(mux->lock);
64 return 0;
65}
66static void mtk_mux_disable_setclr(struct clk_hw *hw)
67{
68 struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
69 unsigned long flags = 0;
70 if (mux->lock)
71 spin_lock_irqsave(mux->lock, flags);
72 else
73 __acquire(mux->lock);
74 regmap_write(mux->regmap, mux->set_ofs,
75 BIT(mux->gate_shift));
76 if (mux->lock)
77 spin_unlock_irqrestore(mux->lock, flags);
78 else
79 __release(mux->lock);
80}
81static int mtk_mux_is_enabled(struct clk_hw *hw)
82{
83 struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
84 u32 val = 0;
85 if (mux->gate_shift < 0)
86 return true;
87 regmap_read(mux->regmap, mux->mux_ofs, &val);
88 return (val & BIT(mux->gate_shift)) == 0;
89}
90static u8 mtk_mux_get_parent(struct clk_hw *hw)
91{
92 struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
93 int num_parents = clk_hw_get_num_parents(hw);
94 u32 mask = GENMASK(mux->mux_width - 1, 0);
95 u32 val = 0;
96 regmap_read(mux->regmap, mux->mux_ofs, &val);
97 val = (val >> mux->mux_shift) & mask;
98 if (val >= num_parents)
99 return -EINVAL;
100 return val;
101}
102static int mtk_mux_set_parent(struct clk_hw *hw, u8 index)
103{
104 struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
105 u32 mask = GENMASK(mux->mux_width - 1, 0)
106 << mux->mux_shift;
107 unsigned long flags = 0;
108 if (mux->lock)
109 spin_lock_irqsave(mux->lock, flags);
110 else
111 __acquire(mux->lock);
112 regmap_update_bits(mux->regmap, mux->mux_ofs, mask,
113 index << mux->mux_shift);
114 if (mux->upd_shift >= 0)
115 regmap_write(mux->regmap, mux->upd_ofs,
116 BIT(mux->upd_shift));
117 if (mux->lock)
118 spin_unlock_irqrestore(mux->lock, flags);
119 else
120 __release(mux->lock);
121 return 0;
122}
123static int mtk_mux_set_parent_setclr(struct clk_hw *hw, u8 index)
124{
125 struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
126 u32 mask = GENMASK(mux->mux_width - 1, 0);
127 u32 val = 0, orig = 0;
128 unsigned long flags = 0;
129 if (mux->lock)
130 spin_lock_irqsave(mux->lock, flags);
131 else
132 __acquire(mux->lock);
133 regmap_read(mux->regmap, mux->mux_ofs, &orig);
134 val = (orig & ~(mask << mux->mux_shift))
135 | (index << mux->mux_shift);
136 if (val != orig) {
137 regmap_write(mux->regmap, mux->clr_ofs,
138 mask << mux->mux_shift);
139 regmap_write(mux->regmap, mux->set_ofs,
140 index << mux->mux_shift);
141 if (mux->upd_shift >= 0)
142 regmap_write(mux->regmap, mux->upd_ofs,
143 BIT(mux->upd_shift));
144 }
145 if (mux->lock)
146 spin_unlock_irqrestore(mux->lock, flags);
147 else
148 __release(mux->lock);
149 return 0;
150}
151const struct clk_ops mtk_mux_ops = {
152 .get_parent = mtk_mux_get_parent,
153 .set_parent = mtk_mux_set_parent,
154};
155const struct clk_ops mtk_mux_clr_set_upd_ops = {
156 .get_parent = mtk_mux_get_parent,
157 .set_parent = mtk_mux_set_parent_setclr,
158};
159const struct clk_ops mtk_mux_gate_ops = {
160 .enable = mtk_mux_enable,
161 .disable = mtk_mux_disable,
162 .is_enabled = mtk_mux_is_enabled,
163 .get_parent = mtk_mux_get_parent,
164 .set_parent = mtk_mux_set_parent,
165};
166const struct clk_ops mtk_mux_gate_clr_set_upd_ops = {
167 .enable = mtk_mux_enable_setclr,
168 .disable = mtk_mux_disable_setclr,
169 .is_enabled = mtk_mux_is_enabled,
170 .get_parent = mtk_mux_get_parent,
171 .set_parent = mtk_mux_set_parent_setclr,
172};
173struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
174 struct regmap *regmap,
175 spinlock_t *lock)
176{
177 struct mtk_clk_mux *clk_mux;
178 struct clk_init_data init;
179 struct clk *clk;
180 clk_mux = kzalloc(sizeof(*clk_mux), GFP_KERNEL);
181 if (!clk_mux)
182 return ERR_PTR(-ENOMEM);
183 init.name = mux->name;
184 init.flags = (mux->flags) | CLK_SET_RATE_PARENT;
185 init.parent_names = mux->parent_names;
186 init.num_parents = mux->num_parents;
187 init.ops = mux->ops;
188 clk_mux->regmap = regmap;
189 clk_mux->name = mux->name;
190 clk_mux->mux_ofs = mux->mux_ofs;
191 clk_mux->set_ofs = mux->set_ofs;
192 clk_mux->clr_ofs = mux->clr_ofs;
193 clk_mux->upd_ofs = mux->upd_ofs;
194 clk_mux->mux_shift = mux->mux_shift;
195 clk_mux->mux_width = mux->mux_width;
196 clk_mux->gate_shift = mux->gate_shift;
197 clk_mux->upd_shift = mux->upd_shift;
198 clk_mux->lock = lock;
199 clk_mux->hw.init = &init;
200 clk = clk_register(NULL, &clk_mux->hw);
201 if (IS_ERR(clk)) {
202 kfree(clk_mux);
203 return clk;
204 }
205 return clk;
206}
207int mtk_clk_register_muxes(const struct mtk_mux *muxes,
208 int num, struct device_node *node,
209 spinlock_t *lock,
210 struct clk_onecell_data *clk_data)
211{
212 struct regmap *regmap;
213 struct clk *clk;
214 int i;
215 regmap = syscon_node_to_regmap(node);
216 if (IS_ERR(regmap)) {
217 pr_notice("Cannot find regmap for %pOF: %ld\n", node,
218 PTR_ERR(regmap));
219 return PTR_ERR(regmap);
220 }
221 for (i = 0; i < num; i++) {
222 const struct mtk_mux *mux = &muxes[i];
223 if (IS_ERR_OR_NULL(clk_data->clks[mux->id])) {
224 clk = mtk_clk_register_mux(mux, regmap, lock);
225 if (IS_ERR(clk)) {
226 pr_notice("Failed to register clk %s: %ld\n",
227 mux->name, PTR_ERR(clk));
228 continue;
229 }
230 clk_data->clks[mux->id] = clk;
231 }
232 }
233 return 0;
234}