Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: qcom: Add support for root clock generators (RCGs)

Add support for the root clock generators on Qualcomm devices.
RCGs are highly customizable mux/divider/counter clocks that can
be used to generate almost any rate desired given some input
source that is faster than the desired rate.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Mike Turquette <mturquette@linaro.org>

authored by

Stephen Boyd and committed by
Mike Turquette
bcd61c0f 9e263131

+969
+2
drivers/clk/qcom/Makefile
··· 2 2 3 3 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-regmap.o 4 4 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-pll.o 5 + clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg.o 6 + clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg2.o
+517
drivers/clk/qcom/clk-rcg.c
··· 1 + /* 2 + * Copyright (c) 2013, The Linux Foundation. All rights reserved. 3 + * 4 + * This software is licensed under the terms of the GNU General Public 5 + * License version 2, as published by the Free Software Foundation, and 6 + * may be copied, distributed, and modified under those terms. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + #include <linux/kernel.h> 15 + #include <linux/bitops.h> 16 + #include <linux/err.h> 17 + #include <linux/export.h> 18 + #include <linux/clk-provider.h> 19 + #include <linux/regmap.h> 20 + 21 + #include <asm/div64.h> 22 + 23 + #include "clk-rcg.h" 24 + 25 + static u32 ns_to_src(struct src_sel *s, u32 ns) 26 + { 27 + ns >>= s->src_sel_shift; 28 + ns &= SRC_SEL_MASK; 29 + return ns; 30 + } 31 + 32 + static u32 src_to_ns(struct src_sel *s, u8 src, u32 ns) 33 + { 34 + u32 mask; 35 + 36 + mask = SRC_SEL_MASK; 37 + mask <<= s->src_sel_shift; 38 + ns &= ~mask; 39 + 40 + ns |= src << s->src_sel_shift; 41 + return ns; 42 + } 43 + 44 + static u8 clk_rcg_get_parent(struct clk_hw *hw) 45 + { 46 + struct clk_rcg *rcg = to_clk_rcg(hw); 47 + int num_parents = __clk_get_num_parents(hw->clk); 48 + u32 ns; 49 + int i; 50 + 51 + regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 52 + ns = ns_to_src(&rcg->s, ns); 53 + for (i = 0; i < num_parents; i++) 54 + if (ns == rcg->s.parent_map[i]) 55 + return i; 56 + 57 + return -EINVAL; 58 + } 59 + 60 + static int reg_to_bank(struct clk_dyn_rcg *rcg, u32 bank) 61 + { 62 + bank &= BIT(rcg->mux_sel_bit); 63 + return !!bank; 64 + } 65 + 66 + static u8 clk_dyn_rcg_get_parent(struct clk_hw *hw) 67 + { 68 + struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); 69 + int num_parents = __clk_get_num_parents(hw->clk); 70 + u32 ns, ctl; 71 + int bank; 72 + int i; 73 + struct src_sel *s; 74 + 75 + regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); 76 + bank = reg_to_bank(rcg, ctl); 77 + s = &rcg->s[bank]; 78 + 79 + regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 80 + ns = ns_to_src(s, ns); 81 + 82 + for (i = 0; i < num_parents; i++) 83 + if (ns == s->parent_map[i]) 84 + return i; 85 + 86 + return -EINVAL; 87 + } 88 + 89 + static int clk_rcg_set_parent(struct clk_hw *hw, u8 index) 90 + { 91 + struct clk_rcg *rcg = to_clk_rcg(hw); 92 + u32 ns; 93 + 94 + regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 95 + ns = src_to_ns(&rcg->s, rcg->s.parent_map[index], ns); 96 + regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 97 + 98 + return 0; 99 + } 100 + 101 + static u32 md_to_m(struct mn *mn, u32 md) 102 + { 103 + md >>= mn->m_val_shift; 104 + md &= BIT(mn->width) - 1; 105 + return md; 106 + } 107 + 108 + static u32 ns_to_pre_div(struct pre_div *p, u32 ns) 109 + { 110 + ns >>= p->pre_div_shift; 111 + ns &= BIT(p->pre_div_width) - 1; 112 + return ns; 113 + } 114 + 115 + static u32 pre_div_to_ns(struct pre_div *p, u8 pre_div, u32 ns) 116 + { 117 + u32 mask; 118 + 119 + mask = BIT(p->pre_div_width) - 1; 120 + mask <<= p->pre_div_shift; 121 + ns &= ~mask; 122 + 123 + ns |= pre_div << p->pre_div_shift; 124 + return ns; 125 + } 126 + 127 + static u32 mn_to_md(struct mn *mn, u32 m, u32 n, u32 md) 128 + { 129 + u32 mask, mask_w; 130 + 131 + mask_w = BIT(mn->width) - 1; 132 + mask = (mask_w << mn->m_val_shift) | mask_w; 133 + md &= ~mask; 134 + 135 + if (n) { 136 + m <<= mn->m_val_shift; 137 + md |= m; 138 + md |= ~n & mask_w; 139 + } 140 + 141 + return md; 142 + } 143 + 144 + static u32 ns_m_to_n(struct mn *mn, u32 ns, u32 m) 145 + { 146 + ns = ~ns >> mn->n_val_shift; 147 + ns &= BIT(mn->width) - 1; 148 + return ns + m; 149 + } 150 + 151 + static u32 reg_to_mnctr_mode(struct mn *mn, u32 val) 152 + { 153 + val >>= mn->mnctr_mode_shift; 154 + val &= MNCTR_MODE_MASK; 155 + return val; 156 + } 157 + 158 + static u32 mn_to_ns(struct mn *mn, u32 m, u32 n, u32 ns) 159 + { 160 + u32 mask; 161 + 162 + mask = BIT(mn->width) - 1; 163 + mask <<= mn->n_val_shift; 164 + ns &= ~mask; 165 + 166 + if (n) { 167 + n = n - m; 168 + n = ~n; 169 + n &= BIT(mn->width) - 1; 170 + n <<= mn->n_val_shift; 171 + ns |= n; 172 + } 173 + 174 + return ns; 175 + } 176 + 177 + static u32 mn_to_reg(struct mn *mn, u32 m, u32 n, u32 val) 178 + { 179 + u32 mask; 180 + 181 + mask = MNCTR_MODE_MASK << mn->mnctr_mode_shift; 182 + mask |= BIT(mn->mnctr_en_bit); 183 + val &= ~mask; 184 + 185 + if (n) { 186 + val |= BIT(mn->mnctr_en_bit); 187 + val |= MNCTR_MODE_DUAL << mn->mnctr_mode_shift; 188 + } 189 + 190 + return val; 191 + } 192 + 193 + static void configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f) 194 + { 195 + u32 ns, md, ctl, *regp; 196 + int bank, new_bank; 197 + struct mn *mn; 198 + struct pre_div *p; 199 + struct src_sel *s; 200 + bool enabled; 201 + u32 md_reg; 202 + u32 bank_reg; 203 + bool banked_mn = !!rcg->mn[1].width; 204 + struct clk_hw *hw = &rcg->clkr.hw; 205 + 206 + enabled = __clk_is_enabled(hw->clk); 207 + 208 + regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 209 + regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); 210 + 211 + if (banked_mn) { 212 + regp = &ctl; 213 + bank_reg = rcg->clkr.enable_reg; 214 + } else { 215 + regp = &ns; 216 + bank_reg = rcg->ns_reg; 217 + } 218 + 219 + bank = reg_to_bank(rcg, *regp); 220 + new_bank = enabled ? !bank : bank; 221 + 222 + if (banked_mn) { 223 + mn = &rcg->mn[new_bank]; 224 + md_reg = rcg->md_reg[new_bank]; 225 + 226 + ns |= BIT(mn->mnctr_reset_bit); 227 + regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 228 + 229 + regmap_read(rcg->clkr.regmap, md_reg, &md); 230 + md = mn_to_md(mn, f->m, f->n, md); 231 + regmap_write(rcg->clkr.regmap, md_reg, md); 232 + 233 + ns = mn_to_ns(mn, f->m, f->n, ns); 234 + regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 235 + 236 + ctl = mn_to_reg(mn, f->m, f->n, ctl); 237 + regmap_write(rcg->clkr.regmap, rcg->clkr.enable_reg, ctl); 238 + 239 + ns &= ~BIT(mn->mnctr_reset_bit); 240 + regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 241 + } else { 242 + p = &rcg->p[new_bank]; 243 + ns = pre_div_to_ns(p, f->pre_div - 1, ns); 244 + } 245 + 246 + s = &rcg->s[new_bank]; 247 + ns = src_to_ns(s, s->parent_map[f->src], ns); 248 + regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 249 + 250 + if (enabled) { 251 + *regp ^= BIT(rcg->mux_sel_bit); 252 + regmap_write(rcg->clkr.regmap, bank_reg, *regp); 253 + } 254 + } 255 + 256 + static int clk_dyn_rcg_set_parent(struct clk_hw *hw, u8 index) 257 + { 258 + struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); 259 + u32 ns, ctl, md, reg; 260 + int bank; 261 + struct freq_tbl f = { 0 }; 262 + bool banked_mn = !!rcg->mn[1].width; 263 + 264 + regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 265 + regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); 266 + reg = banked_mn ? ctl : ns; 267 + 268 + bank = reg_to_bank(rcg, reg); 269 + 270 + if (banked_mn) { 271 + regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md); 272 + f.m = md_to_m(&rcg->mn[bank], md); 273 + f.n = ns_m_to_n(&rcg->mn[bank], ns, f.m); 274 + } else { 275 + f.pre_div = ns_to_pre_div(&rcg->p[bank], ns) + 1; 276 + } 277 + f.src = index; 278 + 279 + configure_bank(rcg, &f); 280 + 281 + return 0; 282 + } 283 + 284 + /* 285 + * Calculate m/n:d rate 286 + * 287 + * parent_rate m 288 + * rate = ----------- x --- 289 + * pre_div n 290 + */ 291 + static unsigned long 292 + calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 pre_div) 293 + { 294 + if (pre_div) 295 + rate /= pre_div + 1; 296 + 297 + if (mode) { 298 + u64 tmp = rate; 299 + tmp *= m; 300 + do_div(tmp, n); 301 + rate = tmp; 302 + } 303 + 304 + return rate; 305 + } 306 + 307 + static unsigned long 308 + clk_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 309 + { 310 + struct clk_rcg *rcg = to_clk_rcg(hw); 311 + u32 pre_div, m = 0, n = 0, ns, md, mode = 0; 312 + struct mn *mn = &rcg->mn; 313 + 314 + regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 315 + pre_div = ns_to_pre_div(&rcg->p, ns); 316 + 317 + if (rcg->mn.width) { 318 + regmap_read(rcg->clkr.regmap, rcg->md_reg, &md); 319 + m = md_to_m(mn, md); 320 + n = ns_m_to_n(mn, ns, m); 321 + /* MN counter mode is in hw.enable_reg sometimes */ 322 + if (rcg->clkr.enable_reg != rcg->ns_reg) 323 + regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &mode); 324 + else 325 + mode = ns; 326 + mode = reg_to_mnctr_mode(mn, mode); 327 + } 328 + 329 + return calc_rate(parent_rate, m, n, mode, pre_div); 330 + } 331 + 332 + static unsigned long 333 + clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 334 + { 335 + struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); 336 + u32 m, n, pre_div, ns, md, mode, reg; 337 + int bank; 338 + struct mn *mn; 339 + bool banked_mn = !!rcg->mn[1].width; 340 + 341 + regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 342 + 343 + if (banked_mn) 344 + regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &reg); 345 + else 346 + reg = ns; 347 + 348 + bank = reg_to_bank(rcg, reg); 349 + 350 + if (banked_mn) { 351 + mn = &rcg->mn[bank]; 352 + regmap_read(rcg->clkr.regmap, rcg->md_reg[bank], &md); 353 + m = md_to_m(mn, md); 354 + n = ns_m_to_n(mn, ns, m); 355 + mode = reg_to_mnctr_mode(mn, reg); 356 + return calc_rate(parent_rate, m, n, mode, 0); 357 + } else { 358 + pre_div = ns_to_pre_div(&rcg->p[bank], ns); 359 + return calc_rate(parent_rate, 0, 0, 0, pre_div); 360 + } 361 + } 362 + 363 + static const 364 + struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate) 365 + { 366 + if (!f) 367 + return NULL; 368 + 369 + for (; f->freq; f++) 370 + if (rate <= f->freq) 371 + return f; 372 + 373 + return NULL; 374 + } 375 + 376 + static long _freq_tbl_determine_rate(struct clk_hw *hw, 377 + const struct freq_tbl *f, unsigned long rate, 378 + unsigned long *p_rate, struct clk **p) 379 + { 380 + unsigned long clk_flags; 381 + 382 + f = find_freq(f, rate); 383 + if (!f) 384 + return -EINVAL; 385 + 386 + clk_flags = __clk_get_flags(hw->clk); 387 + *p = clk_get_parent_by_index(hw->clk, f->src); 388 + if (clk_flags & CLK_SET_RATE_PARENT) { 389 + rate = rate * f->pre_div; 390 + if (f->n) { 391 + u64 tmp = rate; 392 + tmp = tmp * f->n; 393 + do_div(tmp, f->m); 394 + rate = tmp; 395 + } 396 + } else { 397 + rate = __clk_get_rate(*p); 398 + } 399 + *p_rate = rate; 400 + 401 + return f->freq; 402 + } 403 + 404 + static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, 405 + unsigned long *p_rate, struct clk **p) 406 + { 407 + struct clk_rcg *rcg = to_clk_rcg(hw); 408 + 409 + return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p); 410 + } 411 + 412 + static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate, 413 + unsigned long *p_rate, struct clk **p) 414 + { 415 + struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); 416 + 417 + return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p); 418 + } 419 + 420 + static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate, 421 + unsigned long parent_rate) 422 + { 423 + struct clk_rcg *rcg = to_clk_rcg(hw); 424 + const struct freq_tbl *f; 425 + u32 ns, md, ctl; 426 + struct mn *mn = &rcg->mn; 427 + u32 mask = 0; 428 + unsigned int reset_reg; 429 + 430 + f = find_freq(rcg->freq_tbl, rate); 431 + if (!f) 432 + return -EINVAL; 433 + 434 + if (rcg->mn.reset_in_cc) 435 + reset_reg = rcg->clkr.enable_reg; 436 + else 437 + reset_reg = rcg->ns_reg; 438 + 439 + if (rcg->mn.width) { 440 + mask = BIT(mn->mnctr_reset_bit); 441 + regmap_update_bits(rcg->clkr.regmap, reset_reg, mask, mask); 442 + 443 + regmap_read(rcg->clkr.regmap, rcg->md_reg, &md); 444 + md = mn_to_md(mn, f->m, f->n, md); 445 + regmap_write(rcg->clkr.regmap, rcg->md_reg, md); 446 + 447 + regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 448 + /* MN counter mode is in hw.enable_reg sometimes */ 449 + if (rcg->clkr.enable_reg != rcg->ns_reg) { 450 + regmap_read(rcg->clkr.regmap, rcg->clkr.enable_reg, &ctl); 451 + ctl = mn_to_reg(mn, f->m, f->n, ctl); 452 + regmap_write(rcg->clkr.regmap, rcg->clkr.enable_reg, ctl); 453 + } else { 454 + ns = mn_to_reg(mn, f->m, f->n, ns); 455 + } 456 + ns = mn_to_ns(mn, f->m, f->n, ns); 457 + } else { 458 + regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns); 459 + } 460 + 461 + ns = pre_div_to_ns(&rcg->p, f->pre_div - 1, ns); 462 + regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns); 463 + 464 + regmap_update_bits(rcg->clkr.regmap, reset_reg, mask, 0); 465 + 466 + return 0; 467 + } 468 + 469 + static int __clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate) 470 + { 471 + struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw); 472 + const struct freq_tbl *f; 473 + 474 + f = find_freq(rcg->freq_tbl, rate); 475 + if (!f) 476 + return -EINVAL; 477 + 478 + configure_bank(rcg, f); 479 + 480 + return 0; 481 + } 482 + 483 + static int clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate, 484 + unsigned long parent_rate) 485 + { 486 + return __clk_dyn_rcg_set_rate(hw, rate); 487 + } 488 + 489 + static int clk_dyn_rcg_set_rate_and_parent(struct clk_hw *hw, 490 + unsigned long rate, unsigned long parent_rate, u8 index) 491 + { 492 + return __clk_dyn_rcg_set_rate(hw, rate); 493 + } 494 + 495 + const struct clk_ops clk_rcg_ops = { 496 + .enable = clk_enable_regmap, 497 + .disable = clk_disable_regmap, 498 + .get_parent = clk_rcg_get_parent, 499 + .set_parent = clk_rcg_set_parent, 500 + .recalc_rate = clk_rcg_recalc_rate, 501 + .determine_rate = clk_rcg_determine_rate, 502 + .set_rate = clk_rcg_set_rate, 503 + }; 504 + EXPORT_SYMBOL_GPL(clk_rcg_ops); 505 + 506 + const struct clk_ops clk_dyn_rcg_ops = { 507 + .enable = clk_enable_regmap, 508 + .is_enabled = clk_is_enabled_regmap, 509 + .disable = clk_disable_regmap, 510 + .get_parent = clk_dyn_rcg_get_parent, 511 + .set_parent = clk_dyn_rcg_set_parent, 512 + .recalc_rate = clk_dyn_rcg_recalc_rate, 513 + .determine_rate = clk_dyn_rcg_determine_rate, 514 + .set_rate = clk_dyn_rcg_set_rate, 515 + .set_rate_and_parent = clk_dyn_rcg_set_rate_and_parent, 516 + }; 517 + EXPORT_SYMBOL_GPL(clk_dyn_rcg_ops);
+159
drivers/clk/qcom/clk-rcg.h
··· 1 + /* 2 + * Copyright (c) 2013, The Linux Foundation. All rights reserved. 3 + * 4 + * This software is licensed under the terms of the GNU General Public 5 + * License version 2, as published by the Free Software Foundation, and 6 + * may be copied, distributed, and modified under those terms. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + #ifndef __QCOM_CLK_RCG_H__ 15 + #define __QCOM_CLK_RCG_H__ 16 + 17 + #include <linux/clk-provider.h> 18 + #include "clk-regmap.h" 19 + 20 + struct freq_tbl { 21 + unsigned long freq; 22 + u8 src; 23 + u8 pre_div; 24 + u16 m; 25 + u16 n; 26 + }; 27 + 28 + /** 29 + * struct mn - M/N:D counter 30 + * @mnctr_en_bit: bit to enable mn counter 31 + * @mnctr_reset_bit: bit to assert mn counter reset 32 + * @mnctr_mode_shift: lowest bit of mn counter mode field 33 + * @n_val_shift: lowest bit of n value field 34 + * @m_val_shift: lowest bit of m value field 35 + * @width: number of bits in m/n/d values 36 + * @reset_in_cc: true if the mnctr_reset_bit is in the CC register 37 + */ 38 + struct mn { 39 + u8 mnctr_en_bit; 40 + u8 mnctr_reset_bit; 41 + u8 mnctr_mode_shift; 42 + #define MNCTR_MODE_DUAL 0x2 43 + #define MNCTR_MODE_MASK 0x3 44 + u8 n_val_shift; 45 + u8 m_val_shift; 46 + u8 width; 47 + bool reset_in_cc; 48 + }; 49 + 50 + /** 51 + * struct pre_div - pre-divider 52 + * @pre_div_shift: lowest bit of pre divider field 53 + * @pre_div_width: number of bits in predivider 54 + */ 55 + struct pre_div { 56 + u8 pre_div_shift; 57 + u8 pre_div_width; 58 + }; 59 + 60 + /** 61 + * struct src_sel - source selector 62 + * @src_sel_shift: lowest bit of source selection field 63 + * @parent_map: map from software's parent index to hardware's src_sel field 64 + */ 65 + struct src_sel { 66 + u8 src_sel_shift; 67 + #define SRC_SEL_MASK 0x7 68 + const u8 *parent_map; 69 + }; 70 + 71 + /** 72 + * struct clk_rcg - root clock generator 73 + * 74 + * @ns_reg: NS register 75 + * @md_reg: MD register 76 + * @mn: mn counter 77 + * @p: pre divider 78 + * @s: source selector 79 + * @freq_tbl: frequency table 80 + * @clkr: regmap clock handle 81 + * @lock: register lock 82 + * 83 + */ 84 + struct clk_rcg { 85 + u32 ns_reg; 86 + u32 md_reg; 87 + 88 + struct mn mn; 89 + struct pre_div p; 90 + struct src_sel s; 91 + 92 + const struct freq_tbl *freq_tbl; 93 + 94 + struct clk_regmap clkr; 95 + }; 96 + 97 + extern const struct clk_ops clk_rcg_ops; 98 + 99 + #define to_clk_rcg(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg, clkr) 100 + 101 + /** 102 + * struct clk_dyn_rcg - root clock generator with glitch free mux 103 + * 104 + * @mux_sel_bit: bit to switch glitch free mux 105 + * @ns_reg: NS register 106 + * @md_reg: MD0 and MD1 register 107 + * @mn: mn counter (banked) 108 + * @s: source selector (banked) 109 + * @freq_tbl: frequency table 110 + * @clkr: regmap clock handle 111 + * @lock: register lock 112 + * 113 + */ 114 + struct clk_dyn_rcg { 115 + u32 ns_reg; 116 + u32 md_reg[2]; 117 + 118 + u8 mux_sel_bit; 119 + 120 + struct mn mn[2]; 121 + struct pre_div p[2]; 122 + struct src_sel s[2]; 123 + 124 + const struct freq_tbl *freq_tbl; 125 + 126 + struct clk_regmap clkr; 127 + }; 128 + 129 + extern const struct clk_ops clk_dyn_rcg_ops; 130 + 131 + #define to_clk_dyn_rcg(_hw) \ 132 + container_of(to_clk_regmap(_hw), struct clk_dyn_rcg, clkr) 133 + 134 + /** 135 + * struct clk_rcg2 - root clock generator 136 + * 137 + * @cmd_rcgr: corresponds to *_CMD_RCGR 138 + * @mnd_width: number of bits in m/n/d values 139 + * @hid_width: number of bits in half integer divider 140 + * @parent_map: map from software's parent index to hardware's src_sel field 141 + * @freq_tbl: frequency table 142 + * @clkr: regmap clock handle 143 + * @lock: register lock 144 + * 145 + */ 146 + struct clk_rcg2 { 147 + u32 cmd_rcgr; 148 + u8 mnd_width; 149 + u8 hid_width; 150 + const u8 *parent_map; 151 + const struct freq_tbl *freq_tbl; 152 + struct clk_regmap clkr; 153 + }; 154 + 155 + #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr) 156 + 157 + extern const struct clk_ops clk_rcg2_ops; 158 + 159 + #endif
+291
drivers/clk/qcom/clk-rcg2.c
··· 1 + /* 2 + * Copyright (c) 2013, The Linux Foundation. All rights reserved. 3 + * 4 + * This software is licensed under the terms of the GNU General Public 5 + * License version 2, as published by the Free Software Foundation, and 6 + * may be copied, distributed, and modified under those terms. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + #include <linux/kernel.h> 15 + #include <linux/bitops.h> 16 + #include <linux/err.h> 17 + #include <linux/bug.h> 18 + #include <linux/export.h> 19 + #include <linux/clk-provider.h> 20 + #include <linux/delay.h> 21 + #include <linux/regmap.h> 22 + 23 + #include <asm/div64.h> 24 + 25 + #include "clk-rcg.h" 26 + 27 + #define CMD_REG 0x0 28 + #define CMD_UPDATE BIT(0) 29 + #define CMD_ROOT_EN BIT(1) 30 + #define CMD_DIRTY_CFG BIT(4) 31 + #define CMD_DIRTY_N BIT(5) 32 + #define CMD_DIRTY_M BIT(6) 33 + #define CMD_DIRTY_D BIT(7) 34 + #define CMD_ROOT_OFF BIT(31) 35 + 36 + #define CFG_REG 0x4 37 + #define CFG_SRC_DIV_SHIFT 0 38 + #define CFG_SRC_SEL_SHIFT 8 39 + #define CFG_SRC_SEL_MASK (0x7 << CFG_SRC_SEL_SHIFT) 40 + #define CFG_MODE_SHIFT 12 41 + #define CFG_MODE_MASK (0x3 << CFG_MODE_SHIFT) 42 + #define CFG_MODE_DUAL_EDGE (0x2 << CFG_MODE_SHIFT) 43 + 44 + #define M_REG 0x8 45 + #define N_REG 0xc 46 + #define D_REG 0x10 47 + 48 + static int clk_rcg2_is_enabled(struct clk_hw *hw) 49 + { 50 + struct clk_rcg2 *rcg = to_clk_rcg2(hw); 51 + u32 cmd; 52 + int ret; 53 + 54 + ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, &cmd); 55 + if (ret) 56 + return ret; 57 + 58 + return (cmd & CMD_ROOT_OFF) != 0; 59 + } 60 + 61 + static u8 clk_rcg2_get_parent(struct clk_hw *hw) 62 + { 63 + struct clk_rcg2 *rcg = to_clk_rcg2(hw); 64 + int num_parents = __clk_get_num_parents(hw->clk); 65 + u32 cfg; 66 + int i, ret; 67 + 68 + ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg); 69 + if (ret) 70 + return ret; 71 + 72 + cfg &= CFG_SRC_SEL_MASK; 73 + cfg >>= CFG_SRC_SEL_SHIFT; 74 + 75 + for (i = 0; i < num_parents; i++) 76 + if (cfg == rcg->parent_map[i]) 77 + return i; 78 + 79 + return -EINVAL; 80 + } 81 + 82 + static int update_config(struct clk_rcg2 *rcg) 83 + { 84 + int count, ret; 85 + u32 cmd; 86 + struct clk_hw *hw = &rcg->clkr.hw; 87 + const char *name = __clk_get_name(hw->clk); 88 + 89 + ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, 90 + CMD_UPDATE, CMD_UPDATE); 91 + if (ret) 92 + return ret; 93 + 94 + /* Wait for update to take effect */ 95 + for (count = 500; count > 0; count--) { 96 + ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, &cmd); 97 + if (ret) 98 + return ret; 99 + if (!(cmd & CMD_UPDATE)) 100 + return 0; 101 + udelay(1); 102 + } 103 + 104 + WARN(1, "%s: rcg didn't update its configuration.", name); 105 + return 0; 106 + } 107 + 108 + static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index) 109 + { 110 + struct clk_rcg2 *rcg = to_clk_rcg2(hw); 111 + int ret; 112 + 113 + ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, 114 + CFG_SRC_SEL_MASK, 115 + rcg->parent_map[index] << CFG_SRC_SEL_SHIFT); 116 + if (ret) 117 + return ret; 118 + 119 + return update_config(rcg); 120 + } 121 + 122 + /* 123 + * Calculate m/n:d rate 124 + * 125 + * parent_rate m 126 + * rate = ----------- x --- 127 + * hid_div n 128 + */ 129 + static unsigned long 130 + calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div) 131 + { 132 + if (hid_div) { 133 + rate *= 2; 134 + rate /= hid_div + 1; 135 + } 136 + 137 + if (mode) { 138 + u64 tmp = rate; 139 + tmp *= m; 140 + do_div(tmp, n); 141 + rate = tmp; 142 + } 143 + 144 + return rate; 145 + } 146 + 147 + static unsigned long 148 + clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 149 + { 150 + struct clk_rcg2 *rcg = to_clk_rcg2(hw); 151 + u32 cfg, hid_div, m = 0, n = 0, mode = 0, mask; 152 + 153 + regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg); 154 + 155 + if (rcg->mnd_width) { 156 + mask = BIT(rcg->mnd_width) - 1; 157 + regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + M_REG, &m); 158 + m &= mask; 159 + regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + N_REG, &n); 160 + n = ~n; 161 + n &= mask; 162 + n += m; 163 + mode = cfg & CFG_MODE_MASK; 164 + mode >>= CFG_MODE_SHIFT; 165 + } 166 + 167 + mask = BIT(rcg->hid_width) - 1; 168 + hid_div = cfg >> CFG_SRC_DIV_SHIFT; 169 + hid_div &= mask; 170 + 171 + return calc_rate(parent_rate, m, n, mode, hid_div); 172 + } 173 + 174 + static const 175 + struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate) 176 + { 177 + if (!f) 178 + return NULL; 179 + 180 + for (; f->freq; f++) 181 + if (rate <= f->freq) 182 + return f; 183 + 184 + return NULL; 185 + } 186 + 187 + static long _freq_tbl_determine_rate(struct clk_hw *hw, 188 + const struct freq_tbl *f, unsigned long rate, 189 + unsigned long *p_rate, struct clk **p) 190 + { 191 + unsigned long clk_flags; 192 + 193 + f = find_freq(f, rate); 194 + if (!f) 195 + return -EINVAL; 196 + 197 + clk_flags = __clk_get_flags(hw->clk); 198 + *p = clk_get_parent_by_index(hw->clk, f->src); 199 + if (clk_flags & CLK_SET_RATE_PARENT) { 200 + if (f->pre_div) { 201 + rate /= 2; 202 + rate *= f->pre_div + 1; 203 + } 204 + 205 + if (f->n) { 206 + u64 tmp = rate; 207 + tmp = tmp * f->n; 208 + do_div(tmp, f->m); 209 + rate = tmp; 210 + } 211 + } else { 212 + rate = __clk_get_rate(*p); 213 + } 214 + *p_rate = rate; 215 + 216 + return f->freq; 217 + } 218 + 219 + static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate, 220 + unsigned long *p_rate, struct clk **p) 221 + { 222 + struct clk_rcg2 *rcg = to_clk_rcg2(hw); 223 + 224 + return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p); 225 + } 226 + 227 + static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate) 228 + { 229 + struct clk_rcg2 *rcg = to_clk_rcg2(hw); 230 + const struct freq_tbl *f; 231 + u32 cfg, mask; 232 + int ret; 233 + 234 + f = find_freq(rcg->freq_tbl, rate); 235 + if (!f) 236 + return -EINVAL; 237 + 238 + if (rcg->mnd_width && f->n) { 239 + mask = BIT(rcg->mnd_width) - 1; 240 + ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + M_REG, 241 + mask, f->m); 242 + if (ret) 243 + return ret; 244 + 245 + ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + N_REG, 246 + mask, ~(f->n - f->m)); 247 + if (ret) 248 + return ret; 249 + 250 + ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + D_REG, 251 + mask, ~f->n); 252 + if (ret) 253 + return ret; 254 + } 255 + 256 + mask = BIT(rcg->hid_width) - 1; 257 + mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK; 258 + cfg = f->pre_div << CFG_SRC_DIV_SHIFT; 259 + cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT; 260 + if (rcg->mnd_width && f->n) 261 + cfg |= CFG_MODE_DUAL_EDGE; 262 + ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, mask, 263 + cfg); 264 + if (ret) 265 + return ret; 266 + 267 + return update_config(rcg); 268 + } 269 + 270 + static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, 271 + unsigned long parent_rate) 272 + { 273 + return __clk_rcg2_set_rate(hw, rate); 274 + } 275 + 276 + static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw, 277 + unsigned long rate, unsigned long parent_rate, u8 index) 278 + { 279 + return __clk_rcg2_set_rate(hw, rate); 280 + } 281 + 282 + const struct clk_ops clk_rcg2_ops = { 283 + .is_enabled = clk_rcg2_is_enabled, 284 + .get_parent = clk_rcg2_get_parent, 285 + .set_parent = clk_rcg2_set_parent, 286 + .recalc_rate = clk_rcg2_recalc_rate, 287 + .determine_rate = clk_rcg2_determine_rate, 288 + .set_rate = clk_rcg2_set_rate, 289 + .set_rate_and_parent = clk_rcg2_set_rate_and_parent, 290 + }; 291 + EXPORT_SYMBOL_GPL(clk_rcg2_ops);