OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
4 | office | 1 | From patchwork Fri Dec 8 09:42:28 2017 |
2 | Content-Type: text/plain; charset="utf-8" |
||
3 | MIME-Version: 1.0 |
||
4 | Content-Transfer-Encoding: 7bit |
||
5 | Subject: [v4,10/12] clk: qcom: Add safe switch hook for krait mux clocks |
||
6 | From: Sricharan R <sricharan@codeaurora.org> |
||
7 | X-Patchwork-Id: 10102057 |
||
8 | Message-Id: <1512726150-7204-11-git-send-email-sricharan@codeaurora.org> |
||
9 | To: mturquette@baylibre.com, sboyd@codeaurora.org, |
||
10 | devicetree@vger.kernel.org, linux-pm@vger.kernel.org, |
||
11 | linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, |
||
12 | viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org |
||
13 | Cc: sricharan@codeaurora.org |
||
14 | Date: Fri, 8 Dec 2017 15:12:28 +0530 |
||
15 | |||
16 | When the Hfplls are reprogrammed during the rate change, |
||
17 | the primary muxes which are sourced from the same hfpll |
||
18 | for higher frequencies, needs to be switched to the 'safe |
||
19 | secondary mux' as the parent for that small window. This |
||
20 | is done by registering a clk notifier for the muxes and |
||
21 | switching to the safe parent in the PRE_RATE_CHANGE notifier |
||
22 | and back to the original parent in the POST_RATE_CHANGE notifier. |
||
23 | |||
24 | Signed-off-by: Sricharan R <sricharan@codeaurora.org> |
||
25 | --- |
||
26 | drivers/clk/qcom/clk-krait.c | 2 ++ |
||
27 | drivers/clk/qcom/clk-krait.h | 3 +++ |
||
28 | drivers/clk/qcom/krait-cc.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ |
||
29 | 3 files changed, 61 insertions(+) |
||
30 | |||
31 | --- a/drivers/clk/qcom/clk-krait.c |
||
32 | +++ b/drivers/clk/qcom/clk-krait.c |
||
33 | @@ -60,6 +60,8 @@ static int krait_mux_set_parent(struct c |
||
34 | if (__clk_is_enabled(hw->clk)) |
||
35 | __krait_mux_set_sel(mux, sel); |
||
36 | |||
37 | + mux->reparent = true; |
||
38 | + |
||
39 | return 0; |
||
40 | } |
||
41 | |||
42 | --- a/drivers/clk/qcom/clk-krait.h |
||
43 | +++ b/drivers/clk/qcom/clk-krait.h |
||
44 | @@ -23,6 +23,9 @@ struct krait_mux_clk { |
||
45 | u32 shift; |
||
46 | u32 en_mask; |
||
47 | bool lpl; |
||
48 | + u8 safe_sel; |
||
49 | + u8 old_index; |
||
50 | + bool reparent; |
||
51 | |||
52 | struct clk_hw hw; |
||
53 | struct notifier_block clk_nb; |
||
54 | --- a/drivers/clk/qcom/krait-cc.c |
||
55 | +++ b/drivers/clk/qcom/krait-cc.c |
||
56 | @@ -35,6 +35,49 @@ static unsigned int pri_mux_map[] = { |
||
57 | 0, |
||
58 | }; |
||
59 | |||
60 | +/* |
||
61 | + * Notifier function for switching the muxes to safe parent |
||
62 | + * while the hfpll is getting reprogrammed. |
||
63 | + */ |
||
64 | +static int krait_notifier_cb(struct notifier_block *nb, |
||
65 | + unsigned long event, |
||
66 | + void *data) |
||
67 | +{ |
||
68 | + int ret = 0; |
||
69 | + struct krait_mux_clk *mux = container_of(nb, struct krait_mux_clk, |
||
70 | + clk_nb); |
||
71 | + /* Switch to safe parent */ |
||
72 | + if (event == PRE_RATE_CHANGE) { |
||
73 | + mux->old_index = krait_mux_clk_ops.get_parent(&mux->hw); |
||
74 | + ret = krait_mux_clk_ops.set_parent(&mux->hw, mux->safe_sel); |
||
75 | + mux->reparent = false; |
||
76 | + /* |
||
77 | + * By the time POST_RATE_CHANGE notifier is called, |
||
78 | + * clk framework itself would have changed the parent for the new rate. |
||
79 | + * Only otherwise, put back to the old parent. |
||
80 | + */ |
||
81 | + } else if (event == POST_RATE_CHANGE) { |
||
82 | + if (!mux->reparent) |
||
83 | + ret = krait_mux_clk_ops.set_parent(&mux->hw, |
||
84 | + mux->old_index); |
||
85 | + } |
||
86 | + |
||
87 | + return notifier_from_errno(ret); |
||
88 | +} |
||
89 | + |
||
90 | +static int krait_notifier_register(struct device *dev, struct clk *clk, |
||
91 | + struct krait_mux_clk *mux) |
||
92 | +{ |
||
93 | + int ret = 0; |
||
94 | + |
||
95 | + mux->clk_nb.notifier_call = krait_notifier_cb; |
||
96 | + ret = clk_notifier_register(clk, &mux->clk_nb); |
||
97 | + if (ret) |
||
98 | + dev_err(dev, "failed to register clock notifier: %d\n", ret); |
||
99 | + |
||
100 | + return ret; |
||
101 | +} |
||
102 | + |
||
103 | static int |
||
104 | krait_add_div(struct device *dev, int id, const char *s, unsigned int offset) |
||
105 | { |
||
106 | @@ -79,6 +122,7 @@ static int |
||
107 | krait_add_sec_mux(struct device *dev, int id, const char *s, |
||
108 | unsigned int offset, bool unique_aux) |
||
109 | { |
||
110 | + int ret; |
||
111 | struct krait_mux_clk *mux; |
||
112 | static const char *sec_mux_list[] = { |
||
113 | "acpu_aux", |
||
114 | @@ -102,6 +146,7 @@ krait_add_sec_mux(struct device *dev, in |
||
115 | mux->shift = 2; |
||
116 | mux->parent_map = sec_mux_map; |
||
117 | mux->hw.init = &init; |
||
118 | + mux->safe_sel = 0; |
||
119 | |||
120 | init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s); |
||
121 | if (!init.name) |
||
122 | @@ -117,6 +162,11 @@ krait_add_sec_mux(struct device *dev, in |
||
123 | |||
124 | clk = devm_clk_register(dev, &mux->hw); |
||
125 | |||
126 | + ret = krait_notifier_register(dev, clk, mux); |
||
127 | + if (ret) |
||
128 | + goto unique_aux; |
||
129 | + |
||
130 | +unique_aux: |
||
131 | if (unique_aux) |
||
132 | kfree(sec_mux_list[0]); |
||
133 | err_aux: |
||
134 | @@ -128,6 +178,7 @@ static struct clk * |
||
135 | krait_add_pri_mux(struct device *dev, int id, const char *s, |
||
136 | unsigned int offset) |
||
137 | { |
||
138 | + int ret; |
||
139 | struct krait_mux_clk *mux; |
||
140 | const char *p_names[3]; |
||
141 | struct clk_init_data init = { |
||
142 | @@ -148,6 +199,7 @@ krait_add_pri_mux(struct device *dev, in |
||
143 | mux->lpl = id >= 0; |
||
144 | mux->parent_map = pri_mux_map; |
||
145 | mux->hw.init = &init; |
||
146 | + mux->safe_sel = 2; |
||
147 | |||
148 | init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s); |
||
149 | if (!init.name) |
||
150 | @@ -173,6 +225,10 @@ krait_add_pri_mux(struct device *dev, in |
||
151 | |||
152 | clk = devm_clk_register(dev, &mux->hw); |
||
153 | |||
154 | + ret = krait_notifier_register(dev, clk, mux); |
||
155 | + if (ret) |
||
156 | + goto err_p3; |
||
157 | +err_p3: |
||
158 | kfree(p_names[2]); |
||
159 | err_p2: |
||
160 | kfree(p_names[1]); |