Merge "clk: qcom: Add support to force enable/disable the RCG"
This commit is contained in:
commit
a79c822905
2 changed files with 62 additions and 2 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013, 2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
|
@ -158,6 +158,8 @@ extern const struct clk_ops clk_dyn_rcg_ops;
|
|||
* @freq_tbl: frequency table
|
||||
* @current_freq: last cached frequency when using branches with shared RCGs
|
||||
* @clkr: regmap clock handle
|
||||
* @flags: set if RCG needs to be force enabled/disabled during
|
||||
* power sequence.
|
||||
*
|
||||
*/
|
||||
struct clk_rcg2 {
|
||||
|
@ -168,6 +170,9 @@ struct clk_rcg2 {
|
|||
const struct freq_tbl *freq_tbl;
|
||||
unsigned long current_freq;
|
||||
struct clk_regmap clkr;
|
||||
|
||||
#define FORCE_ENABLE_RCGR BIT(0)
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
#define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013, 2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
|
@ -60,6 +60,57 @@ static int clk_rcg2_is_enabled(struct clk_hw *hw)
|
|||
return (cmd & CMD_ROOT_OFF) == 0;
|
||||
}
|
||||
|
||||
static int clk_rcg_set_force_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||
const char *name = clk_hw_get_name(hw);
|
||||
int ret = 0, count;
|
||||
|
||||
/* force enable RCG */
|
||||
ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
|
||||
CMD_ROOT_EN, CMD_ROOT_EN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* wait for RCG to turn ON */
|
||||
for (count = 500; count > 0; count--) {
|
||||
ret = clk_rcg2_is_enabled(hw);
|
||||
if (ret) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
udelay(1);
|
||||
}
|
||||
if (!count)
|
||||
pr_err("%s: RCG did not turn on after force enable\n", name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int clk_rcg2_enable(struct clk_hw *hw)
|
||||
{
|
||||
int ret = 0;
|
||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||
|
||||
if (rcg->flags & FORCE_ENABLE_RCGR)
|
||||
ret = clk_rcg_set_force_enable(hw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void clk_rcg2_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||
|
||||
if (rcg->flags & FORCE_ENABLE_RCGR) {
|
||||
/* force disable RCG - clear CMD_ROOT_EN bit */
|
||||
regmap_update_bits(rcg->clkr.regmap,
|
||||
rcg->cmd_rcgr + CMD_REG, CMD_ROOT_EN, 0);
|
||||
/* Add a delay to disable the RCG */
|
||||
udelay(100);
|
||||
}
|
||||
}
|
||||
|
||||
static u8 clk_rcg2_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||
|
@ -290,6 +341,8 @@ static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw,
|
|||
}
|
||||
|
||||
const struct clk_ops clk_rcg2_ops = {
|
||||
.enable = clk_rcg2_enable,
|
||||
.disable = clk_rcg2_disable,
|
||||
.is_enabled = clk_rcg2_is_enabled,
|
||||
.get_parent = clk_rcg2_get_parent,
|
||||
.set_parent = clk_rcg2_set_parent,
|
||||
|
@ -801,6 +854,8 @@ static int clk_gfx3d_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
}
|
||||
|
||||
const struct clk_ops clk_gfx3d_ops = {
|
||||
.enable = clk_rcg2_enable,
|
||||
.disable = clk_rcg2_disable,
|
||||
.is_enabled = clk_rcg2_is_enabled,
|
||||
.get_parent = clk_rcg2_get_parent,
|
||||
.set_parent = clk_rcg2_set_parent,
|
||||
|
|
Loading…
Add table
Reference in a new issue