Skip to content

Commit b66add7

Browse files
committed
clk: mediatek: mux: add clk notifier functions
With device frequency scaling, the mux clock that (indirectly) feeds the device selects between a dedicated PLL, and some other stable clocks. When a clk rate change is requested, the (normally) upstream PLL is reconfigured. It's possible for the clock output of the PLL to become unstable during this process. To avoid causing the device to glitch, the mux should temporarily be switched over to another "stable" clock during the PLL rate change. This is done with clk notifiers. This patch adds common functions for notifiers to temporarily and transparently reparent mux clocks. This was loosely based on commit 8adfb08 ("clk: sunxi-ng: mux: Add clk notifier functions"). Signed-off-by: Chen-Yu Tsai <wenst@chromium.org> [Angelo: Changed mtk_mux_nb to hold a pointer to clk_ops instead of mtk_mux] Co-developed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: Miles Chen <miles.chen@mediatek.com> Link: https://lore.kernel.org/r/20220927101128.44758-4-angelogioacchino.delregno@collabora.com Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
1 parent 9f94f54 commit b66add7

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

drivers/clk/mediatek/clk-mux.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Author: Owen Chen <owen.chen@mediatek.com>
55
*/
66

7+
#include <linux/clk.h>
78
#include <linux/clk-provider.h>
89
#include <linux/compiler_types.h>
910
#include <linux/container_of.h>
@@ -259,4 +260,41 @@ void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num,
259260
}
260261
EXPORT_SYMBOL_GPL(mtk_clk_unregister_muxes);
261262

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+
262300
MODULE_LICENSE("GPL");

drivers/clk/mediatek/clk-mux.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
#ifndef __DRV_CLK_MTK_MUX_H
88
#define __DRV_CLK_MTK_MUX_H
99

10+
#include <linux/notifier.h>
1011
#include <linux/spinlock.h>
1112
#include <linux/types.h>
1213

1314
struct clk;
1415
struct clk_hw_onecell_data;
1516
struct clk_ops;
17+
struct device;
1618
struct device_node;
1719

1820
struct mtk_mux {
@@ -89,4 +91,17 @@ int mtk_clk_register_muxes(const struct mtk_mux *muxes,
8991
void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num,
9092
struct clk_hw_onecell_data *clk_data);
9193

94+
struct mtk_mux_nb {
95+
struct notifier_block nb;
96+
const struct clk_ops *ops;
97+
98+
u8 bypass_index; /* Which parent to temporarily use */
99+
u8 original_index; /* Set by notifier callback */
100+
};
101+
102+
#define to_mtk_mux_nb(_nb) container_of(_nb, struct mtk_mux_nb, nb)
103+
104+
int devm_mtk_clk_mux_notifier_register(struct device *dev, struct clk *clk,
105+
struct mtk_mux_nb *mux_nb);
106+
92107
#endif /* __DRV_CLK_MTK_MUX_H */

0 commit comments

Comments
 (0)