@@ -62,6 +62,7 @@
* detect voltage droops. We do not add support for ACD as yet.
*/
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@@ -188,10 +189,14 @@ struct clk_cpu_8996_mux {
u32 reg;
u8 shift;
u8 width;
+ struct notifier_block nb;
struct clk_hw *pll;
struct clk_regmap clkr;
};
+#define to_clk_cpu_8996_mux_nb(_nb) \
+ container_of(_nb, struct clk_cpu_8996_mux, nb)
+
static inline
struct clk_cpu_8996_mux *to_clk_cpu_8996_mux_hw(struct clk_hw *hw)
{
@@ -237,6 +242,26 @@ static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
return 0;
}
+int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+ int ret;
+ struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_nb(nb);
+
+ switch (event) {
+ case PRE_RATE_CHANGE:
+ ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw, ALT_INDEX);
+ break;
+ case POST_RATE_CHANGE:
+ ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw, PLL_INDEX);
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+
+ return notifier_from_errno(ret);
+};
const struct clk_ops clk_cpu_8996_mux_ops = {
.set_parent = clk_cpu_8996_mux_set_parent,
.get_parent = clk_cpu_8996_mux_get_parent,
@@ -280,6 +305,7 @@ static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
.shift = 0,
.width = 2,
.pll = &pwrcl_pll.clkr.hw,
+ .nb.notifier_call = cpu_clk_notifier_cb,
.clkr.hw.init = &(struct clk_init_data) {
.name = "pwrcl_pmux",
.parent_names = (const char *[]){
@@ -299,6 +325,7 @@ static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index)
.shift = 0,
.width = 2,
.pll = &perfcl_pll.clkr.hw,
+ .nb.notifier_call = cpu_clk_notifier_cb,
.clkr.hw.init = &(struct clk_init_data) {
.name = "perfcl_pmux",
.parent_names = (const char *[]){
@@ -357,6 +384,12 @@ struct clk_regmap *clks[] = {
clk_alpha_pll_configure(&perfcl_alt_pll, regmap, &altpll_config);
clk_alpha_pll_configure(&pwrcl_alt_pll, regmap, &altpll_config);
+ ret = clk_notifier_register(pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb);
+ if (ret)
+ return ret;
+
+ ret = clk_notifier_register(perfcl_pmux.clkr.hw.clk, &perfcl_pmux.nb);
+
return ret;
}