Skip to content

Commit 249592b

Browse files
pcercueibebarino
authored andcommitted
clk: Support bypassing dividers
When a clock is declared as both CGU_CLK_DIV and CGU_CLK_MUX, the CGU code expects the mux to be applied first, the divider second. On the JZ4760, and maybe on some other SoCs, some clocks also have a mux setting and a divider, but the divider is not applied to all parents selectable from the mux. This could be solved by creating two clocks, one with CGU_CLK_DIV and one with CGU_CLK_MUX, but that would increase the number of clocks. Instead, add a 8-bit mask to CGU_CLK_DIV clocks. If the bit corresponding to the parent clock's index is set, the divider is bypassed. Signed-off-by: Paul Cercueil <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Stephen Boyd <[email protected]>
1 parent 2e1ae04 commit 249592b

File tree

5 files changed

+42
-29
lines changed

5 files changed

+42
-29
lines changed

drivers/clk/ingenic/cgu.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -369,18 +369,23 @@ ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
369369
struct ingenic_cgu *cgu = ingenic_clk->cgu;
370370
unsigned long rate = parent_rate;
371371
u32 div_reg, div;
372+
u8 parent;
372373

373374
if (clk_info->type & CGU_CLK_DIV) {
374-
div_reg = readl(cgu->base + clk_info->div.reg);
375-
div = (div_reg >> clk_info->div.shift) &
376-
GENMASK(clk_info->div.bits - 1, 0);
375+
parent = ingenic_clk_get_parent(hw);
377376

378-
if (clk_info->div.div_table)
379-
div = clk_info->div.div_table[div];
380-
else
381-
div = (div + 1) * clk_info->div.div;
377+
if (!(clk_info->div.bypass_mask & BIT(parent))) {
378+
div_reg = readl(cgu->base + clk_info->div.reg);
379+
div = (div_reg >> clk_info->div.shift) &
380+
GENMASK(clk_info->div.bits - 1, 0);
381+
382+
if (clk_info->div.div_table)
383+
div = clk_info->div.div_table[div];
384+
else
385+
div = (div + 1) * clk_info->div.div;
382386

383-
rate /= div;
387+
rate /= div;
388+
}
384389
} else if (clk_info->type & CGU_CLK_FIXDIV) {
385390
rate /= clk_info->fixdiv.div;
386391
}
@@ -410,10 +415,16 @@ ingenic_clk_calc_hw_div(const struct ingenic_cgu_clk_info *clk_info,
410415
}
411416

412417
static unsigned
413-
ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info,
418+
ingenic_clk_calc_div(struct clk_hw *hw,
419+
const struct ingenic_cgu_clk_info *clk_info,
414420
unsigned long parent_rate, unsigned long req_rate)
415421
{
416422
unsigned int div, hw_div;
423+
u8 parent;
424+
425+
parent = ingenic_clk_get_parent(hw);
426+
if (clk_info->div.bypass_mask & BIT(parent))
427+
return 1;
417428

418429
/* calculate the divide */
419430
div = DIV_ROUND_UP(parent_rate, req_rate);
@@ -448,7 +459,7 @@ ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate,
448459
unsigned int div = 1;
449460

450461
if (clk_info->type & CGU_CLK_DIV)
451-
div = ingenic_clk_calc_div(clk_info, *parent_rate, req_rate);
462+
div = ingenic_clk_calc_div(hw, clk_info, *parent_rate, req_rate);
452463
else if (clk_info->type & CGU_CLK_FIXDIV)
453464
div = clk_info->fixdiv.div;
454465
else if (clk_hw_can_set_rate_parent(hw))
@@ -480,7 +491,7 @@ ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate,
480491
int ret = 0;
481492

482493
if (clk_info->type & CGU_CLK_DIV) {
483-
div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate);
494+
div = ingenic_clk_calc_div(hw, clk_info, parent_rate, req_rate);
484495
rate = DIV_ROUND_UP(parent_rate, div);
485496

486497
if (rate != req_rate)

drivers/clk/ingenic/cgu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ struct ingenic_cgu_mux_info {
8484
* isn't one
8585
* @busy_bit: the index of the busy bit within reg, or -1 if there isn't one
8686
* @stop_bit: the index of the stop bit within reg, or -1 if there isn't one
87+
* @bypass_mask: mask of parent clocks for which the divider does not apply
8788
* @div_table: optional table to map the value read from the register to the
8889
* actual divider value
8990
*/
@@ -95,6 +96,7 @@ struct ingenic_cgu_div_info {
9596
s8 ce_bit;
9697
s8 busy_bit;
9798
s8 stop_bit;
99+
u8 bypass_mask;
98100
const u8 *div_table;
99101
};
100102

drivers/clk/ingenic/jz4725b-cgu.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
8080
"pll half", CGU_CLK_DIV,
8181
.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
8282
.div = {
83-
CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1,
83+
CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0,
8484
jz4725b_cgu_pll_half_div_table,
8585
},
8686
},
@@ -89,7 +89,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
8989
"cclk", CGU_CLK_DIV,
9090
.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
9191
.div = {
92-
CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1,
92+
CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
9393
jz4725b_cgu_cpccr_div_table,
9494
},
9595
},
@@ -98,7 +98,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
9898
"hclk", CGU_CLK_DIV,
9999
.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
100100
.div = {
101-
CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1,
101+
CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
102102
jz4725b_cgu_cpccr_div_table,
103103
},
104104
},
@@ -107,7 +107,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
107107
"pclk", CGU_CLK_DIV,
108108
.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
109109
.div = {
110-
CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1,
110+
CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
111111
jz4725b_cgu_cpccr_div_table,
112112
},
113113
},
@@ -116,7 +116,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
116116
"mclk", CGU_CLK_DIV,
117117
.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
118118
.div = {
119-
CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1,
119+
CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
120120
jz4725b_cgu_cpccr_div_table,
121121
},
122122
},
@@ -125,7 +125,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
125125
"ipu", CGU_CLK_DIV | CGU_CLK_GATE,
126126
.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
127127
.div = {
128-
CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1,
128+
CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,
129129
jz4725b_cgu_cpccr_div_table,
130130
},
131131
.gate = { CGU_REG_CLKGR, 13 },

drivers/clk/ingenic/jz4740-cgu.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
9595
"pll half", CGU_CLK_DIV,
9696
.parents = { JZ4740_CLK_PLL, -1, -1, -1 },
9797
.div = {
98-
CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1,
98+
CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0,
9999
jz4740_cgu_pll_half_div_table,
100100
},
101101
},
@@ -104,7 +104,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
104104
"cclk", CGU_CLK_DIV,
105105
.parents = { JZ4740_CLK_PLL, -1, -1, -1 },
106106
.div = {
107-
CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1,
107+
CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
108108
jz4740_cgu_cpccr_div_table,
109109
},
110110
},
@@ -113,7 +113,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
113113
"hclk", CGU_CLK_DIV,
114114
.parents = { JZ4740_CLK_PLL, -1, -1, -1 },
115115
.div = {
116-
CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1,
116+
CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
117117
jz4740_cgu_cpccr_div_table,
118118
},
119119
},
@@ -122,7 +122,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
122122
"pclk", CGU_CLK_DIV,
123123
.parents = { JZ4740_CLK_PLL, -1, -1, -1 },
124124
.div = {
125-
CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1,
125+
CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
126126
jz4740_cgu_cpccr_div_table,
127127
},
128128
},
@@ -131,7 +131,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
131131
"mclk", CGU_CLK_DIV,
132132
.parents = { JZ4740_CLK_PLL, -1, -1, -1 },
133133
.div = {
134-
CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1,
134+
CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
135135
jz4740_cgu_cpccr_div_table,
136136
},
137137
},
@@ -140,7 +140,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
140140
"lcd", CGU_CLK_DIV | CGU_CLK_GATE,
141141
.parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
142142
.div = {
143-
CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1,
143+
CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1, 0,
144144
jz4740_cgu_cpccr_div_table,
145145
},
146146
.gate = { CGU_REG_CLKGR, 10 },

drivers/clk/ingenic/jz4770-cgu.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,23 +152,23 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
152152
"cclk", CGU_CLK_DIV,
153153
.parents = { JZ4770_CLK_PLL0, },
154154
.div = {
155-
CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1,
155+
CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
156156
jz4770_cgu_cpccr_div_table,
157157
},
158158
},
159159
[JZ4770_CLK_H0CLK] = {
160160
"h0clk", CGU_CLK_DIV,
161161
.parents = { JZ4770_CLK_PLL0, },
162162
.div = {
163-
CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1,
163+
CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
164164
jz4770_cgu_cpccr_div_table,
165165
},
166166
},
167167
[JZ4770_CLK_H1CLK] = {
168168
"h1clk", CGU_CLK_DIV | CGU_CLK_GATE,
169169
.parents = { JZ4770_CLK_PLL0, },
170170
.div = {
171-
CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1,
171+
CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, 0,
172172
jz4770_cgu_cpccr_div_table,
173173
},
174174
.gate = { CGU_REG_CLKGR1, 7 },
@@ -177,15 +177,15 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
177177
"h2clk", CGU_CLK_DIV,
178178
.parents = { JZ4770_CLK_PLL0, },
179179
.div = {
180-
CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1,
180+
CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,
181181
jz4770_cgu_cpccr_div_table,
182182
},
183183
},
184184
[JZ4770_CLK_C1CLK] = {
185185
"c1clk", CGU_CLK_DIV | CGU_CLK_GATE,
186186
.parents = { JZ4770_CLK_PLL0, },
187187
.div = {
188-
CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1,
188+
CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
189189
jz4770_cgu_cpccr_div_table,
190190
},
191191
.gate = { CGU_REG_OPCR, 31, true }, // disable CCLK stop on idle
@@ -194,7 +194,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
194194
"pclk", CGU_CLK_DIV,
195195
.parents = { JZ4770_CLK_PLL0, },
196196
.div = {
197-
CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1,
197+
CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
198198
jz4770_cgu_cpccr_div_table,
199199
},
200200
},

0 commit comments

Comments
 (0)