1dc1a8bc1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23682af46SSoren Brinkmann /*
33682af46SSoren Brinkmann * Zynq PLL driver
43682af46SSoren Brinkmann *
53682af46SSoren Brinkmann * Copyright (C) 2013 Xilinx
63682af46SSoren Brinkmann *
73682af46SSoren Brinkmann * Sören Brinkmann <soren.brinkmann@xilinx.com>
83682af46SSoren Brinkmann */
93682af46SSoren Brinkmann #include <linux/clk/zynq.h>
103682af46SSoren Brinkmann #include <linux/clk-provider.h>
113682af46SSoren Brinkmann #include <linux/slab.h>
123682af46SSoren Brinkmann #include <linux/io.h>
133682af46SSoren Brinkmann
143682af46SSoren Brinkmann /**
15*8a3492cdSShubhrajyoti Datta * struct zynq_pll - pll clock
163682af46SSoren Brinkmann * @hw: Handle between common and hardware-specific interfaces
173682af46SSoren Brinkmann * @pll_ctrl: PLL control register
183682af46SSoren Brinkmann * @pll_status: PLL status register
193682af46SSoren Brinkmann * @lock: Register lock
203682af46SSoren Brinkmann * @lockbit: Indicates the associated PLL_LOCKED bit in the PLL status
213682af46SSoren Brinkmann * register.
223682af46SSoren Brinkmann */
233682af46SSoren Brinkmann struct zynq_pll {
243682af46SSoren Brinkmann struct clk_hw hw;
253682af46SSoren Brinkmann void __iomem *pll_ctrl;
263682af46SSoren Brinkmann void __iomem *pll_status;
273682af46SSoren Brinkmann spinlock_t *lock;
283682af46SSoren Brinkmann u8 lockbit;
293682af46SSoren Brinkmann };
303682af46SSoren Brinkmann #define to_zynq_pll(_hw) container_of(_hw, struct zynq_pll, hw)
313682af46SSoren Brinkmann
323682af46SSoren Brinkmann /* Register bitfield defines */
333682af46SSoren Brinkmann #define PLLCTRL_FBDIV_MASK 0x7f000
343682af46SSoren Brinkmann #define PLLCTRL_FBDIV_SHIFT 12
353682af46SSoren Brinkmann #define PLLCTRL_BPQUAL_MASK (1 << 3)
363682af46SSoren Brinkmann #define PLLCTRL_PWRDWN_MASK 2
373682af46SSoren Brinkmann #define PLLCTRL_PWRDWN_SHIFT 1
383682af46SSoren Brinkmann #define PLLCTRL_RESET_MASK 1
393682af46SSoren Brinkmann #define PLLCTRL_RESET_SHIFT 0
403682af46SSoren Brinkmann
41353dc6c4SSoren Brinkmann #define PLL_FBDIV_MIN 13
42353dc6c4SSoren Brinkmann #define PLL_FBDIV_MAX 66
43353dc6c4SSoren Brinkmann
443682af46SSoren Brinkmann /**
453682af46SSoren Brinkmann * zynq_pll_round_rate() - Round a clock frequency
463682af46SSoren Brinkmann * @hw: Handle between common and hardware-specific interfaces
473682af46SSoren Brinkmann * @rate: Desired clock frequency
483682af46SSoren Brinkmann * @prate: Clock frequency of parent clock
49*8a3492cdSShubhrajyoti Datta * Return: frequency closest to @rate the hardware can generate.
503682af46SSoren Brinkmann */
zynq_pll_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * prate)513682af46SSoren Brinkmann static long zynq_pll_round_rate(struct clk_hw *hw, unsigned long rate,
523682af46SSoren Brinkmann unsigned long *prate)
533682af46SSoren Brinkmann {
543682af46SSoren Brinkmann u32 fbdiv;
553682af46SSoren Brinkmann
563682af46SSoren Brinkmann fbdiv = DIV_ROUND_CLOSEST(rate, *prate);
57353dc6c4SSoren Brinkmann if (fbdiv < PLL_FBDIV_MIN)
58353dc6c4SSoren Brinkmann fbdiv = PLL_FBDIV_MIN;
59353dc6c4SSoren Brinkmann else if (fbdiv > PLL_FBDIV_MAX)
60353dc6c4SSoren Brinkmann fbdiv = PLL_FBDIV_MAX;
613682af46SSoren Brinkmann
623682af46SSoren Brinkmann return *prate * fbdiv;
633682af46SSoren Brinkmann }
643682af46SSoren Brinkmann
653682af46SSoren Brinkmann /**
663682af46SSoren Brinkmann * zynq_pll_recalc_rate() - Recalculate clock frequency
673682af46SSoren Brinkmann * @hw: Handle between common and hardware-specific interfaces
683682af46SSoren Brinkmann * @parent_rate: Clock frequency of parent clock
69*8a3492cdSShubhrajyoti Datta * Return: current clock frequency.
703682af46SSoren Brinkmann */
zynq_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)713682af46SSoren Brinkmann static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
723682af46SSoren Brinkmann unsigned long parent_rate)
733682af46SSoren Brinkmann {
743682af46SSoren Brinkmann struct zynq_pll *clk = to_zynq_pll(hw);
753682af46SSoren Brinkmann u32 fbdiv;
763682af46SSoren Brinkmann
773682af46SSoren Brinkmann /*
783682af46SSoren Brinkmann * makes probably sense to redundantly save fbdiv in the struct
793682af46SSoren Brinkmann * zynq_pll to save the IO access.
803682af46SSoren Brinkmann */
815834fd75SJonas Gorski fbdiv = (readl(clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >>
823682af46SSoren Brinkmann PLLCTRL_FBDIV_SHIFT;
833682af46SSoren Brinkmann
843682af46SSoren Brinkmann return parent_rate * fbdiv;
853682af46SSoren Brinkmann }
863682af46SSoren Brinkmann
873682af46SSoren Brinkmann /**
883682af46SSoren Brinkmann * zynq_pll_is_enabled - Check if a clock is enabled
893682af46SSoren Brinkmann * @hw: Handle between common and hardware-specific interfaces
90*8a3492cdSShubhrajyoti Datta * Return: 1 if the clock is enabled, 0 otherwise.
913682af46SSoren Brinkmann *
923682af46SSoren Brinkmann * Not sure this is a good idea, but since disabled means bypassed for
933682af46SSoren Brinkmann * this clock implementation we say we are always enabled.
943682af46SSoren Brinkmann */
zynq_pll_is_enabled(struct clk_hw * hw)953682af46SSoren Brinkmann static int zynq_pll_is_enabled(struct clk_hw *hw)
963682af46SSoren Brinkmann {
973682af46SSoren Brinkmann unsigned long flags = 0;
983682af46SSoren Brinkmann u32 reg;
993682af46SSoren Brinkmann struct zynq_pll *clk = to_zynq_pll(hw);
1003682af46SSoren Brinkmann
1013682af46SSoren Brinkmann spin_lock_irqsave(clk->lock, flags);
1023682af46SSoren Brinkmann
1035834fd75SJonas Gorski reg = readl(clk->pll_ctrl);
1043682af46SSoren Brinkmann
1053682af46SSoren Brinkmann spin_unlock_irqrestore(clk->lock, flags);
1063682af46SSoren Brinkmann
1073682af46SSoren Brinkmann return !(reg & (PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK));
1083682af46SSoren Brinkmann }
1093682af46SSoren Brinkmann
1103682af46SSoren Brinkmann /**
1113682af46SSoren Brinkmann * zynq_pll_enable - Enable clock
1123682af46SSoren Brinkmann * @hw: Handle between common and hardware-specific interfaces
113*8a3492cdSShubhrajyoti Datta * Return: 0 on success
1143682af46SSoren Brinkmann */
zynq_pll_enable(struct clk_hw * hw)1153682af46SSoren Brinkmann static int zynq_pll_enable(struct clk_hw *hw)
1163682af46SSoren Brinkmann {
1173682af46SSoren Brinkmann unsigned long flags = 0;
1183682af46SSoren Brinkmann u32 reg;
1193682af46SSoren Brinkmann struct zynq_pll *clk = to_zynq_pll(hw);
1203682af46SSoren Brinkmann
1213682af46SSoren Brinkmann if (zynq_pll_is_enabled(hw))
1223682af46SSoren Brinkmann return 0;
1233682af46SSoren Brinkmann
1243682af46SSoren Brinkmann pr_info("PLL: enable\n");
1253682af46SSoren Brinkmann
1263682af46SSoren Brinkmann /* Power up PLL and wait for lock */
1273682af46SSoren Brinkmann spin_lock_irqsave(clk->lock, flags);
1283682af46SSoren Brinkmann
1295834fd75SJonas Gorski reg = readl(clk->pll_ctrl);
1303682af46SSoren Brinkmann reg &= ~(PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK);
1315834fd75SJonas Gorski writel(reg, clk->pll_ctrl);
1325834fd75SJonas Gorski while (!(readl(clk->pll_status) & (1 << clk->lockbit)))
1333682af46SSoren Brinkmann ;
1343682af46SSoren Brinkmann
1353682af46SSoren Brinkmann spin_unlock_irqrestore(clk->lock, flags);
1363682af46SSoren Brinkmann
1373682af46SSoren Brinkmann return 0;
1383682af46SSoren Brinkmann }
1393682af46SSoren Brinkmann
1403682af46SSoren Brinkmann /**
1413682af46SSoren Brinkmann * zynq_pll_disable - Disable clock
1423682af46SSoren Brinkmann * @hw: Handle between common and hardware-specific interfaces
1433682af46SSoren Brinkmann * Returns 0 on success
1443682af46SSoren Brinkmann */
zynq_pll_disable(struct clk_hw * hw)1453682af46SSoren Brinkmann static void zynq_pll_disable(struct clk_hw *hw)
1463682af46SSoren Brinkmann {
1473682af46SSoren Brinkmann unsigned long flags = 0;
1483682af46SSoren Brinkmann u32 reg;
1493682af46SSoren Brinkmann struct zynq_pll *clk = to_zynq_pll(hw);
1503682af46SSoren Brinkmann
1513682af46SSoren Brinkmann if (!zynq_pll_is_enabled(hw))
1523682af46SSoren Brinkmann return;
1533682af46SSoren Brinkmann
1543682af46SSoren Brinkmann pr_info("PLL: shutdown\n");
1553682af46SSoren Brinkmann
1563682af46SSoren Brinkmann /* shut down PLL */
1573682af46SSoren Brinkmann spin_lock_irqsave(clk->lock, flags);
1583682af46SSoren Brinkmann
1595834fd75SJonas Gorski reg = readl(clk->pll_ctrl);
1603682af46SSoren Brinkmann reg |= PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK;
1615834fd75SJonas Gorski writel(reg, clk->pll_ctrl);
1623682af46SSoren Brinkmann
1633682af46SSoren Brinkmann spin_unlock_irqrestore(clk->lock, flags);
1643682af46SSoren Brinkmann }
1653682af46SSoren Brinkmann
1663682af46SSoren Brinkmann static const struct clk_ops zynq_pll_ops = {
1673682af46SSoren Brinkmann .enable = zynq_pll_enable,
1683682af46SSoren Brinkmann .disable = zynq_pll_disable,
1693682af46SSoren Brinkmann .is_enabled = zynq_pll_is_enabled,
1703682af46SSoren Brinkmann .round_rate = zynq_pll_round_rate,
1713682af46SSoren Brinkmann .recalc_rate = zynq_pll_recalc_rate
1723682af46SSoren Brinkmann };
1733682af46SSoren Brinkmann
1743682af46SSoren Brinkmann /**
1753682af46SSoren Brinkmann * clk_register_zynq_pll() - Register PLL with the clock framework
176bc22d596SLee Jones * @name: PLL name
177bc22d596SLee Jones * @parent: Parent clock name
178bc22d596SLee Jones * @pll_ctrl: Pointer to PLL control register
179bc22d596SLee Jones * @pll_status: Pointer to PLL status register
180bc22d596SLee Jones * @lock_index: Bit index to this PLL's lock status bit in @pll_status
181bc22d596SLee Jones * @lock: Register lock
182*8a3492cdSShubhrajyoti Datta * Return: handle to the registered clock.
1833682af46SSoren Brinkmann */
clk_register_zynq_pll(const char * name,const char * parent,void __iomem * pll_ctrl,void __iomem * pll_status,u8 lock_index,spinlock_t * lock)1843682af46SSoren Brinkmann struct clk *clk_register_zynq_pll(const char *name, const char *parent,
1853682af46SSoren Brinkmann void __iomem *pll_ctrl, void __iomem *pll_status, u8 lock_index,
1863682af46SSoren Brinkmann spinlock_t *lock)
1873682af46SSoren Brinkmann {
1883682af46SSoren Brinkmann struct zynq_pll *pll;
1893682af46SSoren Brinkmann struct clk *clk;
1903682af46SSoren Brinkmann u32 reg;
1913682af46SSoren Brinkmann const char *parent_arr[1] = {parent};
1923682af46SSoren Brinkmann unsigned long flags = 0;
1933682af46SSoren Brinkmann struct clk_init_data initd = {
1943682af46SSoren Brinkmann .name = name,
1953682af46SSoren Brinkmann .parent_names = parent_arr,
1963682af46SSoren Brinkmann .ops = &zynq_pll_ops,
1973682af46SSoren Brinkmann .num_parents = 1,
1983682af46SSoren Brinkmann .flags = 0
1993682af46SSoren Brinkmann };
2003682af46SSoren Brinkmann
2013682af46SSoren Brinkmann pll = kmalloc(sizeof(*pll), GFP_KERNEL);
20288cebf5eSSoren Brinkmann if (!pll)
2033682af46SSoren Brinkmann return ERR_PTR(-ENOMEM);
2043682af46SSoren Brinkmann
2053682af46SSoren Brinkmann /* Populate the struct */
2063682af46SSoren Brinkmann pll->hw.init = &initd;
2073682af46SSoren Brinkmann pll->pll_ctrl = pll_ctrl;
2083682af46SSoren Brinkmann pll->pll_status = pll_status;
2093682af46SSoren Brinkmann pll->lockbit = lock_index;
2103682af46SSoren Brinkmann pll->lock = lock;
2113682af46SSoren Brinkmann
2123682af46SSoren Brinkmann spin_lock_irqsave(pll->lock, flags);
2133682af46SSoren Brinkmann
2145834fd75SJonas Gorski reg = readl(pll->pll_ctrl);
2153682af46SSoren Brinkmann reg &= ~PLLCTRL_BPQUAL_MASK;
2165834fd75SJonas Gorski writel(reg, pll->pll_ctrl);
2173682af46SSoren Brinkmann
2183682af46SSoren Brinkmann spin_unlock_irqrestore(pll->lock, flags);
2193682af46SSoren Brinkmann
2203682af46SSoren Brinkmann clk = clk_register(NULL, &pll->hw);
2213682af46SSoren Brinkmann if (WARN_ON(IS_ERR(clk)))
2223682af46SSoren Brinkmann goto free_pll;
2233682af46SSoren Brinkmann
2243682af46SSoren Brinkmann return clk;
2253682af46SSoren Brinkmann
2263682af46SSoren Brinkmann free_pll:
2273682af46SSoren Brinkmann kfree(pll);
2283682af46SSoren Brinkmann
2293682af46SSoren Brinkmann return clk;
2303682af46SSoren Brinkmann }
231