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 and RK3188 */ 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 RK3288_PLL_CON(x) RK2928_PLL_CON(x) 54 #define RK3288_MODE_CON 0x50 55 #define RK3288_CLKSEL_CON(x) ((x) * 0x4 + 0x60) 56 #define RK3288_CLKGATE_CON(x) ((x) * 0x4 + 0x160) 57 #define RK3288_GLB_SRST_FST 0x1b0 58 #define RK3288_GLB_SRST_SND 0x1b4 59 #define RK3288_SOFTRST_CON(x) ((x) * 0x4 + 0x1b8) 60 #define RK3288_MISC_CON 0x1e8 61 #define RK3288_SDMMC_CON0 0x200 62 #define RK3288_SDMMC_CON1 0x204 63 #define RK3288_SDIO0_CON0 0x208 64 #define RK3288_SDIO0_CON1 0x20c 65 #define RK3288_SDIO1_CON0 0x210 66 #define RK3288_SDIO1_CON1 0x214 67 #define RK3288_EMMC_CON0 0x218 68 #define RK3288_EMMC_CON1 0x21c 69 70 #define RK3368_PLL_CON(x) RK2928_PLL_CON(x) 71 #define RK3368_CLKSEL_CON(x) ((x) * 0x4 + 0x100) 72 #define RK3368_CLKGATE_CON(x) ((x) * 0x4 + 0x200) 73 #define RK3368_GLB_SRST_FST 0x280 74 #define RK3368_GLB_SRST_SND 0x284 75 #define RK3368_SOFTRST_CON(x) ((x) * 0x4 + 0x300) 76 #define RK3368_MISC_CON 0x380 77 #define RK3368_SDMMC_CON0 0x400 78 #define RK3368_SDMMC_CON1 0x404 79 #define RK3368_SDIO0_CON0 0x408 80 #define RK3368_SDIO0_CON1 0x40c 81 #define RK3368_SDIO1_CON0 0x410 82 #define RK3368_SDIO1_CON1 0x414 83 #define RK3368_EMMC_CON0 0x418 84 #define RK3368_EMMC_CON1 0x41c 85 86 enum rockchip_pll_type { 87 pll_rk3036, 88 pll_rk3066, 89 }; 90 91 #define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \ 92 _postdiv2, _dsmpd, _frac) \ 93 { \ 94 .rate = _rate##U, \ 95 .fbdiv = _fbdiv, \ 96 .postdiv1 = _postdiv1, \ 97 .refdiv = _refdiv, \ 98 .postdiv2 = _postdiv2, \ 99 .dsmpd = _dsmpd, \ 100 .frac = _frac, \ 101 } 102 103 #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \ 104 { \ 105 .rate = _rate##U, \ 106 .nr = _nr, \ 107 .nf = _nf, \ 108 .no = _no, \ 109 .nb = ((_nf) < 2) ? 1 : (_nf) >> 1, \ 110 } 111 112 #define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb) \ 113 { \ 114 .rate = _rate##U, \ 115 .nr = _nr, \ 116 .nf = _nf, \ 117 .no = _no, \ 118 .nb = _nb, \ 119 } 120 121 struct rockchip_pll_rate_table { 122 unsigned long rate; 123 unsigned int nr; 124 unsigned int nf; 125 unsigned int no; 126 unsigned int nb; 127 /* for RK3036 */ 128 unsigned int fbdiv; 129 unsigned int postdiv1; 130 unsigned int refdiv; 131 unsigned int postdiv2; 132 unsigned int dsmpd; 133 unsigned int frac; 134 }; 135 136 /** 137 * struct rockchip_pll_clock: information about pll clock 138 * @id: platform specific id of the clock. 139 * @name: name of this pll clock. 140 * @parent_name: name of the parent clock. 141 * @flags: optional flags for basic clock. 142 * @con_offset: offset of the register for configuring the PLL. 143 * @mode_offset: offset of the register for configuring the PLL-mode. 144 * @mode_shift: offset inside the mode-register for the mode of this pll. 145 * @lock_shift: offset inside the lock register for the lock status. 146 * @type: Type of PLL to be registered. 147 * @pll_flags: hardware-specific flags 148 * @rate_table: Table of usable pll rates 149 * 150 * Flags: 151 * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the 152 * rate_table parameters and ajust them if necessary. 153 */ 154 struct rockchip_pll_clock { 155 unsigned int id; 156 const char *name; 157 const char *const *parent_names; 158 u8 num_parents; 159 unsigned long flags; 160 int con_offset; 161 int mode_offset; 162 int mode_shift; 163 int lock_shift; 164 enum rockchip_pll_type type; 165 u8 pll_flags; 166 struct rockchip_pll_rate_table *rate_table; 167 }; 168 169 #define ROCKCHIP_PLL_SYNC_RATE BIT(0) 170 171 #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ 172 _lshift, _pflags, _rtable) \ 173 { \ 174 .id = _id, \ 175 .type = _type, \ 176 .name = _name, \ 177 .parent_names = _pnames, \ 178 .num_parents = ARRAY_SIZE(_pnames), \ 179 .flags = CLK_GET_RATE_NOCACHE | _flags, \ 180 .con_offset = _con, \ 181 .mode_offset = _mode, \ 182 .mode_shift = _mshift, \ 183 .lock_shift = _lshift, \ 184 .pll_flags = _pflags, \ 185 .rate_table = _rtable, \ 186 } 187 188 struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, 189 const char *name, const char *const *parent_names, 190 u8 num_parents, void __iomem *base, int con_offset, 191 int grf_lock_offset, int lock_shift, int reg_mode, 192 int mode_shift, struct rockchip_pll_rate_table *rate_table, 193 u8 clk_pll_flags, spinlock_t *lock); 194 195 struct rockchip_cpuclk_clksel { 196 int reg; 197 u32 val; 198 }; 199 200 #define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2 201 struct rockchip_cpuclk_rate_table { 202 unsigned long prate; 203 struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS]; 204 }; 205 206 /** 207 * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock 208 * @core_reg: register offset of the core settings register 209 * @div_core_shift: core divider offset used to divide the pll value 210 * @div_core_mask: core divider mask 211 * @mux_core_shift: offset of the core multiplexer 212 */ 213 struct rockchip_cpuclk_reg_data { 214 int core_reg; 215 u8 div_core_shift; 216 u32 div_core_mask; 217 int mux_core_reg; 218 u8 mux_core_shift; 219 }; 220 221 struct clk *rockchip_clk_register_cpuclk(const char *name, 222 const char *const *parent_names, u8 num_parents, 223 const struct rockchip_cpuclk_reg_data *reg_data, 224 const struct rockchip_cpuclk_rate_table *rates, 225 int nrates, void __iomem *reg_base, spinlock_t *lock); 226 227 struct clk *rockchip_clk_register_mmc(const char *name, 228 const char *const *parent_names, u8 num_parents, 229 void __iomem *reg, int shift); 230 231 #define ROCKCHIP_INVERTER_HIWORD_MASK BIT(0) 232 233 struct clk *rockchip_clk_register_inverter(const char *name, 234 const char *const *parent_names, u8 num_parents, 235 void __iomem *reg, int shift, int flags, 236 spinlock_t *lock); 237 238 #define PNAME(x) static const char *const x[] __initconst 239 240 enum rockchip_clk_branch_type { 241 branch_composite, 242 branch_mux, 243 branch_divider, 244 branch_fraction_divider, 245 branch_gate, 246 branch_mmc, 247 branch_inverter, 248 }; 249 250 struct rockchip_clk_branch { 251 unsigned int id; 252 enum rockchip_clk_branch_type branch_type; 253 const char *name; 254 const char *const *parent_names; 255 u8 num_parents; 256 unsigned long flags; 257 int muxdiv_offset; 258 u8 mux_shift; 259 u8 mux_width; 260 u8 mux_flags; 261 u8 div_shift; 262 u8 div_width; 263 u8 div_flags; 264 struct clk_div_table *div_table; 265 int gate_offset; 266 u8 gate_shift; 267 u8 gate_flags; 268 }; 269 270 #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\ 271 df, go, gs, gf) \ 272 { \ 273 .id = _id, \ 274 .branch_type = branch_composite, \ 275 .name = cname, \ 276 .parent_names = pnames, \ 277 .num_parents = ARRAY_SIZE(pnames), \ 278 .flags = f, \ 279 .muxdiv_offset = mo, \ 280 .mux_shift = ms, \ 281 .mux_width = mw, \ 282 .mux_flags = mf, \ 283 .div_shift = ds, \ 284 .div_width = dw, \ 285 .div_flags = df, \ 286 .gate_offset = go, \ 287 .gate_shift = gs, \ 288 .gate_flags = gf, \ 289 } 290 291 #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \ 292 go, gs, gf) \ 293 { \ 294 .id = _id, \ 295 .branch_type = branch_composite, \ 296 .name = cname, \ 297 .parent_names = (const char *[]){ pname }, \ 298 .num_parents = 1, \ 299 .flags = f, \ 300 .muxdiv_offset = mo, \ 301 .div_shift = ds, \ 302 .div_width = dw, \ 303 .div_flags = df, \ 304 .gate_offset = go, \ 305 .gate_shift = gs, \ 306 .gate_flags = gf, \ 307 } 308 309 #define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\ 310 df, dt, go, gs, gf) \ 311 { \ 312 .id = _id, \ 313 .branch_type = branch_composite, \ 314 .name = cname, \ 315 .parent_names = (const char *[]){ pname }, \ 316 .num_parents = 1, \ 317 .flags = f, \ 318 .muxdiv_offset = mo, \ 319 .div_shift = ds, \ 320 .div_width = dw, \ 321 .div_flags = df, \ 322 .div_table = dt, \ 323 .gate_offset = go, \ 324 .gate_shift = gs, \ 325 .gate_flags = gf, \ 326 } 327 328 #define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \ 329 go, gs, gf) \ 330 { \ 331 .id = _id, \ 332 .branch_type = branch_composite, \ 333 .name = cname, \ 334 .parent_names = pnames, \ 335 .num_parents = ARRAY_SIZE(pnames), \ 336 .flags = f, \ 337 .muxdiv_offset = mo, \ 338 .mux_shift = ms, \ 339 .mux_width = mw, \ 340 .mux_flags = mf, \ 341 .gate_offset = go, \ 342 .gate_shift = gs, \ 343 .gate_flags = gf, \ 344 } 345 346 #define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \ 347 ds, dw, df) \ 348 { \ 349 .id = _id, \ 350 .branch_type = branch_composite, \ 351 .name = cname, \ 352 .parent_names = pnames, \ 353 .num_parents = ARRAY_SIZE(pnames), \ 354 .flags = f, \ 355 .muxdiv_offset = mo, \ 356 .mux_shift = ms, \ 357 .mux_width = mw, \ 358 .mux_flags = mf, \ 359 .div_shift = ds, \ 360 .div_width = dw, \ 361 .div_flags = df, \ 362 .gate_offset = -1, \ 363 } 364 365 #define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms, \ 366 mw, mf, ds, dw, df, dt) \ 367 { \ 368 .id = _id, \ 369 .branch_type = branch_composite, \ 370 .name = cname, \ 371 .parent_names = pnames, \ 372 .num_parents = ARRAY_SIZE(pnames), \ 373 .flags = f, \ 374 .muxdiv_offset = mo, \ 375 .mux_shift = ms, \ 376 .mux_width = mw, \ 377 .mux_flags = mf, \ 378 .div_shift = ds, \ 379 .div_width = dw, \ 380 .div_flags = df, \ 381 .div_table = dt, \ 382 .gate_offset = -1, \ 383 } 384 385 #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\ 386 { \ 387 .id = _id, \ 388 .branch_type = branch_fraction_divider, \ 389 .name = cname, \ 390 .parent_names = (const char *[]){ pname }, \ 391 .num_parents = 1, \ 392 .flags = f, \ 393 .muxdiv_offset = mo, \ 394 .div_shift = 16, \ 395 .div_width = 16, \ 396 .div_flags = df, \ 397 .gate_offset = go, \ 398 .gate_shift = gs, \ 399 .gate_flags = gf, \ 400 } 401 402 #define MUX(_id, cname, pnames, f, o, s, w, mf) \ 403 { \ 404 .id = _id, \ 405 .branch_type = branch_mux, \ 406 .name = cname, \ 407 .parent_names = pnames, \ 408 .num_parents = ARRAY_SIZE(pnames), \ 409 .flags = f, \ 410 .muxdiv_offset = o, \ 411 .mux_shift = s, \ 412 .mux_width = w, \ 413 .mux_flags = mf, \ 414 .gate_offset = -1, \ 415 } 416 417 #define DIV(_id, cname, pname, f, o, s, w, df) \ 418 { \ 419 .id = _id, \ 420 .branch_type = branch_divider, \ 421 .name = cname, \ 422 .parent_names = (const char *[]){ pname }, \ 423 .num_parents = 1, \ 424 .flags = f, \ 425 .muxdiv_offset = o, \ 426 .div_shift = s, \ 427 .div_width = w, \ 428 .div_flags = df, \ 429 .gate_offset = -1, \ 430 } 431 432 #define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \ 433 { \ 434 .id = _id, \ 435 .branch_type = branch_divider, \ 436 .name = cname, \ 437 .parent_names = (const char *[]){ pname }, \ 438 .num_parents = 1, \ 439 .flags = f, \ 440 .muxdiv_offset = o, \ 441 .div_shift = s, \ 442 .div_width = w, \ 443 .div_flags = df, \ 444 .div_table = dt, \ 445 } 446 447 #define GATE(_id, cname, pname, f, o, b, gf) \ 448 { \ 449 .id = _id, \ 450 .branch_type = branch_gate, \ 451 .name = cname, \ 452 .parent_names = (const char *[]){ pname }, \ 453 .num_parents = 1, \ 454 .flags = f, \ 455 .gate_offset = o, \ 456 .gate_shift = b, \ 457 .gate_flags = gf, \ 458 } 459 460 #define MMC(_id, cname, pname, offset, shift) \ 461 { \ 462 .id = _id, \ 463 .branch_type = branch_mmc, \ 464 .name = cname, \ 465 .parent_names = (const char *[]){ pname }, \ 466 .num_parents = 1, \ 467 .muxdiv_offset = offset, \ 468 .div_shift = shift, \ 469 } 470 471 #define INVERTER(_id, cname, pname, io, is, if) \ 472 { \ 473 .id = _id, \ 474 .branch_type = branch_inverter, \ 475 .name = cname, \ 476 .parent_names = (const char *[]){ pname }, \ 477 .num_parents = 1, \ 478 .muxdiv_offset = io, \ 479 .div_shift = is, \ 480 .div_flags = if, \ 481 } 482 483 void rockchip_clk_init(struct device_node *np, void __iomem *base, 484 unsigned long nr_clks); 485 struct regmap *rockchip_clk_get_grf(void); 486 void rockchip_clk_add_lookup(struct clk *clk, unsigned int id); 487 void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list, 488 unsigned int nr_clk); 489 void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, 490 unsigned int nr_pll, int grf_lock_offset); 491 void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name, 492 const char *const *parent_names, u8 num_parents, 493 const struct rockchip_cpuclk_reg_data *reg_data, 494 const struct rockchip_cpuclk_rate_table *rates, 495 int nrates); 496 void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); 497 void rockchip_register_restart_notifier(unsigned int reg); 498 499 #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) 500 501 #ifdef CONFIG_RESET_CONTROLLER 502 void rockchip_register_softrst(struct device_node *np, 503 unsigned int num_regs, 504 void __iomem *base, u8 flags); 505 #else 506 static inline void rockchip_register_softrst(struct device_node *np, 507 unsigned int num_regs, 508 void __iomem *base, u8 flags) 509 { 510 } 511 #endif 512 513 #endif 514