1 /* 2 * Copyright (c) 2014 MundoReader S.L. 3 * Author: Heiko Stuebner <heiko@sntech.de> 4 * 5 * Copyright (c) 2015 Rockchip Electronics Co. Ltd. 6 * Author: Xing Zheng <zhengxing@rock-chips.com> 7 * 8 * based on 9 * 10 * samsung/clk.h 11 * Copyright (c) 2013 Samsung Electronics Co., Ltd. 12 * Copyright (c) 2013 Linaro Ltd. 13 * Author: Thomas Abraham <thomas.ab@samsung.com> 14 * 15 * This program is free software; you can redistribute it and/or modify 16 * it under the terms of the GNU General Public License as published by 17 * the Free Software Foundation; either version 2 of the License, or 18 * (at your option) any later version. 19 * 20 * This program is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * GNU General Public License for more details. 24 */ 25 26 #ifndef CLK_ROCKCHIP_CLK_H 27 #define CLK_ROCKCHIP_CLK_H 28 29 #include <linux/io.h> 30 #include <linux/clk-provider.h> 31 32 struct clk; 33 34 #define HIWORD_UPDATE(val, mask, shift) \ 35 ((val) << (shift) | (mask) << ((shift) + 16)) 36 37 #define RK2928_PLL_CON(x) ((x) * 0x4) 38 #define RK2928_MODE_CON 0x40 39 #define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44) 40 #define RK2928_CLKGATE_CON(x) ((x) * 0x4 + 0xd0) 41 #define RK2928_GLB_SRST_FST 0x100 42 #define RK2928_GLB_SRST_SND 0x104 43 #define RK2928_SOFTRST_CON(x) ((x) * 0x4 + 0x110) 44 #define RK2928_MISC_CON 0x134 45 46 #define RK3036_SDMMC_CON0 0x144 47 #define RK3036_SDMMC_CON1 0x148 48 #define RK3036_SDIO_CON0 0x14c 49 #define RK3036_SDIO_CON1 0x150 50 #define RK3036_EMMC_CON0 0x154 51 #define RK3036_EMMC_CON1 0x158 52 53 #define RK3228_GLB_SRST_FST 0x1f0 54 #define RK3228_GLB_SRST_SND 0x1f4 55 #define RK3228_SDMMC_CON0 0x1c0 56 #define RK3228_SDMMC_CON1 0x1c4 57 #define RK3228_SDIO_CON0 0x1c8 58 #define RK3228_SDIO_CON1 0x1cc 59 #define RK3228_EMMC_CON0 0x1d8 60 #define RK3228_EMMC_CON1 0x1dc 61 62 #define RK3288_PLL_CON(x) RK2928_PLL_CON(x) 63 #define RK3288_MODE_CON 0x50 64 #define RK3288_CLKSEL_CON(x) ((x) * 0x4 + 0x60) 65 #define RK3288_CLKGATE_CON(x) ((x) * 0x4 + 0x160) 66 #define RK3288_GLB_SRST_FST 0x1b0 67 #define RK3288_GLB_SRST_SND 0x1b4 68 #define RK3288_SOFTRST_CON(x) ((x) * 0x4 + 0x1b8) 69 #define RK3288_MISC_CON 0x1e8 70 #define RK3288_SDMMC_CON0 0x200 71 #define RK3288_SDMMC_CON1 0x204 72 #define RK3288_SDIO0_CON0 0x208 73 #define RK3288_SDIO0_CON1 0x20c 74 #define RK3288_SDIO1_CON0 0x210 75 #define RK3288_SDIO1_CON1 0x214 76 #define RK3288_EMMC_CON0 0x218 77 #define RK3288_EMMC_CON1 0x21c 78 79 #define RK3368_PLL_CON(x) RK2928_PLL_CON(x) 80 #define RK3368_CLKSEL_CON(x) ((x) * 0x4 + 0x100) 81 #define RK3368_CLKGATE_CON(x) ((x) * 0x4 + 0x200) 82 #define RK3368_GLB_SRST_FST 0x280 83 #define RK3368_GLB_SRST_SND 0x284 84 #define RK3368_SOFTRST_CON(x) ((x) * 0x4 + 0x300) 85 #define RK3368_MISC_CON 0x380 86 #define RK3368_SDMMC_CON0 0x400 87 #define RK3368_SDMMC_CON1 0x404 88 #define RK3368_SDIO0_CON0 0x408 89 #define RK3368_SDIO0_CON1 0x40c 90 #define RK3368_SDIO1_CON0 0x410 91 #define RK3368_SDIO1_CON1 0x414 92 #define RK3368_EMMC_CON0 0x418 93 #define RK3368_EMMC_CON1 0x41c 94 95 #define RK3399_PLL_CON(x) RK2928_PLL_CON(x) 96 #define RK3399_CLKSEL_CON(x) ((x) * 0x4 + 0x100) 97 #define RK3399_CLKGATE_CON(x) ((x) * 0x4 + 0x300) 98 #define RK3399_SOFTRST_CON(x) ((x) * 0x4 + 0x400) 99 #define RK3399_GLB_SRST_FST 0x500 100 #define RK3399_GLB_SRST_SND 0x504 101 #define RK3399_GLB_CNT_TH 0x508 102 #define RK3399_MISC_CON 0x50c 103 #define RK3399_RST_CON 0x510 104 #define RK3399_RST_ST 0x514 105 #define RK3399_SDMMC_CON0 0x580 106 #define RK3399_SDMMC_CON1 0x584 107 #define RK3399_SDIO_CON0 0x588 108 #define RK3399_SDIO_CON1 0x58c 109 110 #define RK3399_PMU_PLL_CON(x) RK2928_PLL_CON(x) 111 #define RK3399_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x80) 112 #define RK3399_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x100) 113 #define RK3399_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x110) 114 115 enum rockchip_pll_type { 116 pll_rk3036, 117 pll_rk3066, 118 pll_rk3399, 119 }; 120 121 #define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \ 122 _postdiv2, _dsmpd, _frac) \ 123 { \ 124 .rate = _rate##U, \ 125 .fbdiv = _fbdiv, \ 126 .postdiv1 = _postdiv1, \ 127 .refdiv = _refdiv, \ 128 .postdiv2 = _postdiv2, \ 129 .dsmpd = _dsmpd, \ 130 .frac = _frac, \ 131 } 132 133 #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \ 134 { \ 135 .rate = _rate##U, \ 136 .nr = _nr, \ 137 .nf = _nf, \ 138 .no = _no, \ 139 .nb = ((_nf) < 2) ? 1 : (_nf) >> 1, \ 140 } 141 142 #define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb) \ 143 { \ 144 .rate = _rate##U, \ 145 .nr = _nr, \ 146 .nf = _nf, \ 147 .no = _no, \ 148 .nb = _nb, \ 149 } 150 151 /** 152 * struct rockchip_clk_provider - information about clock provider 153 * @reg_base: virtual address for the register base. 154 * @clk_data: holds clock related data like clk* and number of clocks. 155 * @cru_node: device-node of the clock-provider 156 * @grf: regmap of the general-register-files syscon 157 * @lock: maintains exclusion between callbacks for a given clock-provider. 158 */ 159 struct rockchip_clk_provider { 160 void __iomem *reg_base; 161 struct clk_onecell_data clk_data; 162 struct device_node *cru_node; 163 struct regmap *grf; 164 spinlock_t lock; 165 }; 166 167 struct rockchip_pll_rate_table { 168 unsigned long rate; 169 unsigned int nr; 170 unsigned int nf; 171 unsigned int no; 172 unsigned int nb; 173 /* for RK3036/RK3399 */ 174 unsigned int fbdiv; 175 unsigned int postdiv1; 176 unsigned int refdiv; 177 unsigned int postdiv2; 178 unsigned int dsmpd; 179 unsigned int frac; 180 }; 181 182 /** 183 * struct rockchip_pll_clock - information about pll clock 184 * @id: platform specific id of the clock. 185 * @name: name of this pll clock. 186 * @parent_names: name of the parent clock. 187 * @num_parents: number of parents 188 * @flags: optional flags for basic clock. 189 * @con_offset: offset of the register for configuring the PLL. 190 * @mode_offset: offset of the register for configuring the PLL-mode. 191 * @mode_shift: offset inside the mode-register for the mode of this pll. 192 * @lock_shift: offset inside the lock register for the lock status. 193 * @type: Type of PLL to be registered. 194 * @pll_flags: hardware-specific flags 195 * @rate_table: Table of usable pll rates 196 * 197 * Flags: 198 * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the 199 * rate_table parameters and ajust them if necessary. 200 */ 201 struct rockchip_pll_clock { 202 unsigned int id; 203 const char *name; 204 const char *const *parent_names; 205 u8 num_parents; 206 unsigned long flags; 207 int con_offset; 208 int mode_offset; 209 int mode_shift; 210 int lock_shift; 211 enum rockchip_pll_type type; 212 u8 pll_flags; 213 struct rockchip_pll_rate_table *rate_table; 214 }; 215 216 #define ROCKCHIP_PLL_SYNC_RATE BIT(0) 217 218 #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ 219 _lshift, _pflags, _rtable) \ 220 { \ 221 .id = _id, \ 222 .type = _type, \ 223 .name = _name, \ 224 .parent_names = _pnames, \ 225 .num_parents = ARRAY_SIZE(_pnames), \ 226 .flags = CLK_GET_RATE_NOCACHE | _flags, \ 227 .con_offset = _con, \ 228 .mode_offset = _mode, \ 229 .mode_shift = _mshift, \ 230 .lock_shift = _lshift, \ 231 .pll_flags = _pflags, \ 232 .rate_table = _rtable, \ 233 } 234 235 struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, 236 enum rockchip_pll_type pll_type, 237 const char *name, const char *const *parent_names, 238 u8 num_parents, int con_offset, int grf_lock_offset, 239 int lock_shift, int mode_offset, int mode_shift, 240 struct rockchip_pll_rate_table *rate_table, 241 u8 clk_pll_flags); 242 243 struct rockchip_cpuclk_clksel { 244 int reg; 245 u32 val; 246 }; 247 248 #define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2 249 struct rockchip_cpuclk_rate_table { 250 unsigned long prate; 251 struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS]; 252 }; 253 254 /** 255 * struct rockchip_cpuclk_reg_data - register offsets and masks of the cpuclock 256 * @core_reg: register offset of the core settings register 257 * @div_core_shift: core divider offset used to divide the pll value 258 * @div_core_mask: core divider mask 259 * @mux_core_alt: mux value to select alternate parent 260 * @mux_core_main: mux value to select main parent of core 261 * @mux_core_shift: offset of the core multiplexer 262 * @mux_core_mask: core multiplexer mask 263 */ 264 struct rockchip_cpuclk_reg_data { 265 int core_reg; 266 u8 div_core_shift; 267 u32 div_core_mask; 268 u8 mux_core_alt; 269 u8 mux_core_main; 270 u8 mux_core_shift; 271 u32 mux_core_mask; 272 }; 273 274 struct clk *rockchip_clk_register_cpuclk(const char *name, 275 const char *const *parent_names, u8 num_parents, 276 const struct rockchip_cpuclk_reg_data *reg_data, 277 const struct rockchip_cpuclk_rate_table *rates, 278 int nrates, void __iomem *reg_base, spinlock_t *lock); 279 280 struct clk *rockchip_clk_register_mmc(const char *name, 281 const char *const *parent_names, u8 num_parents, 282 void __iomem *reg, int shift); 283 284 #define ROCKCHIP_INVERTER_HIWORD_MASK BIT(0) 285 286 struct clk *rockchip_clk_register_inverter(const char *name, 287 const char *const *parent_names, u8 num_parents, 288 void __iomem *reg, int shift, int flags, 289 spinlock_t *lock); 290 291 #define PNAME(x) static const char *const x[] __initconst 292 293 enum rockchip_clk_branch_type { 294 branch_composite, 295 branch_mux, 296 branch_divider, 297 branch_fraction_divider, 298 branch_gate, 299 branch_mmc, 300 branch_inverter, 301 branch_factor, 302 }; 303 304 struct rockchip_clk_branch { 305 unsigned int id; 306 enum rockchip_clk_branch_type branch_type; 307 const char *name; 308 const char *const *parent_names; 309 u8 num_parents; 310 unsigned long flags; 311 int muxdiv_offset; 312 u8 mux_shift; 313 u8 mux_width; 314 u8 mux_flags; 315 u8 div_shift; 316 u8 div_width; 317 u8 div_flags; 318 struct clk_div_table *div_table; 319 int gate_offset; 320 u8 gate_shift; 321 u8 gate_flags; 322 struct rockchip_clk_branch *child; 323 }; 324 325 #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\ 326 df, go, gs, gf) \ 327 { \ 328 .id = _id, \ 329 .branch_type = branch_composite, \ 330 .name = cname, \ 331 .parent_names = pnames, \ 332 .num_parents = ARRAY_SIZE(pnames), \ 333 .flags = f, \ 334 .muxdiv_offset = mo, \ 335 .mux_shift = ms, \ 336 .mux_width = mw, \ 337 .mux_flags = mf, \ 338 .div_shift = ds, \ 339 .div_width = dw, \ 340 .div_flags = df, \ 341 .gate_offset = go, \ 342 .gate_shift = gs, \ 343 .gate_flags = gf, \ 344 } 345 346 #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \ 347 go, gs, gf) \ 348 { \ 349 .id = _id, \ 350 .branch_type = branch_composite, \ 351 .name = cname, \ 352 .parent_names = (const char *[]){ pname }, \ 353 .num_parents = 1, \ 354 .flags = f, \ 355 .muxdiv_offset = mo, \ 356 .div_shift = ds, \ 357 .div_width = dw, \ 358 .div_flags = df, \ 359 .gate_offset = go, \ 360 .gate_shift = gs, \ 361 .gate_flags = gf, \ 362 } 363 364 #define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\ 365 df, dt, go, gs, gf) \ 366 { \ 367 .id = _id, \ 368 .branch_type = branch_composite, \ 369 .name = cname, \ 370 .parent_names = (const char *[]){ pname }, \ 371 .num_parents = 1, \ 372 .flags = f, \ 373 .muxdiv_offset = mo, \ 374 .div_shift = ds, \ 375 .div_width = dw, \ 376 .div_flags = df, \ 377 .div_table = dt, \ 378 .gate_offset = go, \ 379 .gate_shift = gs, \ 380 .gate_flags = gf, \ 381 } 382 383 #define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \ 384 go, gs, gf) \ 385 { \ 386 .id = _id, \ 387 .branch_type = branch_composite, \ 388 .name = cname, \ 389 .parent_names = pnames, \ 390 .num_parents = ARRAY_SIZE(pnames), \ 391 .flags = f, \ 392 .muxdiv_offset = mo, \ 393 .mux_shift = ms, \ 394 .mux_width = mw, \ 395 .mux_flags = mf, \ 396 .gate_offset = go, \ 397 .gate_shift = gs, \ 398 .gate_flags = gf, \ 399 } 400 401 #define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \ 402 ds, dw, df) \ 403 { \ 404 .id = _id, \ 405 .branch_type = branch_composite, \ 406 .name = cname, \ 407 .parent_names = pnames, \ 408 .num_parents = ARRAY_SIZE(pnames), \ 409 .flags = f, \ 410 .muxdiv_offset = mo, \ 411 .mux_shift = ms, \ 412 .mux_width = mw, \ 413 .mux_flags = mf, \ 414 .div_shift = ds, \ 415 .div_width = dw, \ 416 .div_flags = df, \ 417 .gate_offset = -1, \ 418 } 419 420 #define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms, \ 421 mw, mf, ds, dw, df, dt) \ 422 { \ 423 .id = _id, \ 424 .branch_type = branch_composite, \ 425 .name = cname, \ 426 .parent_names = pnames, \ 427 .num_parents = ARRAY_SIZE(pnames), \ 428 .flags = f, \ 429 .muxdiv_offset = mo, \ 430 .mux_shift = ms, \ 431 .mux_width = mw, \ 432 .mux_flags = mf, \ 433 .div_shift = ds, \ 434 .div_width = dw, \ 435 .div_flags = df, \ 436 .div_table = dt, \ 437 .gate_offset = -1, \ 438 } 439 440 #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\ 441 { \ 442 .id = _id, \ 443 .branch_type = branch_fraction_divider, \ 444 .name = cname, \ 445 .parent_names = (const char *[]){ pname }, \ 446 .num_parents = 1, \ 447 .flags = f, \ 448 .muxdiv_offset = mo, \ 449 .div_shift = 16, \ 450 .div_width = 16, \ 451 .div_flags = df, \ 452 .gate_offset = go, \ 453 .gate_shift = gs, \ 454 .gate_flags = gf, \ 455 } 456 457 #define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch) \ 458 { \ 459 .id = _id, \ 460 .branch_type = branch_fraction_divider, \ 461 .name = cname, \ 462 .parent_names = (const char *[]){ pname }, \ 463 .num_parents = 1, \ 464 .flags = f, \ 465 .muxdiv_offset = mo, \ 466 .div_shift = 16, \ 467 .div_width = 16, \ 468 .div_flags = df, \ 469 .gate_offset = go, \ 470 .gate_shift = gs, \ 471 .gate_flags = gf, \ 472 .child = ch, \ 473 } 474 475 #define COMPOSITE_FRACMUX_NOGATE(_id, cname, pname, f, mo, df, ch) \ 476 { \ 477 .id = _id, \ 478 .branch_type = branch_fraction_divider, \ 479 .name = cname, \ 480 .parent_names = (const char *[]){ pname }, \ 481 .num_parents = 1, \ 482 .flags = f, \ 483 .muxdiv_offset = mo, \ 484 .div_shift = 16, \ 485 .div_width = 16, \ 486 .div_flags = df, \ 487 .gate_offset = -1, \ 488 .child = ch, \ 489 } 490 491 #define MUX(_id, cname, pnames, f, o, s, w, mf) \ 492 { \ 493 .id = _id, \ 494 .branch_type = branch_mux, \ 495 .name = cname, \ 496 .parent_names = pnames, \ 497 .num_parents = ARRAY_SIZE(pnames), \ 498 .flags = f, \ 499 .muxdiv_offset = o, \ 500 .mux_shift = s, \ 501 .mux_width = w, \ 502 .mux_flags = mf, \ 503 .gate_offset = -1, \ 504 } 505 506 #define DIV(_id, cname, pname, f, o, s, w, df) \ 507 { \ 508 .id = _id, \ 509 .branch_type = branch_divider, \ 510 .name = cname, \ 511 .parent_names = (const char *[]){ pname }, \ 512 .num_parents = 1, \ 513 .flags = f, \ 514 .muxdiv_offset = o, \ 515 .div_shift = s, \ 516 .div_width = w, \ 517 .div_flags = df, \ 518 .gate_offset = -1, \ 519 } 520 521 #define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \ 522 { \ 523 .id = _id, \ 524 .branch_type = branch_divider, \ 525 .name = cname, \ 526 .parent_names = (const char *[]){ pname }, \ 527 .num_parents = 1, \ 528 .flags = f, \ 529 .muxdiv_offset = o, \ 530 .div_shift = s, \ 531 .div_width = w, \ 532 .div_flags = df, \ 533 .div_table = dt, \ 534 } 535 536 #define GATE(_id, cname, pname, f, o, b, gf) \ 537 { \ 538 .id = _id, \ 539 .branch_type = branch_gate, \ 540 .name = cname, \ 541 .parent_names = (const char *[]){ pname }, \ 542 .num_parents = 1, \ 543 .flags = f, \ 544 .gate_offset = o, \ 545 .gate_shift = b, \ 546 .gate_flags = gf, \ 547 } 548 549 #define MMC(_id, cname, pname, offset, shift) \ 550 { \ 551 .id = _id, \ 552 .branch_type = branch_mmc, \ 553 .name = cname, \ 554 .parent_names = (const char *[]){ pname }, \ 555 .num_parents = 1, \ 556 .muxdiv_offset = offset, \ 557 .div_shift = shift, \ 558 } 559 560 #define INVERTER(_id, cname, pname, io, is, if) \ 561 { \ 562 .id = _id, \ 563 .branch_type = branch_inverter, \ 564 .name = cname, \ 565 .parent_names = (const char *[]){ pname }, \ 566 .num_parents = 1, \ 567 .muxdiv_offset = io, \ 568 .div_shift = is, \ 569 .div_flags = if, \ 570 } 571 572 #define FACTOR(_id, cname, pname, f, fm, fd) \ 573 { \ 574 .id = _id, \ 575 .branch_type = branch_factor, \ 576 .name = cname, \ 577 .parent_names = (const char *[]){ pname }, \ 578 .num_parents = 1, \ 579 .flags = f, \ 580 .div_shift = fm, \ 581 .div_width = fd, \ 582 } 583 584 #define FACTOR_GATE(_id, cname, pname, f, fm, fd, go, gb, gf) \ 585 { \ 586 .id = _id, \ 587 .branch_type = branch_factor, \ 588 .name = cname, \ 589 .parent_names = (const char *[]){ pname }, \ 590 .num_parents = 1, \ 591 .flags = f, \ 592 .div_shift = fm, \ 593 .div_width = fd, \ 594 .gate_offset = go, \ 595 .gate_shift = gb, \ 596 .gate_flags = gf, \ 597 } 598 599 struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np, 600 void __iomem *base, unsigned long nr_clks); 601 void rockchip_clk_of_add_provider(struct device_node *np, 602 struct rockchip_clk_provider *ctx); 603 void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, 604 struct clk *clk, unsigned int id); 605 void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, 606 struct rockchip_clk_branch *list, 607 unsigned int nr_clk); 608 void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, 609 struct rockchip_pll_clock *pll_list, 610 unsigned int nr_pll, int grf_lock_offset); 611 void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, 612 unsigned int lookup_id, const char *name, 613 const char *const *parent_names, u8 num_parents, 614 const struct rockchip_cpuclk_reg_data *reg_data, 615 const struct rockchip_cpuclk_rate_table *rates, 616 int nrates); 617 void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); 618 void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, 619 unsigned int reg, void (*cb)(void)); 620 621 #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) 622 623 #ifdef CONFIG_RESET_CONTROLLER 624 void rockchip_register_softrst(struct device_node *np, 625 unsigned int num_regs, 626 void __iomem *base, u8 flags); 627 #else 628 static inline void rockchip_register_softrst(struct device_node *np, 629 unsigned int num_regs, 630 void __iomem *base, u8 flags) 631 { 632 } 633 #endif 634 635 #endif 636