1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2014 MediaTek Inc. 4 * Author: James Liao <jamesjj.liao@mediatek.com> 5 */ 6 7 #include <linux/of.h> 8 #include <linux/of_address.h> 9 #include <linux/io.h> 10 #include <linux/module.h> 11 #include <linux/slab.h> 12 #include <linux/clkdev.h> 13 #include <linux/delay.h> 14 15 #include "clk-mtk.h" 16 17 #define REG_CON0 0 18 #define REG_CON1 4 19 20 #define CON0_BASE_EN BIT(0) 21 #define CON0_PWR_ON BIT(0) 22 #define CON0_ISO_EN BIT(1) 23 #define PCW_CHG_MASK BIT(31) 24 25 #define AUDPLL_TUNER_EN BIT(31) 26 27 #define POSTDIV_MASK 0x7 28 29 /* default 7 bits integer, can be overridden with pcwibits. */ 30 #define INTEGER_BITS 7 31 32 /* 33 * MediaTek PLLs are configured through their pcw value. The pcw value describes 34 * a divider in the PLL feedback loop which consists of 7 bits for the integer 35 * part and the remaining bits (if present) for the fractional part. Also they 36 * have a 3 bit power-of-two post divider. 37 */ 38 39 struct mtk_clk_pll { 40 struct clk_hw hw; 41 void __iomem *base_addr; 42 void __iomem *pd_addr; 43 void __iomem *pwr_addr; 44 void __iomem *tuner_addr; 45 void __iomem *tuner_en_addr; 46 void __iomem *pcw_addr; 47 void __iomem *pcw_chg_addr; 48 void __iomem *en_addr; 49 const struct mtk_pll_data *data; 50 }; 51 52 static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw) 53 { 54 return container_of(hw, struct mtk_clk_pll, hw); 55 } 56 57 static int mtk_pll_is_prepared(struct clk_hw *hw) 58 { 59 struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); 60 61 return (readl(pll->en_addr) & BIT(pll->data->pll_en_bit)) != 0; 62 } 63 64 static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin, 65 u32 pcw, int postdiv) 66 { 67 int pcwbits = pll->data->pcwbits; 68 int pcwfbits = 0; 69 int ibits; 70 u64 vco; 71 u8 c = 0; 72 73 /* The fractional part of the PLL divider. */ 74 ibits = pll->data->pcwibits ? pll->data->pcwibits : INTEGER_BITS; 75 if (pcwbits > ibits) 76 pcwfbits = pcwbits - ibits; 77 78 vco = (u64)fin * pcw; 79 80 if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0))) 81 c = 1; 82 83 vco >>= pcwfbits; 84 85 if (c) 86 vco++; 87 88 return ((unsigned long)vco + postdiv - 1) / postdiv; 89 } 90 91 static void __mtk_pll_tuner_enable(struct mtk_clk_pll *pll) 92 { 93 u32 r; 94 95 if (pll->tuner_en_addr) { 96 r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit); 97 writel(r, pll->tuner_en_addr); 98 } else if (pll->tuner_addr) { 99 r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN; 100 writel(r, pll->tuner_addr); 101 } 102 } 103 104 static void __mtk_pll_tuner_disable(struct mtk_clk_pll *pll) 105 { 106 u32 r; 107 108 if (pll->tuner_en_addr) { 109 r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit); 110 writel(r, pll->tuner_en_addr); 111 } else if (pll->tuner_addr) { 112 r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN; 113 writel(r, pll->tuner_addr); 114 } 115 } 116 117 static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw, 118 int postdiv) 119 { 120 u32 chg, val; 121 122 /* disable tuner */ 123 __mtk_pll_tuner_disable(pll); 124 125 /* set postdiv */ 126 val = readl(pll->pd_addr); 127 val &= ~(POSTDIV_MASK << pll->data->pd_shift); 128 val |= (ffs(postdiv) - 1) << pll->data->pd_shift; 129 130 /* postdiv and pcw need to set at the same time if on same register */ 131 if (pll->pd_addr != pll->pcw_addr) { 132 writel(val, pll->pd_addr); 133 val = readl(pll->pcw_addr); 134 } 135 136 /* set pcw */ 137 val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1, 138 pll->data->pcw_shift); 139 val |= pcw << pll->data->pcw_shift; 140 writel(val, pll->pcw_addr); 141 chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK; 142 writel(chg, pll->pcw_chg_addr); 143 if (pll->tuner_addr) 144 writel(val + 1, pll->tuner_addr); 145 146 /* restore tuner_en */ 147 __mtk_pll_tuner_enable(pll); 148 149 udelay(20); 150 } 151 152 /* 153 * mtk_pll_calc_values - calculate good values for a given input frequency. 154 * @pll: The pll 155 * @pcw: The pcw value (output) 156 * @postdiv: The post divider (output) 157 * @freq: The desired target frequency 158 * @fin: The input frequency 159 * 160 */ 161 static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv, 162 u32 freq, u32 fin) 163 { 164 unsigned long fmin = pll->data->fmin ? pll->data->fmin : (1000 * MHZ); 165 const struct mtk_pll_div_table *div_table = pll->data->div_table; 166 u64 _pcw; 167 int ibits; 168 u32 val; 169 170 if (freq > pll->data->fmax) 171 freq = pll->data->fmax; 172 173 if (div_table) { 174 if (freq > div_table[0].freq) 175 freq = div_table[0].freq; 176 177 for (val = 0; div_table[val + 1].freq != 0; val++) { 178 if (freq > div_table[val + 1].freq) 179 break; 180 } 181 *postdiv = 1 << val; 182 } else { 183 for (val = 0; val < 5; val++) { 184 *postdiv = 1 << val; 185 if ((u64)freq * *postdiv >= fmin) 186 break; 187 } 188 } 189 190 /* _pcw = freq * postdiv / fin * 2^pcwfbits */ 191 ibits = pll->data->pcwibits ? pll->data->pcwibits : INTEGER_BITS; 192 _pcw = ((u64)freq << val) << (pll->data->pcwbits - ibits); 193 do_div(_pcw, fin); 194 195 *pcw = (u32)_pcw; 196 } 197 198 static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate, 199 unsigned long parent_rate) 200 { 201 struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); 202 u32 pcw = 0; 203 u32 postdiv; 204 205 mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate); 206 mtk_pll_set_rate_regs(pll, pcw, postdiv); 207 208 return 0; 209 } 210 211 static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw, 212 unsigned long parent_rate) 213 { 214 struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); 215 u32 postdiv; 216 u32 pcw; 217 218 postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & POSTDIV_MASK; 219 postdiv = 1 << postdiv; 220 221 pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift; 222 pcw &= GENMASK(pll->data->pcwbits - 1, 0); 223 224 return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv); 225 } 226 227 static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate, 228 unsigned long *prate) 229 { 230 struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); 231 u32 pcw = 0; 232 int postdiv; 233 234 mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate); 235 236 return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv); 237 } 238 239 static int mtk_pll_prepare(struct clk_hw *hw) 240 { 241 struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); 242 u32 r; 243 u32 div_en_mask; 244 245 r = readl(pll->pwr_addr) | CON0_PWR_ON; 246 writel(r, pll->pwr_addr); 247 udelay(1); 248 249 r = readl(pll->pwr_addr) & ~CON0_ISO_EN; 250 writel(r, pll->pwr_addr); 251 udelay(1); 252 253 r = readl(pll->en_addr) | BIT(pll->data->pll_en_bit); 254 writel(r, pll->en_addr); 255 256 div_en_mask = pll->data->en_mask & ~CON0_BASE_EN; 257 if (div_en_mask) { 258 r = readl(pll->base_addr + REG_CON0) | div_en_mask; 259 writel(r, pll->base_addr + REG_CON0); 260 } 261 262 __mtk_pll_tuner_enable(pll); 263 264 udelay(20); 265 266 if (pll->data->flags & HAVE_RST_BAR) { 267 r = readl(pll->base_addr + REG_CON0); 268 r |= pll->data->rst_bar_mask; 269 writel(r, pll->base_addr + REG_CON0); 270 } 271 272 return 0; 273 } 274 275 static void mtk_pll_unprepare(struct clk_hw *hw) 276 { 277 struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); 278 u32 r; 279 u32 div_en_mask; 280 281 if (pll->data->flags & HAVE_RST_BAR) { 282 r = readl(pll->base_addr + REG_CON0); 283 r &= ~pll->data->rst_bar_mask; 284 writel(r, pll->base_addr + REG_CON0); 285 } 286 287 __mtk_pll_tuner_disable(pll); 288 289 div_en_mask = pll->data->en_mask & ~CON0_BASE_EN; 290 if (div_en_mask) { 291 r = readl(pll->base_addr + REG_CON0) & ~div_en_mask; 292 writel(r, pll->base_addr + REG_CON0); 293 } 294 295 r = readl(pll->en_addr) & ~BIT(pll->data->pll_en_bit); 296 writel(r, pll->en_addr); 297 298 r = readl(pll->pwr_addr) | CON0_ISO_EN; 299 writel(r, pll->pwr_addr); 300 301 r = readl(pll->pwr_addr) & ~CON0_PWR_ON; 302 writel(r, pll->pwr_addr); 303 } 304 305 static const struct clk_ops mtk_pll_ops = { 306 .is_prepared = mtk_pll_is_prepared, 307 .prepare = mtk_pll_prepare, 308 .unprepare = mtk_pll_unprepare, 309 .recalc_rate = mtk_pll_recalc_rate, 310 .round_rate = mtk_pll_round_rate, 311 .set_rate = mtk_pll_set_rate, 312 }; 313 314 static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data, 315 void __iomem *base) 316 { 317 struct mtk_clk_pll *pll; 318 struct clk_init_data init = {}; 319 struct clk *clk; 320 const char *parent_name = "clk26m"; 321 322 pll = kzalloc(sizeof(*pll), GFP_KERNEL); 323 if (!pll) 324 return ERR_PTR(-ENOMEM); 325 326 pll->base_addr = base + data->reg; 327 pll->pwr_addr = base + data->pwr_reg; 328 pll->pd_addr = base + data->pd_reg; 329 pll->pcw_addr = base + data->pcw_reg; 330 if (data->pcw_chg_reg) 331 pll->pcw_chg_addr = base + data->pcw_chg_reg; 332 else 333 pll->pcw_chg_addr = pll->base_addr + REG_CON1; 334 if (data->tuner_reg) 335 pll->tuner_addr = base + data->tuner_reg; 336 if (data->tuner_en_reg || data->tuner_en_bit) 337 pll->tuner_en_addr = base + data->tuner_en_reg; 338 if (data->en_reg) 339 pll->en_addr = base + data->en_reg; 340 else 341 pll->en_addr = pll->base_addr + REG_CON0; 342 pll->hw.init = &init; 343 pll->data = data; 344 345 init.name = data->name; 346 init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0; 347 init.ops = &mtk_pll_ops; 348 if (data->parent_name) 349 init.parent_names = &data->parent_name; 350 else 351 init.parent_names = &parent_name; 352 init.num_parents = 1; 353 354 clk = clk_register(NULL, &pll->hw); 355 356 if (IS_ERR(clk)) 357 kfree(pll); 358 359 return clk; 360 } 361 362 void mtk_clk_register_plls(struct device_node *node, 363 const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data) 364 { 365 void __iomem *base; 366 int i; 367 struct clk *clk; 368 369 base = of_iomap(node, 0); 370 if (!base) { 371 pr_err("%s(): ioremap failed\n", __func__); 372 return; 373 } 374 375 for (i = 0; i < num_plls; i++) { 376 const struct mtk_pll_data *pll = &plls[i]; 377 378 clk = mtk_clk_register_pll(pll, base); 379 380 if (IS_ERR(clk)) { 381 pr_err("Failed to register clk %s: %ld\n", 382 pll->name, PTR_ERR(clk)); 383 continue; 384 } 385 386 clk_data->clks[pll->id] = clk; 387 } 388 } 389 EXPORT_SYMBOL_GPL(mtk_clk_register_plls); 390 391 MODULE_LICENSE("GPL"); 392