clk: s7: fix check efuse clk [1/1]

PD#SWPL-193355

Problem:
clk is restricted by efuse, need check it after enabled

Solution:
add check mechanism

Verify:
s805x3

Change-Id: Iae5ed58299c599fd0bdbb3b1903543528ad05285
Signed-off-by: yiting.deng <yiting.deng@amlogic.com>
This commit is contained in:
yiting.deng
2024-11-29 17:55:36 +08:00
committed by gongwei.chen
parent d1e5aea476
commit b9c8af106c
3 changed files with 132 additions and 13 deletions
+34 -1
View File
@@ -8,6 +8,33 @@
#include <linux/arm-smccc.h>
#include "clk-regmap.h"
static int clk_regmap_check_is_satisfied(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk);
unsigned int val;
int cnt = 3;
if (gate->check_offset) {
do {
if (!cnt) {
pr_err("check %s failed!\n", clk_hw_get_name(hw));
return -ETIMEDOUT;
}
/*
* FIXME: due to hardware reasons, the check will be delayed per 1ms,
* and the splinlock used during the enable period will be delayed
* for at least 1ms.
*/
udelay(1000);
cnt--;
regmap_read(clk->map, gate->check_offset, &val);
} while (!(val & BIT(gate->check_bit)));
}
return 0;
}
static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable)
{
struct clk_regmap *clk = to_clk_regmap(hw);
@@ -22,7 +49,13 @@ static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable)
static int clk_regmap_gate_enable(struct clk_hw *hw)
{
return clk_regmap_gate_endisable(hw, 1);
int ret;
ret = clk_regmap_gate_endisable(hw, 1);
if (ret)
return ret;
return clk_regmap_check_is_satisfied(hw);
}
static void clk_regmap_gate_disable(struct clk_hw *hw)
+2
View File
@@ -45,6 +45,8 @@ struct clk_regmap {
struct clk_regmap_gate_data {
unsigned int offset;
u8 bit_idx;
unsigned int check_offset;
u8 check_bit;
u8 flags;
};
+96 -12
View File
@@ -1246,19 +1246,103 @@ MESON_CLK_MUX_RW(vdec, CLKCTRL_VDEC3_CLK_CTRL, 0x1, 15, NULL, 0,
vdec_parent_data, CLK_SET_RATE_PARENT);
/* cts_hevcf_clk */
MESON_CLK_COMPOSITE_RW(hevcf_0, CLKCTRL_VDEC2_CLK_CTRL, 0x7, 9,
NULL, 0, vdec_pre_parent_data, 0,
CLKCTRL_VDEC2_CLK_CTRL, 0, 7, NULL,
0, CLK_SET_RATE_PARENT,
CLKCTRL_VDEC2_CLK_CTRL, 8,
0, CLK_SET_RATE_PARENT);
static struct clk_regmap hevcf_0_sel = {
.data = &(struct clk_regmap_mux_data) {
.offset = CLKCTRL_VDEC2_CLK_CTRL,
.mask = 0x7,
.shift = 9,
},
.hw.init = &(struct clk_init_data) {
.name = "hevcf_0_sel",
.ops = &clk_regmap_mux_ops,
.parent_data = vdec_pre_parent_data,
.num_parents = ARRAY_SIZE(vdec_pre_parent_data),
},
};
MESON_CLK_COMPOSITE_RW(hevcf_1, CLKCTRL_VDEC4_CLK_CTRL, 0x7, 9,
NULL, 0, vdec_pre_parent_data, 0,
CLKCTRL_VDEC4_CLK_CTRL, 0, 7, NULL,
0, CLK_SET_RATE_PARENT,
CLKCTRL_VDEC4_CLK_CTRL, 8,
0, CLK_SET_RATE_PARENT);
static struct clk_regmap hevcf_0_div = {
.data = &(struct clk_regmap_div_data) {
.offset = CLKCTRL_VDEC2_CLK_CTRL,
.shift = 0,
.width = 7,
},
.hw.init = &(struct clk_init_data) {
.name = "hevcf_0_div",
.ops = &clk_regmap_divider_ops,
.parent_hws = (const struct clk_hw *[]) {
&hevcf_0_sel.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap hevcf_0 = {
.data = &(struct clk_regmap_gate_data) {
.offset = CLKCTRL_VDEC2_CLK_CTRL,
.bit_idx = 8,
.check_offset = CLKCTRL_CHECK_CLK_RESULT,
.check_bit = 1,
},
.hw.init = &(struct clk_init_data) {
.name = "hevcf_0",
.ops = &clk_regmap_gate_ops,
.parent_hws = (const struct clk_hw *[]) {
&hevcf_0_div.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap hevcf_1_sel = {
.data = &(struct clk_regmap_mux_data) {
.offset = CLKCTRL_VDEC4_CLK_CTRL,
.mask = 0x7,
.shift = 9,
},
.hw.init = &(struct clk_init_data) {
.name = "hevcf_1_sel",
.ops = &clk_regmap_mux_ops,
.parent_data = vdec_pre_parent_data,
.num_parents = ARRAY_SIZE(vdec_pre_parent_data),
},
};
static struct clk_regmap hevcf_1_div = {
.data = &(struct clk_regmap_div_data) {
.offset = CLKCTRL_VDEC4_CLK_CTRL,
.shift = 0,
.width = 7,
},
.hw.init = &(struct clk_init_data) {
.name = "hevcf_1_div",
.ops = &clk_regmap_divider_ops,
.parent_hws = (const struct clk_hw *[]) {
&hevcf_1_sel.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap hevcf_1 = {
.data = &(struct clk_regmap_gate_data) {
.offset = CLKCTRL_VDEC4_CLK_CTRL,
.bit_idx = 8,
.check_offset = CLKCTRL_CHECK_CLK_RESULT,
.check_bit = 1,
},
.hw.init = &(struct clk_init_data) {
.name = "hevcf_1",
.ops = &clk_regmap_gate_ops,
.parent_hws = (const struct clk_hw *[]) {
&hevcf_1_div.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static const struct clk_parent_data hevcf_parent_data[] = {
{ .hw = &hevcf_0.hw },