1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Zynq PLL driver 4 * 5 * Copyright (C) 2013 Xilinx 6 * 7 * Sören Brinkmann <soren.brinkmann@xilinx.com> 8 */ 9 #include <linux/clk/zynq.h> 10 #include <linux/clk-provider.h> 11 #include <linux/slab.h> 12 #include <linux/io.h> 13 14 /** 15 * struct zynq_pll - pll clock 16 * @hw: Handle between common and hardware-specific interfaces 17 * @pll_ctrl: PLL control register 18 * @pll_status: PLL status register 19 * @lock: Register lock 20 * @lockbit: Indicates the associated PLL_LOCKED bit in the PLL status 21 * register. 22 */ 23 struct zynq_pll { 24 struct clk_hw hw; 25 void __iomem *pll_ctrl; 26 void __iomem *pll_status; 27 spinlock_t *lock; 28 u8 lockbit; 29 }; 30 #define to_zynq_pll(_hw) container_of(_hw, struct zynq_pll, hw) 31 32 /* Register bitfield defines */ 33 #define PLLCTRL_FBDIV_MASK 0x7f000 34 #define PLLCTRL_FBDIV_SHIFT 12 35 #define PLLCTRL_BPQUAL_MASK (1 << 3) 36 #define PLLCTRL_PWRDWN_MASK 2 37 #define PLLCTRL_PWRDWN_SHIFT 1 38 #define PLLCTRL_RESET_MASK 1 39 #define PLLCTRL_RESET_SHIFT 0 40 41 #define PLL_FBDIV_MIN 13 42 #define PLL_FBDIV_MAX 66 43 44 /** 45 * zynq_pll_round_rate() - Round a clock frequency 46 * @hw: Handle between common and hardware-specific interfaces 47 * @rate: Desired clock frequency 48 * @prate: Clock frequency of parent clock 49 * Return: frequency closest to @rate the hardware can generate. 50 */ 51 static int zynq_pll_determine_rate(struct clk_hw *hw, 52 struct clk_rate_request *req) 53 { 54 u32 fbdiv; 55 56 fbdiv = DIV_ROUND_CLOSEST(req->rate, req->best_parent_rate); 57 if (fbdiv < PLL_FBDIV_MIN) 58 fbdiv = PLL_FBDIV_MIN; 59 else if (fbdiv > PLL_FBDIV_MAX) 60 fbdiv = PLL_FBDIV_MAX; 61 62 req->rate = req->best_parent_rate * fbdiv; 63 64 return 0; 65 } 66 67 /** 68 * zynq_pll_recalc_rate() - Recalculate clock frequency 69 * @hw: Handle between common and hardware-specific interfaces 70 * @parent_rate: Clock frequency of parent clock 71 * Return: current clock frequency. 72 */ 73 static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw, 74 unsigned long parent_rate) 75 { 76 struct zynq_pll *clk = to_zynq_pll(hw); 77 u32 fbdiv; 78 79 /* 80 * makes probably sense to redundantly save fbdiv in the struct 81 * zynq_pll to save the IO access. 82 */ 83 fbdiv = (readl(clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >> 84 PLLCTRL_FBDIV_SHIFT; 85 86 return parent_rate * fbdiv; 87 } 88 89 /** 90 * zynq_pll_is_enabled - Check if a clock is enabled 91 * @hw: Handle between common and hardware-specific interfaces 92 * Return: 1 if the clock is enabled, 0 otherwise. 93 * 94 * Not sure this is a good idea, but since disabled means bypassed for 95 * this clock implementation we say we are always enabled. 96 */ 97 static int zynq_pll_is_enabled(struct clk_hw *hw) 98 { 99 unsigned long flags = 0; 100 u32 reg; 101 struct zynq_pll *clk = to_zynq_pll(hw); 102 103 spin_lock_irqsave(clk->lock, flags); 104 105 reg = readl(clk->pll_ctrl); 106 107 spin_unlock_irqrestore(clk->lock, flags); 108 109 return !(reg & (PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK)); 110 } 111 112 /** 113 * zynq_pll_enable - Enable clock 114 * @hw: Handle between common and hardware-specific interfaces 115 * Return: 0 on success 116 */ 117 static int zynq_pll_enable(struct clk_hw *hw) 118 { 119 unsigned long flags = 0; 120 u32 reg; 121 struct zynq_pll *clk = to_zynq_pll(hw); 122 123 if (zynq_pll_is_enabled(hw)) 124 return 0; 125 126 pr_info("PLL: enable\n"); 127 128 /* Power up PLL and wait for lock */ 129 spin_lock_irqsave(clk->lock, flags); 130 131 reg = readl(clk->pll_ctrl); 132 reg &= ~(PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK); 133 writel(reg, clk->pll_ctrl); 134 while (!(readl(clk->pll_status) & (1 << clk->lockbit))) 135 ; 136 137 spin_unlock_irqrestore(clk->lock, flags); 138 139 return 0; 140 } 141 142 /** 143 * zynq_pll_disable - Disable clock 144 * @hw: Handle between common and hardware-specific interfaces 145 * Returns 0 on success 146 */ 147 static void zynq_pll_disable(struct clk_hw *hw) 148 { 149 unsigned long flags = 0; 150 u32 reg; 151 struct zynq_pll *clk = to_zynq_pll(hw); 152 153 if (!zynq_pll_is_enabled(hw)) 154 return; 155 156 pr_info("PLL: shutdown\n"); 157 158 /* shut down PLL */ 159 spin_lock_irqsave(clk->lock, flags); 160 161 reg = readl(clk->pll_ctrl); 162 reg |= PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK; 163 writel(reg, clk->pll_ctrl); 164 165 spin_unlock_irqrestore(clk->lock, flags); 166 } 167 168 static const struct clk_ops zynq_pll_ops = { 169 .enable = zynq_pll_enable, 170 .disable = zynq_pll_disable, 171 .is_enabled = zynq_pll_is_enabled, 172 .determine_rate = zynq_pll_determine_rate, 173 .recalc_rate = zynq_pll_recalc_rate 174 }; 175 176 /** 177 * clk_register_zynq_pll() - Register PLL with the clock framework 178 * @name: PLL name 179 * @parent: Parent clock name 180 * @pll_ctrl: Pointer to PLL control register 181 * @pll_status: Pointer to PLL status register 182 * @lock_index: Bit index to this PLL's lock status bit in @pll_status 183 * @lock: Register lock 184 * Return: handle to the registered clock. 185 */ 186 struct clk *clk_register_zynq_pll(const char *name, const char *parent, 187 void __iomem *pll_ctrl, void __iomem *pll_status, u8 lock_index, 188 spinlock_t *lock) 189 { 190 struct zynq_pll *pll; 191 struct clk *clk; 192 u32 reg; 193 const char *parent_arr[1] = {parent}; 194 unsigned long flags = 0; 195 struct clk_init_data initd = { 196 .name = name, 197 .parent_names = parent_arr, 198 .ops = &zynq_pll_ops, 199 .num_parents = 1, 200 .flags = 0 201 }; 202 203 pll = kmalloc(sizeof(*pll), GFP_KERNEL); 204 if (!pll) 205 return ERR_PTR(-ENOMEM); 206 207 /* Populate the struct */ 208 pll->hw.init = &initd; 209 pll->pll_ctrl = pll_ctrl; 210 pll->pll_status = pll_status; 211 pll->lockbit = lock_index; 212 pll->lock = lock; 213 214 spin_lock_irqsave(pll->lock, flags); 215 216 reg = readl(pll->pll_ctrl); 217 reg &= ~PLLCTRL_BPQUAL_MASK; 218 writel(reg, pll->pll_ctrl); 219 220 spin_unlock_irqrestore(pll->lock, flags); 221 222 clk = clk_register(NULL, &pll->hw); 223 if (WARN_ON(IS_ERR(clk))) 224 goto free_pll; 225 226 return clk; 227 228 free_pll: 229 kfree(pll); 230 231 return clk; 232 } 233