mirror of
https://github.com/hardkernel/kernel_common_drivers.git
synced 2026-06-25 12:03:48 +09:00
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:
committed by
gongwei.chen
parent
d1e5aea476
commit
b9c8af106c
@@ -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)
|
||||
|
||||
@@ -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
@@ -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 },
|
||||
|
||||
Reference in New Issue
Block a user