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_TUN|-----------> 46 * | |-->|CGU_TUN_IDIV_ROM|-----------> 47 * | |-->|CGU_TUN_IDIV_PWM|-----------> 48 * | 49 * | ------------ 50 * |-->| HDMI PLL | 51 * | ------------ 52 * | | 53 * | |-->|CGU_HDMI_IDIV_APB|------> 54 * | 55 * | ----------- 56 * |-->| DDR PLL | 57 * ----------- 58 * | 59 * |----------------------------> 60 */ 61 62 #define CGU_ARC_IDIV 0x080 63 #define CGU_TUN_IDIV_TUN 0x380 64 #define CGU_TUN_IDIV_ROM 0x390 65 #define CGU_TUN_IDIV_PWM 0x3A0 66 #define CGU_HDMI_IDIV_APB 0x480 67 #define CGU_SYS_IDIV_APB 0x180 68 #define CGU_SYS_IDIV_AXI 0x190 69 #define CGU_SYS_IDIV_ETH 0x1A0 70 #define CGU_SYS_IDIV_USB 0x1B0 71 #define CGU_SYS_IDIV_SDIO 0x1C0 72 #define CGU_SYS_IDIV_HDMI 0x1D0 73 #define CGU_SYS_IDIV_GFX_CORE 0x1E0 74 #define CGU_SYS_IDIV_GFX_DMA 0x1F0 75 #define CGU_SYS_IDIV_GFX_CFG 0x200 76 #define CGU_SYS_IDIV_DMAC_CORE 0x210 77 #define CGU_SYS_IDIV_DMAC_CFG 0x220 78 #define CGU_SYS_IDIV_SDIO_REF 0x230 79 #define CGU_SYS_IDIV_SPI_REF 0x240 80 #define CGU_SYS_IDIV_I2C_REF 0x250 81 #define CGU_SYS_IDIV_UART_REF 0x260 82 #define CGU_SYS_IDIV_EBI_REF 0x270 83 84 #define CGU_IDIV_MASK 0xFF /* All idiv have 8 significant bits */ 85 86 #define CGU_ARC_PLL 0x0 87 #define CGU_SYS_PLL 0x10 88 #define CGU_DDR_PLL 0x20 89 #define CGU_TUN_PLL 0x30 90 #define CGU_HDMI_PLL 0x40 91 92 #define CGU_PLL_CTRL 0x000 /* ARC PLL control register */ 93 #define CGU_PLL_STATUS 0x004 /* ARC PLL status register */ 94 #define CGU_PLL_FMEAS 0x008 /* ARC PLL frequency measurement register */ 95 #define CGU_PLL_MON 0x00C /* ARC PLL monitor register */ 96 97 #define CGU_PLL_CTRL_ODIV_SHIFT 2 98 #define CGU_PLL_CTRL_IDIV_SHIFT 4 99 #define CGU_PLL_CTRL_FBDIV_SHIFT 9 100 #define CGU_PLL_CTRL_BAND_SHIFT 20 101 102 #define CGU_PLL_CTRL_ODIV_MASK GENMASK(3, CGU_PLL_CTRL_ODIV_SHIFT) 103 #define CGU_PLL_CTRL_IDIV_MASK GENMASK(8, CGU_PLL_CTRL_IDIV_SHIFT) 104 #define CGU_PLL_CTRL_FBDIV_MASK GENMASK(15, CGU_PLL_CTRL_FBDIV_SHIFT) 105 106 #define CGU_PLL_CTRL_PD BIT(0) 107 #define CGU_PLL_CTRL_BYPASS BIT(1) 108 109 #define CGU_PLL_STATUS_LOCK BIT(0) 110 #define CGU_PLL_STATUS_ERR BIT(1) 111 112 #define HSDK_PLL_MAX_LOCK_TIME 100 /* 100 us */ 113 114 #define CREG_CORE_IF_DIV 0x000 /* ARC CORE interface divider */ 115 #define CORE_IF_CLK_THRESHOLD_HZ 500000000 116 #define CREG_CORE_IF_CLK_DIV_1 0x0 117 #define CREG_CORE_IF_CLK_DIV_2 0x1 118 119 #define MIN_PLL_RATE 100000000 /* 100 MHz */ 120 #define PARENT_RATE 33333333 /* fixed clock - xtal */ 121 #define CGU_MAX_CLOCKS 26 122 123 #define CGU_SYS_CLOCKS 16 124 #define MAX_AXI_CLOCKS 4 125 126 #define CGU_TUN_CLOCKS 3 127 #define MAX_TUN_CLOCKS 6 128 129 struct hsdk_tun_idiv_cfg { 130 u32 oft; 131 u8 val[MAX_TUN_CLOCKS]; 132 }; 133 134 struct hsdk_tun_clk_cfg { 135 const u32 clk_rate[MAX_TUN_CLOCKS]; 136 const u32 pll_rate[MAX_TUN_CLOCKS]; 137 const struct hsdk_tun_idiv_cfg idiv[CGU_TUN_CLOCKS]; 138 }; 139 140 static const struct hsdk_tun_clk_cfg tun_clk_cfg = { 141 { 25000000, 50000000, 75000000, 100000000, 125000000, 150000000 }, 142 { 600000000, 600000000, 600000000, 600000000, 700000000, 600000000 }, { 143 { CGU_TUN_IDIV_TUN, { 24, 12, 8, 6, 6, 4 } }, 144 { CGU_TUN_IDIV_ROM, { 4, 4, 4, 4, 5, 4 } }, 145 { CGU_TUN_IDIV_PWM, { 8, 8, 8, 8, 10, 8 } } 146 } 147 }; 148 149 struct hsdk_sys_idiv_cfg { 150 u32 oft; 151 u8 val[MAX_AXI_CLOCKS]; 152 }; 153 154 struct hsdk_axi_clk_cfg { 155 const u32 clk_rate[MAX_AXI_CLOCKS]; 156 const u32 pll_rate[MAX_AXI_CLOCKS]; 157 const struct hsdk_sys_idiv_cfg idiv[CGU_SYS_CLOCKS]; 158 }; 159 160 static const struct hsdk_axi_clk_cfg axi_clk_cfg = { 161 { 200000000, 400000000, 600000000, 800000000 }, 162 { 800000000, 800000000, 600000000, 800000000 }, { 163 { CGU_SYS_IDIV_APB, { 4, 4, 3, 4 } }, /* APB */ 164 { CGU_SYS_IDIV_AXI, { 4, 2, 1, 1 } }, /* AXI */ 165 { CGU_SYS_IDIV_ETH, { 2, 2, 2, 2 } }, /* ETH */ 166 { CGU_SYS_IDIV_USB, { 2, 2, 2, 2 } }, /* USB */ 167 { CGU_SYS_IDIV_SDIO, { 2, 2, 2, 2 } }, /* SDIO */ 168 { CGU_SYS_IDIV_HDMI, { 2, 2, 2, 2 } }, /* HDMI */ 169 { CGU_SYS_IDIV_GFX_CORE, { 1, 1, 1, 1 } }, /* GPU-CORE */ 170 { CGU_SYS_IDIV_GFX_DMA, { 2, 2, 2, 2 } }, /* GPU-DMA */ 171 { CGU_SYS_IDIV_GFX_CFG, { 4, 4, 3, 4 } }, /* GPU-CFG */ 172 { CGU_SYS_IDIV_DMAC_CORE,{ 2, 2, 2, 2 } }, /* DMAC-CORE */ 173 { CGU_SYS_IDIV_DMAC_CFG, { 4, 4, 3, 4 } }, /* DMAC-CFG */ 174 { CGU_SYS_IDIV_SDIO_REF, { 8, 8, 6, 8 } }, /* SDIO-REF */ 175 { CGU_SYS_IDIV_SPI_REF, { 24, 24, 18, 24 } }, /* SPI-REF */ 176 { CGU_SYS_IDIV_I2C_REF, { 4, 4, 3, 4 } }, /* I2C-REF */ 177 { CGU_SYS_IDIV_UART_REF, { 24, 24, 18, 24 } }, /* UART-REF */ 178 { CGU_SYS_IDIV_EBI_REF, { 16, 16, 12, 16 } } /* EBI-REF */ 179 } 180 }; 181 182 struct hsdk_pll_cfg { 183 u32 rate; 184 u32 idiv; 185 u32 fbdiv; 186 u32 odiv; 187 u32 band; 188 }; 189 190 static const struct hsdk_pll_cfg asdt_pll_cfg[] = { 191 { 100000000, 0, 11, 3, 0 }, 192 { 125000000, 0, 14, 3, 0 }, 193 { 133000000, 0, 15, 3, 0 }, 194 { 150000000, 0, 17, 3, 0 }, 195 { 200000000, 1, 47, 3, 0 }, 196 { 233000000, 1, 27, 2, 0 }, 197 { 300000000, 1, 35, 2, 0 }, 198 { 333000000, 1, 39, 2, 0 }, 199 { 400000000, 1, 47, 2, 0 }, 200 { 500000000, 0, 14, 1, 0 }, 201 { 600000000, 0, 17, 1, 0 }, 202 { 700000000, 0, 20, 1, 0 }, 203 { 800000000, 0, 23, 1, 0 }, 204 { 900000000, 1, 26, 0, 0 }, 205 { 1000000000, 1, 29, 0, 0 }, 206 { 1100000000, 1, 32, 0, 0 }, 207 { 1200000000, 1, 35, 0, 0 }, 208 { 1300000000, 1, 38, 0, 0 }, 209 { 1400000000, 1, 41, 0, 0 }, 210 { 1500000000, 1, 44, 0, 0 }, 211 { 1600000000, 1, 47, 0, 0 }, 212 {} 213 }; 214 215 static const struct hsdk_pll_cfg hdmi_pll_cfg[] = { 216 { 297000000, 0, 21, 2, 0 }, 217 { 540000000, 0, 19, 1, 0 }, 218 { 594000000, 0, 21, 1, 0 }, 219 {} 220 }; 221 222 struct hsdk_cgu_clk { 223 /* CGU block register */ 224 void __iomem *cgu_regs; 225 /* CREG block register */ 226 void __iomem *creg_regs; 227 228 /* PLLs registers */ 229 void __iomem *regs; 230 /* PLLs special registers */ 231 void __iomem *spec_regs; 232 /* PLLs devdata */ 233 const struct hsdk_pll_devdata *pll_devdata; 234 235 /* Dividers registers */ 236 void __iomem *idiv_regs; 237 }; 238 239 struct hsdk_pll_devdata { 240 const struct hsdk_pll_cfg *pll_cfg; 241 int (*update_rate)(struct hsdk_cgu_clk *clk, unsigned long rate, 242 const struct hsdk_pll_cfg *cfg); 243 }; 244 245 static int hsdk_pll_core_update_rate(struct hsdk_cgu_clk *, unsigned long, 246 const struct hsdk_pll_cfg *); 247 static int hsdk_pll_comm_update_rate(struct hsdk_cgu_clk *, unsigned long, 248 const struct hsdk_pll_cfg *); 249 250 static const struct hsdk_pll_devdata core_pll_dat = { 251 .pll_cfg = asdt_pll_cfg, 252 .update_rate = hsdk_pll_core_update_rate, 253 }; 254 255 static const struct hsdk_pll_devdata sdt_pll_dat = { 256 .pll_cfg = asdt_pll_cfg, 257 .update_rate = hsdk_pll_comm_update_rate, 258 }; 259 260 static const struct hsdk_pll_devdata hdmi_pll_dat = { 261 .pll_cfg = hdmi_pll_cfg, 262 .update_rate = hsdk_pll_comm_update_rate, 263 }; 264 265 static ulong idiv_set(struct clk *, ulong); 266 static ulong cpu_clk_set(struct clk *, ulong); 267 static ulong axi_clk_set(struct clk *, ulong); 268 static ulong tun_clk_set(struct clk *, ulong); 269 static ulong idiv_get(struct clk *); 270 static int idiv_off(struct clk *); 271 static ulong pll_set(struct clk *, ulong); 272 static ulong pll_get(struct clk *); 273 274 struct hsdk_cgu_clock_map { 275 u32 cgu_pll_oft; 276 u32 creg_div_oft; 277 u32 cgu_div_oft; 278 const struct hsdk_pll_devdata *pll_devdata; 279 ulong (*get_rate)(struct clk *clk); 280 ulong (*set_rate)(struct clk *clk, ulong rate); 281 int (*disable)(struct clk *clk); 282 }; 283 284 static const struct hsdk_cgu_clock_map clock_map[] = { 285 { CGU_ARC_PLL, 0, 0, &core_pll_dat, pll_get, pll_set, NULL }, 286 { CGU_ARC_PLL, 0, CGU_ARC_IDIV, &core_pll_dat, idiv_get, cpu_clk_set, idiv_off }, 287 { CGU_DDR_PLL, 0, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, 288 { CGU_SYS_PLL, 0, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, 289 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_APB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 290 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_AXI, &sdt_pll_dat, idiv_get, axi_clk_set, idiv_off }, 291 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_ETH, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 292 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_USB, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 293 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_SDIO, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 294 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_HDMI, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 295 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_GFX_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 296 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_GFX_DMA, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 297 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_GFX_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 298 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_DMAC_CORE, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 299 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_DMAC_CFG, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 300 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_SDIO_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 301 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_SPI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 302 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_I2C_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 303 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_UART_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 304 { CGU_SYS_PLL, 0, CGU_SYS_IDIV_EBI_REF, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 305 { CGU_TUN_PLL, 0, 0, &sdt_pll_dat, pll_get, pll_set, NULL }, 306 { CGU_TUN_PLL, 0, CGU_TUN_IDIV_TUN, &sdt_pll_dat, idiv_get, tun_clk_set, idiv_off }, 307 { CGU_TUN_PLL, 0, CGU_TUN_IDIV_ROM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 308 { CGU_TUN_PLL, 0, CGU_TUN_IDIV_PWM, &sdt_pll_dat, idiv_get, idiv_set, idiv_off }, 309 { CGU_HDMI_PLL, 0, 0, &hdmi_pll_dat, pll_get, pll_set, NULL }, 310 { CGU_HDMI_PLL, 0, CGU_HDMI_IDIV_APB, &hdmi_pll_dat, idiv_get, idiv_set, idiv_off } 311 }; 312 313 static inline void hsdk_idiv_write(struct hsdk_cgu_clk *clk, u32 val) 314 { 315 iowrite32(val, clk->idiv_regs); 316 } 317 318 static inline u32 hsdk_idiv_read(struct hsdk_cgu_clk *clk) 319 { 320 return ioread32(clk->idiv_regs); 321 } 322 323 static inline void hsdk_pll_write(struct hsdk_cgu_clk *clk, u32 reg, u32 val) 324 { 325 iowrite32(val, clk->regs + reg); 326 } 327 328 static inline u32 hsdk_pll_read(struct hsdk_cgu_clk *clk, u32 reg) 329 { 330 return ioread32(clk->regs + reg); 331 } 332 333 static inline void hsdk_pll_spcwrite(struct hsdk_cgu_clk *clk, u32 reg, u32 val) 334 { 335 iowrite32(val, clk->spec_regs + reg); 336 } 337 338 static inline u32 hsdk_pll_spcread(struct hsdk_cgu_clk *clk, u32 reg) 339 { 340 return ioread32(clk->spec_regs + reg); 341 } 342 343 static inline void hsdk_pll_set_cfg(struct hsdk_cgu_clk *clk, 344 const struct hsdk_pll_cfg *cfg) 345 { 346 u32 val = 0; 347 348 /* Powerdown and Bypass bits should be cleared */ 349 val |= cfg->idiv << CGU_PLL_CTRL_IDIV_SHIFT; 350 val |= cfg->fbdiv << CGU_PLL_CTRL_FBDIV_SHIFT; 351 val |= cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT; 352 val |= cfg->band << CGU_PLL_CTRL_BAND_SHIFT; 353 354 pr_debug("write configurarion: %#x\n", val); 355 356 hsdk_pll_write(clk, CGU_PLL_CTRL, val); 357 } 358 359 static inline bool hsdk_pll_is_locked(struct hsdk_cgu_clk *clk) 360 { 361 return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_LOCK); 362 } 363 364 static inline bool hsdk_pll_is_err(struct hsdk_cgu_clk *clk) 365 { 366 return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_ERR); 367 } 368 369 static ulong pll_get(struct clk *sclk) 370 { 371 u32 val; 372 u64 rate; 373 u32 idiv, fbdiv, odiv; 374 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 375 376 val = hsdk_pll_read(clk, CGU_PLL_CTRL); 377 378 pr_debug("current configurarion: %#x\n", val); 379 380 /* Check if PLL is disabled */ 381 if (val & CGU_PLL_CTRL_PD) 382 return 0; 383 384 /* Check if PLL is bypassed */ 385 if (val & CGU_PLL_CTRL_BYPASS) 386 return PARENT_RATE; 387 388 /* input divider = reg.idiv + 1 */ 389 idiv = 1 + ((val & CGU_PLL_CTRL_IDIV_MASK) >> CGU_PLL_CTRL_IDIV_SHIFT); 390 /* fb divider = 2*(reg.fbdiv + 1) */ 391 fbdiv = 2 * (1 + ((val & CGU_PLL_CTRL_FBDIV_MASK) >> CGU_PLL_CTRL_FBDIV_SHIFT)); 392 /* output divider = 2^(reg.odiv) */ 393 odiv = 1 << ((val & CGU_PLL_CTRL_ODIV_MASK) >> CGU_PLL_CTRL_ODIV_SHIFT); 394 395 rate = (u64)PARENT_RATE * fbdiv; 396 do_div(rate, idiv * odiv); 397 398 return rate; 399 } 400 401 static unsigned long hsdk_pll_round_rate(struct clk *sclk, unsigned long rate) 402 { 403 int i; 404 unsigned long best_rate; 405 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 406 const struct hsdk_pll_cfg *pll_cfg = clk->pll_devdata->pll_cfg; 407 408 if (pll_cfg[0].rate == 0) 409 return -EINVAL; 410 411 best_rate = pll_cfg[0].rate; 412 413 for (i = 1; pll_cfg[i].rate != 0; i++) { 414 if (abs(rate - pll_cfg[i].rate) < abs(rate - best_rate)) 415 best_rate = pll_cfg[i].rate; 416 } 417 418 pr_debug("chosen best rate: %lu\n", best_rate); 419 420 return best_rate; 421 } 422 423 static int hsdk_pll_comm_update_rate(struct hsdk_cgu_clk *clk, 424 unsigned long rate, 425 const struct hsdk_pll_cfg *cfg) 426 { 427 hsdk_pll_set_cfg(clk, cfg); 428 429 /* 430 * Wait until CGU relocks and check error status. 431 * If after timeout CGU is unlocked yet return error. 432 */ 433 udelay(HSDK_PLL_MAX_LOCK_TIME); 434 if (!hsdk_pll_is_locked(clk)) 435 return -ETIMEDOUT; 436 437 if (hsdk_pll_is_err(clk)) 438 return -EINVAL; 439 440 return 0; 441 } 442 443 static int hsdk_pll_core_update_rate(struct hsdk_cgu_clk *clk, 444 unsigned long rate, 445 const struct hsdk_pll_cfg *cfg) 446 { 447 /* 448 * When core clock exceeds 500MHz, the divider for the interface 449 * clock must be programmed to div-by-2. 450 */ 451 if (rate > CORE_IF_CLK_THRESHOLD_HZ) 452 hsdk_pll_spcwrite(clk, CREG_CORE_IF_DIV, CREG_CORE_IF_CLK_DIV_2); 453 454 hsdk_pll_set_cfg(clk, cfg); 455 456 /* 457 * Wait until CGU relocks and check error status. 458 * If after timeout CGU is unlocked yet return error. 459 */ 460 udelay(HSDK_PLL_MAX_LOCK_TIME); 461 if (!hsdk_pll_is_locked(clk)) 462 return -ETIMEDOUT; 463 464 if (hsdk_pll_is_err(clk)) 465 return -EINVAL; 466 467 /* 468 * Program divider to div-by-1 if we succesfuly set core clock below 469 * 500MHz threshold. 470 */ 471 if (rate <= CORE_IF_CLK_THRESHOLD_HZ) 472 hsdk_pll_spcwrite(clk, CREG_CORE_IF_DIV, CREG_CORE_IF_CLK_DIV_1); 473 474 return 0; 475 } 476 477 static ulong pll_set(struct clk *sclk, ulong rate) 478 { 479 int i; 480 unsigned long best_rate; 481 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 482 const struct hsdk_pll_cfg *pll_cfg = clk->pll_devdata->pll_cfg; 483 484 best_rate = hsdk_pll_round_rate(sclk, rate); 485 486 for (i = 0; pll_cfg[i].rate != 0; i++) { 487 if (pll_cfg[i].rate == best_rate) { 488 return clk->pll_devdata->update_rate(clk, best_rate, 489 &pll_cfg[i]); 490 } 491 } 492 493 pr_err("invalid rate=%ld Hz, parent_rate=%d Hz\n", best_rate, PARENT_RATE); 494 495 return -EINVAL; 496 } 497 498 static int idiv_off(struct clk *sclk) 499 { 500 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 501 502 hsdk_idiv_write(clk, 0); 503 504 return 0; 505 } 506 507 static ulong idiv_get(struct clk *sclk) 508 { 509 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 510 ulong parent_rate = pll_get(sclk); 511 u32 div_factor = hsdk_idiv_read(clk); 512 513 div_factor &= CGU_IDIV_MASK; 514 515 pr_debug("current configurarion: %#x (%d)\n", div_factor, div_factor); 516 517 if (div_factor == 0) 518 return 0; 519 520 return parent_rate / div_factor; 521 } 522 523 /* Special behavior: wen we set this clock we set both idiv and pll */ 524 static ulong cpu_clk_set(struct clk *sclk, ulong rate) 525 { 526 ulong ret; 527 528 ret = pll_set(sclk, rate); 529 idiv_set(sclk, rate); 530 531 return ret; 532 } 533 534 /* Special behavior: wen we set this clock we set both idiv and pll and all pll dividers */ 535 static ulong axi_clk_set(struct clk *sclk, ulong rate) 536 { 537 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 538 ulong pll_rate; 539 int i, freq_idx = -1; 540 ulong ret = 0; 541 542 pll_rate = pll_get(sclk); 543 544 for (i = 0; i < MAX_AXI_CLOCKS; i++) { 545 if (axi_clk_cfg.clk_rate[i] == rate) { 546 freq_idx = i; 547 break; 548 } 549 } 550 551 if (freq_idx < 0) { 552 pr_err("axi clk: invalid rate=%ld Hz\n", rate); 553 return -EINVAL; 554 } 555 556 /* configure PLL before dividers */ 557 if (axi_clk_cfg.pll_rate[freq_idx] < pll_rate) 558 ret = pll_set(sclk, axi_clk_cfg.pll_rate[freq_idx]); 559 560 /* configure SYS dividers */ 561 for (i = 0; i < CGU_SYS_CLOCKS; i++) { 562 clk->idiv_regs = clk->cgu_regs + axi_clk_cfg.idiv[i].oft; 563 hsdk_idiv_write(clk, axi_clk_cfg.idiv[i].val[freq_idx]); 564 } 565 566 /* configure PLL after dividers */ 567 if (axi_clk_cfg.pll_rate[freq_idx] >= pll_rate) 568 ret = pll_set(sclk, axi_clk_cfg.pll_rate[freq_idx]); 569 570 return ret; 571 } 572 573 static ulong tun_clk_set(struct clk *sclk, ulong rate) 574 { 575 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 576 ulong pll_rate; 577 int i, freq_idx = -1; 578 ulong ret = 0; 579 580 pll_rate = pll_get(sclk); 581 582 for (i = 0; i < MAX_TUN_CLOCKS; i++) { 583 if (tun_clk_cfg.clk_rate[i] == rate) { 584 freq_idx = i; 585 break; 586 } 587 } 588 589 if (freq_idx < 0) { 590 pr_err("tun clk: invalid rate=%ld Hz\n", rate); 591 return -EINVAL; 592 } 593 594 /* configure PLL before dividers */ 595 if (tun_clk_cfg.pll_rate[freq_idx] < pll_rate) 596 ret = pll_set(sclk, tun_clk_cfg.pll_rate[freq_idx]); 597 598 /* configure SYS dividers */ 599 for (i = 0; i < CGU_TUN_CLOCKS; i++) { 600 clk->idiv_regs = clk->cgu_regs + tun_clk_cfg.idiv[i].oft; 601 hsdk_idiv_write(clk, tun_clk_cfg.idiv[i].val[freq_idx]); 602 } 603 604 /* configure PLL after dividers */ 605 if (tun_clk_cfg.pll_rate[freq_idx] >= pll_rate) 606 ret = pll_set(sclk, tun_clk_cfg.pll_rate[freq_idx]); 607 608 return ret; 609 } 610 611 static ulong idiv_set(struct clk *sclk, ulong rate) 612 { 613 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 614 ulong parent_rate = pll_get(sclk); 615 u32 div_factor; 616 617 div_factor = parent_rate / rate; 618 if (abs(rate - parent_rate / (div_factor + 1)) <= 619 abs(rate - parent_rate / div_factor)) { 620 div_factor += 1; 621 } 622 623 if (div_factor & ~CGU_IDIV_MASK) { 624 pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: max divider valie is%d\n", 625 rate, parent_rate, div_factor, CGU_IDIV_MASK); 626 627 div_factor = CGU_IDIV_MASK; 628 } 629 630 if (div_factor == 0) { 631 pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: min divider valie is 1\n", 632 rate, parent_rate, div_factor); 633 634 div_factor = 1; 635 } 636 637 hsdk_idiv_write(clk, div_factor); 638 639 return 0; 640 } 641 642 static int hsdk_prepare_clock_tree_branch(struct clk *sclk) 643 { 644 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); 645 646 if (sclk->id >= CGU_MAX_CLOCKS) 647 return -EINVAL; 648 649 clk->pll_devdata = clock_map[sclk->id].pll_devdata; 650 clk->regs = clk->cgu_regs + clock_map[sclk->id].cgu_pll_oft; 651 clk->spec_regs = clk->creg_regs + clock_map[sclk->id].creg_div_oft; 652 clk->idiv_regs = clk->cgu_regs + clock_map[sclk->id].cgu_div_oft; 653 654 return 0; 655 } 656 657 static ulong hsdk_cgu_get_rate(struct clk *sclk) 658 { 659 if (hsdk_prepare_clock_tree_branch(sclk)) 660 return -EINVAL; 661 662 return clock_map[sclk->id].get_rate(sclk); 663 } 664 665 static ulong hsdk_cgu_set_rate(struct clk *sclk, ulong rate) 666 { 667 if (hsdk_prepare_clock_tree_branch(sclk)) 668 return -EINVAL; 669 670 return clock_map[sclk->id].set_rate(sclk, rate); 671 } 672 673 static int hsdk_cgu_disable(struct clk *sclk) 674 { 675 if (hsdk_prepare_clock_tree_branch(sclk)) 676 return -EINVAL; 677 678 if (clock_map[sclk->id].disable) 679 return clock_map[sclk->id].disable(sclk); 680 681 return -ENOTSUPP; 682 } 683 684 static const struct clk_ops hsdk_cgu_ops = { 685 .set_rate = hsdk_cgu_set_rate, 686 .get_rate = hsdk_cgu_get_rate, 687 .disable = hsdk_cgu_disable, 688 }; 689 690 static int hsdk_cgu_clk_probe(struct udevice *dev) 691 { 692 struct hsdk_cgu_clk *pll_clk = dev_get_priv(dev); 693 694 BUILD_BUG_ON(ARRAY_SIZE(clock_map) != CGU_MAX_CLOCKS); 695 696 pll_clk->cgu_regs = (void __iomem *)devfdt_get_addr_index(dev, 0); 697 if (!pll_clk->cgu_regs) 698 return -EINVAL; 699 700 pll_clk->creg_regs = (void __iomem *)devfdt_get_addr_index(dev, 1); 701 if (!pll_clk->creg_regs) 702 return -EINVAL; 703 704 return 0; 705 } 706 707 static const struct udevice_id hsdk_cgu_clk_id[] = { 708 { .compatible = "snps,hsdk-cgu-clock" }, 709 { } 710 }; 711 712 U_BOOT_DRIVER(hsdk_cgu_clk) = { 713 .name = "hsdk-cgu-clk", 714 .id = UCLASS_CLK, 715 .of_match = hsdk_cgu_clk_id, 716 .probe = hsdk_cgu_clk_probe, 717 .priv_auto_alloc_size = sizeof(struct hsdk_cgu_clk), 718 .ops = &hsdk_cgu_ops, 719 }; 720