1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Toshiba Visconti PLL driver 4 * 5 * Copyright (c) 2021 TOSHIBA CORPORATION 6 * Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation 7 * 8 * Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> 9 */ 10 11 #include <linux/bitfield.h> 12 #include <linux/clk-provider.h> 13 #include <linux/delay.h> 14 #include <linux/slab.h> 15 #include <linux/io.h> 16 17 #include "pll.h" 18 19 struct visconti_pll { 20 struct clk_hw hw; 21 void __iomem *pll_base; 22 spinlock_t *lock; 23 unsigned long flags; 24 const struct visconti_pll_rate_table *rate_table; 25 size_t rate_count; 26 struct visconti_pll_provider *ctx; 27 }; 28 29 #define PLL_CONF_REG 0x0000 30 #define PLL_CTRL_REG 0x0004 31 #define PLL_FRACMODE_REG 0x0010 32 #define PLL_INTIN_REG 0x0014 33 #define PLL_FRACIN_REG 0x0018 34 #define PLL_REFDIV_REG 0x001c 35 #define PLL_POSTDIV_REG 0x0020 36 37 #define PLL_CONFIG_SEL BIT(0) 38 #define PLL_PLLEN BIT(4) 39 #define PLL_BYPASS BIT(16) 40 #define PLL_INTIN_MASK GENMASK(11, 0) 41 #define PLL_FRACIN_MASK GENMASK(23, 0) 42 #define PLL_REFDIV_MASK GENMASK(5, 0) 43 #define PLL_POSTDIV_MASK GENMASK(2, 0) 44 45 #define PLL0_FRACMODE_DACEN BIT(4) 46 #define PLL0_FRACMODE_DSMEN BIT(0) 47 48 #define PLL_CREATE_FRACMODE(table) (table->dacen << 4 | table->dsmen) 49 #define PLL_CREATE_OSTDIV(table) (table->postdiv2 << 4 | table->postdiv1) 50 51 static inline struct visconti_pll *to_visconti_pll(struct clk_hw *hw) 52 { 53 return container_of(hw, struct visconti_pll, hw); 54 } 55 56 static void visconti_pll_get_params(struct visconti_pll *pll, 57 struct visconti_pll_rate_table *rate_table) 58 { 59 u32 postdiv, val; 60 61 val = readl(pll->pll_base + PLL_FRACMODE_REG); 62 63 rate_table->dacen = FIELD_GET(PLL0_FRACMODE_DACEN, val); 64 rate_table->dsmen = FIELD_GET(PLL0_FRACMODE_DSMEN, val); 65 66 rate_table->fracin = readl(pll->pll_base + PLL_FRACIN_REG) & PLL_FRACIN_MASK; 67 rate_table->intin = readl(pll->pll_base + PLL_INTIN_REG) & PLL_INTIN_MASK; 68 rate_table->refdiv = readl(pll->pll_base + PLL_REFDIV_REG) & PLL_REFDIV_MASK; 69 70 postdiv = readl(pll->pll_base + PLL_POSTDIV_REG); 71 rate_table->postdiv1 = postdiv & PLL_POSTDIV_MASK; 72 rate_table->postdiv2 = (postdiv >> 4) & PLL_POSTDIV_MASK; 73 } 74 75 static const struct visconti_pll_rate_table *visconti_get_pll_settings(struct visconti_pll *pll, 76 unsigned long rate) 77 { 78 const struct visconti_pll_rate_table *rate_table = pll->rate_table; 79 int i; 80 81 for (i = 0; i < pll->rate_count; i++) 82 if (rate == rate_table[i].rate) 83 return &rate_table[i]; 84 85 return NULL; 86 } 87 88 static unsigned long visconti_get_pll_rate_from_data(struct visconti_pll *pll, 89 const struct visconti_pll_rate_table *rate) 90 { 91 const struct visconti_pll_rate_table *rate_table = pll->rate_table; 92 int i; 93 94 for (i = 0; i < pll->rate_count; i++) 95 if (memcmp(&rate_table[i].dacen, &rate->dacen, 96 sizeof(*rate) - sizeof(unsigned long)) == 0) 97 return rate_table[i].rate; 98 99 /* set default */ 100 return rate_table[0].rate; 101 } 102 103 static int visconti_pll_determine_rate(struct clk_hw *hw, 104 struct clk_rate_request *req) 105 { 106 struct visconti_pll *pll = to_visconti_pll(hw); 107 const struct visconti_pll_rate_table *rate_table = pll->rate_table; 108 int i; 109 110 /* Assuming rate_table is in descending order */ 111 for (i = 0; i < pll->rate_count; i++) 112 if (req->rate >= rate_table[i].rate) { 113 req->rate = rate_table[i].rate; 114 115 return 0; 116 } 117 118 /* return minimum supported value */ 119 req->rate = rate_table[i - 1].rate; 120 121 return 0; 122 } 123 124 static unsigned long visconti_pll_recalc_rate(struct clk_hw *hw, 125 unsigned long parent_rate) 126 { 127 struct visconti_pll *pll = to_visconti_pll(hw); 128 struct visconti_pll_rate_table rate_table; 129 130 memset(&rate_table, 0, sizeof(rate_table)); 131 visconti_pll_get_params(pll, &rate_table); 132 133 return visconti_get_pll_rate_from_data(pll, &rate_table); 134 } 135 136 static int visconti_pll_set_params(struct visconti_pll *pll, 137 const struct visconti_pll_rate_table *rate_table) 138 { 139 writel(PLL_CREATE_FRACMODE(rate_table), pll->pll_base + PLL_FRACMODE_REG); 140 writel(PLL_CREATE_OSTDIV(rate_table), pll->pll_base + PLL_POSTDIV_REG); 141 writel(rate_table->intin, pll->pll_base + PLL_INTIN_REG); 142 writel(rate_table->fracin, pll->pll_base + PLL_FRACIN_REG); 143 writel(rate_table->refdiv, pll->pll_base + PLL_REFDIV_REG); 144 145 return 0; 146 } 147 148 static int visconti_pll_set_rate(struct clk_hw *hw, unsigned long rate, 149 unsigned long parent_rate) 150 { 151 struct visconti_pll *pll = to_visconti_pll(hw); 152 const struct visconti_pll_rate_table *rate_table; 153 154 rate_table = visconti_get_pll_settings(pll, rate); 155 if (!rate_table) 156 return -EINVAL; 157 158 return visconti_pll_set_params(pll, rate_table); 159 } 160 161 static int visconti_pll_is_enabled(struct clk_hw *hw) 162 { 163 struct visconti_pll *pll = to_visconti_pll(hw); 164 u32 reg; 165 166 reg = readl(pll->pll_base + PLL_CTRL_REG); 167 168 return (reg & PLL_PLLEN); 169 } 170 171 static int visconti_pll_enable(struct clk_hw *hw) 172 { 173 struct visconti_pll *pll = to_visconti_pll(hw); 174 const struct visconti_pll_rate_table *rate_table = pll->rate_table; 175 unsigned long flags; 176 u32 reg; 177 178 if (visconti_pll_is_enabled(hw)) 179 return 0; 180 181 spin_lock_irqsave(pll->lock, flags); 182 183 writel(PLL_CONFIG_SEL, pll->pll_base + PLL_CONF_REG); 184 185 reg = readl(pll->pll_base + PLL_CTRL_REG); 186 reg |= PLL_BYPASS; 187 writel(reg, pll->pll_base + PLL_CTRL_REG); 188 189 visconti_pll_set_params(pll, &rate_table[0]); 190 191 reg = readl(pll->pll_base + PLL_CTRL_REG); 192 reg &= ~PLL_PLLEN; 193 writel(reg, pll->pll_base + PLL_CTRL_REG); 194 195 udelay(1); 196 197 reg = readl(pll->pll_base + PLL_CTRL_REG); 198 reg |= PLL_PLLEN; 199 writel(reg, pll->pll_base + PLL_CTRL_REG); 200 201 udelay(40); 202 203 reg = readl(pll->pll_base + PLL_CTRL_REG); 204 reg &= ~PLL_BYPASS; 205 writel(reg, pll->pll_base + PLL_CTRL_REG); 206 207 spin_unlock_irqrestore(pll->lock, flags); 208 209 return 0; 210 } 211 212 static void visconti_pll_disable(struct clk_hw *hw) 213 { 214 struct visconti_pll *pll = to_visconti_pll(hw); 215 unsigned long flags; 216 u32 reg; 217 218 if (!visconti_pll_is_enabled(hw)) 219 return; 220 221 spin_lock_irqsave(pll->lock, flags); 222 223 writel(PLL_CONFIG_SEL, pll->pll_base + PLL_CONF_REG); 224 225 reg = readl(pll->pll_base + PLL_CTRL_REG); 226 reg |= PLL_BYPASS; 227 writel(reg, pll->pll_base + PLL_CTRL_REG); 228 229 reg = readl(pll->pll_base + PLL_CTRL_REG); 230 reg &= ~PLL_PLLEN; 231 writel(reg, pll->pll_base + PLL_CTRL_REG); 232 233 spin_unlock_irqrestore(pll->lock, flags); 234 } 235 236 static const struct clk_ops visconti_pll_ops = { 237 .enable = visconti_pll_enable, 238 .disable = visconti_pll_disable, 239 .is_enabled = visconti_pll_is_enabled, 240 .determine_rate = visconti_pll_determine_rate, 241 .recalc_rate = visconti_pll_recalc_rate, 242 .set_rate = visconti_pll_set_rate, 243 }; 244 245 static struct clk_hw *visconti_register_pll(struct visconti_pll_provider *ctx, 246 const char *name, 247 const char *parent_name, 248 int offset, 249 const struct visconti_pll_rate_table *rate_table, 250 spinlock_t *lock) 251 { 252 struct clk_init_data init; 253 struct visconti_pll *pll; 254 struct clk_hw *pll_hw_clk; 255 size_t len; 256 int ret; 257 258 pll = kzalloc(sizeof(*pll), GFP_KERNEL); 259 if (!pll) 260 return ERR_PTR(-ENOMEM); 261 262 init.name = name; 263 init.flags = CLK_IGNORE_UNUSED; 264 init.parent_names = &parent_name; 265 init.num_parents = 1; 266 267 for (len = 0; rate_table[len].rate != 0; ) 268 len++; 269 pll->rate_count = len; 270 pll->rate_table = kmemdup_array(rate_table, 271 pll->rate_count, sizeof(*pll->rate_table), 272 GFP_KERNEL); 273 WARN(!pll->rate_table, "%s: could not allocate rate table for %s\n", __func__, name); 274 275 init.ops = &visconti_pll_ops; 276 pll->hw.init = &init; 277 pll->pll_base = ctx->reg_base + offset; 278 pll->lock = lock; 279 pll->ctx = ctx; 280 281 pll_hw_clk = &pll->hw; 282 ret = clk_hw_register(NULL, &pll->hw); 283 if (ret) { 284 pr_err("failed to register pll clock %s : %d\n", name, ret); 285 kfree(pll->rate_table); 286 kfree(pll); 287 pll_hw_clk = ERR_PTR(ret); 288 } 289 290 return pll_hw_clk; 291 } 292 293 static void visconti_pll_add_lookup(struct visconti_pll_provider *ctx, 294 struct clk_hw *hw_clk, 295 unsigned int id) 296 { 297 if (id) 298 ctx->clk_data.hws[id] = hw_clk; 299 } 300 301 void __init visconti_register_plls(struct visconti_pll_provider *ctx, 302 const struct visconti_pll_info *list, 303 unsigned int nr_plls, 304 spinlock_t *lock) 305 { 306 int idx; 307 308 for (idx = 0; idx < nr_plls; idx++, list++) { 309 struct clk_hw *clk; 310 311 clk = visconti_register_pll(ctx, 312 list->name, 313 list->parent, 314 list->base_reg, 315 list->rate_table, 316 lock); 317 if (IS_ERR(clk)) { 318 pr_err("failed to register clock %s\n", list->name); 319 continue; 320 } 321 322 visconti_pll_add_lookup(ctx, clk, list->id); 323 } 324 } 325 326 struct visconti_pll_provider * __init visconti_init_pll(struct device_node *np, 327 void __iomem *base, 328 unsigned long nr_plls) 329 { 330 struct visconti_pll_provider *ctx; 331 int i; 332 333 ctx = kzalloc(struct_size(ctx, clk_data.hws, nr_plls), GFP_KERNEL); 334 if (!ctx) 335 return ERR_PTR(-ENOMEM); 336 337 ctx->node = np; 338 ctx->reg_base = base; 339 ctx->clk_data.num = nr_plls; 340 341 for (i = 0; i < nr_plls; ++i) 342 ctx->clk_data.hws[i] = ERR_PTR(-ENOENT); 343 344 return ctx; 345 } 346