1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018 MediaTek Inc.
4 * Author: Owen Chen <owen.chen@mediatek.com>
8 #include <linux/clk-provider.h>
9 #include <linux/compiler_types.h>
10 #include <linux/container_of.h>
11 #include <linux/err.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/module.h>
14 #include <linux/regmap.h>
15 #include <linux/spinlock.h>
16 #include <linux/slab.h>
22 struct regmap
*regmap
;
23 const struct mtk_mux
*data
;
28 static inline struct mtk_clk_mux
*to_mtk_clk_mux(struct clk_hw
*hw
)
30 return container_of(hw
, struct mtk_clk_mux
, hw
);
33 static int mtk_clk_mux_enable_setclr(struct clk_hw
*hw
)
35 struct mtk_clk_mux
*mux
= to_mtk_clk_mux(hw
);
36 unsigned long flags
= 0;
39 spin_lock_irqsave(mux
->lock
, flags
);
43 regmap_write(mux
->regmap
, mux
->data
->clr_ofs
,
44 BIT(mux
->data
->gate_shift
));
47 * If the parent has been changed when the clock was disabled, it will
48 * not be effective yet. Set the update bit to ensure the mux gets
51 if (mux
->reparent
&& mux
->data
->upd_shift
>= 0) {
52 regmap_write(mux
->regmap
, mux
->data
->upd_ofs
,
53 BIT(mux
->data
->upd_shift
));
54 mux
->reparent
= false;
58 spin_unlock_irqrestore(mux
->lock
, flags
);
65 static void mtk_clk_mux_disable_setclr(struct clk_hw
*hw
)
67 struct mtk_clk_mux
*mux
= to_mtk_clk_mux(hw
);
69 regmap_write(mux
->regmap
, mux
->data
->set_ofs
,
70 BIT(mux
->data
->gate_shift
));
73 static int mtk_clk_mux_is_enabled(struct clk_hw
*hw
)
75 struct mtk_clk_mux
*mux
= to_mtk_clk_mux(hw
);
78 regmap_read(mux
->regmap
, mux
->data
->mux_ofs
, &val
);
80 return (val
& BIT(mux
->data
->gate_shift
)) == 0;
83 static u8
mtk_clk_mux_get_parent(struct clk_hw
*hw
)
85 struct mtk_clk_mux
*mux
= to_mtk_clk_mux(hw
);
86 u32 mask
= GENMASK(mux
->data
->mux_width
- 1, 0);
89 regmap_read(mux
->regmap
, mux
->data
->mux_ofs
, &val
);
90 val
= (val
>> mux
->data
->mux_shift
) & mask
;
92 if (mux
->data
->parent_index
) {
95 for (i
= 0; i
< mux
->data
->num_parents
; i
++)
96 if (mux
->data
->parent_index
[i
] == val
)
99 /* Not found: return an impossible index to generate error */
100 return mux
->data
->num_parents
+ 1;
106 static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw
*hw
, u8 index
)
108 struct mtk_clk_mux
*mux
= to_mtk_clk_mux(hw
);
109 u32 mask
= GENMASK(mux
->data
->mux_width
- 1, 0);
111 unsigned long flags
= 0;
114 spin_lock_irqsave(mux
->lock
, flags
);
116 __acquire(mux
->lock
);
118 if (mux
->data
->parent_index
)
119 index
= mux
->data
->parent_index
[index
];
121 regmap_read(mux
->regmap
, mux
->data
->mux_ofs
, &orig
);
122 val
= (orig
& ~(mask
<< mux
->data
->mux_shift
))
123 | (index
<< mux
->data
->mux_shift
);
126 regmap_write(mux
->regmap
, mux
->data
->clr_ofs
,
127 mask
<< mux
->data
->mux_shift
);
128 regmap_write(mux
->regmap
, mux
->data
->set_ofs
,
129 index
<< mux
->data
->mux_shift
);
131 if (mux
->data
->upd_shift
>= 0) {
132 regmap_write(mux
->regmap
, mux
->data
->upd_ofs
,
133 BIT(mux
->data
->upd_shift
));
134 mux
->reparent
= true;
139 spin_unlock_irqrestore(mux
->lock
, flags
);
141 __release(mux
->lock
);
146 static int mtk_clk_mux_determine_rate(struct clk_hw
*hw
,
147 struct clk_rate_request
*req
)
149 struct mtk_clk_mux
*mux
= to_mtk_clk_mux(hw
);
151 return clk_mux_determine_rate_flags(hw
, req
, mux
->data
->flags
);
154 const struct clk_ops mtk_mux_clr_set_upd_ops
= {
155 .get_parent
= mtk_clk_mux_get_parent
,
156 .set_parent
= mtk_clk_mux_set_parent_setclr_lock
,
157 .determine_rate
= mtk_clk_mux_determine_rate
,
159 EXPORT_SYMBOL_GPL(mtk_mux_clr_set_upd_ops
);
161 const struct clk_ops mtk_mux_gate_clr_set_upd_ops
= {
162 .enable
= mtk_clk_mux_enable_setclr
,
163 .disable
= mtk_clk_mux_disable_setclr
,
164 .is_enabled
= mtk_clk_mux_is_enabled
,
165 .get_parent
= mtk_clk_mux_get_parent
,
166 .set_parent
= mtk_clk_mux_set_parent_setclr_lock
,
167 .determine_rate
= mtk_clk_mux_determine_rate
,
169 EXPORT_SYMBOL_GPL(mtk_mux_gate_clr_set_upd_ops
);
171 static struct clk_hw
*mtk_clk_register_mux(struct device
*dev
,
172 const struct mtk_mux
*mux
,
173 struct regmap
*regmap
,
176 struct mtk_clk_mux
*clk_mux
;
177 struct clk_init_data init
= {};
180 clk_mux
= kzalloc(sizeof(*clk_mux
), GFP_KERNEL
);
182 return ERR_PTR(-ENOMEM
);
184 init
.name
= mux
->name
;
185 init
.flags
= mux
->flags
;
186 init
.parent_names
= mux
->parent_names
;
187 init
.num_parents
= mux
->num_parents
;
190 clk_mux
->regmap
= regmap
;
192 clk_mux
->lock
= lock
;
193 clk_mux
->hw
.init
= &init
;
195 ret
= clk_hw_register(dev
, &clk_mux
->hw
);
204 static void mtk_clk_unregister_mux(struct clk_hw
*hw
)
206 struct mtk_clk_mux
*mux
;
210 mux
= to_mtk_clk_mux(hw
);
212 clk_hw_unregister(hw
);
216 int mtk_clk_register_muxes(struct device
*dev
,
217 const struct mtk_mux
*muxes
,
218 int num
, struct device_node
*node
,
220 struct clk_hw_onecell_data
*clk_data
)
222 struct regmap
*regmap
;
226 regmap
= device_node_to_regmap(node
);
227 if (IS_ERR(regmap
)) {
228 pr_err("Cannot find regmap for %pOF: %pe\n", node
, regmap
);
229 return PTR_ERR(regmap
);
232 for (i
= 0; i
< num
; i
++) {
233 const struct mtk_mux
*mux
= &muxes
[i
];
235 if (!IS_ERR_OR_NULL(clk_data
->hws
[mux
->id
])) {
236 pr_warn("%pOF: Trying to register duplicate clock ID: %d\n",
241 hw
= mtk_clk_register_mux(dev
, mux
, regmap
, lock
);
244 pr_err("Failed to register clk %s: %pe\n", mux
->name
,
249 clk_data
->hws
[mux
->id
] = hw
;
256 const struct mtk_mux
*mux
= &muxes
[i
];
258 if (IS_ERR_OR_NULL(clk_data
->hws
[mux
->id
]))
261 mtk_clk_unregister_mux(clk_data
->hws
[mux
->id
]);
262 clk_data
->hws
[mux
->id
] = ERR_PTR(-ENOENT
);
267 EXPORT_SYMBOL_GPL(mtk_clk_register_muxes
);
269 void mtk_clk_unregister_muxes(const struct mtk_mux
*muxes
, int num
,
270 struct clk_hw_onecell_data
*clk_data
)
277 for (i
= num
; i
> 0; i
--) {
278 const struct mtk_mux
*mux
= &muxes
[i
- 1];
280 if (IS_ERR_OR_NULL(clk_data
->hws
[mux
->id
]))
283 mtk_clk_unregister_mux(clk_data
->hws
[mux
->id
]);
284 clk_data
->hws
[mux
->id
] = ERR_PTR(-ENOENT
);
287 EXPORT_SYMBOL_GPL(mtk_clk_unregister_muxes
);
290 * This clock notifier is called when the frequency of the parent
291 * PLL clock is to be changed. The idea is to switch the parent to a
292 * stable clock, such as the main oscillator, while the PLL frequency
295 static int mtk_clk_mux_notifier_cb(struct notifier_block
*nb
,
296 unsigned long event
, void *_data
)
298 struct clk_notifier_data
*data
= _data
;
299 struct clk_hw
*hw
= __clk_get_hw(data
->clk
);
300 struct mtk_mux_nb
*mux_nb
= to_mtk_mux_nb(nb
);
304 case PRE_RATE_CHANGE
:
305 mux_nb
->original_index
= mux_nb
->ops
->get_parent(hw
);
306 ret
= mux_nb
->ops
->set_parent(hw
, mux_nb
->bypass_index
);
308 case POST_RATE_CHANGE
:
309 case ABORT_RATE_CHANGE
:
310 ret
= mux_nb
->ops
->set_parent(hw
, mux_nb
->original_index
);
314 return notifier_from_errno(ret
);
317 int devm_mtk_clk_mux_notifier_register(struct device
*dev
, struct clk
*clk
,
318 struct mtk_mux_nb
*mux_nb
)
320 mux_nb
->nb
.notifier_call
= mtk_clk_mux_notifier_cb
;
322 return devm_clk_notifier_register(dev
, clk
, &mux_nb
->nb
);
324 EXPORT_SYMBOL_GPL(devm_mtk_clk_mux_notifier_register
);
326 MODULE_LICENSE("GPL");