Skip to content

Commit 6435c49

Browse files
committed
Merge tag 'renesas-clk-for-v5.14-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers into clk-renesas
Pull Renesas clk driver updates from Geert Uytterhoeven: - Add support for CPU core clock boost modes on R-Car Gen3 - Add ISPCS (Image Signal Processor) clocks on R-Car V3U - Switch SH/R-Mobile and R-Car "DIV6" clocks to .determine_rate() and improve support for multiple parents - Switch RZ/N1 divider clocks to .determine_rate() - Add ZA2 (Audio Clock Generator) clock on R-Car D3 - Minor fixes and improvements * tag 'renesas-clk-for-v5.14-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers: clk: renesas: r8a77995: Add ZA2 clock clk: renesas: cpg-mssr: Make srstclr[] comment block consistent clk: renesas: cpg-mssr: Remove unused [RM]MSTPCR() definitions clk: renesas: r9a06g032: Switch to .determine_rate() clk: renesas: div6: Implement range checking clk: renesas: div6: Consider all parents for requested rate clk: renesas: div6: Switch to .determine_rate() clk: renesas: div6: Simplify src mask handling clk: renesas: div6: Use clamp() instead of clamp_t() clk: renesas: rcar-usb2-clock-sel: Fix error handling in .probe() clk: renesas: r8a779a0: Add ISPCS clocks clk: renesas: rcar-gen3: Add boost support to Z clocks clk: renesas: rcar-gen3: Add custom clock for PLLs clk: renesas: rcar-gen3: Increase Z clock accuracy clk: renesas: rcar-gen3: Grammar s/dependent of/dependent on/ clk: renesas: rcar-gen3: Remove superfluous masking in cpg_z_clk_set_rate() clk: renesas: rcar-gen3: Make cpg_z_clk.mask u32 clk: renesas: rcar-gen3: Update Z clock rate formula in comments
2 parents 6efb943 + 790c06c commit 6435c49

File tree

7 files changed

+244
-83
lines changed

7 files changed

+244
-83
lines changed

drivers/clk/renesas/clk-div6.c

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,15 @@
2828
* @hw: handle between common and hardware-specific interfaces
2929
* @reg: IO-remapped register
3030
* @div: divisor value (1-64)
31-
* @src_shift: Shift to access the register bits to select the parent clock
32-
* @src_width: Number of register bits to select the parent clock (may be 0)
31+
* @src_mask: Bitmask covering the register bits to select the parent clock
3332
* @nb: Notifier block to save/restore clock state for system resume
3433
* @parents: Array to map from valid parent clocks indices to hardware indices
3534
*/
3635
struct div6_clock {
3736
struct clk_hw hw;
3837
void __iomem *reg;
3938
unsigned int div;
40-
u32 src_shift;
41-
u32 src_width;
39+
u32 src_mask;
4240
struct notifier_block nb;
4341
u8 parents[];
4442
};
@@ -99,15 +97,52 @@ static unsigned int cpg_div6_clock_calc_div(unsigned long rate,
9997
rate = 1;
10098

10199
div = DIV_ROUND_CLOSEST(parent_rate, rate);
102-
return clamp_t(unsigned int, div, 1, 64);
100+
return clamp(div, 1U, 64U);
103101
}
104102

105-
static long cpg_div6_clock_round_rate(struct clk_hw *hw, unsigned long rate,
106-
unsigned long *parent_rate)
103+
static int cpg_div6_clock_determine_rate(struct clk_hw *hw,
104+
struct clk_rate_request *req)
107105
{
108-
unsigned int div = cpg_div6_clock_calc_div(rate, *parent_rate);
106+
unsigned long prate, calc_rate, diff, best_rate, best_prate;
107+
unsigned int num_parents = clk_hw_get_num_parents(hw);
108+
struct clk_hw *parent, *best_parent = NULL;
109+
unsigned int i, min_div, max_div, div;
110+
unsigned long min_diff = ULONG_MAX;
111+
112+
for (i = 0; i < num_parents; i++) {
113+
parent = clk_hw_get_parent_by_index(hw, i);
114+
if (!parent)
115+
continue;
116+
117+
prate = clk_hw_get_rate(parent);
118+
if (!prate)
119+
continue;
120+
121+
min_div = max(DIV_ROUND_UP(prate, req->max_rate), 1UL);
122+
max_div = req->min_rate ? min(prate / req->min_rate, 64UL) : 64;
123+
if (max_div < min_div)
124+
continue;
125+
126+
div = cpg_div6_clock_calc_div(req->rate, prate);
127+
div = clamp(div, min_div, max_div);
128+
calc_rate = prate / div;
129+
diff = calc_rate > req->rate ? calc_rate - req->rate
130+
: req->rate - calc_rate;
131+
if (diff < min_diff) {
132+
best_rate = calc_rate;
133+
best_parent = parent;
134+
best_prate = prate;
135+
min_diff = diff;
136+
}
137+
}
138+
139+
if (!best_parent)
140+
return -EINVAL;
109141

110-
return *parent_rate / div;
142+
req->best_parent_rate = best_prate;
143+
req->best_parent_hw = best_parent;
144+
req->rate = best_rate;
145+
return 0;
111146
}
112147

113148
static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -133,11 +168,11 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw)
133168
unsigned int i;
134169
u8 hw_index;
135170

136-
if (clock->src_width == 0)
171+
if (clock->src_mask == 0)
137172
return 0;
138173

139-
hw_index = (readl(clock->reg) >> clock->src_shift) &
140-
(BIT(clock->src_width) - 1);
174+
hw_index = (readl(clock->reg) & clock->src_mask) >>
175+
__ffs(clock->src_mask);
141176
for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
142177
if (clock->parents[i] == hw_index)
143178
return i;
@@ -151,18 +186,13 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw)
151186
static int cpg_div6_clock_set_parent(struct clk_hw *hw, u8 index)
152187
{
153188
struct div6_clock *clock = to_div6_clock(hw);
154-
u8 hw_index;
155-
u32 mask;
189+
u32 src;
156190

157191
if (index >= clk_hw_get_num_parents(hw))
158192
return -EINVAL;
159193

160-
mask = ~((BIT(clock->src_width) - 1) << clock->src_shift);
161-
hw_index = clock->parents[index];
162-
163-
writel((readl(clock->reg) & mask) | (hw_index << clock->src_shift),
164-
clock->reg);
165-
194+
src = clock->parents[index] << __ffs(clock->src_mask);
195+
writel((readl(clock->reg) & ~clock->src_mask) | src, clock->reg);
166196
return 0;
167197
}
168198

@@ -173,7 +203,7 @@ static const struct clk_ops cpg_div6_clock_ops = {
173203
.get_parent = cpg_div6_clock_get_parent,
174204
.set_parent = cpg_div6_clock_set_parent,
175205
.recalc_rate = cpg_div6_clock_recalc_rate,
176-
.round_rate = cpg_div6_clock_round_rate,
206+
.determine_rate = cpg_div6_clock_determine_rate,
177207
.set_rate = cpg_div6_clock_set_rate,
178208
};
179209

@@ -236,17 +266,15 @@ struct clk * __init cpg_div6_register(const char *name,
236266
switch (num_parents) {
237267
case 1:
238268
/* fixed parent clock */
239-
clock->src_shift = clock->src_width = 0;
269+
clock->src_mask = 0;
240270
break;
241271
case 4:
242272
/* clock with EXSRC bits 6-7 */
243-
clock->src_shift = 6;
244-
clock->src_width = 2;
273+
clock->src_mask = GENMASK(7, 6);
245274
break;
246275
case 8:
247276
/* VCLK with EXSRC bits 12-14 */
248-
clock->src_shift = 12;
249-
clock->src_width = 3;
277+
clock->src_mask = GENMASK(14, 12);
250278
break;
251279
default:
252280
pr_err("%s: invalid number of parents for DIV6 clock %s\n",

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = {
7575
DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000),
7676

7777
/* Core Clock Outputs */
78+
DEF_FIXED("za2", R8A77995_CLK_ZA2, CLK_PLL0D3, 2, 1),
7879
DEF_FIXED("z2", R8A77995_CLK_Z2, CLK_PLL0D3, 1, 1),
7980
DEF_FIXED("ztr", R8A77995_CLK_ZTR, CLK_PLL1, 6, 1),
8081
DEF_FIXED("zt", R8A77995_CLK_ZT, CLK_PLL1, 4, 1),

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
180180
DEF_MOD("i2c4", 522, R8A779A0_CLK_S1D4),
181181
DEF_MOD("i2c5", 523, R8A779A0_CLK_S1D4),
182182
DEF_MOD("i2c6", 524, R8A779A0_CLK_S1D4),
183+
DEF_MOD("ispcs0", 612, R8A779A0_CLK_S1D1),
184+
DEF_MOD("ispcs1", 613, R8A779A0_CLK_S1D1),
185+
DEF_MOD("ispcs2", 614, R8A779A0_CLK_S1D1),
186+
DEF_MOD("ispcs3", 615, R8A779A0_CLK_S1D1),
183187
DEF_MOD("msi0", 618, R8A779A0_CLK_MSO),
184188
DEF_MOD("msi1", 619, R8A779A0_CLK_MSO),
185189
DEF_MOD("msi2", 620, R8A779A0_CLK_MSO),

drivers/clk/renesas/r9a06g032-clocks.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -604,20 +604,19 @@ r9a06g032_div_clamp_div(struct r9a06g032_clk_div *clk,
604604
return div;
605605
}
606606

607-
static long
608-
r9a06g032_div_round_rate(struct clk_hw *hw,
609-
unsigned long rate, unsigned long *prate)
607+
static int
608+
r9a06g032_div_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
610609
{
611610
struct r9a06g032_clk_div *clk = to_r9a06g032_div(hw);
612-
u32 div = DIV_ROUND_UP(*prate, rate);
611+
u32 div = DIV_ROUND_UP(req->best_parent_rate, req->rate);
613612

614613
pr_devel("%s %pC %ld (prate %ld) (wanted div %u)\n", __func__,
615-
hw->clk, rate, *prate, div);
614+
hw->clk, req->rate, req->best_parent_rate, div);
616615
pr_devel(" min %d (%ld) max %d (%ld)\n",
617-
clk->min, DIV_ROUND_UP(*prate, clk->min),
618-
clk->max, DIV_ROUND_UP(*prate, clk->max));
616+
clk->min, DIV_ROUND_UP(req->best_parent_rate, clk->min),
617+
clk->max, DIV_ROUND_UP(req->best_parent_rate, clk->max));
619618

620-
div = r9a06g032_div_clamp_div(clk, rate, *prate);
619+
div = r9a06g032_div_clamp_div(clk, req->rate, req->best_parent_rate);
621620
/*
622621
* this is a hack. Currently the serial driver asks for a clock rate
623622
* that is 16 times the baud rate -- and that is wildly outside the
@@ -630,11 +629,13 @@ r9a06g032_div_round_rate(struct clk_hw *hw,
630629
if (clk->index == R9A06G032_DIV_UART ||
631630
clk->index == R9A06G032_DIV_P2_PG) {
632631
pr_devel("%s div uart hack!\n", __func__);
633-
return clk_get_rate(hw->clk);
632+
req->rate = clk_get_rate(hw->clk);
633+
return 0;
634634
}
635+
req->rate = DIV_ROUND_UP(req->best_parent_rate, div);
635636
pr_devel("%s %pC %ld / %u = %ld\n", __func__, hw->clk,
636-
*prate, div, DIV_ROUND_UP(*prate, div));
637-
return DIV_ROUND_UP(*prate, div);
637+
req->best_parent_rate, div, req->rate);
638+
return 0;
638639
}
639640

640641
static int
@@ -663,7 +664,7 @@ r9a06g032_div_set_rate(struct clk_hw *hw,
663664

664665
static const struct clk_ops r9a06g032_clk_div_ops = {
665666
.recalc_rate = r9a06g032_div_recalc_rate,
666-
.round_rate = r9a06g032_div_round_rate,
667+
.determine_rate = r9a06g032_div_determine_rate,
667668
.set_rate = r9a06g032_div_set_rate,
668669
};
669670

0 commit comments

Comments
 (0)