Skip to content

Commit 56242a1

Browse files
morimotopmundt
authored andcommitted
sh: clkfwk: setup clock parent from current register value
Some clocks can select its parent clock by CPG register. But it might have been modified by boot-loader or something. This patch removed fixed initial parent clock, and setup it from their current register settings. It works on div6 reparent clocks for now. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
1 parent a9098b3 commit 56242a1

4 files changed

Lines changed: 46 additions & 8 deletions

File tree

arch/arm/mach-shmobile/clock-sh7372.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,11 +411,11 @@ static struct clk *fsibckcr_parent[] = {
411411
};
412412

413413
static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
414-
[DIV6_HDMI] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, HDMICKCR, 0,
414+
[DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0,
415415
hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
416-
[DIV6_FSIA] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, FSIACKCR, 0,
416+
[DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0,
417417
fsiackcr_parent, ARRAY_SIZE(fsiackcr_parent), 6, 2),
418-
[DIV6_FSIB] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, FSIBCKCR, 0,
418+
[DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0,
419419
fsibckcr_parent, ARRAY_SIZE(fsibckcr_parent), 6, 2),
420420
};
421421

arch/sh/kernel/cpu/sh4a/clock-sh7724.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ static struct clk *fclkbcr_parent[] = {
189189
};
190190

191191
static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
192-
[DIV6_FA] = SH_CLK_DIV6_EXT(&div3_clk, FCLKACR, 0,
192+
[DIV6_FA] = SH_CLK_DIV6_EXT(FCLKACR, 0,
193193
fclkacr_parent, ARRAY_SIZE(fclkacr_parent), 6, 2),
194-
[DIV6_FB] = SH_CLK_DIV6_EXT(&div3_clk, FCLKBCR, 0,
194+
[DIV6_FB] = SH_CLK_DIV6_EXT(FCLKBCR, 0,
195195
fclkbcr_parent, ARRAY_SIZE(fclkbcr_parent), 6, 2),
196196
};
197197

drivers/sh/clk/cpg.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,38 @@ static struct clk_ops sh_clk_div6_reparent_clk_ops = {
167167
.set_parent = sh_clk_div6_set_parent,
168168
};
169169

170+
static int __init sh_clk_init_parent(struct clk *clk)
171+
{
172+
u32 val;
173+
174+
if (clk->parent)
175+
return 0;
176+
177+
if (!clk->parent_table || !clk->parent_num)
178+
return 0;
179+
180+
if (!clk->src_width) {
181+
pr_err("sh_clk_init_parent: cannot select parent clock\n");
182+
return -EINVAL;
183+
}
184+
185+
val = (__raw_readl(clk->enable_reg) >> clk->src_shift);
186+
val &= (1 << clk->src_width) - 1;
187+
188+
if (val >= clk->parent_num) {
189+
pr_err("sh_clk_init_parent: parent table size failed\n");
190+
return -EINVAL;
191+
}
192+
193+
clk->parent = clk->parent_table[val];
194+
if (!clk->parent) {
195+
pr_err("sh_clk_init_parent: unable to set parent");
196+
return -EINVAL;
197+
}
198+
199+
return 0;
200+
}
201+
170202
static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
171203
struct clk_ops *ops)
172204
{
@@ -190,6 +222,9 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
190222
clkp->ops = ops;
191223
clkp->freq_table = freq_table + (k * freq_table_size);
192224
clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
225+
ret = sh_clk_init_parent(clkp);
226+
if (ret < 0)
227+
break;
193228

194229
ret = clk_register(clkp);
195230
}

include/linux/sh_clk.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,9 @@ int sh_clk_div4_enable_register(struct clk *clks, int nr,
131131
int sh_clk_div4_reparent_register(struct clk *clks, int nr,
132132
struct clk_div4_table *table);
133133

134-
#define SH_CLK_DIV6_EXT(_parent, _reg, _flags, _parents, \
134+
#define SH_CLK_DIV6_EXT(_reg, _flags, _parents, \
135135
_num_parents, _src_shift, _src_width) \
136136
{ \
137-
.parent = _parent, \
138137
.enable_reg = (void __iomem *)_reg, \
139138
.flags = _flags, \
140139
.parent_table = _parents, \
@@ -144,7 +143,11 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
144143
}
145144

146145
#define SH_CLK_DIV6(_parent, _reg, _flags) \
147-
SH_CLK_DIV6_EXT(_parent, _reg, _flags, NULL, 0, 0, 0)
146+
{ \
147+
.parent = _parent, \
148+
.enable_reg = (void __iomem *)_reg, \
149+
.flags = _flags, \
150+
}
148151

149152
int sh_clk_div6_register(struct clk *clks, int nr);
150153
int sh_clk_div6_reparent_register(struct clk *clks, int nr);

0 commit comments

Comments
 (0)