Skip to content

Commit 16b86e5

Browse files
claudiubezneageertu
authored andcommitted
clk: renesas: rzg2l: Refactor SD mux driver
Refactor SD MUX driver to be able to reuse the same code on RZ/G3S. RZ/G2{L,UL} has a limitation with regards to switching the clock source for SD MUX (MUX clock source has to be switched to 266MHz before switching b/w 533MHz and 400MHz). Rework the handling of this limitation to use a clock notifier that is registered according to platform based initialization data, so the SD MUX code can be reused on RZ/G3S. As RZ/G2{L,UL} and RZ/G3S use different bits in different registers to check if the clock switching has been done, this configuration (register offset, register bits and bitfield width) is now passed through struct cpg_core_clk::sconf (status configuration) from platform specific initialization code. Along with struct cpg_core_clk::sconf the mux table indices are also passed from platform specific initialization code. Also, mux flags are now passed to DEF_SD_MUX() as they will be used later by RZ/G3S. CPG_WEN_BIT macro has been introduced to select properly the WEN bit of various registers. Signed-off-by: Claudiu Beznea <[email protected]> Reviewed-by: Geert Uytterhoeven <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Geert Uytterhoeven <[email protected]>
1 parent 3e8008f commit 16b86e5

File tree

4 files changed

+139
-51
lines changed

4 files changed

+139
-51
lines changed

drivers/clk/renesas/r9a07g043-cpg.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
#define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2)
2222
#define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2)
2323

24+
/* Clock status configuration. */
25+
#define SEL_SDHI0_STS SEL_PLL_PACK(CPG_CLKSTATUS, 28, 1)
26+
#define SEL_SDHI1_STS SEL_PLL_PACK(CPG_CLKSTATUS, 29, 1)
27+
2428
enum clk_ids {
2529
/* Core Clock Outputs exported to DT */
2630
LAST_DT_CORE_CLK = R9A07G043_CLK_P0_DIV2,
@@ -85,6 +89,8 @@ static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" };
8589
static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
8690
static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
8791

92+
static const u32 mtable_sdhi[] = { 1, 2, 3 };
93+
8894
static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = {
8995
/* External Clock Inputs */
9096
DEF_INPUT("extal", CLK_EXTAL),
@@ -130,8 +136,10 @@ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = {
130136
DEF_MUX("HP", R9A07G043_CLK_HP, SEL_PLL6_2, sel_pll6_2),
131137
DEF_FIXED("SPI0", R9A07G043_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2),
132138
DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
133-
DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, sel_shdi),
134-
DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, sel_shdi),
139+
DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi,
140+
mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
141+
DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi,
142+
mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
135143
DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G043_CLK_SD0, 1, 4),
136144
DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G043_CLK_SD1, 1, 4),
137145
};

drivers/clk/renesas/r9a07g044-cpg.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
#define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2)
2323
#define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2)
2424

25+
/* Clock status configuration. */
26+
#define SEL_SDHI0_STS SEL_PLL_PACK(CPG_CLKSTATUS, 28, 1)
27+
#define SEL_SDHI1_STS SEL_PLL_PACK(CPG_CLKSTATUS, 29, 1)
28+
2529
enum clk_ids {
2630
/* Core Clock Outputs exported to DT */
2731
LAST_DT_CORE_CLK = R9A07G054_CLK_DRP_A,
@@ -105,6 +109,8 @@ static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
105109
static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
106110
static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" };
107111

112+
static const u32 mtable_sdhi[] = { 1, 2, 3 };
113+
108114
static const struct {
109115
struct cpg_core_clk common[56];
110116
#ifdef CONFIG_CLK_R9A07G054
@@ -170,8 +176,10 @@ static const struct {
170176
DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2, sel_pll6_2),
171177
DEF_FIXED("SPI0", R9A07G044_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2),
172178
DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
173-
DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, sel_shdi),
174-
DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, sel_shdi),
179+
DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi,
180+
mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
181+
DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi,
182+
mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
175183
DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4),
176184
DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4),
177185
DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8),

drivers/clk/renesas/rzg2l-cpg.c

Lines changed: 108 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -61,31 +61,37 @@
6161
#define GET_REG_SAMPLL_CLK1(val) ((val >> 22) & 0xfff)
6262
#define GET_REG_SAMPLL_CLK2(val) ((val >> 12) & 0xfff)
6363

64+
#define CPG_WEN_BIT BIT(16)
65+
6466
#define MAX_VCLK_FREQ (148500000)
6567

6668
/**
6769
* struct clk_hw_data - clock hardware data
6870
* @hw: clock hw
6971
* @conf: clock configuration (register offset, shift, width)
72+
* @sconf: clock status configuration (register offset, shift, width)
7073
* @priv: CPG private data structure
7174
*/
7275
struct clk_hw_data {
7376
struct clk_hw hw;
7477
u32 conf;
78+
u32 sconf;
7579
struct rzg2l_cpg_priv *priv;
7680
};
7781

7882
#define to_clk_hw_data(_hw) container_of(_hw, struct clk_hw_data, hw)
7983

8084
/**
81-
* struct sd_hw_data - SD clock hardware data
85+
* struct sd_mux_hw_data - SD MUX clock hardware data
8286
* @hw_data: clock hw data
87+
* @mtable: clock mux table
8388
*/
84-
struct sd_hw_data {
89+
struct sd_mux_hw_data {
8590
struct clk_hw_data hw_data;
91+
const u32 *mtable;
8692
};
8793

88-
#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw_data)
94+
#define to_sd_mux_hw_data(_hw) container_of(_hw, struct sd_mux_hw_data, hw_data)
8995

9096
struct rzg2l_pll5_param {
9197
u32 pl5_fracin;
@@ -142,6 +148,76 @@ static void rzg2l_cpg_del_clk_provider(void *data)
142148
of_clk_del_provider(data);
143149
}
144150

151+
/* Must be called in atomic context. */
152+
static int rzg2l_cpg_wait_clk_update_done(void __iomem *base, u32 conf)
153+
{
154+
u32 bitmask = GENMASK(GET_WIDTH(conf) - 1, 0) << GET_SHIFT(conf);
155+
u32 off = GET_REG_OFFSET(conf);
156+
u32 val;
157+
158+
return readl_poll_timeout_atomic(base + off, val, !(val & bitmask), 10, 200);
159+
}
160+
161+
int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event,
162+
void *data)
163+
{
164+
struct clk_notifier_data *cnd = data;
165+
struct clk_hw *hw = __clk_get_hw(cnd->clk);
166+
struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
167+
struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
168+
u32 off = GET_REG_OFFSET(clk_hw_data->conf);
169+
u32 shift = GET_SHIFT(clk_hw_data->conf);
170+
const u32 clk_src_266 = 3;
171+
unsigned long flags;
172+
int ret;
173+
174+
if (event != PRE_RATE_CHANGE || (cnd->new_rate / MEGA == 266))
175+
return NOTIFY_DONE;
176+
177+
spin_lock_irqsave(&priv->rmw_lock, flags);
178+
179+
/*
180+
* As per the HW manual, we should not directly switch from 533 MHz to
181+
* 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz)
182+
* to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first,
183+
* and then switch to the target setting (2’b01 (533 MHz) or 2’b10
184+
* (400 MHz)).
185+
* Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock
186+
* switching register is prohibited.
187+
* The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and
188+
* the index to value mapping is done by adding 1 to the index.
189+
*/
190+
191+
writel((CPG_WEN_BIT | clk_src_266) << shift, priv->base + off);
192+
193+
/* Wait for the update done. */
194+
ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf);
195+
196+
spin_unlock_irqrestore(&priv->rmw_lock, flags);
197+
198+
if (ret)
199+
dev_err(priv->dev, "failed to switch to safe clk source\n");
200+
201+
return notifier_from_errno(ret);
202+
}
203+
204+
static int rzg2l_register_notifier(struct clk_hw *hw, const struct cpg_core_clk *core,
205+
struct rzg2l_cpg_priv *priv)
206+
{
207+
struct notifier_block *nb;
208+
209+
if (!core->notifier)
210+
return 0;
211+
212+
nb = devm_kzalloc(priv->dev, sizeof(*nb), GFP_KERNEL);
213+
if (!nb)
214+
return -ENOMEM;
215+
216+
nb->notifier_call = core->notifier;
217+
218+
return clk_notifier_register(hw->clk, nb);
219+
}
220+
145221
static struct clk * __init
146222
rzg2l_cpg_div_clk_register(const struct cpg_core_clk *core,
147223
struct clk **clks,
@@ -205,62 +281,43 @@ rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core,
205281
static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
206282
{
207283
struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
284+
struct sd_mux_hw_data *sd_mux_hw_data = to_sd_mux_hw_data(clk_hw_data);
208285
struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
209286
u32 off = GET_REG_OFFSET(clk_hw_data->conf);
210287
u32 shift = GET_SHIFT(clk_hw_data->conf);
211-
const u32 clk_src_266 = 2;
212-
u32 msk, val, bitmask;
213288
unsigned long flags;
289+
u32 val;
214290
int ret;
215291

216-
/*
217-
* As per the HW manual, we should not directly switch from 533 MHz to
218-
* 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz)
219-
* to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first,
220-
* and then switch to the target setting (2’b01 (533 MHz) or 2’b10
221-
* (400 MHz)).
222-
* Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock
223-
* switching register is prohibited.
224-
* The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and
225-
* the index to value mapping is done by adding 1 to the index.
226-
*/
227-
bitmask = (GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0) << shift) << 16;
228-
msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS;
292+
val = clk_mux_index_to_val(sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, index);
293+
229294
spin_lock_irqsave(&priv->rmw_lock, flags);
230-
if (index != clk_src_266) {
231-
writel(bitmask | ((clk_src_266 + 1) << shift), priv->base + off);
232-
233-
ret = readl_poll_timeout_atomic(priv->base + CPG_CLKSTATUS, val,
234-
!(val & msk), 10,
235-
CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US);
236-
if (ret)
237-
goto unlock;
238-
}
239295

240-
writel(bitmask | ((index + 1) << shift), priv->base + off);
296+
writel((CPG_WEN_BIT | val) << shift, priv->base + off);
297+
298+
/* Wait for the update done. */
299+
ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf);
241300

242-
ret = readl_poll_timeout_atomic(priv->base + CPG_CLKSTATUS, val,
243-
!(val & msk), 10,
244-
CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US);
245-
unlock:
246301
spin_unlock_irqrestore(&priv->rmw_lock, flags);
247302

248303
if (ret)
249-
dev_err(priv->dev, "failed to switch clk source\n");
304+
dev_err(priv->dev, "Failed to switch parent\n");
250305

251306
return ret;
252307
}
253308

254309
static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw)
255310
{
256311
struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
312+
struct sd_mux_hw_data *sd_mux_hw_data = to_sd_mux_hw_data(clk_hw_data);
257313
struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
258-
u32 val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf));
314+
u32 val;
259315

316+
val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf));
260317
val >>= GET_SHIFT(clk_hw_data->conf);
261318
val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0);
262319

263-
return val ? val - 1 : 0;
320+
return clk_mux_val_to_index(hw, sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, val);
264321
}
265322

266323
static const struct clk_ops rzg2l_cpg_sd_clk_mux_ops = {
@@ -274,31 +331,40 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core,
274331
void __iomem *base,
275332
struct rzg2l_cpg_priv *priv)
276333
{
277-
struct sd_hw_data *sd_hw_data;
334+
struct sd_mux_hw_data *sd_mux_hw_data;
278335
struct clk_init_data init;
279336
struct clk_hw *clk_hw;
280337
int ret;
281338

282-
sd_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_hw_data), GFP_KERNEL);
283-
if (!sd_hw_data)
339+
sd_mux_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_mux_hw_data), GFP_KERNEL);
340+
if (!sd_mux_hw_data)
284341
return ERR_PTR(-ENOMEM);
285342

286-
sd_hw_data->hw_data.priv = priv;
287-
sd_hw_data->hw_data.conf = core->conf;
343+
sd_mux_hw_data->hw_data.priv = priv;
344+
sd_mux_hw_data->hw_data.conf = core->conf;
345+
sd_mux_hw_data->hw_data.sconf = core->sconf;
346+
sd_mux_hw_data->mtable = core->mtable;
288347

289348
init.name = core->name;
290349
init.ops = &rzg2l_cpg_sd_clk_mux_ops;
291-
init.flags = 0;
350+
init.flags = core->flag;
292351
init.num_parents = core->num_parents;
293352
init.parent_names = core->parent_names;
294353

295-
clk_hw = &sd_hw_data->hw_data.hw;
354+
clk_hw = &sd_mux_hw_data->hw_data.hw;
296355
clk_hw->init = &init;
297356

298357
ret = devm_clk_hw_register(priv->dev, clk_hw);
299358
if (ret)
300359
return ERR_PTR(ret);
301360

361+
ret = rzg2l_register_notifier(clk_hw, core, priv);
362+
if (ret) {
363+
dev_err(priv->dev, "Failed to register notifier for %s\n",
364+
core->name);
365+
return ERR_PTR(ret);
366+
}
367+
302368
return clk_hw->clk;
303369
}
304370

drivers/clk/renesas/rzg2l-cpg.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#ifndef __RENESAS_RZG2L_CPG_H__
1010
#define __RENESAS_RZG2L_CPG_H__
1111

12+
#include <linux/notifier.h>
13+
1214
#define CPG_SIPLL5_STBY (0x140)
1315
#define CPG_SIPLL5_CLK1 (0x144)
1416
#define CPG_SIPLL5_CLK3 (0x14C)
@@ -42,8 +44,6 @@
4244
#define CPG_CLKSTATUS_SELSDHI0_STS BIT(28)
4345
#define CPG_CLKSTATUS_SELSDHI1_STS BIT(29)
4446

45-
#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 200
46-
4747
/* n = 0/1/2 for PLL1/4/6 */
4848
#define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n))
4949
#define CPG_SAMPLL_CLK2(n) (0x08 + (16 * n))
@@ -86,8 +86,11 @@ struct cpg_core_clk {
8686
unsigned int mult;
8787
unsigned int type;
8888
unsigned int conf;
89+
unsigned int sconf;
8990
const struct clk_div_table *dtable;
91+
const u32 *mtable;
9092
const char * const *parent_names;
93+
notifier_fn_t notifier;
9194
u32 flag;
9295
u32 mux_flags;
9396
int num_parents;
@@ -150,10 +153,11 @@ enum clk_types {
150153
.parent_names = _parent_names, \
151154
.num_parents = ARRAY_SIZE(_parent_names), \
152155
.mux_flags = CLK_MUX_READ_ONLY)
153-
#define DEF_SD_MUX(_name, _id, _conf, _parent_names) \
154-
DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, \
156+
#define DEF_SD_MUX(_name, _id, _conf, _sconf, _parent_names, _mtable, _clk_flags, _notifier) \
157+
DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, .sconf = _sconf, \
155158
.parent_names = _parent_names, \
156-
.num_parents = ARRAY_SIZE(_parent_names))
159+
.num_parents = ARRAY_SIZE(_parent_names), \
160+
.mtable = _mtable, .flag = _clk_flags, .notifier = _notifier)
157161
#define DEF_PLL5_FOUTPOSTDIV(_name, _id, _parent) \
158162
DEF_TYPE(_name, _id, CLK_TYPE_SIPLL5, .parent = _parent)
159163
#define DEF_PLL5_4_MUX(_name, _id, _conf, _parent_names) \
@@ -272,4 +276,6 @@ extern const struct rzg2l_cpg_info r9a07g044_cpg_info;
272276
extern const struct rzg2l_cpg_info r9a07g054_cpg_info;
273277
extern const struct rzg2l_cpg_info r9a09g011_cpg_info;
274278

279+
int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event, void *data);
280+
275281
#endif

0 commit comments

Comments
 (0)