1 /* 2 * Copyright (c) 2014 MundoReader S.L. 3 * Author: Heiko Stuebner <heiko@sntech.de> 4 * 5 * based on 6 * 7 * samsung/clk.h 8 * Copyright (c) 2013 Samsung Electronics Co., Ltd. 9 * Copyright (c) 2013 Linaro Ltd. 10 * Author: Thomas Abraham <thomas.ab@samsung.com> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 */ 22 23 #ifndef CLK_ROCKCHIP_CLK_H 24 #define CLK_ROCKCHIP_CLK_H 25 26 #include <linux/io.h> 27 28 struct clk; 29 30 #define HIWORD_UPDATE(val, mask, shift) \ 31 ((val) << (shift) | (mask) << ((shift) + 16)) 32 33 /* register positions shared by RK2928, RK3066 and RK3188 */ 34 #define RK2928_PLL_CON(x) ((x) * 0x4) 35 #define RK2928_MODE_CON 0x40 36 #define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44) 37 #define RK2928_CLKGATE_CON(x) ((x) * 0x4 + 0xd0) 38 #define RK2928_GLB_SRST_FST 0x100 39 #define RK2928_GLB_SRST_SND 0x104 40 #define RK2928_SOFTRST_CON(x) ((x) * 0x4 + 0x110) 41 #define RK2928_MISC_CON 0x134 42 43 #define RK3288_PLL_CON(x) RK2928_PLL_CON(x) 44 #define RK3288_MODE_CON 0x50 45 #define RK3288_CLKSEL_CON(x) ((x) * 0x4 + 0x60) 46 #define RK3288_CLKGATE_CON(x) ((x) * 0x4 + 0x160) 47 #define RK3288_GLB_SRST_FST 0x1b0 48 #define RK3288_GLB_SRST_SND 0x1b4 49 #define RK3288_SOFTRST_CON(x) ((x) * 0x4 + 0x1b8) 50 #define RK3288_MISC_CON 0x1e8 51 #define RK3288_SDMMC_CON0 0x200 52 #define RK3288_SDMMC_CON1 0x204 53 #define RK3288_SDIO0_CON0 0x208 54 #define RK3288_SDIO0_CON1 0x20c 55 #define RK3288_SDIO1_CON0 0x210 56 #define RK3288_SDIO1_CON1 0x214 57 #define RK3288_EMMC_CON0 0x218 58 #define RK3288_EMMC_CON1 0x21c 59 60 #define RK3368_PLL_CON(x) RK2928_PLL_CON(x) 61 #define RK3368_CLKSEL_CON(x) ((x) * 0x4 + 0x100) 62 #define RK3368_CLKGATE_CON(x) ((x) * 0x4 + 0x200) 63 #define RK3368_GLB_SRST_FST 0x280 64 #define RK3368_GLB_SRST_SND 0x284 65 #define RK3368_SOFTRST_CON(x) ((x) * 0x4 + 0x300) 66 #define RK3368_MISC_CON 0x380 67 #define RK3368_SDMMC_CON0 0x400 68 #define RK3368_SDMMC_CON1 0x404 69 #define RK3368_SDIO0_CON0 0x408 70 #define RK3368_SDIO0_CON1 0x40c 71 #define RK3368_SDIO1_CON0 0x410 72 #define RK3368_SDIO1_CON1 0x414 73 #define RK3368_EMMC_CON0 0x418 74 #define RK3368_EMMC_CON1 0x41c 75 76 enum rockchip_pll_type { 77 pll_rk3066, 78 }; 79 80 #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \ 81 { \ 82 .rate = _rate##U, \ 83 .nr = _nr, \ 84 .nf = _nf, \ 85 .no = _no, \ 86 .nb = ((_nf) < 2) ? 1 : (_nf) >> 1, \ 87 } 88 89 #define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb) \ 90 { \ 91 .rate = _rate##U, \ 92 .nr = _nr, \ 93 .nf = _nf, \ 94 .no = _no, \ 95 .nb = _nb, \ 96 } 97 98 struct rockchip_pll_rate_table { 99 unsigned long rate; 100 unsigned int nr; 101 unsigned int nf; 102 unsigned int no; 103 unsigned int nb; 104 }; 105 106 /** 107 * struct rockchip_pll_clock: information about pll clock 108 * @id: platform specific id of the clock. 109 * @name: name of this pll clock. 110 * @parent_name: name of the parent clock. 111 * @flags: optional flags for basic clock. 112 * @con_offset: offset of the register for configuring the PLL. 113 * @mode_offset: offset of the register for configuring the PLL-mode. 114 * @mode_shift: offset inside the mode-register for the mode of this pll. 115 * @lock_shift: offset inside the lock register for the lock status. 116 * @type: Type of PLL to be registered. 117 * @pll_flags: hardware-specific flags 118 * @rate_table: Table of usable pll rates 119 * 120 * Flags: 121 * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the 122 * rate_table parameters and ajust them if necessary. 123 */ 124 struct rockchip_pll_clock { 125 unsigned int id; 126 const char *name; 127 const char *const *parent_names; 128 u8 num_parents; 129 unsigned long flags; 130 int con_offset; 131 int mode_offset; 132 int mode_shift; 133 int lock_shift; 134 enum rockchip_pll_type type; 135 u8 pll_flags; 136 struct rockchip_pll_rate_table *rate_table; 137 }; 138 139 #define ROCKCHIP_PLL_SYNC_RATE BIT(0) 140 141 #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ 142 _lshift, _pflags, _rtable) \ 143 { \ 144 .id = _id, \ 145 .type = _type, \ 146 .name = _name, \ 147 .parent_names = _pnames, \ 148 .num_parents = ARRAY_SIZE(_pnames), \ 149 .flags = CLK_GET_RATE_NOCACHE | _flags, \ 150 .con_offset = _con, \ 151 .mode_offset = _mode, \ 152 .mode_shift = _mshift, \ 153 .lock_shift = _lshift, \ 154 .pll_flags = _pflags, \ 155 .rate_table = _rtable, \ 156 } 157 158 struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, 159 const char *name, const char *const *parent_names, 160 u8 num_parents, void __iomem *base, int con_offset, 161 int grf_lock_offset, int lock_shift, int reg_mode, 162 int mode_shift, struct rockchip_pll_rate_table *rate_table, 163 u8 clk_pll_flags, spinlock_t *lock); 164 165 struct rockchip_cpuclk_clksel { 166 int reg; 167 u32 val; 168 }; 169 170 #define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2 171 struct rockchip_cpuclk_rate_table { 172 unsigned long prate; 173 struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS]; 174 }; 175 176 /** 177 * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock 178 * @core_reg: register offset of the core settings register 179 * @div_core_shift: core divider offset used to divide the pll value 180 * @div_core_mask: core divider mask 181 * @mux_core_shift: offset of the core multiplexer 182 */ 183 struct rockchip_cpuclk_reg_data { 184 int core_reg; 185 u8 div_core_shift; 186 u32 div_core_mask; 187 int mux_core_reg; 188 u8 mux_core_shift; 189 }; 190 191 struct clk *rockchip_clk_register_cpuclk(const char *name, 192 const char *const *parent_names, u8 num_parents, 193 const struct rockchip_cpuclk_reg_data *reg_data, 194 const struct rockchip_cpuclk_rate_table *rates, 195 int nrates, void __iomem *reg_base, spinlock_t *lock); 196 197 struct clk *rockchip_clk_register_mmc(const char *name, 198 const char *const *parent_names, u8 num_parents, 199 void __iomem *reg, int shift); 200 201 #define ROCKCHIP_INVERTER_HIWORD_MASK BIT(0) 202 203 struct clk *rockchip_clk_register_inverter(const char *name, 204 const char *const *parent_names, u8 num_parents, 205 void __iomem *reg, int shift, int flags, 206 spinlock_t *lock); 207 208 #define PNAME(x) static const char *const x[] __initconst 209 210 enum rockchip_clk_branch_type { 211 branch_composite, 212 branch_mux, 213 branch_divider, 214 branch_fraction_divider, 215 branch_gate, 216 branch_mmc, 217 branch_inverter, 218 }; 219 220 struct rockchip_clk_branch { 221 unsigned int id; 222 enum rockchip_clk_branch_type branch_type; 223 const char *name; 224 const char *const *parent_names; 225 u8 num_parents; 226 unsigned long flags; 227 int muxdiv_offset; 228 u8 mux_shift; 229 u8 mux_width; 230 u8 mux_flags; 231 u8 div_shift; 232 u8 div_width; 233 u8 div_flags; 234 struct clk_div_table *div_table; 235 int gate_offset; 236 u8 gate_shift; 237 u8 gate_flags; 238 }; 239 240 #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\ 241 df, go, gs, gf) \ 242 { \ 243 .id = _id, \ 244 .branch_type = branch_composite, \ 245 .name = cname, \ 246 .parent_names = pnames, \ 247 .num_parents = ARRAY_SIZE(pnames), \ 248 .flags = f, \ 249 .muxdiv_offset = mo, \ 250 .mux_shift = ms, \ 251 .mux_width = mw, \ 252 .mux_flags = mf, \ 253 .div_shift = ds, \ 254 .div_width = dw, \ 255 .div_flags = df, \ 256 .gate_offset = go, \ 257 .gate_shift = gs, \ 258 .gate_flags = gf, \ 259 } 260 261 #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \ 262 go, gs, gf) \ 263 { \ 264 .id = _id, \ 265 .branch_type = branch_composite, \ 266 .name = cname, \ 267 .parent_names = (const char *[]){ pname }, \ 268 .num_parents = 1, \ 269 .flags = f, \ 270 .muxdiv_offset = mo, \ 271 .div_shift = ds, \ 272 .div_width = dw, \ 273 .div_flags = df, \ 274 .gate_offset = go, \ 275 .gate_shift = gs, \ 276 .gate_flags = gf, \ 277 } 278 279 #define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\ 280 df, dt, go, gs, gf) \ 281 { \ 282 .id = _id, \ 283 .branch_type = branch_composite, \ 284 .name = cname, \ 285 .parent_names = (const char *[]){ pname }, \ 286 .num_parents = 1, \ 287 .flags = f, \ 288 .muxdiv_offset = mo, \ 289 .div_shift = ds, \ 290 .div_width = dw, \ 291 .div_flags = df, \ 292 .div_table = dt, \ 293 .gate_offset = go, \ 294 .gate_shift = gs, \ 295 .gate_flags = gf, \ 296 } 297 298 #define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \ 299 go, gs, gf) \ 300 { \ 301 .id = _id, \ 302 .branch_type = branch_composite, \ 303 .name = cname, \ 304 .parent_names = pnames, \ 305 .num_parents = ARRAY_SIZE(pnames), \ 306 .flags = f, \ 307 .muxdiv_offset = mo, \ 308 .mux_shift = ms, \ 309 .mux_width = mw, \ 310 .mux_flags = mf, \ 311 .gate_offset = go, \ 312 .gate_shift = gs, \ 313 .gate_flags = gf, \ 314 } 315 316 #define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \ 317 ds, dw, df) \ 318 { \ 319 .id = _id, \ 320 .branch_type = branch_composite, \ 321 .name = cname, \ 322 .parent_names = pnames, \ 323 .num_parents = ARRAY_SIZE(pnames), \ 324 .flags = f, \ 325 .muxdiv_offset = mo, \ 326 .mux_shift = ms, \ 327 .mux_width = mw, \ 328 .mux_flags = mf, \ 329 .div_shift = ds, \ 330 .div_width = dw, \ 331 .div_flags = df, \ 332 .gate_offset = -1, \ 333 } 334 335 #define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms, \ 336 mw, mf, ds, dw, df, dt) \ 337 { \ 338 .id = _id, \ 339 .branch_type = branch_composite, \ 340 .name = cname, \ 341 .parent_names = pnames, \ 342 .num_parents = ARRAY_SIZE(pnames), \ 343 .flags = f, \ 344 .muxdiv_offset = mo, \ 345 .mux_shift = ms, \ 346 .mux_width = mw, \ 347 .mux_flags = mf, \ 348 .div_shift = ds, \ 349 .div_width = dw, \ 350 .div_flags = df, \ 351 .div_table = dt, \ 352 .gate_offset = -1, \ 353 } 354 355 #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\ 356 { \ 357 .id = _id, \ 358 .branch_type = branch_fraction_divider, \ 359 .name = cname, \ 360 .parent_names = (const char *[]){ pname }, \ 361 .num_parents = 1, \ 362 .flags = f, \ 363 .muxdiv_offset = mo, \ 364 .div_shift = 16, \ 365 .div_width = 16, \ 366 .div_flags = df, \ 367 .gate_offset = go, \ 368 .gate_shift = gs, \ 369 .gate_flags = gf, \ 370 } 371 372 #define MUX(_id, cname, pnames, f, o, s, w, mf) \ 373 { \ 374 .id = _id, \ 375 .branch_type = branch_mux, \ 376 .name = cname, \ 377 .parent_names = pnames, \ 378 .num_parents = ARRAY_SIZE(pnames), \ 379 .flags = f, \ 380 .muxdiv_offset = o, \ 381 .mux_shift = s, \ 382 .mux_width = w, \ 383 .mux_flags = mf, \ 384 .gate_offset = -1, \ 385 } 386 387 #define DIV(_id, cname, pname, f, o, s, w, df) \ 388 { \ 389 .id = _id, \ 390 .branch_type = branch_divider, \ 391 .name = cname, \ 392 .parent_names = (const char *[]){ pname }, \ 393 .num_parents = 1, \ 394 .flags = f, \ 395 .muxdiv_offset = o, \ 396 .div_shift = s, \ 397 .div_width = w, \ 398 .div_flags = df, \ 399 .gate_offset = -1, \ 400 } 401 402 #define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \ 403 { \ 404 .id = _id, \ 405 .branch_type = branch_divider, \ 406 .name = cname, \ 407 .parent_names = (const char *[]){ pname }, \ 408 .num_parents = 1, \ 409 .flags = f, \ 410 .muxdiv_offset = o, \ 411 .div_shift = s, \ 412 .div_width = w, \ 413 .div_flags = df, \ 414 .div_table = dt, \ 415 } 416 417 #define GATE(_id, cname, pname, f, o, b, gf) \ 418 { \ 419 .id = _id, \ 420 .branch_type = branch_gate, \ 421 .name = cname, \ 422 .parent_names = (const char *[]){ pname }, \ 423 .num_parents = 1, \ 424 .flags = f, \ 425 .gate_offset = o, \ 426 .gate_shift = b, \ 427 .gate_flags = gf, \ 428 } 429 430 #define MMC(_id, cname, pname, offset, shift) \ 431 { \ 432 .id = _id, \ 433 .branch_type = branch_mmc, \ 434 .name = cname, \ 435 .parent_names = (const char *[]){ pname }, \ 436 .num_parents = 1, \ 437 .muxdiv_offset = offset, \ 438 .div_shift = shift, \ 439 } 440 441 #define INVERTER(_id, cname, pname, io, is, if) \ 442 { \ 443 .id = _id, \ 444 .branch_type = branch_inverter, \ 445 .name = cname, \ 446 .parent_names = (const char *[]){ pname }, \ 447 .num_parents = 1, \ 448 .muxdiv_offset = io, \ 449 .div_shift = is, \ 450 .div_flags = if, \ 451 } 452 453 void rockchip_clk_init(struct device_node *np, void __iomem *base, 454 unsigned long nr_clks); 455 struct regmap *rockchip_clk_get_grf(void); 456 void rockchip_clk_add_lookup(struct clk *clk, unsigned int id); 457 void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list, 458 unsigned int nr_clk); 459 void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, 460 unsigned int nr_pll, int grf_lock_offset); 461 void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name, 462 const char *const *parent_names, u8 num_parents, 463 const struct rockchip_cpuclk_reg_data *reg_data, 464 const struct rockchip_cpuclk_rate_table *rates, 465 int nrates); 466 void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); 467 void rockchip_register_restart_notifier(unsigned int reg); 468 469 #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) 470 471 #ifdef CONFIG_RESET_CONTROLLER 472 void rockchip_register_softrst(struct device_node *np, 473 unsigned int num_regs, 474 void __iomem *base, u8 flags); 475 #else 476 static inline void rockchip_register_softrst(struct device_node *np, 477 unsigned int num_regs, 478 void __iomem *base, u8 flags) 479 { 480 } 481 #endif 482 483 #endif 484