From 77edc8b34520164e906a430b3e2097cf1cbe67dc Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 23 Sep 2019 23:48:28 +0530 Subject: [PATCH] clk: qcom: osm: Add determine_rate ops for OSM CPU clock driver Clock rates are stored in unsigned long field, but round_rate ops returns a long value which is causing to long overflow if the CPU clock rate exceeds 2GHz, so define the determine_rate ops. Change-Id: I2c48dc51bdf6be260fb4697012d08237cbba3f21 Signed-off-by: Taniya Das --- drivers/clk/qcom/clk-cpu-osm.c | 57 ++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c index f53d1eee6c6e..48ea05d15dd3 100644 --- a/drivers/clk/qcom/clk-cpu-osm.c +++ b/drivers/clk/qcom/clk-cpu-osm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -76,7 +76,7 @@ static DEFINE_VDD_REGS_INIT(vdd_pwrcl_mx_ao, 1); struct osm_entry { u16 virtual_corner; u16 open_loop_volt; - long frequency; + unsigned long frequency; u32 lval; u16 ccount; }; @@ -143,7 +143,8 @@ static inline bool is_better_rate(unsigned long req, unsigned long best, return (req <= new && new < best) || (best < req && best < new); } -static int clk_osm_search_table(struct osm_entry *table, int entries, long rate) +static int clk_osm_search_table(struct osm_entry *table, int entries, + unsigned long rate) { int index; @@ -173,21 +174,21 @@ static unsigned long clk_osm_recalc_rate(struct clk_hw *hw, return c->rate; } -static long clk_osm_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int clk_osm_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { int i; unsigned long rrate = 0; - - if (!hw) - return -EINVAL; + unsigned long rate = req->rate; /* * If the rate passed in is 0, return the first frequency in the * FMAX table. */ - if (!rate) - return hw->init->rate_max[0]; + if (!rate) { + req->rate = hw->init->rate_max[0]; + return 0; + } for (i = 0; i < hw->init->num_rate_max; i++) { if (is_better_rate(rate, rrate, hw->init->rate_max[i])) { @@ -197,10 +198,12 @@ static long clk_osm_round_rate(struct clk_hw *hw, unsigned long rate, } } - pr_debug("%s: rate %lu, rrate %ld, Rate max %ld\n", __func__, rate, - rrate, hw->init->rate_max[i]); + req->rate = rrate; - return rrate; + pr_debug("clk:%s rate %lu, rrate %lu, Rate max %lu index %u\n", + hw->init->name, rate, rrate, hw->init->rate_max[i], i); + + return 0; } static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate, @@ -282,40 +285,40 @@ static unsigned long clk_cpu_recalc_rate(struct clk_hw *hw, return parent->osm_table[index].frequency; } -static long clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int clk_cpu_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_hw *parent_hw = clk_hw_get_parent(hw); + unsigned long rate = req->rate; - if (!parent_hw) - return -EINVAL; + req->rate = clk_hw_round_rate(parent_hw, rate); - *parent_rate = rate; - return clk_hw_round_rate(parent_hw, rate); + return 0; } static int l3_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_osm *cpuclk = to_clk_osm(hw); + struct clk_rate_request req; int index = 0; - unsigned long r_rate; int count = 40; u32 curr_lval; if (!cpuclk) return -EINVAL; - r_rate = clk_osm_round_rate(hw, rate, NULL); + req.rate = rate; + clk_osm_determine_rate(hw, &req); - if (rate != r_rate) { + if (rate != req.rate) { pr_err("invalid requested rate=%ld\n", rate); return -EINVAL; } /* Convert rate to table index */ index = clk_osm_search_table(cpuclk->osm_table, - cpuclk->num_entries, r_rate); + cpuclk->num_entries, req.rate); if (index < 0) { pr_err("cannot set %s to %lu\n", clk_hw_get_name(hw), rate); return -EINVAL; @@ -370,7 +373,7 @@ static unsigned long l3_clk_recalc_rate(struct clk_hw *hw, } static const struct clk_ops clk_ops_l3_osm = { - .round_rate = clk_osm_round_rate, + .determine_rate = clk_osm_determine_rate, .list_rate = clk_osm_list_rate, .recalc_rate = l3_clk_recalc_rate, .set_rate = l3_clk_set_rate, @@ -379,23 +382,23 @@ static const struct clk_ops clk_ops_l3_osm = { static const struct clk_ops clk_ops_pwrcl_core = { .set_rate = clk_pwrcl_set_rate, - .round_rate = clk_cpu_round_rate, + .determine_rate = clk_cpu_determine_rate, .recalc_rate = clk_cpu_recalc_rate, .debug_init = clk_debug_measure_add, }; static const struct clk_ops clk_ops_perfcl_core = { .set_rate = clk_cpu_set_rate, - .round_rate = clk_cpu_round_rate, + .determine_rate = clk_cpu_determine_rate, .recalc_rate = clk_cpu_recalc_rate, .debug_init = clk_debug_measure_add, }; static const struct clk_ops clk_ops_cpu_osm = { .set_rate = clk_osm_set_rate, - .round_rate = clk_osm_round_rate, .recalc_rate = clk_osm_recalc_rate, .list_rate = clk_osm_list_rate, + .determine_rate = clk_osm_determine_rate, .debug_init = clk_debug_measure_add, };