Skip to content

Commit bb6d3fa

Browse files
Wolfram Sanggeertu
authored andcommitted
clk: renesas: rcar-gen3: Switch to new SD clock handling
The old SD handling code was huge and could not handle all the details which showed up on R-Car Gen3 SoCs meanwhile. It is time to switch to another design. Have SDnH a separate clock, use the existing divider clocks and move the errata handling from the clock driver to the SDHI driver where it belongs. This patch removes the old SD handling code and switch to the new one. This updates the SDHI driver at the same time. Because the SDHI driver can only communicate with the clock driver via clk_set_rate(), I don't see an alternative to this flag-day-approach, so we cross subsystems here. The patch sadly looks messy for the CPG lib, but it is basically a huge chunk of code removed and smaller chunks added. It looks much better when you just view the resulting source file. Signed-off-by: Wolfram Sang <[email protected]> Acked-by: Ulf Hansson <[email protected]> # For MMC Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Geert Uytterhoeven <[email protected]>
1 parent 627151b commit bb6d3fa

File tree

6 files changed

+56
-207
lines changed

6 files changed

+56
-207
lines changed

drivers/clk/renesas/r8a779a0-cpg-mssr.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -479,10 +479,8 @@ static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev,
479479
__clk_get_name(parent), notifiers);
480480

481481
case CLK_TYPE_R8A779A0_SD:
482-
return cpg_sd_clk_register(core->name, base, core->offset,
483-
__clk_get_name(parent), notifiers,
484-
false);
485-
break;
482+
return cpg_sd_clk_register(core->name, base + core->offset,
483+
__clk_get_name(parent));
486484

487485
case CLK_TYPE_R8A779A0_MDSEL:
488486
/*

drivers/clk/renesas/rcar-cpg-lib.c

Lines changed: 27 additions & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -66,214 +66,48 @@ void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
6666
* SDn Clock
6767
*/
6868

69-
struct clk * __init cpg_sdh_clk_register(const char *name,
70-
void __iomem *sdnckcr, const char *parent_name,
71-
struct raw_notifier_head *notifiers)
72-
{
73-
/* placeholder during transition */
74-
return clk_register_fixed_factor(NULL, name, parent_name, 0, 1, 1);
75-
}
76-
77-
#define CPG_SD_STP_HCK BIT(9)
78-
#define CPG_SD_STP_CK BIT(8)
79-
80-
#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK)
81-
#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0)
82-
83-
#define CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) \
84-
{ \
85-
.val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
86-
((sd_srcfc) << 2) | \
87-
((sd_fc) << 0), \
88-
.div = (sd_div), \
89-
}
90-
91-
struct sd_div_table {
92-
u32 val;
93-
unsigned int div;
94-
};
69+
#define SDnSRCFC_SHIFT 2
70+
#define STPnHCK BIT(9 - SDnSRCFC_SHIFT)
9571

96-
struct sd_clock {
97-
struct clk_hw hw;
98-
const struct sd_div_table *div_table;
99-
struct cpg_simple_notifier csn;
100-
unsigned int div_num;
101-
unsigned int cur_div_idx;
102-
};
103-
104-
/* SDn divider
105-
* sd_srcfc sd_fc div
106-
* stp_hck (div) (div) = sd_srcfc x sd_fc
107-
*---------------------------------------------------------
108-
* 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP)
109-
* 0 1 (2) 1 (4) 8 : SDR50
110-
* 1 2 (4) 1 (4) 16 : HS / SDR25
111-
* 1 3 (8) 1 (4) 32 : NS / SDR12
112-
* 1 4 (16) 1 (4) 64
113-
* 0 0 (1) 0 (2) 2
114-
* 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP)
115-
* 1 2 (4) 0 (2) 8
116-
* 1 3 (8) 0 (2) 16
117-
* 1 4 (16) 0 (2) 32
118-
*
119-
* NOTE: There is a quirk option to ignore the first row of the dividers
120-
* table when searching for suitable settings. This is because HS400 on
121-
* early ES versions of H3 and M3-W requires a specific setting to work.
122-
*/
123-
static const struct sd_div_table cpg_sd_div_table[] = {
124-
/* CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) */
125-
CPG_SD_DIV_TABLE_DATA(0, 0, 1, 4),
126-
CPG_SD_DIV_TABLE_DATA(0, 1, 1, 8),
127-
CPG_SD_DIV_TABLE_DATA(1, 2, 1, 16),
128-
CPG_SD_DIV_TABLE_DATA(1, 3, 1, 32),
129-
CPG_SD_DIV_TABLE_DATA(1, 4, 1, 64),
130-
CPG_SD_DIV_TABLE_DATA(0, 0, 0, 2),
131-
CPG_SD_DIV_TABLE_DATA(0, 1, 0, 4),
132-
CPG_SD_DIV_TABLE_DATA(1, 2, 0, 8),
133-
CPG_SD_DIV_TABLE_DATA(1, 3, 0, 16),
134-
CPG_SD_DIV_TABLE_DATA(1, 4, 0, 32),
72+
static const struct clk_div_table cpg_sdh_div_table[] = {
73+
{ 0, 1 }, { 1, 2 }, { STPnHCK | 2, 4 }, { STPnHCK | 3, 8 },
74+
{ STPnHCK | 4, 16 }, { 0, 0 },
13575
};
13676

137-
#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw)
138-
139-
static int cpg_sd_clock_enable(struct clk_hw *hw)
140-
{
141-
struct sd_clock *clock = to_sd_clock(hw);
142-
143-
cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK,
144-
clock->div_table[clock->cur_div_idx].val &
145-
CPG_SD_STP_MASK);
146-
147-
return 0;
148-
}
149-
150-
static void cpg_sd_clock_disable(struct clk_hw *hw)
151-
{
152-
struct sd_clock *clock = to_sd_clock(hw);
153-
154-
cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK);
155-
}
156-
157-
static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
77+
struct clk * __init cpg_sdh_clk_register(const char *name,
78+
void __iomem *sdnckcr, const char *parent_name,
79+
struct raw_notifier_head *notifiers)
15880
{
159-
struct sd_clock *clock = to_sd_clock(hw);
160-
161-
return !(readl(clock->csn.reg) & CPG_SD_STP_MASK);
162-
}
81+
struct cpg_simple_notifier *csn;
82+
struct clk *clk;
16383

164-
static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
165-
unsigned long parent_rate)
166-
{
167-
struct sd_clock *clock = to_sd_clock(hw);
84+
csn = kzalloc(sizeof(*csn), GFP_KERNEL);
85+
if (!csn)
86+
return ERR_PTR(-ENOMEM);
16887

169-
return DIV_ROUND_CLOSEST(parent_rate,
170-
clock->div_table[clock->cur_div_idx].div);
171-
}
88+
csn->reg = sdnckcr;
17289

173-
static int cpg_sd_clock_determine_rate(struct clk_hw *hw,
174-
struct clk_rate_request *req)
175-
{
176-
unsigned long best_rate = ULONG_MAX, diff_min = ULONG_MAX;
177-
struct sd_clock *clock = to_sd_clock(hw);
178-
unsigned long calc_rate, diff;
179-
unsigned int i;
180-
181-
for (i = 0; i < clock->div_num; i++) {
182-
calc_rate = DIV_ROUND_CLOSEST(req->best_parent_rate,
183-
clock->div_table[i].div);
184-
if (calc_rate < req->min_rate || calc_rate > req->max_rate)
185-
continue;
186-
187-
diff = calc_rate > req->rate ? calc_rate - req->rate
188-
: req->rate - calc_rate;
189-
if (diff < diff_min) {
190-
best_rate = calc_rate;
191-
diff_min = diff;
192-
}
90+
clk = clk_register_divider_table(NULL, name, parent_name, 0, sdnckcr,
91+
SDnSRCFC_SHIFT, 8, 0, cpg_sdh_div_table,
92+
&cpg_lock);
93+
if (IS_ERR(clk)) {
94+
kfree(csn);
95+
return clk;
19396
}
19497

195-
if (best_rate == ULONG_MAX)
196-
return -EINVAL;
197-
198-
req->rate = best_rate;
199-
return 0;
200-
}
201-
202-
static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
203-
unsigned long parent_rate)
204-
{
205-
struct sd_clock *clock = to_sd_clock(hw);
206-
unsigned int i;
207-
208-
for (i = 0; i < clock->div_num; i++)
209-
if (rate == DIV_ROUND_CLOSEST(parent_rate,
210-
clock->div_table[i].div))
211-
break;
212-
213-
if (i >= clock->div_num)
214-
return -EINVAL;
215-
216-
clock->cur_div_idx = i;
217-
218-
cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK,
219-
clock->div_table[i].val &
220-
(CPG_SD_STP_MASK | CPG_SD_FC_MASK));
221-
222-
return 0;
98+
cpg_simple_notifier_register(notifiers, csn);
99+
return clk;
223100
}
224101

225-
static const struct clk_ops cpg_sd_clock_ops = {
226-
.enable = cpg_sd_clock_enable,
227-
.disable = cpg_sd_clock_disable,
228-
.is_enabled = cpg_sd_clock_is_enabled,
229-
.recalc_rate = cpg_sd_clock_recalc_rate,
230-
.determine_rate = cpg_sd_clock_determine_rate,
231-
.set_rate = cpg_sd_clock_set_rate,
102+
static const struct clk_div_table cpg_sd_div_table[] = {
103+
{ 0, 2 }, { 1, 4 }, { 0, 0 },
232104
};
233105

234106
struct clk * __init cpg_sd_clk_register(const char *name,
235-
void __iomem *base, unsigned int offset, const char *parent_name,
236-
struct raw_notifier_head *notifiers, bool skip_first)
107+
void __iomem *sdnckcr, const char *parent_name)
237108
{
238-
struct clk_init_data init = {};
239-
struct sd_clock *clock;
240-
struct clk *clk;
241-
u32 val;
242-
243-
clock = kzalloc(sizeof(*clock), GFP_KERNEL);
244-
if (!clock)
245-
return ERR_PTR(-ENOMEM);
246-
247-
init.name = name;
248-
init.ops = &cpg_sd_clock_ops;
249-
init.flags = CLK_SET_RATE_PARENT;
250-
init.parent_names = &parent_name;
251-
init.num_parents = 1;
252-
253-
clock->csn.reg = base + offset;
254-
clock->hw.init = &init;
255-
clock->div_table = cpg_sd_div_table;
256-
clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
257-
258-
if (skip_first) {
259-
clock->div_table++;
260-
clock->div_num--;
261-
}
262-
263-
val = readl(clock->csn.reg) & ~CPG_SD_FC_MASK;
264-
val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK);
265-
writel(val, clock->csn.reg);
266-
267-
clk = clk_register(NULL, &clock->hw);
268-
if (IS_ERR(clk))
269-
goto free_clock;
270-
271-
cpg_simple_notifier_register(notifiers, &clock->csn);
272-
return clk;
273-
274-
free_clock:
275-
kfree(clock);
276-
return clk;
109+
return clk_register_divider_table(NULL, name, parent_name, 0, sdnckcr,
110+
0, 2, 0, cpg_sd_div_table, &cpg_lock);
277111
}
278112

279113
struct rpc_clock {

drivers/clk/renesas/rcar-cpg-lib.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ struct clk * __init cpg_sdh_clk_register(const char *name,
3131
struct raw_notifier_head *notifiers);
3232

3333
struct clk * __init cpg_sd_clk_register(const char *name,
34-
void __iomem *base, unsigned int offset, const char *parent_name,
35-
struct raw_notifier_head *notifiers, bool skip_first);
34+
void __iomem *sdnckcr, const char *parent_name);
3635

3736
struct clk * __init cpg_rpc_clk_register(const char *name,
3837
void __iomem *rpcckcr, const char *parent_name,

drivers/clk/renesas/rcar-gen3-cpg.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -406,9 +406,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
406406
__clk_get_name(parent), notifiers);
407407

408408
case CLK_TYPE_GEN3_SD:
409-
return cpg_sd_clk_register(core->name, base, core->offset,
410-
__clk_get_name(parent), notifiers,
411-
cpg_quirks & SD_SKIP_FIRST);
409+
return cpg_sd_clk_register(core->name, base + core->offset,
410+
__clk_get_name(parent));
412411

413412
case CLK_TYPE_GEN3_R:
414413
if (cpg_quirks & RCKCR_CKSEL) {

drivers/mmc/host/renesas_sdhi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct tmio_mmc_dma {
6060

6161
struct renesas_sdhi {
6262
struct clk *clk;
63+
struct clk *clkh;
6364
struct clk *clk_cd;
6465
struct tmio_mmc_data mmc_data;
6566
struct tmio_mmc_dma dma_priv;

drivers/mmc/host/renesas_sdhi_core.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,12 @@ static int renesas_sdhi_clk_enable(struct tmio_mmc_host *host)
127127
}
128128

129129
static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
130-
unsigned int new_clock)
130+
unsigned int wanted_clock)
131131
{
132132
struct renesas_sdhi *priv = host_to_priv(host);
133+
struct clk *ref_clk = priv->clk;
133134
unsigned int freq, diff, best_freq = 0, diff_min = ~0;
135+
unsigned int new_clock, clkh_shift = 0;
134136
int i;
135137

136138
/*
@@ -141,18 +143,27 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
141143
if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2) || mmc_doing_tune(host->mmc))
142144
return clk_get_rate(priv->clk);
143145

146+
if (priv->clkh) {
147+
bool use_4tap = priv->quirks && priv->quirks->hs400_4taps;
148+
bool need_slow_clkh = (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104) ||
149+
(host->mmc->ios.timing == MMC_TIMING_MMC_HS400);
150+
clkh_shift = use_4tap && need_slow_clkh ? 1 : 2;
151+
ref_clk = priv->clkh;
152+
}
153+
154+
new_clock = wanted_clock << clkh_shift;
155+
144156
/*
145157
* We want the bus clock to be as close as possible to, but no
146158
* greater than, new_clock. As we can divide by 1 << i for
147159
* any i in [0, 9] we want the input clock to be as close as
148160
* possible, but no greater than, new_clock << i.
149161
*/
150162
for (i = min(9, ilog2(UINT_MAX / new_clock)); i >= 0; i--) {
151-
freq = clk_round_rate(priv->clk, new_clock << i);
163+
freq = clk_round_rate(ref_clk, new_clock << i);
152164
if (freq > (new_clock << i)) {
153165
/* Too fast; look for a slightly slower option */
154-
freq = clk_round_rate(priv->clk,
155-
(new_clock << i) / 4 * 3);
166+
freq = clk_round_rate(ref_clk, (new_clock << i) / 4 * 3);
156167
if (freq > (new_clock << i))
157168
continue;
158169
}
@@ -164,7 +175,10 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host,
164175
}
165176
}
166177

167-
clk_set_rate(priv->clk, best_freq);
178+
clk_set_rate(ref_clk, best_freq);
179+
180+
if (priv->clkh)
181+
clk_set_rate(priv->clk, best_freq >> clkh_shift);
168182

169183
return clk_get_rate(priv->clk);
170184
}
@@ -947,6 +961,10 @@ int renesas_sdhi_probe(struct platform_device *pdev,
947961
mmc_data->max_segs = of_data->max_segs;
948962
dma_priv->dma_buswidth = of_data->dma_buswidth;
949963
host->bus_shift = of_data->bus_shift;
964+
/* Fallback for old DTs */
965+
if (of_data->sdhi_flags & SDHI_FLAG_NEED_CLKH_FALLBACK)
966+
priv->clkh = clk_get_parent(clk_get_parent(priv->clk));
967+
950968
}
951969

952970
host->write16_hook = renesas_sdhi_write16_hook;

0 commit comments

Comments
 (0)