Skip to content

Commit eaff336

Browse files
bijudasgeertu
authored andcommitted
clk: renesas: rzg2l: Add SDHI clk mux support
Add SDHI clk mux support to select SDHI clock from different clock sources. As per HW manual, direct clock switching from 533MHz to 400MHz and vice versa is not recommended. So added support for handling this in mux. Signed-off-by: Biju Das <[email protected]> Reviewed-by: Lad Prabhakar <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Geert Uytterhoeven <[email protected]>
1 parent 27c9d76 commit eaff336

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed

drivers/clk/renesas/rzg2l-cpg.c

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/delay.h>
1818
#include <linux/device.h>
1919
#include <linux/init.h>
20+
#include <linux/iopoll.h>
2021
#include <linux/mod_devicetable.h>
2122
#include <linux/module.h>
2223
#include <linux/of_address.h>
@@ -55,6 +56,14 @@
5556
#define GET_REG_SAMPLL_CLK1(val) ((val >> 22) & 0xfff)
5657
#define GET_REG_SAMPLL_CLK2(val) ((val >> 12) & 0xfff)
5758

59+
struct sd_hw_data {
60+
struct clk_hw hw;
61+
u32 conf;
62+
struct rzg2l_cpg_priv *priv;
63+
};
64+
65+
#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw)
66+
5867
/**
5968
* struct rzg2l_cpg_priv - Clock Pulse Generator Private Data
6069
*
@@ -150,6 +159,112 @@ rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core,
150159
return clk_hw->clk;
151160
}
152161

162+
static int rzg2l_cpg_sd_clk_mux_determine_rate(struct clk_hw *hw,
163+
struct clk_rate_request *req)
164+
{
165+
return clk_mux_determine_rate_flags(hw, req, 0);
166+
}
167+
168+
static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
169+
{
170+
struct sd_hw_data *hwdata = to_sd_hw_data(hw);
171+
struct rzg2l_cpg_priv *priv = hwdata->priv;
172+
u32 off = GET_REG_OFFSET(hwdata->conf);
173+
u32 shift = GET_SHIFT(hwdata->conf);
174+
const u32 clk_src_266 = 2;
175+
u32 bitmask;
176+
177+
/*
178+
* As per the HW manual, we should not directly switch from 533 MHz to
179+
* 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz)
180+
* to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first,
181+
* and then switch to the target setting (2’b01 (533 MHz) or 2’b10
182+
* (400 MHz)).
183+
* Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock
184+
* switching register is prohibited.
185+
* The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and
186+
* the index to value mapping is done by adding 1 to the index.
187+
*/
188+
bitmask = (GENMASK(GET_WIDTH(hwdata->conf) - 1, 0) << shift) << 16;
189+
if (index != clk_src_266) {
190+
u32 msk, val;
191+
int ret;
192+
193+
writel(bitmask | ((clk_src_266 + 1) << shift), priv->base + off);
194+
195+
msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS;
196+
197+
ret = readl_poll_timeout(priv->base + CPG_CLKSTATUS, val,
198+
!(val & msk), 100,
199+
CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US);
200+
if (ret) {
201+
dev_err(priv->dev, "failed to switch clk source\n");
202+
return ret;
203+
}
204+
}
205+
206+
writel(bitmask | ((index + 1) << shift), priv->base + off);
207+
208+
return 0;
209+
}
210+
211+
static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw)
212+
{
213+
struct sd_hw_data *hwdata = to_sd_hw_data(hw);
214+
struct rzg2l_cpg_priv *priv = hwdata->priv;
215+
u32 val = readl(priv->base + GET_REG_OFFSET(hwdata->conf));
216+
217+
val >>= GET_SHIFT(hwdata->conf);
218+
val &= GENMASK(GET_WIDTH(hwdata->conf) - 1, 0);
219+
if (val) {
220+
val--;
221+
} else {
222+
/* Prohibited clk source, change it to 533 MHz(reset value) */
223+
rzg2l_cpg_sd_clk_mux_set_parent(hw, 0);
224+
}
225+
226+
return val;
227+
}
228+
229+
static const struct clk_ops rzg2l_cpg_sd_clk_mux_ops = {
230+
.determine_rate = rzg2l_cpg_sd_clk_mux_determine_rate,
231+
.set_parent = rzg2l_cpg_sd_clk_mux_set_parent,
232+
.get_parent = rzg2l_cpg_sd_clk_mux_get_parent,
233+
};
234+
235+
static struct clk * __init
236+
rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core,
237+
void __iomem *base,
238+
struct rzg2l_cpg_priv *priv)
239+
{
240+
struct sd_hw_data *clk_hw_data;
241+
struct clk_init_data init;
242+
struct clk_hw *clk_hw;
243+
int ret;
244+
245+
clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
246+
if (!clk_hw_data)
247+
return ERR_PTR(-ENOMEM);
248+
249+
clk_hw_data->priv = priv;
250+
clk_hw_data->conf = core->conf;
251+
252+
init.name = GET_SHIFT(core->conf) ? "sd1" : "sd0";
253+
init.ops = &rzg2l_cpg_sd_clk_mux_ops;
254+
init.flags = 0;
255+
init.num_parents = core->num_parents;
256+
init.parent_names = core->parent_names;
257+
258+
clk_hw = &clk_hw_data->hw;
259+
clk_hw->init = &init;
260+
261+
ret = devm_clk_hw_register(priv->dev, clk_hw);
262+
if (ret)
263+
return ERR_PTR(ret);
264+
265+
return clk_hw->clk;
266+
}
267+
153268
struct pll_clk {
154269
struct clk_hw hw;
155270
unsigned int conf;
@@ -311,6 +426,9 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
311426
case CLK_TYPE_MUX:
312427
clk = rzg2l_cpg_mux_clk_register(core, priv->base, priv);
313428
break;
429+
case CLK_TYPE_SD_MUX:
430+
clk = rzg2l_cpg_sd_mux_clk_register(core, priv->base, priv);
431+
break;
314432
default:
315433
goto fail;
316434
}

drivers/clk/renesas/rzg2l-cpg.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,15 @@
1111

1212
#define CPG_PL2_DDIV (0x204)
1313
#define CPG_PL3A_DDIV (0x208)
14+
#define CPG_CLKSTATUS (0x280)
1415
#define CPG_PL3_SSEL (0x408)
1516
#define CPG_PL6_ETH_SSEL (0x418)
1617

18+
#define CPG_CLKSTATUS_SELSDHI0_STS BIT(28)
19+
#define CPG_CLKSTATUS_SELSDHI1_STS BIT(29)
20+
21+
#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 20000
22+
1723
/* n = 0/1/2 for PLL1/4/6 */
1824
#define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n))
1925
#define CPG_SAMPLL_CLK2(n) (0x08 + (16 * n))
@@ -67,6 +73,9 @@ enum clk_types {
6773

6874
/* Clock with clock source selector */
6975
CLK_TYPE_MUX,
76+
77+
/* Clock with SD clock source selector */
78+
CLK_TYPE_SD_MUX,
7079
};
7180

7281
#define DEF_TYPE(_name, _id, _type...) \
@@ -87,6 +96,9 @@ enum clk_types {
8796
DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = _conf, \
8897
.parent_names = _parent_names, .num_parents = _num_parents, \
8998
.flag = _flag, .mux_flags = _mux_flags)
99+
#define DEF_SD_MUX(_name, _id, _conf, _parent_names, _num_parents) \
100+
DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, \
101+
.parent_names = _parent_names, .num_parents = _num_parents)
90102

91103
/**
92104
* struct rzg2l_mod_clk - Module Clocks definitions

0 commit comments

Comments
 (0)