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 <tdas@codeaurora.org>
This commit is contained in:
parent
3364ad120f
commit
77edc8b345
1 changed files with 30 additions and 27 deletions
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue