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 31 struct clk; 32 33 #define HIWORD_UPDATE(val, mask, shift) \ 34 ((val) << (shift) | (mask) << ((shift) + 16)) 35 36 /* register positions shared by RK2928, RK3036, RK3066, RK3188 and RK3228 */ 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 enum rockchip_pll_type { 96 pll_rk3036, 97 pll_rk3066, 98 }; 99 100 #define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \ 101 _postdiv2, _dsmpd, _frac) \ 102 { \ 103 .rate = _rate##U, \ 104 .fbdiv = _fbdiv, \ 105 .postdiv1 = _postdiv1, \ 106 .refdiv = _refdiv, \ 107 .postdiv2 = _postdiv2, \ 108 .dsmpd = _dsmpd, \ 109 .frac = _frac, \ 110 } 111 112 #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \ 113 { \ 114 .rate = _rate##U, \ 115 .nr = _nr, \ 116 .nf = _nf, \ 117 .no = _no, \ 118 .nb = ((_nf) < 2) ? 1 : (_nf) >> 1, \ 119 } 120 121 #define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb) \ 122 { \ 123 .rate = _rate##U, \ 124 .nr = _nr, \ 125 .nf = _nf, \ 126 .no = _no, \ 127 .nb = _nb, \ 128 } 129 130 struct rockchip_pll_rate_table { 131 unsigned long rate; 132 unsigned int nr; 133 unsigned int nf; 134 unsigned int no; 135 unsigned int nb; 136 /* for RK3036 */ 137 unsigned int fbdiv; 138 unsigned int postdiv1; 139 unsigned int refdiv; 140 unsigned int postdiv2; 141 unsigned int dsmpd; 142 unsigned int frac; 143 }; 144 145 /** 146 * struct rockchip_pll_clock: information about pll clock 147 * @id: platform specific id of the clock. 148 * @name: name of this pll clock. 149 * @parent_name: name of the parent clock. 150 * @flags: optional flags for basic clock. 151 * @con_offset: offset of the register for configuring the PLL. 152 * @mode_offset: offset of the register for configuring the PLL-mode. 153 * @mode_shift: offset inside the mode-register for the mode of this pll. 154 * @lock_shift: offset inside the lock register for the lock status. 155 * @type: Type of PLL to be registered. 156 * @pll_flags: hardware-specific flags 157 * @rate_table: Table of usable pll rates 158 * 159 * Flags: 160 * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the 161 * rate_table parameters and ajust them if necessary. 162 */ 163 struct rockchip_pll_clock { 164 unsigned int id; 165 const char *name; 166 const char *const *parent_names; 167 u8 num_parents; 168 unsigned long flags; 169 int con_offset; 170 int mode_offset; 171 int mode_shift; 172 int lock_shift; 173 enum rockchip_pll_type type; 174 u8 pll_flags; 175 struct rockchip_pll_rate_table *rate_table; 176 }; 177 178 #define ROCKCHIP_PLL_SYNC_RATE BIT(0) 179 180 #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ 181 _lshift, _pflags, _rtable) \ 182 { \ 183 .id = _id, \ 184 .type = _type, \ 185 .name = _name, \ 186 .parent_names = _pnames, \ 187 .num_parents = ARRAY_SIZE(_pnames), \ 188 .flags = CLK_GET_RATE_NOCACHE | _flags, \ 189 .con_offset = _con, \ 190 .mode_offset = _mode, \ 191 .mode_shift = _mshift, \ 192 .lock_shift = _lshift, \ 193 .pll_flags = _pflags, \ 194 .rate_table = _rtable, \ 195 } 196 197 struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, 198 const char *name, const char *const *parent_names, 199 u8 num_parents, void __iomem *base, int con_offset, 200 int grf_lock_offset, int lock_shift, int reg_mode, 201 int mode_shift, struct rockchip_pll_rate_table *rate_table, 202 u8 clk_pll_flags, spinlock_t *lock); 203 204 struct rockchip_cpuclk_clksel { 205 int reg; 206 u32 val; 207 }; 208 209 #define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2 210 struct rockchip_cpuclk_rate_table { 211 unsigned long prate; 212 struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS]; 213 }; 214 215 /** 216 * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock 217 * @core_reg: register offset of the core settings register 218 * @div_core_shift: core divider offset used to divide the pll value 219 * @div_core_mask: core divider mask 220 * @mux_core_shift: offset of the core multiplexer 221 */ 222 struct rockchip_cpuclk_reg_data { 223 int core_reg; 224 u8 div_core_shift; 225 u32 div_core_mask; 226 int mux_core_reg; 227 u8 mux_core_shift; 228 }; 229 230 struct clk *rockchip_clk_register_cpuclk(const char *name, 231 const char *const *parent_names, u8 num_parents, 232 const struct rockchip_cpuclk_reg_data *reg_data, 233 const struct rockchip_cpuclk_rate_table *rates, 234 int nrates, void __iomem *reg_base, spinlock_t *lock); 235 236 struct clk *rockchip_clk_register_mmc(const char *name, 237 const char *const *parent_names, u8 num_parents, 238 void __iomem *reg, int shift); 239 240 #define ROCKCHIP_INVERTER_HIWORD_MASK BIT(0) 241 242 struct clk *rockchip_clk_register_inverter(const char *name, 243 const char *const *parent_names, u8 num_parents, 244 void __iomem *reg, int shift, int flags, 245 spinlock_t *lock); 246 247 #define PNAME(x) static const char *const x[] __initconst 248 249 enum rockchip_clk_branch_type { 250 branch_composite, 251 branch_mux, 252 branch_divider, 253 branch_fraction_divider, 254 branch_gate, 255 branch_mmc, 256 branch_inverter, 257 branch_factor, 258 }; 259 260 struct rockchip_clk_branch { 261 unsigned int id; 262 enum rockchip_clk_branch_type branch_type; 263 const char *name; 264 const char *const *parent_names; 265 u8 num_parents; 266 unsigned long flags; 267 int muxdiv_offset; 268 u8 mux_shift; 269 u8 mux_width; 270 u8 mux_flags; 271 u8 div_shift; 272 u8 div_width; 273 u8 div_flags; 274 struct clk_div_table *div_table; 275 int gate_offset; 276 u8 gate_shift; 277 u8 gate_flags; 278 struct rockchip_clk_branch *child; 279 }; 280 281 #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\ 282 df, go, gs, gf) \ 283 { \ 284 .id = _id, \ 285 .branch_type = branch_composite, \ 286 .name = cname, \ 287 .parent_names = pnames, \ 288 .num_parents = ARRAY_SIZE(pnames), \ 289 .flags = f, \ 290 .muxdiv_offset = mo, \ 291 .mux_shift = ms, \ 292 .mux_width = mw, \ 293 .mux_flags = mf, \ 294 .div_shift = ds, \ 295 .div_width = dw, \ 296 .div_flags = df, \ 297 .gate_offset = go, \ 298 .gate_shift = gs, \ 299 .gate_flags = gf, \ 300 } 301 302 #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \ 303 go, gs, gf) \ 304 { \ 305 .id = _id, \ 306 .branch_type = branch_composite, \ 307 .name = cname, \ 308 .parent_names = (const char *[]){ pname }, \ 309 .num_parents = 1, \ 310 .flags = f, \ 311 .muxdiv_offset = mo, \ 312 .div_shift = ds, \ 313 .div_width = dw, \ 314 .div_flags = df, \ 315 .gate_offset = go, \ 316 .gate_shift = gs, \ 317 .gate_flags = gf, \ 318 } 319 320 #define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\ 321 df, dt, go, gs, gf) \ 322 { \ 323 .id = _id, \ 324 .branch_type = branch_composite, \ 325 .name = cname, \ 326 .parent_names = (const char *[]){ pname }, \ 327 .num_parents = 1, \ 328 .flags = f, \ 329 .muxdiv_offset = mo, \ 330 .div_shift = ds, \ 331 .div_width = dw, \ 332 .div_flags = df, \ 333 .div_table = dt, \ 334 .gate_offset = go, \ 335 .gate_shift = gs, \ 336 .gate_flags = gf, \ 337 } 338 339 #define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \ 340 go, gs, gf) \ 341 { \ 342 .id = _id, \ 343 .branch_type = branch_composite, \ 344 .name = cname, \ 345 .parent_names = pnames, \ 346 .num_parents = ARRAY_SIZE(pnames), \ 347 .flags = f, \ 348 .muxdiv_offset = mo, \ 349 .mux_shift = ms, \ 350 .mux_width = mw, \ 351 .mux_flags = mf, \ 352 .gate_offset = go, \ 353 .gate_shift = gs, \ 354 .gate_flags = gf, \ 355 } 356 357 #define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \ 358 ds, dw, df) \ 359 { \ 360 .id = _id, \ 361 .branch_type = branch_composite, \ 362 .name = cname, \ 363 .parent_names = pnames, \ 364 .num_parents = ARRAY_SIZE(pnames), \ 365 .flags = f, \ 366 .muxdiv_offset = mo, \ 367 .mux_shift = ms, \ 368 .mux_width = mw, \ 369 .mux_flags = mf, \ 370 .div_shift = ds, \ 371 .div_width = dw, \ 372 .div_flags = df, \ 373 .gate_offset = -1, \ 374 } 375 376 #define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms, \ 377 mw, mf, ds, dw, df, dt) \ 378 { \ 379 .id = _id, \ 380 .branch_type = branch_composite, \ 381 .name = cname, \ 382 .parent_names = pnames, \ 383 .num_parents = ARRAY_SIZE(pnames), \ 384 .flags = f, \ 385 .muxdiv_offset = mo, \ 386 .mux_shift = ms, \ 387 .mux_width = mw, \ 388 .mux_flags = mf, \ 389 .div_shift = ds, \ 390 .div_width = dw, \ 391 .div_flags = df, \ 392 .div_table = dt, \ 393 .gate_offset = -1, \ 394 } 395 396 #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\ 397 { \ 398 .id = _id, \ 399 .branch_type = branch_fraction_divider, \ 400 .name = cname, \ 401 .parent_names = (const char *[]){ pname }, \ 402 .num_parents = 1, \ 403 .flags = f, \ 404 .muxdiv_offset = mo, \ 405 .div_shift = 16, \ 406 .div_width = 16, \ 407 .div_flags = df, \ 408 .gate_offset = go, \ 409 .gate_shift = gs, \ 410 .gate_flags = gf, \ 411 } 412 413 #define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch) \ 414 { \ 415 .id = _id, \ 416 .branch_type = branch_fraction_divider, \ 417 .name = cname, \ 418 .parent_names = (const char *[]){ pname }, \ 419 .num_parents = 1, \ 420 .flags = f, \ 421 .muxdiv_offset = mo, \ 422 .div_shift = 16, \ 423 .div_width = 16, \ 424 .div_flags = df, \ 425 .gate_offset = go, \ 426 .gate_shift = gs, \ 427 .gate_flags = gf, \ 428 .child = ch, \ 429 } 430 431 #define MUX(_id, cname, pnames, f, o, s, w, mf) \ 432 { \ 433 .id = _id, \ 434 .branch_type = branch_mux, \ 435 .name = cname, \ 436 .parent_names = pnames, \ 437 .num_parents = ARRAY_SIZE(pnames), \ 438 .flags = f, \ 439 .muxdiv_offset = o, \ 440 .mux_shift = s, \ 441 .mux_width = w, \ 442 .mux_flags = mf, \ 443 .gate_offset = -1, \ 444 } 445 446 #define DIV(_id, cname, pname, f, o, s, w, df) \ 447 { \ 448 .id = _id, \ 449 .branch_type = branch_divider, \ 450 .name = cname, \ 451 .parent_names = (const char *[]){ pname }, \ 452 .num_parents = 1, \ 453 .flags = f, \ 454 .muxdiv_offset = o, \ 455 .div_shift = s, \ 456 .div_width = w, \ 457 .div_flags = df, \ 458 .gate_offset = -1, \ 459 } 460 461 #define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \ 462 { \ 463 .id = _id, \ 464 .branch_type = branch_divider, \ 465 .name = cname, \ 466 .parent_names = (const char *[]){ pname }, \ 467 .num_parents = 1, \ 468 .flags = f, \ 469 .muxdiv_offset = o, \ 470 .div_shift = s, \ 471 .div_width = w, \ 472 .div_flags = df, \ 473 .div_table = dt, \ 474 } 475 476 #define GATE(_id, cname, pname, f, o, b, gf) \ 477 { \ 478 .id = _id, \ 479 .branch_type = branch_gate, \ 480 .name = cname, \ 481 .parent_names = (const char *[]){ pname }, \ 482 .num_parents = 1, \ 483 .flags = f, \ 484 .gate_offset = o, \ 485 .gate_shift = b, \ 486 .gate_flags = gf, \ 487 } 488 489 #define MMC(_id, cname, pname, offset, shift) \ 490 { \ 491 .id = _id, \ 492 .branch_type = branch_mmc, \ 493 .name = cname, \ 494 .parent_names = (const char *[]){ pname }, \ 495 .num_parents = 1, \ 496 .muxdiv_offset = offset, \ 497 .div_shift = shift, \ 498 } 499 500 #define INVERTER(_id, cname, pname, io, is, if) \ 501 { \ 502 .id = _id, \ 503 .branch_type = branch_inverter, \ 504 .name = cname, \ 505 .parent_names = (const char *[]){ pname }, \ 506 .num_parents = 1, \ 507 .muxdiv_offset = io, \ 508 .div_shift = is, \ 509 .div_flags = if, \ 510 } 511 512 #define FACTOR(_id, cname, pname, f, fm, fd) \ 513 { \ 514 .id = _id, \ 515 .branch_type = branch_factor, \ 516 .name = cname, \ 517 .parent_names = (const char *[]){ pname }, \ 518 .num_parents = 1, \ 519 .flags = f, \ 520 .div_shift = fm, \ 521 .div_width = fd, \ 522 } 523 524 #define FACTOR_GATE(_id, cname, pname, f, fm, fd, go, gb, gf) \ 525 { \ 526 .id = _id, \ 527 .branch_type = branch_factor, \ 528 .name = cname, \ 529 .parent_names = (const char *[]){ pname }, \ 530 .num_parents = 1, \ 531 .flags = f, \ 532 .div_shift = fm, \ 533 .div_width = fd, \ 534 .gate_offset = go, \ 535 .gate_shift = gb, \ 536 .gate_flags = gf, \ 537 } 538 539 void rockchip_clk_init(struct device_node *np, void __iomem *base, 540 unsigned long nr_clks); 541 struct regmap *rockchip_clk_get_grf(void); 542 void rockchip_clk_add_lookup(struct clk *clk, unsigned int id); 543 void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list, 544 unsigned int nr_clk); 545 void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, 546 unsigned int nr_pll, int grf_lock_offset); 547 void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name, 548 const char *const *parent_names, u8 num_parents, 549 const struct rockchip_cpuclk_reg_data *reg_data, 550 const struct rockchip_cpuclk_rate_table *rates, 551 int nrates); 552 void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); 553 void rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void)); 554 555 #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) 556 557 #ifdef CONFIG_RESET_CONTROLLER 558 void rockchip_register_softrst(struct device_node *np, 559 unsigned int num_regs, 560 void __iomem *base, u8 flags); 561 #else 562 static inline void rockchip_register_softrst(struct device_node *np, 563 unsigned int num_regs, 564 void __iomem *base, u8 flags) 565 { 566 } 567 #endif 568 569 #endif 570