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