1 // SPDX-License-Identifier: GPL-2.0+ 2 3 #define pr_fmt(fmt) "clk-aspeed: " fmt 4 5 #include <linux/clk-provider.h> 6 #include <linux/mfd/syscon.h> 7 #include <linux/of_address.h> 8 #include <linux/of_device.h> 9 #include <linux/platform_device.h> 10 #include <linux/regmap.h> 11 #include <linux/slab.h> 12 #include <linux/spinlock.h> 13 14 #include <dt-bindings/clock/aspeed-clock.h> 15 16 #define ASPEED_NUM_CLKS 35 17 18 #define ASPEED_RESET_CTRL 0x04 19 #define ASPEED_CLK_SELECTION 0x08 20 #define ASPEED_CLK_STOP_CTRL 0x0c 21 #define ASPEED_MPLL_PARAM 0x20 22 #define ASPEED_HPLL_PARAM 0x24 23 #define AST2500_HPLL_BYPASS_EN BIT(20) 24 #define AST2400_HPLL_STRAPPED BIT(18) 25 #define AST2400_HPLL_BYPASS_EN BIT(17) 26 #define ASPEED_MISC_CTRL 0x2c 27 #define UART_DIV13_EN BIT(12) 28 #define ASPEED_STRAP 0x70 29 #define CLKIN_25MHZ_EN BIT(23) 30 #define AST2400_CLK_SOURCE_SEL BIT(18) 31 #define ASPEED_CLK_SELECTION_2 0xd8 32 33 /* Globally visible clocks */ 34 static DEFINE_SPINLOCK(aspeed_clk_lock); 35 36 /* Keeps track of all clocks */ 37 static struct clk_hw_onecell_data *aspeed_clk_data; 38 39 static void __iomem *scu_base; 40 41 /** 42 * struct aspeed_gate_data - Aspeed gated clocks 43 * @clock_idx: bit used to gate this clock in the clock register 44 * @reset_idx: bit used to reset this IP in the reset register. -1 if no 45 * reset is required when enabling the clock 46 * @name: the clock name 47 * @parent_name: the name of the parent clock 48 * @flags: standard clock framework flags 49 */ 50 struct aspeed_gate_data { 51 u8 clock_idx; 52 s8 reset_idx; 53 const char *name; 54 const char *parent_name; 55 unsigned long flags; 56 }; 57 58 /** 59 * struct aspeed_clk_gate - Aspeed specific clk_gate structure 60 * @hw: handle between common and hardware-specific interfaces 61 * @reg: register controlling gate 62 * @clock_idx: bit used to gate this clock in the clock register 63 * @reset_idx: bit used to reset this IP in the reset register. -1 if no 64 * reset is required when enabling the clock 65 * @flags: hardware-specific flags 66 * @lock: register lock 67 * 68 * Some of the clocks in the Aspeed SoC must be put in reset before enabling. 69 * This modified version of clk_gate allows an optional reset bit to be 70 * specified. 71 */ 72 struct aspeed_clk_gate { 73 struct clk_hw hw; 74 struct regmap *map; 75 u8 clock_idx; 76 s8 reset_idx; 77 u8 flags; 78 spinlock_t *lock; 79 }; 80 81 #define to_aspeed_clk_gate(_hw) container_of(_hw, struct aspeed_clk_gate, hw) 82 83 /* TODO: ask Aspeed about the actual parent data */ 84 static const struct aspeed_gate_data aspeed_gates[] = { 85 /* clk rst name parent flags */ 86 [ASPEED_CLK_GATE_ECLK] = { 0, -1, "eclk-gate", "eclk", 0 }, /* Video Engine */ 87 [ASPEED_CLK_GATE_GCLK] = { 1, 7, "gclk-gate", NULL, 0 }, /* 2D engine */ 88 [ASPEED_CLK_GATE_MCLK] = { 2, -1, "mclk-gate", "mpll", CLK_IS_CRITICAL }, /* SDRAM */ 89 [ASPEED_CLK_GATE_VCLK] = { 3, 6, "vclk-gate", NULL, 0 }, /* Video Capture */ 90 [ASPEED_CLK_GATE_BCLK] = { 4, 10, "bclk-gate", "bclk", 0 }, /* PCIe/PCI */ 91 [ASPEED_CLK_GATE_DCLK] = { 5, -1, "dclk-gate", NULL, 0 }, /* DAC */ 92 [ASPEED_CLK_GATE_REFCLK] = { 6, -1, "refclk-gate", "clkin", CLK_IS_CRITICAL }, 93 [ASPEED_CLK_GATE_USBPORT2CLK] = { 7, 3, "usb-port2-gate", NULL, 0 }, /* USB2.0 Host port 2 */ 94 [ASPEED_CLK_GATE_LCLK] = { 8, 5, "lclk-gate", NULL, 0 }, /* LPC */ 95 [ASPEED_CLK_GATE_USBUHCICLK] = { 9, 15, "usb-uhci-gate", NULL, 0 }, /* USB1.1 (requires port 2 enabled) */ 96 [ASPEED_CLK_GATE_D1CLK] = { 10, 13, "d1clk-gate", NULL, 0 }, /* GFX CRT */ 97 [ASPEED_CLK_GATE_YCLK] = { 13, 4, "yclk-gate", NULL, 0 }, /* HAC */ 98 [ASPEED_CLK_GATE_USBPORT1CLK] = { 14, 14, "usb-port1-gate", NULL, 0 }, /* USB2 hub/USB2 host port 1/USB1.1 dev */ 99 [ASPEED_CLK_GATE_UART1CLK] = { 15, -1, "uart1clk-gate", "uart", 0 }, /* UART1 */ 100 [ASPEED_CLK_GATE_UART2CLK] = { 16, -1, "uart2clk-gate", "uart", 0 }, /* UART2 */ 101 [ASPEED_CLK_GATE_UART5CLK] = { 17, -1, "uart5clk-gate", "uart", 0 }, /* UART5 */ 102 [ASPEED_CLK_GATE_ESPICLK] = { 19, -1, "espiclk-gate", NULL, 0 }, /* eSPI */ 103 [ASPEED_CLK_GATE_MAC1CLK] = { 20, 11, "mac1clk-gate", "mac", 0 }, /* MAC1 */ 104 [ASPEED_CLK_GATE_MAC2CLK] = { 21, 12, "mac2clk-gate", "mac", 0 }, /* MAC2 */ 105 [ASPEED_CLK_GATE_RSACLK] = { 24, -1, "rsaclk-gate", NULL, 0 }, /* RSA */ 106 [ASPEED_CLK_GATE_UART3CLK] = { 25, -1, "uart3clk-gate", "uart", 0 }, /* UART3 */ 107 [ASPEED_CLK_GATE_UART4CLK] = { 26, -1, "uart4clk-gate", "uart", 0 }, /* UART4 */ 108 [ASPEED_CLK_GATE_SDCLKCLK] = { 27, 16, "sdclk-gate", NULL, 0 }, /* SDIO/SD */ 109 [ASPEED_CLK_GATE_LHCCLK] = { 28, -1, "lhclk-gate", "lhclk", 0 }, /* LPC master/LPC+ */ 110 }; 111 112 static const struct clk_div_table ast2500_mac_div_table[] = { 113 { 0x0, 4 }, /* Yep, really. Aspeed confirmed this is correct */ 114 { 0x1, 4 }, 115 { 0x2, 6 }, 116 { 0x3, 8 }, 117 { 0x4, 10 }, 118 { 0x5, 12 }, 119 { 0x6, 14 }, 120 { 0x7, 16 }, 121 { 0 } 122 }; 123 124 static const struct clk_div_table ast2400_div_table[] = { 125 { 0x0, 2 }, 126 { 0x1, 4 }, 127 { 0x2, 6 }, 128 { 0x3, 8 }, 129 { 0x4, 10 }, 130 { 0x5, 12 }, 131 { 0x6, 14 }, 132 { 0x7, 16 }, 133 { 0 } 134 }; 135 136 static const struct clk_div_table ast2500_div_table[] = { 137 { 0x0, 4 }, 138 { 0x1, 8 }, 139 { 0x2, 12 }, 140 { 0x3, 16 }, 141 { 0x4, 20 }, 142 { 0x5, 24 }, 143 { 0x6, 28 }, 144 { 0x7, 32 }, 145 { 0 } 146 }; 147 148 static struct clk_hw *aspeed_ast2400_calc_pll(const char *name, u32 val) 149 { 150 unsigned int mult, div; 151 152 if (val & AST2400_HPLL_BYPASS_EN) { 153 /* Pass through mode */ 154 mult = div = 1; 155 } else { 156 /* F = 24Mhz * (2-OD) * [(N + 2) / (D + 1)] */ 157 u32 n = (val >> 5) & 0x3f; 158 u32 od = (val >> 4) & 0x1; 159 u32 d = val & 0xf; 160 161 mult = (2 - od) * (n + 2); 162 div = d + 1; 163 } 164 return clk_hw_register_fixed_factor(NULL, name, "clkin", 0, 165 mult, div); 166 }; 167 168 static struct clk_hw *aspeed_ast2500_calc_pll(const char *name, u32 val) 169 { 170 unsigned int mult, div; 171 172 if (val & AST2500_HPLL_BYPASS_EN) { 173 /* Pass through mode */ 174 mult = div = 1; 175 } else { 176 /* F = clkin * [(M+1) / (N+1)] / (P + 1) */ 177 u32 p = (val >> 13) & 0x3f; 178 u32 m = (val >> 5) & 0xff; 179 u32 n = val & 0x1f; 180 181 mult = (m + 1) / (n + 1); 182 div = p + 1; 183 } 184 185 return clk_hw_register_fixed_factor(NULL, name, "clkin", 0, 186 mult, div); 187 } 188 189 struct aspeed_clk_soc_data { 190 const struct clk_div_table *div_table; 191 const struct clk_div_table *mac_div_table; 192 struct clk_hw *(*calc_pll)(const char *name, u32 val); 193 }; 194 195 static const struct aspeed_clk_soc_data ast2500_data = { 196 .div_table = ast2500_div_table, 197 .mac_div_table = ast2500_mac_div_table, 198 .calc_pll = aspeed_ast2500_calc_pll, 199 }; 200 201 static const struct aspeed_clk_soc_data ast2400_data = { 202 .div_table = ast2400_div_table, 203 .mac_div_table = ast2400_div_table, 204 .calc_pll = aspeed_ast2400_calc_pll, 205 }; 206 207 static int aspeed_clk_enable(struct clk_hw *hw) 208 { 209 struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw); 210 unsigned long flags; 211 u32 clk = BIT(gate->clock_idx); 212 u32 rst = BIT(gate->reset_idx); 213 214 spin_lock_irqsave(gate->lock, flags); 215 216 if (gate->reset_idx >= 0) { 217 /* Put IP in reset */ 218 regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst, rst); 219 220 /* Delay 100us */ 221 udelay(100); 222 } 223 224 /* Enable clock */ 225 regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, 0); 226 227 if (gate->reset_idx >= 0) { 228 /* A delay of 10ms is specified by the ASPEED docs */ 229 mdelay(10); 230 231 /* Take IP out of reset */ 232 regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst, 0); 233 } 234 235 spin_unlock_irqrestore(gate->lock, flags); 236 237 return 0; 238 } 239 240 static void aspeed_clk_disable(struct clk_hw *hw) 241 { 242 struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw); 243 unsigned long flags; 244 u32 clk = BIT(gate->clock_idx); 245 246 spin_lock_irqsave(gate->lock, flags); 247 248 regmap_update_bits(gate->map, ASPEED_CLK_STOP_CTRL, clk, clk); 249 250 spin_unlock_irqrestore(gate->lock, flags); 251 } 252 253 static int aspeed_clk_is_enabled(struct clk_hw *hw) 254 { 255 struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw); 256 u32 clk = BIT(gate->clock_idx); 257 u32 reg; 258 259 regmap_read(gate->map, ASPEED_CLK_STOP_CTRL, ®); 260 261 return (reg & clk) ? 0 : 1; 262 } 263 264 static const struct clk_ops aspeed_clk_gate_ops = { 265 .enable = aspeed_clk_enable, 266 .disable = aspeed_clk_disable, 267 .is_enabled = aspeed_clk_is_enabled, 268 }; 269 270 static struct clk_hw *aspeed_clk_hw_register_gate(struct device *dev, 271 const char *name, const char *parent_name, unsigned long flags, 272 struct regmap *map, u8 clock_idx, u8 reset_idx, 273 u8 clk_gate_flags, spinlock_t *lock) 274 { 275 struct aspeed_clk_gate *gate; 276 struct clk_init_data init; 277 struct clk_hw *hw; 278 int ret; 279 280 gate = kzalloc(sizeof(*gate), GFP_KERNEL); 281 if (!gate) 282 return ERR_PTR(-ENOMEM); 283 284 init.name = name; 285 init.ops = &aspeed_clk_gate_ops; 286 init.flags = flags; 287 init.parent_names = parent_name ? &parent_name : NULL; 288 init.num_parents = parent_name ? 1 : 0; 289 290 gate->map = map; 291 gate->clock_idx = clock_idx; 292 gate->reset_idx = reset_idx; 293 gate->flags = clk_gate_flags; 294 gate->lock = lock; 295 gate->hw.init = &init; 296 297 hw = &gate->hw; 298 ret = clk_hw_register(dev, hw); 299 if (ret) { 300 kfree(gate); 301 hw = ERR_PTR(ret); 302 } 303 304 return hw; 305 } 306 307 static int aspeed_clk_probe(struct platform_device *pdev) 308 { 309 const struct aspeed_clk_soc_data *soc_data; 310 struct device *dev = &pdev->dev; 311 struct regmap *map; 312 struct clk_hw *hw; 313 u32 val, rate; 314 int i; 315 316 map = syscon_node_to_regmap(dev->of_node); 317 if (IS_ERR(map)) { 318 dev_err(dev, "no syscon regmap\n"); 319 return PTR_ERR(map); 320 } 321 322 /* SoC generations share common layouts but have different divisors */ 323 soc_data = of_device_get_match_data(dev); 324 if (!soc_data) { 325 dev_err(dev, "no match data for platform\n"); 326 return -EINVAL; 327 } 328 329 /* UART clock div13 setting */ 330 regmap_read(map, ASPEED_MISC_CTRL, &val); 331 if (val & UART_DIV13_EN) 332 rate = 24000000 / 13; 333 else 334 rate = 24000000; 335 /* TODO: Find the parent data for the uart clock */ 336 hw = clk_hw_register_fixed_rate(dev, "uart", NULL, 0, rate); 337 if (IS_ERR(hw)) 338 return PTR_ERR(hw); 339 aspeed_clk_data->hws[ASPEED_CLK_UART] = hw; 340 341 /* 342 * Memory controller (M-PLL) PLL. This clock is configured by the 343 * bootloader, and is exposed to Linux as a read-only clock rate. 344 */ 345 regmap_read(map, ASPEED_MPLL_PARAM, &val); 346 hw = soc_data->calc_pll("mpll", val); 347 if (IS_ERR(hw)) 348 return PTR_ERR(hw); 349 aspeed_clk_data->hws[ASPEED_CLK_MPLL] = hw; 350 351 /* SD/SDIO clock divider (TODO: There's a gate too) */ 352 hw = clk_hw_register_divider_table(dev, "sdio", "hpll", 0, 353 scu_base + ASPEED_CLK_SELECTION, 12, 3, 0, 354 soc_data->div_table, 355 &aspeed_clk_lock); 356 if (IS_ERR(hw)) 357 return PTR_ERR(hw); 358 aspeed_clk_data->hws[ASPEED_CLK_SDIO] = hw; 359 360 /* MAC AHB bus clock divider */ 361 hw = clk_hw_register_divider_table(dev, "mac", "hpll", 0, 362 scu_base + ASPEED_CLK_SELECTION, 16, 3, 0, 363 soc_data->mac_div_table, 364 &aspeed_clk_lock); 365 if (IS_ERR(hw)) 366 return PTR_ERR(hw); 367 aspeed_clk_data->hws[ASPEED_CLK_MAC] = hw; 368 369 /* LPC Host (LHCLK) clock divider */ 370 hw = clk_hw_register_divider_table(dev, "lhclk", "hpll", 0, 371 scu_base + ASPEED_CLK_SELECTION, 20, 3, 0, 372 soc_data->div_table, 373 &aspeed_clk_lock); 374 if (IS_ERR(hw)) 375 return PTR_ERR(hw); 376 aspeed_clk_data->hws[ASPEED_CLK_LHCLK] = hw; 377 378 /* P-Bus (BCLK) clock divider */ 379 hw = clk_hw_register_divider_table(dev, "bclk", "hpll", 0, 380 scu_base + ASPEED_CLK_SELECTION_2, 0, 2, 0, 381 soc_data->div_table, 382 &aspeed_clk_lock); 383 if (IS_ERR(hw)) 384 return PTR_ERR(hw); 385 aspeed_clk_data->hws[ASPEED_CLK_BCLK] = hw; 386 387 /* 388 * TODO: There are a number of clocks that not included in this driver 389 * as more information is required: 390 * D2-PLL 391 * D-PLL 392 * YCLK 393 * RGMII 394 * RMII 395 * UART[1..5] clock source mux 396 * Video Engine (ECLK) mux and clock divider 397 */ 398 399 for (i = 0; i < ARRAY_SIZE(aspeed_gates); i++) { 400 const struct aspeed_gate_data *gd = &aspeed_gates[i]; 401 402 hw = aspeed_clk_hw_register_gate(dev, 403 gd->name, 404 gd->parent_name, 405 gd->flags, 406 map, 407 gd->clock_idx, 408 gd->reset_idx, 409 CLK_GATE_SET_TO_DISABLE, 410 &aspeed_clk_lock); 411 if (IS_ERR(hw)) 412 return PTR_ERR(hw); 413 aspeed_clk_data->hws[i] = hw; 414 } 415 416 return 0; 417 }; 418 419 static const struct of_device_id aspeed_clk_dt_ids[] = { 420 { .compatible = "aspeed,ast2400-scu", .data = &ast2400_data }, 421 { .compatible = "aspeed,ast2500-scu", .data = &ast2500_data }, 422 { } 423 }; 424 425 static struct platform_driver aspeed_clk_driver = { 426 .probe = aspeed_clk_probe, 427 .driver = { 428 .name = "aspeed-clk", 429 .of_match_table = aspeed_clk_dt_ids, 430 .suppress_bind_attrs = true, 431 }, 432 }; 433 builtin_platform_driver(aspeed_clk_driver); 434 435 static void __init aspeed_ast2400_cc(struct regmap *map) 436 { 437 struct clk_hw *hw; 438 u32 val, freq, div; 439 440 /* 441 * CLKIN is the crystal oscillator, 24, 48 or 25MHz selected by 442 * strapping 443 */ 444 regmap_read(map, ASPEED_STRAP, &val); 445 if (val & CLKIN_25MHZ_EN) 446 freq = 25000000; 447 else if (val & AST2400_CLK_SOURCE_SEL) 448 freq = 48000000; 449 else 450 freq = 24000000; 451 hw = clk_hw_register_fixed_rate(NULL, "clkin", NULL, 0, freq); 452 pr_debug("clkin @%u MHz\n", freq / 1000000); 453 454 /* 455 * High-speed PLL clock derived from the crystal. This the CPU clock, 456 * and we assume that it is enabled 457 */ 458 regmap_read(map, ASPEED_HPLL_PARAM, &val); 459 WARN(val & AST2400_HPLL_STRAPPED, "hpll is strapped not configured"); 460 aspeed_clk_data->hws[ASPEED_CLK_HPLL] = aspeed_ast2400_calc_pll("hpll", val); 461 462 /* 463 * Strap bits 11:10 define the CPU/AHB clock frequency ratio (aka HCLK) 464 * 00: Select CPU:AHB = 1:1 465 * 01: Select CPU:AHB = 2:1 466 * 10: Select CPU:AHB = 4:1 467 * 11: Select CPU:AHB = 3:1 468 */ 469 regmap_read(map, ASPEED_STRAP, &val); 470 val = (val >> 10) & 0x3; 471 div = val + 1; 472 if (div == 3) 473 div = 4; 474 else if (div == 4) 475 div = 3; 476 hw = clk_hw_register_fixed_factor(NULL, "ahb", "hpll", 0, 1, div); 477 aspeed_clk_data->hws[ASPEED_CLK_AHB] = hw; 478 479 /* APB clock clock selection register SCU08 (aka PCLK) */ 480 hw = clk_hw_register_divider_table(NULL, "apb", "hpll", 0, 481 scu_base + ASPEED_CLK_SELECTION, 23, 3, 0, 482 ast2400_div_table, 483 &aspeed_clk_lock); 484 aspeed_clk_data->hws[ASPEED_CLK_APB] = hw; 485 } 486 487 static void __init aspeed_ast2500_cc(struct regmap *map) 488 { 489 struct clk_hw *hw; 490 u32 val, freq, div; 491 492 /* CLKIN is the crystal oscillator, 24 or 25MHz selected by strapping */ 493 regmap_read(map, ASPEED_STRAP, &val); 494 if (val & CLKIN_25MHZ_EN) 495 freq = 25000000; 496 else 497 freq = 24000000; 498 hw = clk_hw_register_fixed_rate(NULL, "clkin", NULL, 0, freq); 499 pr_debug("clkin @%u MHz\n", freq / 1000000); 500 501 /* 502 * High-speed PLL clock derived from the crystal. This the CPU clock, 503 * and we assume that it is enabled 504 */ 505 regmap_read(map, ASPEED_HPLL_PARAM, &val); 506 aspeed_clk_data->hws[ASPEED_CLK_HPLL] = aspeed_ast2500_calc_pll("hpll", val); 507 508 /* Strap bits 11:9 define the AXI/AHB clock frequency ratio (aka HCLK)*/ 509 regmap_read(map, ASPEED_STRAP, &val); 510 val = (val >> 9) & 0x7; 511 WARN(val == 0, "strapping is zero: cannot determine ahb clock"); 512 div = 2 * (val + 1); 513 hw = clk_hw_register_fixed_factor(NULL, "ahb", "hpll", 0, 1, div); 514 aspeed_clk_data->hws[ASPEED_CLK_AHB] = hw; 515 516 /* APB clock clock selection register SCU08 (aka PCLK) */ 517 regmap_read(map, ASPEED_CLK_SELECTION, &val); 518 val = (val >> 23) & 0x7; 519 div = 4 * (val + 1); 520 hw = clk_hw_register_fixed_factor(NULL, "apb", "hpll", 0, 1, div); 521 aspeed_clk_data->hws[ASPEED_CLK_APB] = hw; 522 }; 523 524 static void __init aspeed_cc_init(struct device_node *np) 525 { 526 struct regmap *map; 527 u32 val; 528 int ret; 529 int i; 530 531 scu_base = of_iomap(np, 0); 532 if (IS_ERR(scu_base)) 533 return; 534 535 aspeed_clk_data = kzalloc(sizeof(*aspeed_clk_data) + 536 sizeof(*aspeed_clk_data->hws) * ASPEED_NUM_CLKS, 537 GFP_KERNEL); 538 if (!aspeed_clk_data) 539 return; 540 541 /* 542 * This way all clocks fetched before the platform device probes, 543 * except those we assign here for early use, will be deferred. 544 */ 545 for (i = 0; i < ASPEED_NUM_CLKS; i++) 546 aspeed_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER); 547 548 map = syscon_node_to_regmap(np); 549 if (IS_ERR(map)) { 550 pr_err("no syscon regmap\n"); 551 return; 552 } 553 /* 554 * We check that the regmap works on this very first access, 555 * but as this is an MMIO-backed regmap, subsequent regmap 556 * access is not going to fail and we skip error checks from 557 * this point. 558 */ 559 ret = regmap_read(map, ASPEED_STRAP, &val); 560 if (ret) { 561 pr_err("failed to read strapping register\n"); 562 return; 563 } 564 565 if (of_device_is_compatible(np, "aspeed,ast2400-scu")) 566 aspeed_ast2400_cc(map); 567 else if (of_device_is_compatible(np, "aspeed,ast2500-scu")) 568 aspeed_ast2500_cc(map); 569 else 570 pr_err("unknown platform, failed to add clocks\n"); 571 572 aspeed_clk_data->num = ASPEED_NUM_CLKS; 573 ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, aspeed_clk_data); 574 if (ret) 575 pr_err("failed to add DT provider: %d\n", ret); 576 }; 577 CLK_OF_DECLARE_DRIVER(aspeed_cc_g5, "aspeed,ast2500-scu", aspeed_cc_init); 578 CLK_OF_DECLARE_DRIVER(aspeed_cc_g4, "aspeed,ast2400-scu", aspeed_cc_init); 579