Skip to content

Commit 4a3de5a

Browse files
MrVanabelvesa
authored andcommitted
clk: imx: clk-composite-93: check slice busy
i.MX93 CCM ROOT STAT register has a SLICE_BUSY bit: indication for clock generation logic is applying new setting. 0b - Clock generation logic is not busy. 1b - Clock generation logic is applying new setting. So when set parent/rate/gate, need check this bit. Introduce specific ops to do the work. Signed-off-by: Peng Fan <peng.fan@nxp.com> Reviewed-by: Ye Li <ye.li@nxp.com> Reviewed-by: Jacky Bai <ping.bai@nxp.com> Reviewed-by: Abel Vesa <abel.vesa@linaro.org> Signed-off-by: Abel Vesa <abel.vesa@linaro.org> Link: https://lore.kernel.org/r/20220830033137.4149542-4-peng.fan@oss.nxp.com
1 parent 90e5807 commit 4a3de5a

File tree

1 file changed

+160
-3
lines changed

1 file changed

+160
-3
lines changed

drivers/clk/imx/clk-composite-93.c

Lines changed: 160 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,176 @@
99
#include <linux/errno.h>
1010
#include <linux/export.h>
1111
#include <linux/io.h>
12+
#include <linux/iopoll.h>
1213
#include <linux/slab.h>
1314

1415
#include "clk.h"
1516

17+
#define TIMEOUT_US 500U
18+
1619
#define CCM_DIV_SHIFT 0
1720
#define CCM_DIV_WIDTH 8
1821
#define CCM_MUX_SHIFT 8
1922
#define CCM_MUX_MASK 3
2023
#define CCM_OFF_SHIFT 24
24+
#define CCM_BUSY_SHIFT 28
2125

26+
#define STAT_OFFSET 0x4
2227
#define AUTHEN_OFFSET 0x30
2328
#define TZ_NS_SHIFT 9
2429
#define TZ_NS_MASK BIT(9)
2530

31+
static int imx93_clk_composite_wait_ready(struct clk_hw *hw, void __iomem *reg)
32+
{
33+
int ret;
34+
u32 val;
35+
36+
ret = readl_poll_timeout_atomic(reg + STAT_OFFSET, val, !(val & BIT(CCM_BUSY_SHIFT)),
37+
0, TIMEOUT_US);
38+
if (ret)
39+
pr_err("Slice[%s] busy timeout\n", clk_hw_get_name(hw));
40+
41+
return ret;
42+
}
43+
44+
static void imx93_clk_composite_gate_endisable(struct clk_hw *hw, int enable)
45+
{
46+
struct clk_gate *gate = to_clk_gate(hw);
47+
unsigned long flags;
48+
u32 reg;
49+
50+
if (gate->lock)
51+
spin_lock_irqsave(gate->lock, flags);
52+
53+
reg = readl(gate->reg);
54+
55+
if (enable)
56+
reg &= ~BIT(gate->bit_idx);
57+
else
58+
reg |= BIT(gate->bit_idx);
59+
60+
writel(reg, gate->reg);
61+
62+
imx93_clk_composite_wait_ready(hw, gate->reg);
63+
64+
if (gate->lock)
65+
spin_unlock_irqrestore(gate->lock, flags);
66+
}
67+
68+
static int imx93_clk_composite_gate_enable(struct clk_hw *hw)
69+
{
70+
imx93_clk_composite_gate_endisable(hw, 1);
71+
72+
return 0;
73+
}
74+
75+
static void imx93_clk_composite_gate_disable(struct clk_hw *hw)
76+
{
77+
imx93_clk_composite_gate_endisable(hw, 0);
78+
}
79+
80+
static const struct clk_ops imx93_clk_composite_gate_ops = {
81+
.enable = imx93_clk_composite_gate_enable,
82+
.disable = imx93_clk_composite_gate_disable,
83+
.is_enabled = clk_gate_is_enabled,
84+
};
85+
86+
static unsigned long
87+
imx93_clk_composite_divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
88+
{
89+
return clk_divider_ops.recalc_rate(hw, parent_rate);
90+
}
91+
92+
static long
93+
imx93_clk_composite_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate)
94+
{
95+
return clk_divider_ops.round_rate(hw, rate, prate);
96+
}
97+
98+
static int
99+
imx93_clk_composite_divider_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
100+
{
101+
return clk_divider_ops.determine_rate(hw, req);
102+
}
103+
104+
static int imx93_clk_composite_divider_set_rate(struct clk_hw *hw, unsigned long rate,
105+
unsigned long parent_rate)
106+
{
107+
struct clk_divider *divider = to_clk_divider(hw);
108+
int value;
109+
unsigned long flags = 0;
110+
u32 val;
111+
int ret;
112+
113+
value = divider_get_val(rate, parent_rate, divider->table, divider->width, divider->flags);
114+
if (value < 0)
115+
return value;
116+
117+
if (divider->lock)
118+
spin_lock_irqsave(divider->lock, flags);
119+
120+
val = readl(divider->reg);
121+
val &= ~(clk_div_mask(divider->width) << divider->shift);
122+
val |= (u32)value << divider->shift;
123+
writel(val, divider->reg);
124+
125+
ret = imx93_clk_composite_wait_ready(hw, divider->reg);
126+
127+
if (divider->lock)
128+
spin_unlock_irqrestore(divider->lock, flags);
129+
130+
return ret;
131+
}
132+
133+
static const struct clk_ops imx93_clk_composite_divider_ops = {
134+
.recalc_rate = imx93_clk_composite_divider_recalc_rate,
135+
.round_rate = imx93_clk_composite_divider_round_rate,
136+
.determine_rate = imx93_clk_composite_divider_determine_rate,
137+
.set_rate = imx93_clk_composite_divider_set_rate,
138+
};
139+
140+
static u8 imx93_clk_composite_mux_get_parent(struct clk_hw *hw)
141+
{
142+
return clk_mux_ops.get_parent(hw);
143+
}
144+
145+
static int imx93_clk_composite_mux_set_parent(struct clk_hw *hw, u8 index)
146+
{
147+
struct clk_mux *mux = to_clk_mux(hw);
148+
u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
149+
unsigned long flags = 0;
150+
u32 reg;
151+
int ret;
152+
153+
if (mux->lock)
154+
spin_lock_irqsave(mux->lock, flags);
155+
156+
reg = readl(mux->reg);
157+
reg &= ~(mux->mask << mux->shift);
158+
val = val << mux->shift;
159+
reg |= val;
160+
writel(reg, mux->reg);
161+
162+
ret = imx93_clk_composite_wait_ready(hw, mux->reg);
163+
164+
if (mux->lock)
165+
spin_unlock_irqrestore(mux->lock, flags);
166+
167+
return ret;
168+
}
169+
170+
static int
171+
imx93_clk_composite_mux_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
172+
{
173+
return clk_mux_ops.determine_rate(hw, req);
174+
}
175+
176+
static const struct clk_ops imx93_clk_composite_mux_ops = {
177+
.get_parent = imx93_clk_composite_mux_get_parent,
178+
.set_parent = imx93_clk_composite_mux_set_parent,
179+
.determine_rate = imx93_clk_composite_mux_determine_rate,
180+
};
181+
26182
struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *parent_names,
27183
int num_parents, void __iomem *reg,
28184
unsigned long flags)
@@ -74,9 +230,10 @@ struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *p
74230
gate->flags = CLK_GATE_SET_TO_DISABLE;
75231

76232
hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
77-
mux_hw, &clk_mux_ops, div_hw,
78-
&clk_divider_ops, gate_hw,
79-
&clk_gate_ops, flags | CLK_SET_RATE_NO_REPARENT);
233+
mux_hw, &imx93_clk_composite_mux_ops, div_hw,
234+
&imx93_clk_composite_divider_ops, gate_hw,
235+
&imx93_clk_composite_gate_ops,
236+
flags | CLK_SET_RATE_NO_REPARENT);
80237
}
81238

82239
if (IS_ERR(hw))

0 commit comments

Comments
 (0)