Skip to content

Commit 99d01e0

Browse files
shenkibebarino
authored andcommitted
clk: aspeed: Register core clocks
This registers the core clocks; those which are required to calculate the rate of the timer peripheral so the system can load a clocksource driver. Reviewed-by: Andrew Jeffery <[email protected]> Signed-off-by: Joel Stanley <[email protected]> Reviewed-by: Benjamin Herrenschmidt <[email protected]> Signed-off-by: Stephen Boyd <[email protected]>
1 parent 5eda5d7 commit 99d01e0

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed

drivers/clk/clk-aspeed.c

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,23 @@
1313

1414
#define ASPEED_NUM_CLKS 35
1515

16+
#define ASPEED_RESET_CTRL 0x04
17+
#define ASPEED_CLK_SELECTION 0x08
18+
#define ASPEED_CLK_STOP_CTRL 0x0c
19+
#define ASPEED_MPLL_PARAM 0x20
20+
#define ASPEED_HPLL_PARAM 0x24
21+
#define AST2500_HPLL_BYPASS_EN BIT(20)
22+
#define AST2400_HPLL_STRAPPED BIT(18)
23+
#define AST2400_HPLL_BYPASS_EN BIT(17)
24+
#define ASPEED_MISC_CTRL 0x2c
25+
#define UART_DIV13_EN BIT(12)
1626
#define ASPEED_STRAP 0x70
27+
#define CLKIN_25MHZ_EN BIT(23)
28+
#define AST2400_CLK_SOURCE_SEL BIT(18)
29+
#define ASPEED_CLK_SELECTION_2 0xd8
30+
31+
/* Globally visible clocks */
32+
static DEFINE_SPINLOCK(aspeed_clk_lock);
1733

1834
/* Keeps track of all clocks */
1935
static struct clk_hw_onecell_data *aspeed_clk_data;
@@ -91,6 +107,160 @@ static const struct aspeed_gate_data aspeed_gates[] = {
91107
[ASPEED_CLK_GATE_LHCCLK] = { 28, -1, "lhclk-gate", "lhclk", 0 }, /* LPC master/LPC+ */
92108
};
93109

110+
static const struct clk_div_table ast2400_div_table[] = {
111+
{ 0x0, 2 },
112+
{ 0x1, 4 },
113+
{ 0x2, 6 },
114+
{ 0x3, 8 },
115+
{ 0x4, 10 },
116+
{ 0x5, 12 },
117+
{ 0x6, 14 },
118+
{ 0x7, 16 },
119+
{ 0 }
120+
};
121+
122+
static const struct clk_div_table ast2500_div_table[] = {
123+
{ 0x0, 4 },
124+
{ 0x1, 8 },
125+
{ 0x2, 12 },
126+
{ 0x3, 16 },
127+
{ 0x4, 20 },
128+
{ 0x5, 24 },
129+
{ 0x6, 28 },
130+
{ 0x7, 32 },
131+
{ 0 }
132+
};
133+
134+
static struct clk_hw *aspeed_ast2400_calc_pll(const char *name, u32 val)
135+
{
136+
unsigned int mult, div;
137+
138+
if (val & AST2400_HPLL_BYPASS_EN) {
139+
/* Pass through mode */
140+
mult = div = 1;
141+
} else {
142+
/* F = 24Mhz * (2-OD) * [(N + 2) / (D + 1)] */
143+
u32 n = (val >> 5) & 0x3f;
144+
u32 od = (val >> 4) & 0x1;
145+
u32 d = val & 0xf;
146+
147+
mult = (2 - od) * (n + 2);
148+
div = d + 1;
149+
}
150+
return clk_hw_register_fixed_factor(NULL, name, "clkin", 0,
151+
mult, div);
152+
};
153+
154+
static struct clk_hw *aspeed_ast2500_calc_pll(const char *name, u32 val)
155+
{
156+
unsigned int mult, div;
157+
158+
if (val & AST2500_HPLL_BYPASS_EN) {
159+
/* Pass through mode */
160+
mult = div = 1;
161+
} else {
162+
/* F = clkin * [(M+1) / (N+1)] / (P + 1) */
163+
u32 p = (val >> 13) & 0x3f;
164+
u32 m = (val >> 5) & 0xff;
165+
u32 n = val & 0x1f;
166+
167+
mult = (m + 1) / (n + 1);
168+
div = p + 1;
169+
}
170+
171+
return clk_hw_register_fixed_factor(NULL, name, "clkin", 0,
172+
mult, div);
173+
}
174+
175+
static void __init aspeed_ast2400_cc(struct regmap *map)
176+
{
177+
struct clk_hw *hw;
178+
u32 val, freq, div;
179+
180+
/*
181+
* CLKIN is the crystal oscillator, 24, 48 or 25MHz selected by
182+
* strapping
183+
*/
184+
regmap_read(map, ASPEED_STRAP, &val);
185+
if (val & CLKIN_25MHZ_EN)
186+
freq = 25000000;
187+
else if (val & AST2400_CLK_SOURCE_SEL)
188+
freq = 48000000;
189+
else
190+
freq = 24000000;
191+
hw = clk_hw_register_fixed_rate(NULL, "clkin", NULL, 0, freq);
192+
pr_debug("clkin @%u MHz\n", freq / 1000000);
193+
194+
/*
195+
* High-speed PLL clock derived from the crystal. This the CPU clock,
196+
* and we assume that it is enabled
197+
*/
198+
regmap_read(map, ASPEED_HPLL_PARAM, &val);
199+
WARN(val & AST2400_HPLL_STRAPPED, "hpll is strapped not configured");
200+
aspeed_clk_data->hws[ASPEED_CLK_HPLL] = aspeed_ast2400_calc_pll("hpll", val);
201+
202+
/*
203+
* Strap bits 11:10 define the CPU/AHB clock frequency ratio (aka HCLK)
204+
* 00: Select CPU:AHB = 1:1
205+
* 01: Select CPU:AHB = 2:1
206+
* 10: Select CPU:AHB = 4:1
207+
* 11: Select CPU:AHB = 3:1
208+
*/
209+
regmap_read(map, ASPEED_STRAP, &val);
210+
val = (val >> 10) & 0x3;
211+
div = val + 1;
212+
if (div == 3)
213+
div = 4;
214+
else if (div == 4)
215+
div = 3;
216+
hw = clk_hw_register_fixed_factor(NULL, "ahb", "hpll", 0, 1, div);
217+
aspeed_clk_data->hws[ASPEED_CLK_AHB] = hw;
218+
219+
/* APB clock clock selection register SCU08 (aka PCLK) */
220+
hw = clk_hw_register_divider_table(NULL, "apb", "hpll", 0,
221+
scu_base + ASPEED_CLK_SELECTION, 23, 3, 0,
222+
ast2400_div_table,
223+
&aspeed_clk_lock);
224+
aspeed_clk_data->hws[ASPEED_CLK_APB] = hw;
225+
}
226+
227+
static void __init aspeed_ast2500_cc(struct regmap *map)
228+
{
229+
struct clk_hw *hw;
230+
u32 val, freq, div;
231+
232+
/* CLKIN is the crystal oscillator, 24 or 25MHz selected by strapping */
233+
regmap_read(map, ASPEED_STRAP, &val);
234+
if (val & CLKIN_25MHZ_EN)
235+
freq = 25000000;
236+
else
237+
freq = 24000000;
238+
hw = clk_hw_register_fixed_rate(NULL, "clkin", NULL, 0, freq);
239+
pr_debug("clkin @%u MHz\n", freq / 1000000);
240+
241+
/*
242+
* High-speed PLL clock derived from the crystal. This the CPU clock,
243+
* and we assume that it is enabled
244+
*/
245+
regmap_read(map, ASPEED_HPLL_PARAM, &val);
246+
aspeed_clk_data->hws[ASPEED_CLK_HPLL] = aspeed_ast2500_calc_pll("hpll", val);
247+
248+
/* Strap bits 11:9 define the AXI/AHB clock frequency ratio (aka HCLK)*/
249+
regmap_read(map, ASPEED_STRAP, &val);
250+
val = (val >> 9) & 0x7;
251+
WARN(val == 0, "strapping is zero: cannot determine ahb clock");
252+
div = 2 * (val + 1);
253+
hw = clk_hw_register_fixed_factor(NULL, "ahb", "hpll", 0, 1, div);
254+
aspeed_clk_data->hws[ASPEED_CLK_AHB] = hw;
255+
256+
/* APB clock clock selection register SCU08 (aka PCLK) */
257+
regmap_read(map, ASPEED_CLK_SELECTION, &val);
258+
val = (val >> 23) & 0x7;
259+
div = 4 * (val + 1);
260+
hw = clk_hw_register_fixed_factor(NULL, "apb", "hpll", 0, 1, div);
261+
aspeed_clk_data->hws[ASPEED_CLK_APB] = hw;
262+
};
263+
94264
static void __init aspeed_cc_init(struct device_node *np)
95265
{
96266
struct regmap *map;
@@ -132,6 +302,13 @@ static void __init aspeed_cc_init(struct device_node *np)
132302
return;
133303
}
134304

305+
if (of_device_is_compatible(np, "aspeed,ast2400-scu"))
306+
aspeed_ast2400_cc(map);
307+
else if (of_device_is_compatible(np, "aspeed,ast2500-scu"))
308+
aspeed_ast2500_cc(map);
309+
else
310+
pr_err("unknown platform, failed to add clocks\n");
311+
135312
aspeed_clk_data->num = ASPEED_NUM_CLKS;
136313
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, aspeed_clk_data);
137314
if (ret)

0 commit comments

Comments
 (0)