• Home
  • Raw
  • Download

Lines Matching +full:clk +full:- +full:csr

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * clk-xgene.c - AppliedMicro X-Gene Clock Interface
13 #include <linux/clk-provider.h>
31 static inline u32 xgene_clk_read(void __iomem *csr) in xgene_clk_read() argument
33 return readl_relaxed(csr); in xgene_clk_read()
36 static inline void xgene_clk_write(u32 data, void __iomem *csr) in xgene_clk_write() argument
38 writel_relaxed(data, csr); in xgene_clk_write()
63 data = xgene_clk_read(pllclk->reg + pllclk->pll_offset); in xgene_clk_pll_is_enabled()
81 pll = xgene_clk_read(pllclk->reg + pllclk->pll_offset); in xgene_clk_pll_recalc_rate()
83 if (pllclk->version <= 1) { in xgene_clk_pll_recalc_rate()
84 if (pllclk->type == PLL_TYPE_PCP) { in xgene_clk_pll_recalc_rate()
113 pllclk->version); in xgene_clk_pll_recalc_rate()
123 static struct clk *xgene_register_clk_pll(struct device *dev, in xgene_register_clk_pll()
129 struct clk *clk; in xgene_register_clk_pll() local
135 return ERR_PTR(-ENOMEM); in xgene_register_clk_pll()
143 apmclk->version = version; in xgene_register_clk_pll()
144 apmclk->reg = reg; in xgene_register_clk_pll()
145 apmclk->lock = lock; in xgene_register_clk_pll()
146 apmclk->pll_offset = pll_offset; in xgene_register_clk_pll()
147 apmclk->type = type; in xgene_register_clk_pll()
148 apmclk->hw.init = &init; in xgene_register_clk_pll()
151 clk = clk_register(dev, &apmclk->hw); in xgene_register_clk_pll()
152 if (IS_ERR(clk)) { in xgene_register_clk_pll()
153 pr_err("%s: could not register clk %s\n", __func__, name); in xgene_register_clk_pll()
157 return clk; in xgene_register_clk_pll()
162 if (of_device_is_compatible(np, "apm,xgene-socpll-clock")) in xgene_pllclk_version()
164 if (of_device_is_compatible(np, "apm,xgene-pcppll-clock")) in xgene_pllclk_version()
171 const char *clk_name = np->full_name; in xgene_pllclk_init()
172 struct clk *clk; in xgene_pllclk_init() local
178 pr_err("Unable to map CSR register for %pOF\n", np); in xgene_pllclk_init()
181 of_property_read_string(np, "clock-output-names", &clk_name); in xgene_pllclk_init()
182 clk = xgene_register_clk_pll(NULL, in xgene_pllclk_init()
186 if (!IS_ERR(clk)) { in xgene_pllclk_init()
187 of_clk_add_provider(np, of_clk_src_simple_get, clk); in xgene_pllclk_init()
188 clk_register_clkdev(clk, clk_name, NULL); in xgene_pllclk_init()
204 * struct xgene_clk_pmd - PMD clock
206 * @hw: handle between common and hardware-specific interfaces
212 * XGENE_CLK_PMD_SCALE_INVERTED - By default the scaler is the value read
217 * 0 for (denom - 0) / denom,
218 * 1 for (denom - 1) / denom and etc.
245 if (fd->lock) in xgene_clk_pmd_recalc_rate()
246 spin_lock_irqsave(fd->lock, flags); in xgene_clk_pmd_recalc_rate()
248 __acquire(fd->lock); in xgene_clk_pmd_recalc_rate()
250 val = readl(fd->reg); in xgene_clk_pmd_recalc_rate()
252 if (fd->lock) in xgene_clk_pmd_recalc_rate()
253 spin_unlock_irqrestore(fd->lock, flags); in xgene_clk_pmd_recalc_rate()
255 __release(fd->lock); in xgene_clk_pmd_recalc_rate()
259 scale = (val & fd->mask) >> fd->shift; in xgene_clk_pmd_recalc_rate()
260 if (fd->flags & XGENE_CLK_PMD_SCALE_INVERTED) in xgene_clk_pmd_recalc_rate()
261 scale = fd->denom - scale; in xgene_clk_pmd_recalc_rate()
266 do_div(ret, fd->denom); in xgene_clk_pmd_recalc_rate()
284 ret = rate * fd->denom; in xgene_clk_pmd_round_rate()
288 do_div(ret, fd->denom); in xgene_clk_pmd_round_rate()
307 ret = rate * fd->denom; in xgene_clk_pmd_set_rate()
311 if (fd->flags & XGENE_CLK_PMD_SCALE_INVERTED) in xgene_clk_pmd_set_rate()
312 scale = fd->denom - scale; in xgene_clk_pmd_set_rate()
314 scale--; in xgene_clk_pmd_set_rate()
316 if (fd->lock) in xgene_clk_pmd_set_rate()
317 spin_lock_irqsave(fd->lock, flags); in xgene_clk_pmd_set_rate()
319 __acquire(fd->lock); in xgene_clk_pmd_set_rate()
321 val = readl(fd->reg); in xgene_clk_pmd_set_rate()
322 val &= ~fd->mask; in xgene_clk_pmd_set_rate()
323 val |= (scale << fd->shift); in xgene_clk_pmd_set_rate()
324 writel(val, fd->reg); in xgene_clk_pmd_set_rate()
326 if (fd->lock) in xgene_clk_pmd_set_rate()
327 spin_unlock_irqrestore(fd->lock, flags); in xgene_clk_pmd_set_rate()
329 __release(fd->lock); in xgene_clk_pmd_set_rate()
340 static struct clk *
348 struct clk *clk; in xgene_register_clk_pmd() local
352 return ERR_PTR(-ENOMEM); in xgene_register_clk_pmd()
360 fd->reg = reg; in xgene_register_clk_pmd()
361 fd->shift = shift; in xgene_register_clk_pmd()
362 fd->mask = (BIT(width) - 1) << shift; in xgene_register_clk_pmd()
363 fd->denom = denom; in xgene_register_clk_pmd()
364 fd->flags = clk_flags; in xgene_register_clk_pmd()
365 fd->lock = lock; in xgene_register_clk_pmd()
366 fd->hw.init = &init; in xgene_register_clk_pmd()
368 clk = clk_register(dev, &fd->hw); in xgene_register_clk_pmd()
369 if (IS_ERR(clk)) { in xgene_register_clk_pmd()
370 pr_err("%s: could not register clk %s\n", __func__, name); in xgene_register_clk_pmd()
375 return clk; in xgene_register_clk_pmd()
380 const char *clk_name = np->full_name; in xgene_pmdclk_init()
383 struct clk *clk; in xgene_pmdclk_init() local
403 of_property_read_string(np, "clock-output-names", &clk_name); in xgene_pmdclk_init()
408 clk = xgene_register_clk_pmd(NULL, clk_name, in xgene_pmdclk_init()
413 if (!IS_ERR(clk)) { in xgene_pmdclk_init()
414 of_clk_add_provider(np, of_clk_src_simple_get, clk); in xgene_pmdclk_init()
415 clk_register_clkdev(clk, clk_name, NULL); in xgene_pmdclk_init()
425 void __iomem *csr_reg; /* CSR for IP clock */
426 u32 reg_clk_offset; /* Offset to clock enable CSR */
428 u32 reg_csr_offset; /* Offset to CSR reset */
429 u32 reg_csr_mask; /* Mask bit for disable CSR reset */
430 void __iomem *divider_reg; /* CSR for divider */
450 if (pclk->lock) in xgene_clk_enable()
451 spin_lock_irqsave(pclk->lock, flags); in xgene_clk_enable()
453 if (pclk->param.csr_reg) { in xgene_clk_enable()
456 data = xgene_clk_read(pclk->param.csr_reg + in xgene_clk_enable()
457 pclk->param.reg_clk_offset); in xgene_clk_enable()
458 data |= pclk->param.reg_clk_mask; in xgene_clk_enable()
459 xgene_clk_write(data, pclk->param.csr_reg + in xgene_clk_enable()
460 pclk->param.reg_clk_offset); in xgene_clk_enable()
461 pr_debug("%s clk offset 0x%08X mask 0x%08X value 0x%08X\n", in xgene_clk_enable()
463 pclk->param.reg_clk_offset, pclk->param.reg_clk_mask, in xgene_clk_enable()
466 /* Second enable the CSR */ in xgene_clk_enable()
467 data = xgene_clk_read(pclk->param.csr_reg + in xgene_clk_enable()
468 pclk->param.reg_csr_offset); in xgene_clk_enable()
469 data &= ~pclk->param.reg_csr_mask; in xgene_clk_enable()
470 xgene_clk_write(data, pclk->param.csr_reg + in xgene_clk_enable()
471 pclk->param.reg_csr_offset); in xgene_clk_enable()
472 pr_debug("%s csr offset 0x%08X mask 0x%08X value 0x%08X\n", in xgene_clk_enable()
474 pclk->param.reg_csr_offset, pclk->param.reg_csr_mask, in xgene_clk_enable()
478 if (pclk->lock) in xgene_clk_enable()
479 spin_unlock_irqrestore(pclk->lock, flags); in xgene_clk_enable()
490 if (pclk->lock) in xgene_clk_disable()
491 spin_lock_irqsave(pclk->lock, flags); in xgene_clk_disable()
493 if (pclk->param.csr_reg) { in xgene_clk_disable()
495 /* First put the CSR in reset */ in xgene_clk_disable()
496 data = xgene_clk_read(pclk->param.csr_reg + in xgene_clk_disable()
497 pclk->param.reg_csr_offset); in xgene_clk_disable()
498 data |= pclk->param.reg_csr_mask; in xgene_clk_disable()
499 xgene_clk_write(data, pclk->param.csr_reg + in xgene_clk_disable()
500 pclk->param.reg_csr_offset); in xgene_clk_disable()
503 data = xgene_clk_read(pclk->param.csr_reg + in xgene_clk_disable()
504 pclk->param.reg_clk_offset); in xgene_clk_disable()
505 data &= ~pclk->param.reg_clk_mask; in xgene_clk_disable()
506 xgene_clk_write(data, pclk->param.csr_reg + in xgene_clk_disable()
507 pclk->param.reg_clk_offset); in xgene_clk_disable()
510 if (pclk->lock) in xgene_clk_disable()
511 spin_unlock_irqrestore(pclk->lock, flags); in xgene_clk_disable()
519 if (pclk->param.csr_reg) { in xgene_clk_is_enabled()
521 data = xgene_clk_read(pclk->param.csr_reg + in xgene_clk_is_enabled()
522 pclk->param.reg_clk_offset); in xgene_clk_is_enabled()
524 data & pclk->param.reg_clk_mask ? "enabled" : in xgene_clk_is_enabled()
528 if (!pclk->param.csr_reg) in xgene_clk_is_enabled()
530 return data & pclk->param.reg_clk_mask ? 1 : 0; in xgene_clk_is_enabled()
539 if (pclk->param.divider_reg) { in xgene_clk_recalc_rate()
540 data = xgene_clk_read(pclk->param.divider_reg + in xgene_clk_recalc_rate()
541 pclk->param.reg_divider_offset); in xgene_clk_recalc_rate()
542 data >>= pclk->param.reg_divider_shift; in xgene_clk_recalc_rate()
543 data &= (1 << pclk->param.reg_divider_width) - 1; in xgene_clk_recalc_rate()
566 if (pclk->lock) in xgene_clk_set_rate()
567 spin_lock_irqsave(pclk->lock, flags); in xgene_clk_set_rate()
569 if (pclk->param.divider_reg) { in xgene_clk_set_rate()
574 divider &= (1 << pclk->param.reg_divider_width) - 1; in xgene_clk_set_rate()
575 divider <<= pclk->param.reg_divider_shift; in xgene_clk_set_rate()
578 data = xgene_clk_read(pclk->param.divider_reg + in xgene_clk_set_rate()
579 pclk->param.reg_divider_offset); in xgene_clk_set_rate()
580 data &= ~(((1 << pclk->param.reg_divider_width) - 1) in xgene_clk_set_rate()
581 << pclk->param.reg_divider_shift); in xgene_clk_set_rate()
583 xgene_clk_write(data, pclk->param.divider_reg + in xgene_clk_set_rate()
584 pclk->param.reg_divider_offset); in xgene_clk_set_rate()
591 if (pclk->lock) in xgene_clk_set_rate()
592 spin_unlock_irqrestore(pclk->lock, flags); in xgene_clk_set_rate()
604 if (pclk->param.divider_reg) { in xgene_clk_round_rate()
625 static struct clk *xgene_register_clk(struct device *dev, in xgene_register_clk()
630 struct clk *clk; in xgene_register_clk() local
637 return ERR_PTR(-ENOMEM); in xgene_register_clk()
645 apmclk->lock = lock; in xgene_register_clk()
646 apmclk->hw.init = &init; in xgene_register_clk()
647 apmclk->param = *parameters; in xgene_register_clk()
650 clk = clk_register(dev, &apmclk->hw); in xgene_register_clk()
651 if (IS_ERR(clk)) { in xgene_register_clk()
652 pr_err("%s: could not register clk %s\n", __func__, name); in xgene_register_clk()
654 return clk; in xgene_register_clk()
658 rc = clk_register_clkdev(clk, name, NULL); in xgene_register_clk()
660 pr_err("%s: could not register lookup clk %s\n", in xgene_register_clk()
663 return clk; in xgene_register_clk()
668 const char *clk_name = np->full_name; in xgene_devclk_init()
669 struct clk *clk; in xgene_devclk_init() local
697 if (strcmp(res.name, "div-reg") == 0) in xgene_devclk_init()
699 else /* if (strcmp(res->name, "csr-reg") == 0) */ in xgene_devclk_init()
702 if (of_property_read_u32(np, "csr-offset", &parameters.reg_csr_offset)) in xgene_devclk_init()
704 if (of_property_read_u32(np, "csr-mask", &parameters.reg_csr_mask)) in xgene_devclk_init()
706 if (of_property_read_u32(np, "enable-offset", in xgene_devclk_init()
709 if (of_property_read_u32(np, "enable-mask", &parameters.reg_clk_mask)) in xgene_devclk_init()
711 if (of_property_read_u32(np, "divider-offset", in xgene_devclk_init()
714 if (of_property_read_u32(np, "divider-width", in xgene_devclk_init()
717 if (of_property_read_u32(np, "divider-shift", in xgene_devclk_init()
720 of_property_read_string(np, "clock-output-names", &clk_name); in xgene_devclk_init()
722 clk = xgene_register_clk(NULL, clk_name, in xgene_devclk_init()
724 if (IS_ERR(clk)) in xgene_devclk_init()
727 rc = of_clk_add_provider(np, of_clk_src_simple_get, clk); in xgene_devclk_init()
729 pr_err("%s: could register provider clk %pOF\n", __func__, np); in xgene_devclk_init()
740 CLK_OF_DECLARE(xgene_socpll_clock, "apm,xgene-socpll-clock", xgene_socpllclk_init);
741 CLK_OF_DECLARE(xgene_pcppll_clock, "apm,xgene-pcppll-clock", xgene_pcppllclk_init);
742 CLK_OF_DECLARE(xgene_pmd_clock, "apm,xgene-pmd-clock", xgene_pmdclk_init);
743 CLK_OF_DECLARE(xgene_socpll_v2_clock, "apm,xgene-socpll-v2-clock",
745 CLK_OF_DECLARE(xgene_pcppll_v2_clock, "apm,xgene-pcppll-v2-clock",
747 CLK_OF_DECLARE(xgene_dev_clock, "apm,xgene-device-clock", xgene_devclk_init);