]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0 |
14e4b149 | 2 | /* |
3 | * (C) Copyright 2016 Google, Inc | |
14e4b149 | 4 | */ |
5 | ||
6 | #include <common.h> | |
7 | #include <clk-uclass.h> | |
8 | #include <dm.h> | |
f7ae49fc | 9 | #include <log.h> |
14e4b149 | 10 | #include <asm/io.h> |
11 | #include <asm/arch/scu_ast2500.h> | |
12 | #include <dm/lists.h> | |
13 | #include <dt-bindings/clock/ast2500-scu.h> | |
c05ed00a | 14 | #include <linux/delay.h> |
61b29b82 | 15 | #include <linux/err.h> |
14e4b149 | 16 | |
3b95902d | 17 | /* |
18 | * MAC Clock Delay settings, taken from Aspeed SDK | |
19 | */ | |
20 | #define RGMII_TXCLK_ODLY 8 | |
21 | #define RMII_RXCLK_IDLY 2 | |
22 | ||
23 | /* | |
24 | * TGMII Clock Duty constants, taken from Aspeed SDK | |
25 | */ | |
26 | #define RGMII2_TXCK_DUTY 0x66 | |
27 | #define RGMII1_TXCK_DUTY 0x64 | |
28 | ||
29 | #define D2PLL_DEFAULT_RATE (250 * 1000 * 1000) | |
30 | ||
14e4b149 | 31 | DECLARE_GLOBAL_DATA_PTR; |
32 | ||
33 | /* | |
3b95902d | 34 | * Clock divider/multiplier configuration struct. |
14e4b149 | 35 | * For H-PLL and M-PLL the formula is |
36 | * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1) | |
37 | * M - Numerator | |
38 | * N - Denumerator | |
39 | * P - Post Divider | |
40 | * They have the same layout in their control register. | |
3b95902d | 41 | * |
42 | * D-PLL and D2-PLL have extra divider (OD + 1), which is not | |
43 | * yet needed and ignored by clock configurations. | |
14e4b149 | 44 | */ |
3b95902d | 45 | struct ast2500_div_config { |
46 | unsigned int num; | |
47 | unsigned int denum; | |
48 | unsigned int post_div; | |
49 | }; | |
14e4b149 | 50 | |
51 | /* | |
52 | * Get the rate of the M-PLL clock from input clock frequency and | |
53 | * the value of the M-PLL Parameter Register. | |
54 | */ | |
55 | static ulong ast2500_get_mpll_rate(ulong clkin, u32 mpll_reg) | |
56 | { | |
defb1849 | 57 | const ulong num = (mpll_reg & SCU_MPLL_NUM_MASK) >> SCU_MPLL_NUM_SHIFT; |
58 | const ulong denum = (mpll_reg & SCU_MPLL_DENUM_MASK) | |
59 | >> SCU_MPLL_DENUM_SHIFT; | |
60 | const ulong post_div = (mpll_reg & SCU_MPLL_POST_MASK) | |
61 | >> SCU_MPLL_POST_SHIFT; | |
14e4b149 | 62 | |
d5ce3574 | 63 | return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1); |
14e4b149 | 64 | } |
65 | ||
66 | /* | |
67 | * Get the rate of the H-PLL clock from input clock frequency and | |
68 | * the value of the H-PLL Parameter Register. | |
69 | */ | |
70 | static ulong ast2500_get_hpll_rate(ulong clkin, u32 hpll_reg) | |
71 | { | |
defb1849 | 72 | const ulong num = (hpll_reg & SCU_HPLL_NUM_MASK) >> SCU_HPLL_NUM_SHIFT; |
73 | const ulong denum = (hpll_reg & SCU_HPLL_DENUM_MASK) | |
74 | >> SCU_HPLL_DENUM_SHIFT; | |
75 | const ulong post_div = (hpll_reg & SCU_HPLL_POST_MASK) | |
76 | >> SCU_HPLL_POST_SHIFT; | |
14e4b149 | 77 | |
d5ce3574 | 78 | return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1); |
14e4b149 | 79 | } |
80 | ||
81 | static ulong ast2500_get_clkin(struct ast2500_scu *scu) | |
82 | { | |
83 | return readl(&scu->hwstrap) & SCU_HWSTRAP_CLKIN_25MHZ | |
84 | ? 25 * 1000 * 1000 : 24 * 1000 * 1000; | |
85 | } | |
86 | ||
87 | /** | |
88 | * Get current rate or uart clock | |
89 | * | |
90 | * @scu SCU registers | |
91 | * @uart_index UART index, 1-5 | |
92 | * | |
93 | * @return current setting for uart clock rate | |
94 | */ | |
95 | static ulong ast2500_get_uart_clk_rate(struct ast2500_scu *scu, int uart_index) | |
96 | { | |
97 | /* | |
98 | * ast2500 datasheet is very confusing when it comes to UART clocks, | |
99 | * especially when CLKIN = 25 MHz. The settings are in | |
100 | * different registers and it is unclear how they interact. | |
101 | * | |
102 | * This has only been tested with default settings and CLKIN = 24 MHz. | |
103 | */ | |
104 | ulong uart_clkin; | |
105 | ||
106 | if (readl(&scu->misc_ctrl2) & | |
107 | (1 << (uart_index - 1 + SCU_MISC2_UARTCLK_SHIFT))) | |
108 | uart_clkin = 192 * 1000 * 1000; | |
109 | else | |
110 | uart_clkin = 24 * 1000 * 1000; | |
111 | ||
112 | if (readl(&scu->misc_ctrl1) & SCU_MISC_UARTCLK_DIV13) | |
113 | uart_clkin /= 13; | |
114 | ||
115 | return uart_clkin; | |
116 | } | |
117 | ||
118 | static ulong ast2500_clk_get_rate(struct clk *clk) | |
119 | { | |
120 | struct ast2500_clk_priv *priv = dev_get_priv(clk->dev); | |
121 | ulong clkin = ast2500_get_clkin(priv->scu); | |
122 | ulong rate; | |
123 | ||
124 | switch (clk->id) { | |
125 | case PLL_HPLL: | |
126 | case ARMCLK: | |
127 | /* | |
128 | * This ignores dynamic/static slowdown of ARMCLK and may | |
129 | * be inaccurate. | |
130 | */ | |
131 | rate = ast2500_get_hpll_rate(clkin, | |
132 | readl(&priv->scu->h_pll_param)); | |
133 | break; | |
134 | case MCLK_DDR: | |
135 | rate = ast2500_get_mpll_rate(clkin, | |
136 | readl(&priv->scu->m_pll_param)); | |
137 | break; | |
4999bb06 | 138 | case BCLK_PCLK: |
139 | { | |
140 | ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1) | |
defb1849 | 141 | & SCU_PCLK_DIV_MASK) |
142 | >> SCU_PCLK_DIV_SHIFT); | |
4999bb06 | 143 | rate = ast2500_get_hpll_rate(clkin, |
defb1849 | 144 | readl(&priv-> |
145 | scu->h_pll_param)); | |
4999bb06 | 146 | rate = rate / apb_div; |
147 | } | |
148 | break; | |
38c9f08b EJ |
149 | case BCLK_SDCLK: |
150 | { | |
151 | ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1) | |
152 | & SCU_SDCLK_DIV_MASK) | |
153 | >> SCU_SDCLK_DIV_SHIFT); | |
154 | rate = ast2500_get_hpll_rate(clkin, | |
155 | readl(&priv-> | |
156 | scu->h_pll_param)); | |
157 | rate = rate / apb_div; | |
158 | } | |
159 | break; | |
14e4b149 | 160 | case PCLK_UART1: |
161 | rate = ast2500_get_uart_clk_rate(priv->scu, 1); | |
162 | break; | |
163 | case PCLK_UART2: | |
164 | rate = ast2500_get_uart_clk_rate(priv->scu, 2); | |
165 | break; | |
166 | case PCLK_UART3: | |
167 | rate = ast2500_get_uart_clk_rate(priv->scu, 3); | |
168 | break; | |
169 | case PCLK_UART4: | |
170 | rate = ast2500_get_uart_clk_rate(priv->scu, 4); | |
171 | break; | |
172 | case PCLK_UART5: | |
173 | rate = ast2500_get_uart_clk_rate(priv->scu, 5); | |
174 | break; | |
175 | default: | |
176 | return -ENOENT; | |
177 | } | |
178 | ||
179 | return rate; | |
180 | } | |
181 | ||
1e5d8aaf CLG |
182 | struct ast2500_clock_config { |
183 | ulong input_rate; | |
184 | ulong rate; | |
185 | struct ast2500_div_config cfg; | |
186 | }; | |
187 | ||
188 | static const struct ast2500_clock_config ast2500_clock_config_defaults[] = { | |
189 | { 24000000, 250000000, { .num = 124, .denum = 1, .post_div = 5 } }, | |
190 | }; | |
191 | ||
192 | static bool ast2500_get_clock_config_default(ulong input_rate, | |
193 | ulong requested_rate, | |
194 | struct ast2500_div_config *cfg) | |
195 | { | |
196 | int i; | |
197 | ||
198 | for (i = 0; i < ARRAY_SIZE(ast2500_clock_config_defaults); i++) { | |
199 | const struct ast2500_clock_config *default_cfg = | |
200 | &ast2500_clock_config_defaults[i]; | |
201 | if (default_cfg->input_rate == input_rate && | |
202 | default_cfg->rate == requested_rate) { | |
203 | *cfg = default_cfg->cfg; | |
204 | return true; | |
205 | } | |
206 | } | |
207 | ||
208 | return false; | |
209 | } | |
210 | ||
3b95902d | 211 | /* |
212 | * @input_rate - the rate of input clock in Hz | |
213 | * @requested_rate - desired output rate in Hz | |
214 | * @div - this is an IN/OUT parameter, at input all fields of the config | |
215 | * need to be set to their maximum allowed values. | |
216 | * The result (the best config we could find), would also be returned | |
217 | * in this structure. | |
218 | * | |
219 | * @return The clock rate, when the resulting div_config is used. | |
220 | */ | |
221 | static ulong ast2500_calc_clock_config(ulong input_rate, ulong requested_rate, | |
222 | struct ast2500_div_config *cfg) | |
14e4b149 | 223 | { |
14e4b149 | 224 | /* |
3b95902d | 225 | * The assumption is that kHz precision is good enough and |
226 | * also enough to avoid overflow when multiplying. | |
14e4b149 | 227 | */ |
3b95902d | 228 | const ulong input_rate_khz = input_rate / 1000; |
229 | const ulong rate_khz = requested_rate / 1000; | |
230 | const struct ast2500_div_config max_vals = *cfg; | |
231 | struct ast2500_div_config it = { 0, 0, 0 }; | |
232 | ulong delta = rate_khz; | |
233 | ulong new_rate_khz = 0; | |
234 | ||
1e5d8aaf CLG |
235 | /* |
236 | * Look for a well known frequency first. | |
237 | */ | |
238 | if (ast2500_get_clock_config_default(input_rate, requested_rate, cfg)) | |
239 | return requested_rate; | |
240 | ||
3b95902d | 241 | for (; it.denum <= max_vals.denum; ++it.denum) { |
242 | for (it.post_div = 0; it.post_div <= max_vals.post_div; | |
243 | ++it.post_div) { | |
244 | it.num = (rate_khz * (it.post_div + 1) / input_rate_khz) | |
245 | * (it.denum + 1); | |
246 | if (it.num > max_vals.num) | |
247 | continue; | |
248 | ||
249 | new_rate_khz = (input_rate_khz | |
250 | * ((it.num + 1) / (it.denum + 1))) | |
251 | / (it.post_div + 1); | |
14e4b149 | 252 | |
253 | /* Keep the rate below requested one. */ | |
254 | if (new_rate_khz > rate_khz) | |
255 | continue; | |
256 | ||
257 | if (new_rate_khz - rate_khz < delta) { | |
258 | delta = new_rate_khz - rate_khz; | |
3b95902d | 259 | *cfg = it; |
14e4b149 | 260 | if (delta == 0) |
3b95902d | 261 | return new_rate_khz * 1000; |
14e4b149 | 262 | } |
263 | } | |
264 | } | |
265 | ||
3b95902d | 266 | return new_rate_khz * 1000; |
267 | } | |
268 | ||
269 | static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate) | |
270 | { | |
271 | ulong clkin = ast2500_get_clkin(scu); | |
272 | u32 mpll_reg; | |
273 | struct ast2500_div_config div_cfg = { | |
defb1849 | 274 | .num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT), |
275 | .denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT), | |
276 | .post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT), | |
3b95902d | 277 | }; |
278 | ||
279 | ast2500_calc_clock_config(clkin, rate, &div_cfg); | |
280 | ||
14e4b149 | 281 | mpll_reg = readl(&scu->m_pll_param); |
defb1849 | 282 | mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK |
283 | | SCU_MPLL_DENUM_MASK); | |
3b95902d | 284 | mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT) |
285 | | (div_cfg.num << SCU_MPLL_NUM_SHIFT) | |
286 | | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT); | |
14e4b149 | 287 | |
413353b3 | 288 | ast_scu_unlock(scu); |
14e4b149 | 289 | writel(mpll_reg, &scu->m_pll_param); |
413353b3 | 290 | ast_scu_lock(scu); |
14e4b149 | 291 | |
292 | return ast2500_get_mpll_rate(clkin, mpll_reg); | |
293 | } | |
294 | ||
3b95902d | 295 | static ulong ast2500_configure_mac(struct ast2500_scu *scu, int index) |
296 | { | |
297 | ulong clkin = ast2500_get_clkin(scu); | |
298 | ulong hpll_rate = ast2500_get_hpll_rate(clkin, | |
299 | readl(&scu->h_pll_param)); | |
300 | ulong required_rate; | |
301 | u32 hwstrap; | |
302 | u32 divisor; | |
303 | u32 reset_bit; | |
304 | u32 clkstop_bit; | |
305 | ||
306 | /* | |
307 | * According to data sheet, for 10/100 mode the MAC clock frequency | |
308 | * should be at least 25MHz and for 1000 mode at least 100MHz | |
309 | */ | |
310 | hwstrap = readl(&scu->hwstrap); | |
311 | if (hwstrap & (SCU_HWSTRAP_MAC1_RGMII | SCU_HWSTRAP_MAC2_RGMII)) | |
312 | required_rate = 100 * 1000 * 1000; | |
313 | else | |
314 | required_rate = 25 * 1000 * 1000; | |
315 | ||
316 | divisor = hpll_rate / required_rate; | |
317 | ||
318 | if (divisor < 4) { | |
319 | /* Clock can't run fast enough, but let's try anyway */ | |
320 | debug("MAC clock too slow\n"); | |
321 | divisor = 4; | |
322 | } else if (divisor > 16) { | |
323 | /* Can't slow down the clock enough, but let's try anyway */ | |
324 | debug("MAC clock too fast\n"); | |
325 | divisor = 16; | |
326 | } | |
327 | ||
328 | switch (index) { | |
329 | case 1: | |
330 | reset_bit = SCU_SYSRESET_MAC1; | |
331 | clkstop_bit = SCU_CLKSTOP_MAC1; | |
332 | break; | |
333 | case 2: | |
334 | reset_bit = SCU_SYSRESET_MAC2; | |
335 | clkstop_bit = SCU_CLKSTOP_MAC2; | |
336 | break; | |
337 | default: | |
338 | return -EINVAL; | |
339 | } | |
340 | ||
341 | ast_scu_unlock(scu); | |
342 | clrsetbits_le32(&scu->clk_sel1, SCU_MACCLK_MASK, | |
343 | ((divisor - 2) / 2) << SCU_MACCLK_SHIFT); | |
344 | ||
345 | /* | |
346 | * Disable MAC, start its clock and re-enable it. | |
347 | * The procedure and the delays (100us & 10ms) are | |
348 | * specified in the datasheet. | |
349 | */ | |
350 | setbits_le32(&scu->sysreset_ctrl1, reset_bit); | |
351 | udelay(100); | |
352 | clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit); | |
353 | mdelay(10); | |
354 | clrbits_le32(&scu->sysreset_ctrl1, reset_bit); | |
355 | ||
356 | writel((RGMII2_TXCK_DUTY << SCU_CLKDUTY_RGMII2TXCK_SHIFT) | |
357 | | (RGMII1_TXCK_DUTY << SCU_CLKDUTY_RGMII1TXCK_SHIFT), | |
358 | &scu->clk_duty_sel); | |
359 | ||
360 | ast_scu_lock(scu); | |
361 | ||
362 | return required_rate; | |
363 | } | |
364 | ||
365 | static ulong ast2500_configure_d2pll(struct ast2500_scu *scu, ulong rate) | |
366 | { | |
367 | /* | |
368 | * The values and the meaning of the next three | |
369 | * parameters are undocumented. Taken from Aspeed SDK. | |
1e5d8aaf CLG |
370 | * |
371 | * TODO([email protected]): the SIP and SIC values depend on the | |
372 | * Numerator value | |
3b95902d | 373 | */ |
374 | const u32 d2_pll_ext_param = 0x2c; | |
375 | const u32 d2_pll_sip = 0x11; | |
376 | const u32 d2_pll_sic = 0x18; | |
377 | u32 clk_delay_settings = | |
378 | (RMII_RXCLK_IDLY << SCU_MICDS_MAC1RMII_RDLY_SHIFT) | |
379 | | (RMII_RXCLK_IDLY << SCU_MICDS_MAC2RMII_RDLY_SHIFT) | |
380 | | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT) | |
381 | | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT); | |
382 | struct ast2500_div_config div_cfg = { | |
383 | .num = SCU_D2PLL_NUM_MASK >> SCU_D2PLL_NUM_SHIFT, | |
384 | .denum = SCU_D2PLL_DENUM_MASK >> SCU_D2PLL_DENUM_SHIFT, | |
385 | .post_div = SCU_D2PLL_POST_MASK >> SCU_D2PLL_POST_SHIFT, | |
386 | }; | |
387 | ulong clkin = ast2500_get_clkin(scu); | |
388 | ulong new_rate; | |
389 | ||
390 | ast_scu_unlock(scu); | |
391 | writel((d2_pll_ext_param << SCU_D2PLL_EXT1_PARAM_SHIFT) | |
392 | | SCU_D2PLL_EXT1_OFF | |
393 | | SCU_D2PLL_EXT1_RESET, &scu->d2_pll_ext_param[0]); | |
394 | ||
395 | /* | |
396 | * Select USB2.0 port1 PHY clock as a clock source for GCRT. | |
397 | * This would disconnect it from D2-PLL. | |
398 | */ | |
399 | clrsetbits_le32(&scu->misc_ctrl1, SCU_MISC_D2PLL_OFF, | |
400 | SCU_MISC_GCRT_USB20CLK); | |
401 | ||
402 | new_rate = ast2500_calc_clock_config(clkin, rate, &div_cfg); | |
403 | writel((d2_pll_sip << SCU_D2PLL_SIP_SHIFT) | |
404 | | (d2_pll_sic << SCU_D2PLL_SIC_SHIFT) | |
405 | | (div_cfg.num << SCU_D2PLL_NUM_SHIFT) | |
406 | | (div_cfg.denum << SCU_D2PLL_DENUM_SHIFT) | |
407 | | (div_cfg.post_div << SCU_D2PLL_POST_SHIFT), | |
408 | &scu->d2_pll_param); | |
409 | ||
410 | clrbits_le32(&scu->d2_pll_ext_param[0], | |
411 | SCU_D2PLL_EXT1_OFF | SCU_D2PLL_EXT1_RESET); | |
412 | ||
413 | clrsetbits_le32(&scu->misc_ctrl2, | |
414 | SCU_MISC2_RGMII_HPLL | SCU_MISC2_RMII_MPLL | |
415 | | SCU_MISC2_RGMII_CLKDIV_MASK | | |
416 | SCU_MISC2_RMII_CLKDIV_MASK, | |
417 | (4 << SCU_MISC2_RMII_CLKDIV_SHIFT)); | |
418 | ||
419 | writel(clk_delay_settings | SCU_MICDS_RGMIIPLL, &scu->mac_clk_delay); | |
420 | writel(clk_delay_settings, &scu->mac_clk_delay_100M); | |
421 | writel(clk_delay_settings, &scu->mac_clk_delay_10M); | |
422 | ||
423 | ast_scu_lock(scu); | |
424 | ||
425 | return new_rate; | |
426 | } | |
427 | ||
14e4b149 | 428 | static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate) |
429 | { | |
430 | struct ast2500_clk_priv *priv = dev_get_priv(clk->dev); | |
431 | ||
432 | ulong new_rate; | |
433 | switch (clk->id) { | |
434 | case PLL_MPLL: | |
435 | case MCLK_DDR: | |
436 | new_rate = ast2500_configure_ddr(priv->scu, rate); | |
437 | break; | |
3b95902d | 438 | case PLL_D2PLL: |
439 | new_rate = ast2500_configure_d2pll(priv->scu, rate); | |
440 | break; | |
14e4b149 | 441 | default: |
442 | return -ENOENT; | |
443 | } | |
444 | ||
445 | return new_rate; | |
446 | } | |
447 | ||
3b95902d | 448 | static int ast2500_clk_enable(struct clk *clk) |
449 | { | |
450 | struct ast2500_clk_priv *priv = dev_get_priv(clk->dev); | |
451 | ||
452 | switch (clk->id) { | |
38c9f08b EJ |
453 | case BCLK_SDCLK: |
454 | if (readl(&priv->scu->clk_stop_ctrl1) & SCU_CLKSTOP_SDCLK) { | |
455 | ast_scu_unlock(priv->scu); | |
456 | ||
457 | setbits_le32(&priv->scu->sysreset_ctrl1, | |
458 | SCU_SYSRESET_SDIO); | |
459 | udelay(100); | |
460 | clrbits_le32(&priv->scu->clk_stop_ctrl1, | |
461 | SCU_CLKSTOP_SDCLK); | |
462 | mdelay(10); | |
463 | clrbits_le32(&priv->scu->sysreset_ctrl1, | |
464 | SCU_SYSRESET_SDIO); | |
465 | ||
466 | ast_scu_lock(priv->scu); | |
467 | } | |
468 | break; | |
3b95902d | 469 | /* |
470 | * For MAC clocks the clock rate is | |
471 | * configured based on whether RGMII or RMII mode has been selected | |
472 | * through hardware strapping. | |
473 | */ | |
474 | case PCLK_MAC1: | |
475 | ast2500_configure_mac(priv->scu, 1); | |
476 | break; | |
477 | case PCLK_MAC2: | |
478 | ast2500_configure_mac(priv->scu, 2); | |
479 | break; | |
480 | case PLL_D2PLL: | |
481 | ast2500_configure_d2pll(priv->scu, D2PLL_DEFAULT_RATE); | |
64ae8234 | 482 | break; |
3b95902d | 483 | default: |
484 | return -ENOENT; | |
485 | } | |
486 | ||
487 | return 0; | |
488 | } | |
489 | ||
14e4b149 | 490 | struct clk_ops ast2500_clk_ops = { |
491 | .get_rate = ast2500_clk_get_rate, | |
492 | .set_rate = ast2500_clk_set_rate, | |
3b95902d | 493 | .enable = ast2500_clk_enable, |
14e4b149 | 494 | }; |
495 | ||
b2b1100a | 496 | static int ast2500_clk_ofdata_to_platdata(struct udevice *dev) |
14e4b149 | 497 | { |
498 | struct ast2500_clk_priv *priv = dev_get_priv(dev); | |
499 | ||
a821c4af | 500 | priv->scu = devfdt_get_addr_ptr(dev); |
14e4b149 | 501 | if (IS_ERR(priv->scu)) |
502 | return PTR_ERR(priv->scu); | |
503 | ||
504 | return 0; | |
505 | } | |
506 | ||
507 | static int ast2500_clk_bind(struct udevice *dev) | |
508 | { | |
509 | int ret; | |
510 | ||
511 | /* The reset driver does not have a device node, so bind it here */ | |
512 | ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev); | |
513 | if (ret) | |
514 | debug("Warning: No reset driver: ret=%d\n", ret); | |
515 | ||
516 | return 0; | |
517 | } | |
518 | ||
519 | static const struct udevice_id ast2500_clk_ids[] = { | |
520 | { .compatible = "aspeed,ast2500-scu" }, | |
521 | { } | |
522 | }; | |
523 | ||
524 | U_BOOT_DRIVER(aspeed_ast2500_scu) = { | |
525 | .name = "aspeed_ast2500_scu", | |
526 | .id = UCLASS_CLK, | |
527 | .of_match = ast2500_clk_ids, | |
528 | .priv_auto_alloc_size = sizeof(struct ast2500_clk_priv), | |
529 | .ops = &ast2500_clk_ops, | |
530 | .bind = ast2500_clk_bind, | |
b2b1100a | 531 | .ofdata_to_platdata = ast2500_clk_ofdata_to_platdata, |
14e4b149 | 532 | }; |