1 /* 2 * Synopsys HSDK SDP CGU clock driver 3 * 4 * Copyright (C) 2017 Synopsys 5 * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> 6 * 7 * This file is licensed under the terms of the GNU General Public 8 * License version 2. This program is licensed "as is" without any 9 * warranty of any kind, whether express or implied. 10 */ 11 12 #include <common.h> 13 #include <clk-uclass.h> 14 #include <div64.h> 15 #include <dm.h> 16 #include <linux/io.h> 17 18 /* 19 * Synopsys ARC HSDK clock tree. 20 * 21 * ------------------ 22 * | 33.33 MHz xtal | 23 * ------------------ 24 * | 25 * | ----------- 26 * |-->| ARC PLL | 27 * | ----------- 28 * | | 29 * | |-->|CGU_ARC_IDIV|-----------> 30 * | |-->|CREG_CORE_IF_DIV|-------> 31 * | 32 * | -------------- 33 * |-->| SYSTEM PLL | 34 * | -------------- 35 * | | 36 * | |-->|CGU_SYS_IDIV_APB|-------> 37 * | |-->|CGU_SYS_IDIV_AXI|-------> 38 * | |-->|CGU_SYS_IDIV_*|---------> 39 * | |-->|CGU_SYS_IDIV_EBI_REF|---> 40 * | 41 * | -------------- 42 * |-->| TUNNEL PLL | 43 * | -------------- 44 * | | 45 * | |-->|CGU_TUN_IDIV|-----------> 46 * | 47 * | ------------ 48 * |-->| HDMI PLL | 49 * | ------------ 50 * | | 51 * | |-->|CGU_HDMI_IDIV_APB|------> 52 * | 53 * | ----------- 54 * |-->| DDR PLL | 55 * ----------- 56 * | 57 * |----------------------------> 58 */ 59 60 DECLARE_GLOBAL_DATA_PTR; 61 62 #define CGU_ARC_IDIV 0x080 63 #define CGU_TUN_IDIV 0x380 64 #define CGU_HDMI_IDIV_APB 0x480 65 #define CGU_SYS_IDIV_APB 0x180 66 #define CGU_SYS_IDIV_AXI 0x190 67 #define CGU_SYS_IDIV_ETH 0x1A0 68 #define CGU_SYS_IDIV_USB 0x1B0 69 #define CGU_SYS_IDIV_SDIO 0x1C0 70 #define CGU_SYS_IDIV_HDMI 0x1D0 71 #define CGU_SYS_IDIV_GFX_CORE 0x1E0 72 #define CGU_SYS_IDIV_GFX_DMA 0x1F0 73 #define CGU_SYS_IDIV_GFX_CFG 0x200 74 #define CGU_SYS_IDIV_DMAC_CORE 0x210 75 #define CGU_SYS_IDIV_DMAC_CFG 0x220 76 #define CGU_SYS_IDIV_SDIO_REF 0x230 77 #define CGU_SYS_IDIV_SPI_REF 0x240 78 #define CGU_SYS_IDIV_I2C_REF 0x250 79 #define CGU_SYS_IDIV_UART_REF 0x260 80 #define CGU_SYS_IDIV_EBI_REF 0x270 81 82 #define CGU_IDIV_MASK 0xFF /* All idiv have 8 significant bits */ 83 84 #define CGU_ARC_PLL 0x0 85 #define CGU_SYS_PLL 0x10 86 #define CGU_DDR_PLL 0x20 87 #define CGU_TUN_PLL 0x30 88 #define CGU_HDMI_PLL 0x40 89 90 #define CGU_PLL_CTRL 0x000 /* ARC PLL control register */ 91 #define CGU_PLL_STATUS 0x004 /* ARC PLL status register */ 92 #define CGU_PLL_FMEAS 0x008 /* ARC PLL frequency measurement register */ 93 #define CGU_PLL_MON 0x00C /* ARC PLL monitor register */ 94 95 #define CGU_PLL_CTRL_ODIV_SHIFT 2 96 #define CGU_PLL_CTRL_IDIV_SHIFT 4 97 #define CGU_PLL_CTRL_FBDIV_SHIFT 9 98 #define CGU_PLL_CTRL_BAND_SHIFT 20 99 100 #define CGU_PLL_CTRL_ODIV_MASK GENMASK(3, CGU_PLL_CTRL_ODIV_SHIFT) 101 #define CGU_PLL_CTRL_IDIV_MASK GENMASK(8, CGU_PLL_CTRL_IDIV_SHIFT) 102 #define CGU_PLL_CTRL_FBDIV_MASK GENMASK(15, CGU_PLL_CTRL_FBDIV_SHIFT) 103 104 #define CGU_PLL_CTRL_PD BIT(0) 105 #define CGU_PLL_CTRL_BYPASS BIT(1) 106 107 #define CGU_PLL_STATUS_LOCK BIT(0) 108 #define CGU_PLL_STATUS_ERR BIT(1) 109 110 #define HSDK_PLL_MAX_LOCK_TIME 100 /* 100 us */ 111 112 #define CREG_CORE_IF_DIV 0x000 /* ARC CORE interface divider */ 113 #define CORE_IF_CLK_THRESHOLD_HZ 500000000 114 #define CREG_CORE_IF_CLK_DIV_1 0x0 115 #define CREG_CORE_IF_CLK_DIV_2 0x1 116 117 #define PARENT_RATE 33333333 /* fixed clock - xtal */ 118 #define CGU_MAX_CLOCKS 24 119 120 struct hsdk_pll_cfg { 121 u32 rate; 122 u32 idiv; 123 u32 fbdiv; 124 u32 odiv; 125 u32 band; 126 }; 127 128 static const struct hsdk_pll_cfg asdt_pll_cfg[] = { 129 { 100000000, 0, 11, 3, 0 }, 130 { 125000000, 0, 14, 3, 0 }, 131 { 133000000, 0, 15, 3, 0 }, 132 { 150000000, 0, 17, 3, 0 }, 133 { 200000000, 1, 47, 3, 0 }, 134 { 233000000, 1, 27, 2, 0 }, 135 { 300000000, 1, 35, 2, 0 }, 136 { 333000000, 1, 39, 2, 0 }, 137 { 400000000, 1, 47, 2, 0 }, 138 { 500000000, 0, 14, 1, 0 }, 139 { 600000000, 0, 17, 1, 0 }, 140 { 700000000, 0, 20, 1, 0 }, 141 { 800000000, 0, 23, 1, 0 }, 142 { 900000000, 1, 26, 0, 0 }, 143 { 1000000000, 1, 29, 0, 0 }, 144 { 1100000000, 1, 32, 0, 0 }, 145 { 1200000000, 1, 35, 0, 0 }, 146 { 1300000000, 1, 38, 0, 0 }, 147 { 1400000000, 1, 41, 0, 0 }, 148 { 1500000000, 1, 44, 0, 0 }, 149 { 1600000000, 1, 47, 0, 0 }, 150 {} 151 }; 152 153 static const struct hsdk_pll_cfg hdmi_pll_cfg[] = { 154 { 297000000, 0, 21, 2, 0 }, 155 { 540000000, 0, 19, 1, 0 }, 156 { 594000000, 0, 21, 1, 0 }, 157 {} 158 }; 159 160 struct hsdk_cgu_clk { 161 /* CGU block register */ 162 void __iomem *cgu_regs; 163 /* CREG block register */ 164 void __iomem *creg_regs; 165 166 /* PLLs registers */ 167 void __iomem *regs; 168 /* PLLs special registers */ 169 void __iomem *spec_regs; 170 /* PLLs devdata */ 171 const struct hsdk_pll_devdata *pll_devdata; 172 173 /* Dividers registers */ 174 void __iomem *idiv_regs; 175 }; 176 177 struct hsdk_pll_devdata { 178 const struct hsdk_pll_cfg *pll_cfg; 179 int (*update_rate)(struct hsdk_cgu_clk *clk, unsigned long rate, 180 const struct hsdk_pll_cfg *cfg); 181 }; 182 183 static int hsdk_pll_core_update_rate(struct hsdk_cgu_clk *, unsigned long, 184 const struct hsdk_pll_cfg *); 185 static int hsdk_pll_comm_update_rate(struct hsdk_cgu_clk *, unsigned long, 186 const struct hsdk_pll_cfg *); 187 188 static const struct hsdk_pll_devdata core_pll_dat = { 189 .pll_cfg = asdt_pll_cfg, 190 .update_rate = hsdk_pll_core_update_rate, 191 }; 192 193 static const struct hsdk_pll_devdata sdt_pll_dat = { 194 .pll_cfg = asdt_pll_cfg, 195 .update_rate = hsdk_pll_comm_update_rate, 196 }; 197 198 static const struct hsdk_pll_devdata hdmi_pll_dat = { 199 .pll_cfg = hdmi_pll_cfg, 200 .update_rate = hsdk_pll_comm_update_rate, 201 }; 202 203 static ulong idiv_set(struct clk *, ulong); 204 static ulong idiv_get(struct clk *); 205 static int idiv_off(struct clk *); 206 static ulong pll_set(struct clk *, ulong); 207 static ulong pll_get(struct clk *); 208 209 struct hsdk_cgu_clock_map { 210 u32 cgu_pll_oft; 211 u32 creg_div_oft; 212 u32 cgu_div_oft; 213 const struct hsdk_pll_devdata *pll_devdata; 214 ulong (*get_rate)(struct clk *clk); 215 ulong (*set_rate)(struct clk *clk, ulong rate); 216 int (*disable)(struct clk *clk); 217 }; 218 219 static const struct hsdk_cgu_clock_map clock_map[] = { 220 { CGU_ARC_PLL, 0, 0, &core_pll_dat, pll_get, pll_set, NULL }, 221 { CGU_ARC_PLL, 0, CGU_ARC_IDIV, &core_pll_dat, idiv_get, idiv_set, idiv_off }, 222 { CGU_DDR_PLL, 0, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, 223 { CGU_SYS_PLL, 0, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, 224 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_APB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 225 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_AXI, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 226 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_ETH, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 227 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_USB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 228 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_SDIO, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 229 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_HDMI, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 230 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_GFX_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 231 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_GFX_DMA, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 232 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_GFX_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 233 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_DMAC_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 234 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_DMAC_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 235 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_SDIO_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 236 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_SPI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 237 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_I2C_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 238 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_UART_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 239 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_EBI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 240 { CGU_TUN_PLL, 0, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, 241 { CGU_TUN_PLL, 0, CGU_TUN_IDIV, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 242 { CGU_HDMI_PLL, 0, 0, &hdmi_pll_dat, pll_get, pll_set, NULL }, 243 { CGU_HDMI_PLL, 0, CGU_HDMI_IDIV_APB, &hdmi_pll_dat, idiv_get, idiv_set, idiv_off } 244 }; 245 246 static inline void hsdk_idiv_write(struct hsdk_cgu_clk *clk, u32 val) 247 { 248 iowrite32(val, clk->idiv_regs); 249 } 250 251 static inline u32 hsdk_idiv_read(struct hsdk_cgu_clk *clk) 252 { 253 return ioread32(clk->idiv_regs); 254 } 255 256 static inline void hsdk_pll_write(struct hsdk_cgu_clk *clk, u32 reg, u32 val) 257 { 258 iowrite32(val, clk->regs + reg); 259 } 260 261 static inline u32 hsdk_pll_read(struct hsdk_cgu_clk *clk, u32 reg) 262 { 263 return ioread32(clk->regs + reg); 264 } 265 266 static inline void hsdk_pll_spcwrite(struct hsdk_cgu_clk *clk, u32 reg, u32 val) 267 { 268 iowrite32(val, clk->spec_regs + reg); 269 } 270 271 static inline u32 hsdk_pll_spcread(struct hsdk_cgu_clk *clk, u32 reg) 272 { 273 return ioread32(clk->spec_regs + reg); 274 } 275 276 static inline void hsdk_pll_set_cfg(struct hsdk_cgu_clk *clk, 277 const struct hsdk_pll_cfg *cfg) 278 { 279 u32 val = 0; 280 281 /* Powerdown and Bypass bits should be cleared */ 282 val |= cfg->idiv << CGU_PLL_CTRL_IDIV_SHIFT; 283 val |= cfg->fbdiv << CGU_PLL_CTRL_FBDIV_SHIFT; 284 val |= cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT; 285 val |= cfg->band << CGU_PLL_CTRL_BAND_SHIFT; 286 287 pr_debug("write configurarion: %#x\n", val); 288 289 hsdk_pll_write(clk, CGU_PLL_CTRL, val); 290 } 291 292 static inline bool hsdk_pll_is_locked(struct hsdk_cgu_clk *clk) 293 { 294 return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_LOCK); 295 } 296 297 static inline bool hsdk_pll_is_err(struct hsdk_cgu_clk *clk) 298 { 299 return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_ERR); 300 } 301 302 static ulong pll_get(struct clk *sclk) 303 { 304 u32 val; 305 u64 rate; 306 u32 idiv, fbdiv, odiv; 307 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 308 309 val = hsdk_pll_read(clk, CGU_PLL_CTRL); 310 311 pr_debug("current configurarion: %#x\n", val); 312 313 /* Check if PLL is disabled */ 314 if (val & CGU_PLL_CTRL_PD) 315 return 0; 316 317 /* Check if PLL is bypassed */ 318 if (val & CGU_PLL_CTRL_BYPASS) 319 return PARENT_RATE; 320 321 /* input divider = reg.idiv + 1 */ 322 idiv = 1 + ((val & CGU_PLL_CTRL_IDIV_MASK) >> CGU_PLL_CTRL_IDIV_SHIFT); 323 /* fb divider = 2*(reg.fbdiv + 1) */ 324 fbdiv = 2 * (1 + ((val & CGU_PLL_CTRL_FBDIV_MASK) >> CGU_PLL_CTRL_FBDIV_SHIFT)); 325 /* output divider = 2^(reg.odiv) */ 326 odiv = 1 << ((val & CGU_PLL_CTRL_ODIV_MASK) >> CGU_PLL_CTRL_ODIV_SHIFT); 327 328 rate = (u64)PARENT_RATE * fbdiv; 329 do_div(rate, idiv * odiv); 330 331 return rate; 332 } 333 334 static unsigned long hsdk_pll_round_rate(struct clk *sclk, unsigned long rate) 335 { 336 int i; 337 unsigned long best_rate; 338 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 339 const struct hsdk_pll_cfg *pll_cfg = clk->pll_devdata->pll_cfg; 340 341 if (pll_cfg[0].rate == 0) 342 return -EINVAL; 343 344 best_rate = pll_cfg[0].rate; 345 346 for (i = 1; pll_cfg[i].rate != 0; i++) { 347 if (abs(rate - pll_cfg[i].rate) < abs(rate - best_rate)) 348 best_rate = pll_cfg[i].rate; 349 } 350 351 pr_debug("chosen best rate: %lu\n", best_rate); 352 353 return best_rate; 354 } 355 356 static int hsdk_pll_comm_update_rate(struct hsdk_cgu_clk *clk, 357 unsigned long rate, 358 const struct hsdk_pll_cfg *cfg) 359 { 360 hsdk_pll_set_cfg(clk, cfg); 361 362 /* 363 * Wait until CGU relocks and check error status. 364 * If after timeout CGU is unlocked yet return error. 365 */ 366 udelay(HSDK_PLL_MAX_LOCK_TIME); 367 if (!hsdk_pll_is_locked(clk)) 368 return -ETIMEDOUT; 369 370 if (hsdk_pll_is_err(clk)) 371 return -EINVAL; 372 373 return 0; 374 } 375 376 static int hsdk_pll_core_update_rate(struct hsdk_cgu_clk *clk, 377 unsigned long rate, 378 const struct hsdk_pll_cfg *cfg) 379 { 380 /* 381 * When core clock exceeds 500MHz, the divider for the interface 382 * clock must be programmed to div-by-2. 383 */ 384 if (rate > CORE_IF_CLK_THRESHOLD_HZ) 385 hsdk_pll_spcwrite(clk, CREG_CORE_IF_DIV, CREG_CORE_IF_CLK_DIV_2); 386 387 hsdk_pll_set_cfg(clk, cfg); 388 389 /* 390 * Wait until CGU relocks and check error status. 391 * If after timeout CGU is unlocked yet return error. 392 */ 393 udelay(HSDK_PLL_MAX_LOCK_TIME); 394 if (!hsdk_pll_is_locked(clk)) 395 return -ETIMEDOUT; 396 397 if (hsdk_pll_is_err(clk)) 398 return -EINVAL; 399 400 /* 401 * Program divider to div-by-1 if we succesfuly set core clock below 402 * 500MHz threshold. 403 */ 404 if (rate <= CORE_IF_CLK_THRESHOLD_HZ) 405 hsdk_pll_spcwrite(clk, CREG_CORE_IF_DIV, CREG_CORE_IF_CLK_DIV_1); 406 407 return 0; 408 } 409 410 static ulong pll_set(struct clk *sclk, ulong rate) 411 { 412 int i; 413 unsigned long best_rate; 414 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 415 const struct hsdk_pll_cfg *pll_cfg = clk->pll_devdata->pll_cfg; 416 417 best_rate = hsdk_pll_round_rate(sclk, rate); 418 419 for (i = 0; pll_cfg[i].rate != 0; i++) { 420 if (pll_cfg[i].rate == best_rate) { 421 return clk->pll_devdata->update_rate(clk, best_rate, 422 &pll_cfg[i]); 423 } 424 } 425 426 pr_err("invalid rate=%ld, parent_rate=%d\n", best_rate, PARENT_RATE); 427 428 return -EINVAL; 429 } 430 431 static int idiv_off(struct clk *sclk) 432 { 433 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 434 435 hsdk_idiv_write(clk, 0); 436 437 return 0; 438 } 439 440 static ulong idiv_get(struct clk *sclk) 441 { 442 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 443 ulong parent_rate = pll_get(sclk); 444 u32 div_factor = hsdk_idiv_read(clk); 445 446 div_factor &= CGU_IDIV_MASK; 447 448 pr_debug("current configurarion: %#x (%d)\n", div_factor, div_factor); 449 450 if (div_factor == 0) 451 return 0; 452 453 return parent_rate / div_factor; 454 } 455 456 static ulong idiv_set(struct clk *sclk, ulong rate) 457 { 458 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 459 ulong parent_rate = pll_get(sclk); 460 u32 div_factor; 461 462 div_factor = parent_rate / rate; 463 if (abs(rate - parent_rate / (div_factor + 1)) <= 464 abs(rate - parent_rate / div_factor)) { 465 div_factor += 1; 466 } 467 468 if (div_factor & ~CGU_IDIV_MASK) { 469 pr_err("invalid rate=%ld, parent_rate=%ld, div=%d: max divider valie is%d\n", 470 rate, parent_rate, div_factor, CGU_IDIV_MASK); 471 472 div_factor = CGU_IDIV_MASK; 473 } 474 475 if (div_factor == 0) { 476 pr_err("invalid rate=%ld, parent_rate=%ld, div=%d: min divider valie is 1\n", 477 rate, parent_rate, div_factor); 478 479 div_factor = 1; 480 } 481 482 hsdk_idiv_write(clk, div_factor); 483 484 return 0; 485 } 486 487 static int hsdk_prepare_clock_tree_branch(struct clk *sclk) 488 { 489 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 490 491 if (sclk->id >= CGU_MAX_CLOCKS) 492 return -EINVAL; 493 494 clk->pll_devdata = clock_map[sclk->id].pll_devdata; 495 clk->regs = clk->cgu_regs + clock_map[sclk->id].cgu_pll_oft; 496 clk->spec_regs = clk->creg_regs + clock_map[sclk->id].creg_div_oft; 497 clk->idiv_regs = clk->cgu_regs + clock_map[sclk->id].cgu_div_oft; 498 499 return 0; 500 } 501 502 static ulong hsdk_cgu_get_rate(struct clk *sclk) 503 { 504 if (hsdk_prepare_clock_tree_branch(sclk)) 505 return -EINVAL; 506 507 return clock_map[sclk->id].get_rate(sclk); 508 } 509 510 static ulong hsdk_cgu_set_rate(struct clk *sclk, ulong rate) 511 { 512 if (hsdk_prepare_clock_tree_branch(sclk)) 513 return -EINVAL; 514 515 return clock_map[sclk->id].set_rate(sclk, rate); 516 } 517 518 static int hsdk_cgu_disable(struct clk *sclk) 519 { 520 if (hsdk_prepare_clock_tree_branch(sclk)) 521 return -EINVAL; 522 523 if (clock_map[sclk->id].disable) 524 return clock_map[sclk->id].disable(sclk); 525 526 return -ENOTSUPP; 527 } 528 529 static const struct clk_ops hsdk_cgu_ops = { 530 .set_rate = hsdk_cgu_set_rate, 531 .get_rate = hsdk_cgu_get_rate, 532 .disable = hsdk_cgu_disable, 533 }; 534 535 static int hsdk_cgu_clk_probe(struct udevice *dev) 536 { 537 struct hsdk_cgu_clk *pll_clk = dev_get_priv(dev); 538 539 BUILD_BUG_ON(ARRAY_SIZE(clock_map) != CGU_MAX_CLOCKS); 540 541 pll_clk->cgu_regs = (void __iomem *)devfdt_get_addr_index(dev, 0); 542 if (!pll_clk->cgu_regs) 543 return -EINVAL; 544 545 pll_clk->creg_regs = (void __iomem *)devfdt_get_addr_index(dev, 1); 546 if (!pll_clk->creg_regs) 547 return -EINVAL; 548 549 return 0; 550 } 551 552 static const struct udevice_id hsdk_cgu_clk_id[] = { 553 { .compatible = "snps,hsdk-cgu-clock" }, 554 { } 555 }; 556 557 U_BOOT_DRIVER(hsdk_cgu_clk) = { 558 .name = "hsdk-cgu-clk", 559 .id = UCLASS_CLK, 560 .of_match = hsdk_cgu_clk_id, 561 .probe = hsdk_cgu_clk_probe, 562 .platdata_auto_alloc_size = sizeof(struct hsdk_cgu_clk), 563 .ops = &hsdk_cgu_ops, 564 }; 565