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
|
* This software is licensed under the terms of the GNU General Public
|
||||||
* License version 2, as published by the Free Software Foundation, and
|
* 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
|
* @freq_tbl: frequency table
|
||||||
* @current_freq: last cached frequency when using branches with shared RCGs
|
* @current_freq: last cached frequency when using branches with shared RCGs
|
||||||
* @clkr: regmap clock handle
|
* @clkr: regmap clock handle
|
||||||
|
* @flags: set if RCG needs to be force enabled/disabled during
|
||||||
|
* power sequence.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct clk_rcg2 {
|
struct clk_rcg2 {
|
||||||
|
@ -168,6 +170,9 @@ struct clk_rcg2 {
|
||||||
const struct freq_tbl *freq_tbl;
|
const struct freq_tbl *freq_tbl;
|
||||||
unsigned long current_freq;
|
unsigned long current_freq;
|
||||||
struct clk_regmap clkr;
|
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)
|
#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
|
* This software is licensed under the terms of the GNU General Public
|
||||||
* License version 2, as published by the Free Software Foundation, and
|
* 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;
|
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)
|
static u8 clk_rcg2_get_parent(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct clk_rcg2 *rcg = to_clk_rcg2(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 = {
|
const struct clk_ops clk_rcg2_ops = {
|
||||||
|
.enable = clk_rcg2_enable,
|
||||||
|
.disable = clk_rcg2_disable,
|
||||||
.is_enabled = clk_rcg2_is_enabled,
|
.is_enabled = clk_rcg2_is_enabled,
|
||||||
.get_parent = clk_rcg2_get_parent,
|
.get_parent = clk_rcg2_get_parent,
|
||||||
.set_parent = clk_rcg2_set_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 = {
|
const struct clk_ops clk_gfx3d_ops = {
|
||||||
|
.enable = clk_rcg2_enable,
|
||||||
|
.disable = clk_rcg2_disable,
|
||||||
.is_enabled = clk_rcg2_is_enabled,
|
.is_enabled = clk_rcg2_is_enabled,
|
||||||
.get_parent = clk_rcg2_get_parent,
|
.get_parent = clk_rcg2_get_parent,
|
||||||
.set_parent = clk_rcg2_set_parent,
|
.set_parent = clk_rcg2_set_parent,
|
||||||
|
|
Loading…
Add table
Reference in a new issue