Lines Matching +full:max +full:- +full:clk +full:- +full:rate +full:- +full:hz
13 #include <clk-uclass.h>
21 * ------------------
23 * ------------------
25 * | -----------
26 * |-->| ARC PLL |
27 * | -----------
29 * | |-->|CGU_ARC_IDIV|----------->
30 * | |-->|CREG_CORE_IF_DIV|------->
32 * | --------------
33 * |-->| SYSTEM PLL |
34 * | --------------
36 * | |-->|CGU_SYS_IDIV_APB|------->
37 * | |-->|CGU_SYS_IDIV_AXI|------->
38 * | |-->|CGU_SYS_IDIV_*|--------->
39 * | |-->|CGU_SYS_IDIV_EBI_REF|--->
41 * | --------------
42 * |-->| TUNNEL PLL |
43 * | --------------
45 * | |-->|CGU_TUN_IDIV_TUN|----------->
46 * | |-->|CGU_TUN_IDIV_ROM|----------->
47 * | |-->|CGU_TUN_IDIV_PWM|----------->
49 * | ------------
50 * |-->| HDMI PLL |
51 * | ------------
53 * | |-->|CGU_HDMI_IDIV_APB|------>
55 * | -----------
56 * |-->| DDR PLL |
57 * -----------
59 * |---------------------------->
120 #define PARENT_RATE 33333333 /* fixed clock - xtal */
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 */
183 u32 rate; member
241 int (*update_rate)(struct hsdk_cgu_clk *clk, unsigned long rate,
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 *);
279 ulong (*get_rate)(struct clk *clk);
280 ulong (*set_rate)(struct clk *clk, ulong rate);
281 int (*disable)(struct clk *clk);
313 static inline void hsdk_idiv_write(struct hsdk_cgu_clk *clk, u32 val) in hsdk_idiv_write() argument
315 iowrite32(val, clk->idiv_regs); in hsdk_idiv_write()
318 static inline u32 hsdk_idiv_read(struct hsdk_cgu_clk *clk) in hsdk_idiv_read() argument
320 return ioread32(clk->idiv_regs); in hsdk_idiv_read()
323 static inline void hsdk_pll_write(struct hsdk_cgu_clk *clk, u32 reg, u32 val) in hsdk_pll_write() argument
325 iowrite32(val, clk->regs + reg); in hsdk_pll_write()
328 static inline u32 hsdk_pll_read(struct hsdk_cgu_clk *clk, u32 reg) in hsdk_pll_read() argument
330 return ioread32(clk->regs + reg); in hsdk_pll_read()
333 static inline void hsdk_pll_spcwrite(struct hsdk_cgu_clk *clk, u32 reg, u32 val) in hsdk_pll_spcwrite() argument
335 iowrite32(val, clk->spec_regs + reg); in hsdk_pll_spcwrite()
338 static inline u32 hsdk_pll_spcread(struct hsdk_cgu_clk *clk, u32 reg) in hsdk_pll_spcread() argument
340 return ioread32(clk->spec_regs + reg); in hsdk_pll_spcread()
343 static inline void hsdk_pll_set_cfg(struct hsdk_cgu_clk *clk, in hsdk_pll_set_cfg() argument
349 val |= cfg->idiv << CGU_PLL_CTRL_IDIV_SHIFT; in hsdk_pll_set_cfg()
350 val |= cfg->fbdiv << CGU_PLL_CTRL_FBDIV_SHIFT; in hsdk_pll_set_cfg()
351 val |= cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT; in hsdk_pll_set_cfg()
352 val |= cfg->band << CGU_PLL_CTRL_BAND_SHIFT; in hsdk_pll_set_cfg()
356 hsdk_pll_write(clk, CGU_PLL_CTRL, val); in hsdk_pll_set_cfg()
359 static inline bool hsdk_pll_is_locked(struct hsdk_cgu_clk *clk) in hsdk_pll_is_locked() argument
361 return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_LOCK); in hsdk_pll_is_locked()
364 static inline bool hsdk_pll_is_err(struct hsdk_cgu_clk *clk) in hsdk_pll_is_err() argument
366 return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_ERR); in hsdk_pll_is_err()
369 static ulong pll_get(struct clk *sclk) in pll_get()
372 u64 rate; in pll_get() local
374 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); in pll_get() local
376 val = hsdk_pll_read(clk, CGU_PLL_CTRL); in pll_get()
395 rate = (u64)PARENT_RATE * fbdiv; in pll_get()
396 do_div(rate, idiv * odiv); in pll_get()
398 return rate; in pll_get()
401 static unsigned long hsdk_pll_round_rate(struct clk *sclk, unsigned long rate) in hsdk_pll_round_rate() argument
405 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); in hsdk_pll_round_rate() local
406 const struct hsdk_pll_cfg *pll_cfg = clk->pll_devdata->pll_cfg; in hsdk_pll_round_rate()
408 if (pll_cfg[0].rate == 0) in hsdk_pll_round_rate()
409 return -EINVAL; in hsdk_pll_round_rate()
411 best_rate = pll_cfg[0].rate; in hsdk_pll_round_rate()
413 for (i = 1; pll_cfg[i].rate != 0; i++) { in hsdk_pll_round_rate()
414 if (abs(rate - pll_cfg[i].rate) < abs(rate - best_rate)) in hsdk_pll_round_rate()
415 best_rate = pll_cfg[i].rate; in hsdk_pll_round_rate()
418 pr_debug("chosen best rate: %lu\n", best_rate); in hsdk_pll_round_rate()
423 static int hsdk_pll_comm_update_rate(struct hsdk_cgu_clk *clk, in hsdk_pll_comm_update_rate() argument
424 unsigned long rate, in hsdk_pll_comm_update_rate() argument
427 hsdk_pll_set_cfg(clk, cfg); in hsdk_pll_comm_update_rate()
434 if (!hsdk_pll_is_locked(clk)) in hsdk_pll_comm_update_rate()
435 return -ETIMEDOUT; in hsdk_pll_comm_update_rate()
437 if (hsdk_pll_is_err(clk)) in hsdk_pll_comm_update_rate()
438 return -EINVAL; in hsdk_pll_comm_update_rate()
443 static int hsdk_pll_core_update_rate(struct hsdk_cgu_clk *clk, in hsdk_pll_core_update_rate() argument
444 unsigned long rate, in hsdk_pll_core_update_rate() argument
449 * clock must be programmed to div-by-2. in hsdk_pll_core_update_rate()
451 if (rate > CORE_IF_CLK_THRESHOLD_HZ) in hsdk_pll_core_update_rate()
452 hsdk_pll_spcwrite(clk, CREG_CORE_IF_DIV, CREG_CORE_IF_CLK_DIV_2); in hsdk_pll_core_update_rate()
454 hsdk_pll_set_cfg(clk, cfg); in hsdk_pll_core_update_rate()
461 if (!hsdk_pll_is_locked(clk)) in hsdk_pll_core_update_rate()
462 return -ETIMEDOUT; in hsdk_pll_core_update_rate()
464 if (hsdk_pll_is_err(clk)) in hsdk_pll_core_update_rate()
465 return -EINVAL; in hsdk_pll_core_update_rate()
468 * Program divider to div-by-1 if we succesfuly set core clock below in hsdk_pll_core_update_rate()
471 if (rate <= CORE_IF_CLK_THRESHOLD_HZ) in hsdk_pll_core_update_rate()
472 hsdk_pll_spcwrite(clk, CREG_CORE_IF_DIV, CREG_CORE_IF_CLK_DIV_1); in hsdk_pll_core_update_rate()
477 static ulong pll_set(struct clk *sclk, ulong rate) in pll_set() argument
481 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); in pll_set() local
482 const struct hsdk_pll_cfg *pll_cfg = clk->pll_devdata->pll_cfg; in pll_set()
484 best_rate = hsdk_pll_round_rate(sclk, rate); in pll_set()
486 for (i = 0; pll_cfg[i].rate != 0; i++) { in pll_set()
487 if (pll_cfg[i].rate == best_rate) { in pll_set()
488 return clk->pll_devdata->update_rate(clk, best_rate, in pll_set()
493 pr_err("invalid rate=%ld Hz, parent_rate=%d Hz\n", best_rate, PARENT_RATE); in pll_set()
495 return -EINVAL; in pll_set()
498 static int idiv_off(struct clk *sclk) in idiv_off()
500 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); in idiv_off() local
502 hsdk_idiv_write(clk, 0); in idiv_off()
507 static ulong idiv_get(struct clk *sclk) in idiv_get()
509 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); in idiv_get() local
511 u32 div_factor = hsdk_idiv_read(clk); in idiv_get()
524 static ulong cpu_clk_set(struct clk *sclk, ulong rate) in cpu_clk_set() argument
528 ret = pll_set(sclk, rate); in cpu_clk_set()
529 idiv_set(sclk, rate); in cpu_clk_set()
535 static ulong axi_clk_set(struct clk *sclk, ulong rate) in axi_clk_set() argument
537 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); in axi_clk_set() local
539 int i, freq_idx = -1; in axi_clk_set()
545 if (axi_clk_cfg.clk_rate[i] == rate) { in axi_clk_set()
552 pr_err("axi clk: invalid rate=%ld Hz\n", rate); in axi_clk_set()
553 return -EINVAL; in axi_clk_set()
562 clk->idiv_regs = clk->cgu_regs + axi_clk_cfg.idiv[i].oft; in axi_clk_set()
563 hsdk_idiv_write(clk, axi_clk_cfg.idiv[i].val[freq_idx]); in axi_clk_set()
573 static ulong tun_clk_set(struct clk *sclk, ulong rate) in tun_clk_set() argument
575 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); in tun_clk_set() local
577 int i, freq_idx = -1; in tun_clk_set()
583 if (tun_clk_cfg.clk_rate[i] == rate) { in tun_clk_set()
590 pr_err("tun clk: invalid rate=%ld Hz\n", rate); in tun_clk_set()
591 return -EINVAL; in tun_clk_set()
600 clk->idiv_regs = clk->cgu_regs + tun_clk_cfg.idiv[i].oft; in tun_clk_set()
601 hsdk_idiv_write(clk, tun_clk_cfg.idiv[i].val[freq_idx]); in tun_clk_set()
611 static ulong idiv_set(struct clk *sclk, ulong rate) in idiv_set() argument
613 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); in idiv_set() local
617 div_factor = parent_rate / rate; in idiv_set()
618 if (abs(rate - parent_rate / (div_factor + 1)) <= in idiv_set()
619 abs(rate - parent_rate / div_factor)) { in idiv_set()
624 pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: max divider valie is%d\n", in idiv_set()
625 rate, parent_rate, div_factor, CGU_IDIV_MASK); in idiv_set()
631 pr_err("invalid rate=%ld Hz, parent_rate=%ld Hz, div=%d: min divider valie is 1\n", in idiv_set()
632 rate, parent_rate, div_factor); in idiv_set()
637 hsdk_idiv_write(clk, div_factor); in idiv_set()
642 static int hsdk_prepare_clock_tree_branch(struct clk *sclk) in hsdk_prepare_clock_tree_branch()
644 struct hsdk_cgu_clk *clk = dev_get_priv(sclk->dev); in hsdk_prepare_clock_tree_branch() local
646 if (sclk->id >= CGU_MAX_CLOCKS) in hsdk_prepare_clock_tree_branch()
647 return -EINVAL; in hsdk_prepare_clock_tree_branch()
649 clk->pll_devdata = clock_map[sclk->id].pll_devdata; in hsdk_prepare_clock_tree_branch()
650 clk->regs = clk->cgu_regs + clock_map[sclk->id].cgu_pll_oft; in hsdk_prepare_clock_tree_branch()
651 clk->spec_regs = clk->creg_regs + clock_map[sclk->id].creg_div_oft; in hsdk_prepare_clock_tree_branch()
652 clk->idiv_regs = clk->cgu_regs + clock_map[sclk->id].cgu_div_oft; in hsdk_prepare_clock_tree_branch()
657 static ulong hsdk_cgu_get_rate(struct clk *sclk) in hsdk_cgu_get_rate()
660 return -EINVAL; in hsdk_cgu_get_rate()
662 return clock_map[sclk->id].get_rate(sclk); in hsdk_cgu_get_rate()
665 static ulong hsdk_cgu_set_rate(struct clk *sclk, ulong rate) in hsdk_cgu_set_rate() argument
668 return -EINVAL; in hsdk_cgu_set_rate()
670 return clock_map[sclk->id].set_rate(sclk, rate); in hsdk_cgu_set_rate()
673 static int hsdk_cgu_disable(struct clk *sclk) in hsdk_cgu_disable()
676 return -EINVAL; in hsdk_cgu_disable()
678 if (clock_map[sclk->id].disable) in hsdk_cgu_disable()
679 return clock_map[sclk->id].disable(sclk); in hsdk_cgu_disable()
681 return -ENOTSUPP; in hsdk_cgu_disable()
696 pll_clk->cgu_regs = (void __iomem *)devfdt_get_addr_index(dev, 0); in hsdk_cgu_clk_probe()
697 if (!pll_clk->cgu_regs) in hsdk_cgu_clk_probe()
698 return -EINVAL; in hsdk_cgu_clk_probe()
700 pll_clk->creg_regs = (void __iomem *)devfdt_get_addr_index(dev, 1); in hsdk_cgu_clk_probe()
701 if (!pll_clk->creg_regs) in hsdk_cgu_clk_probe()
702 return -EINVAL; in hsdk_cgu_clk_probe()
708 { .compatible = "snps,hsdk-cgu-clock" },
713 .name = "hsdk-cgu-clk",