| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- From patchwork Fri Dec 8 09:42:28 2017
- Content-Type: text/plain; charset="utf-8"
- MIME-Version: 1.0
- Content-Transfer-Encoding: 7bit
- Subject: [v4,10/12] clk: qcom: Add safe switch hook for krait mux clocks
- From: Sricharan R <[email protected]>
- X-Patchwork-Id: 10102057
- Message-Id: <[email protected]>
- To: [email protected], [email protected],
- [email protected], [email protected],
- [email protected], [email protected],
- [email protected], [email protected]
- Cc: [email protected]
- Date: Fri, 8 Dec 2017 15:12:28 +0530
- When the Hfplls are reprogrammed during the rate change,
- the primary muxes which are sourced from the same hfpll
- for higher frequencies, needs to be switched to the 'safe
- secondary mux' as the parent for that small window. This
- is done by registering a clk notifier for the muxes and
- switching to the safe parent in the PRE_RATE_CHANGE notifier
- and back to the original parent in the POST_RATE_CHANGE notifier.
- Signed-off-by: Sricharan R <[email protected]>
- ---
- drivers/clk/qcom/clk-krait.c | 2 ++
- drivers/clk/qcom/clk-krait.h | 3 +++
- drivers/clk/qcom/krait-cc.c | 56 ++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 61 insertions(+)
- --- a/drivers/clk/qcom/clk-krait.c
- +++ b/drivers/clk/qcom/clk-krait.c
- @@ -60,6 +60,8 @@ static int krait_mux_set_parent(struct c
- if (__clk_is_enabled(hw->clk))
- __krait_mux_set_sel(mux, sel);
-
- + mux->reparent = true;
- +
- return 0;
- }
-
- --- a/drivers/clk/qcom/clk-krait.h
- +++ b/drivers/clk/qcom/clk-krait.h
- @@ -23,6 +23,9 @@ struct krait_mux_clk {
- u32 shift;
- u32 en_mask;
- bool lpl;
- + u8 safe_sel;
- + u8 old_index;
- + bool reparent;
-
- struct clk_hw hw;
- struct notifier_block clk_nb;
- --- a/drivers/clk/qcom/krait-cc.c
- +++ b/drivers/clk/qcom/krait-cc.c
- @@ -35,6 +35,49 @@ static unsigned int pri_mux_map[] = {
- 0,
- };
-
- +/*
- + * Notifier function for switching the muxes to safe parent
- + * while the hfpll is getting reprogrammed.
- + */
- +static int krait_notifier_cb(struct notifier_block *nb,
- + unsigned long event,
- + void *data)
- +{
- + int ret = 0;
- + struct krait_mux_clk *mux = container_of(nb, struct krait_mux_clk,
- + clk_nb);
- + /* Switch to safe parent */
- + if (event == PRE_RATE_CHANGE) {
- + mux->old_index = krait_mux_clk_ops.get_parent(&mux->hw);
- + ret = krait_mux_clk_ops.set_parent(&mux->hw, mux->safe_sel);
- + mux->reparent = false;
- + /*
- + * By the time POST_RATE_CHANGE notifier is called,
- + * clk framework itself would have changed the parent for the new rate.
- + * Only otherwise, put back to the old parent.
- + */
- + } else if (event == POST_RATE_CHANGE) {
- + if (!mux->reparent)
- + ret = krait_mux_clk_ops.set_parent(&mux->hw,
- + mux->old_index);
- + }
- +
- + return notifier_from_errno(ret);
- +}
- +
- +static int krait_notifier_register(struct device *dev, struct clk *clk,
- + struct krait_mux_clk *mux)
- +{
- + int ret = 0;
- +
- + mux->clk_nb.notifier_call = krait_notifier_cb;
- + ret = clk_notifier_register(clk, &mux->clk_nb);
- + if (ret)
- + dev_err(dev, "failed to register clock notifier: %d\n", ret);
- +
- + return ret;
- +}
- +
- static int
- krait_add_div(struct device *dev, int id, const char *s, unsigned int offset)
- {
- @@ -79,6 +122,7 @@ static int
- krait_add_sec_mux(struct device *dev, int id, const char *s,
- unsigned int offset, bool unique_aux)
- {
- + int ret;
- struct krait_mux_clk *mux;
- static const char *sec_mux_list[] = {
- "acpu_aux",
- @@ -102,6 +146,7 @@ krait_add_sec_mux(struct device *dev, in
- mux->shift = 2;
- mux->parent_map = sec_mux_map;
- mux->hw.init = &init;
- + mux->safe_sel = 0;
-
- init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
- if (!init.name)
- @@ -117,6 +162,11 @@ krait_add_sec_mux(struct device *dev, in
-
- clk = devm_clk_register(dev, &mux->hw);
-
- + ret = krait_notifier_register(dev, clk, mux);
- + if (ret)
- + goto unique_aux;
- +
- +unique_aux:
- if (unique_aux)
- kfree(sec_mux_list[0]);
- err_aux:
- @@ -128,6 +178,7 @@ static struct clk *
- krait_add_pri_mux(struct device *dev, int id, const char *s,
- unsigned int offset)
- {
- + int ret;
- struct krait_mux_clk *mux;
- const char *p_names[3];
- struct clk_init_data init = {
- @@ -148,6 +199,7 @@ krait_add_pri_mux(struct device *dev, in
- mux->lpl = id >= 0;
- mux->parent_map = pri_mux_map;
- mux->hw.init = &init;
- + mux->safe_sel = 2;
-
- init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s);
- if (!init.name)
- @@ -173,6 +225,10 @@ krait_add_pri_mux(struct device *dev, in
-
- clk = devm_clk_register(dev, &mux->hw);
-
- + ret = krait_notifier_register(dev, clk, mux);
- + if (ret)
- + goto err_p3;
- +err_p3:
- kfree(p_names[2]);
- err_p2:
- kfree(p_names[1]);
|