|
4 | 4 | * Author: Owen Chen <owen.chen@mediatek.com>
|
5 | 5 | */
|
6 | 6 |
|
| 7 | +#include <linux/clk.h> |
7 | 8 | #include <linux/clk-provider.h>
|
8 | 9 | #include <linux/compiler_types.h>
|
9 | 10 | #include <linux/container_of.h>
|
@@ -259,4 +260,41 @@ void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num,
|
259 | 260 | }
|
260 | 261 | EXPORT_SYMBOL_GPL(mtk_clk_unregister_muxes);
|
261 | 262 |
|
| 263 | +/* |
| 264 | + * This clock notifier is called when the frequency of the parent |
| 265 | + * PLL clock is to be changed. The idea is to switch the parent to a |
| 266 | + * stable clock, such as the main oscillator, while the PLL frequency |
| 267 | + * stabilizes. |
| 268 | + */ |
| 269 | +static int mtk_clk_mux_notifier_cb(struct notifier_block *nb, |
| 270 | + unsigned long event, void *_data) |
| 271 | +{ |
| 272 | + struct clk_notifier_data *data = _data; |
| 273 | + struct clk_hw *hw = __clk_get_hw(data->clk); |
| 274 | + struct mtk_mux_nb *mux_nb = to_mtk_mux_nb(nb); |
| 275 | + int ret = 0; |
| 276 | + |
| 277 | + switch (event) { |
| 278 | + case PRE_RATE_CHANGE: |
| 279 | + mux_nb->original_index = mux_nb->ops->get_parent(hw); |
| 280 | + ret = mux_nb->ops->set_parent(hw, mux_nb->bypass_index); |
| 281 | + break; |
| 282 | + case POST_RATE_CHANGE: |
| 283 | + case ABORT_RATE_CHANGE: |
| 284 | + ret = mux_nb->ops->set_parent(hw, mux_nb->original_index); |
| 285 | + break; |
| 286 | + } |
| 287 | + |
| 288 | + return notifier_from_errno(ret); |
| 289 | +} |
| 290 | + |
| 291 | +int devm_mtk_clk_mux_notifier_register(struct device *dev, struct clk *clk, |
| 292 | + struct mtk_mux_nb *mux_nb) |
| 293 | +{ |
| 294 | + mux_nb->nb.notifier_call = mtk_clk_mux_notifier_cb; |
| 295 | + |
| 296 | + return devm_clk_notifier_register(dev, clk, &mux_nb->nb); |
| 297 | +} |
| 298 | +EXPORT_SYMBOL_GPL(devm_mtk_clk_mux_notifier_register); |
| 299 | + |
262 | 300 | MODULE_LICENSE("GPL");
|
0 commit comments