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 #include <linux/clk.h> 28 #include <linux/clk-provider.h> 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 enum rockchip_pll_type { 61 pll_rk3066, 62 }; 63 64 #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \ 65 { \ 66 .rate = _rate##U, \ 67 .nr = _nr, \ 68 .nf = _nf, \ 69 .no = _no, \ 70 .bwadj = (_nf >> 1), \ 71 } 72 73 #define RK3066_PLL_RATE_BWADJ(_rate, _nr, _nf, _no, _bw) \ 74 { \ 75 .rate = _rate##U, \ 76 .nr = _nr, \ 77 .nf = _nf, \ 78 .no = _no, \ 79 .bwadj = _bw, \ 80 } 81 82 struct rockchip_pll_rate_table { 83 unsigned long rate; 84 unsigned int nr; 85 unsigned int nf; 86 unsigned int no; 87 unsigned int bwadj; 88 }; 89 90 /** 91 * struct rockchip_pll_clock: information about pll clock 92 * @id: platform specific id of the clock. 93 * @name: name of this pll clock. 94 * @parent_name: name of the parent clock. 95 * @flags: optional flags for basic clock. 96 * @con_offset: offset of the register for configuring the PLL. 97 * @mode_offset: offset of the register for configuring the PLL-mode. 98 * @mode_shift: offset inside the mode-register for the mode of this pll. 99 * @lock_shift: offset inside the lock register for the lock status. 100 * @type: Type of PLL to be registered. 101 * @pll_flags: hardware-specific flags 102 * @rate_table: Table of usable pll rates 103 * 104 * Flags: 105 * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the 106 * rate_table parameters and ajust them if necessary. 107 */ 108 struct rockchip_pll_clock { 109 unsigned int id; 110 const char *name; 111 const char **parent_names; 112 u8 num_parents; 113 unsigned long flags; 114 int con_offset; 115 int mode_offset; 116 int mode_shift; 117 int lock_shift; 118 enum rockchip_pll_type type; 119 u8 pll_flags; 120 struct rockchip_pll_rate_table *rate_table; 121 }; 122 123 #define ROCKCHIP_PLL_SYNC_RATE BIT(0) 124 125 #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ 126 _lshift, _pflags, _rtable) \ 127 { \ 128 .id = _id, \ 129 .type = _type, \ 130 .name = _name, \ 131 .parent_names = _pnames, \ 132 .num_parents = ARRAY_SIZE(_pnames), \ 133 .flags = CLK_GET_RATE_NOCACHE | _flags, \ 134 .con_offset = _con, \ 135 .mode_offset = _mode, \ 136 .mode_shift = _mshift, \ 137 .lock_shift = _lshift, \ 138 .pll_flags = _pflags, \ 139 .rate_table = _rtable, \ 140 } 141 142 struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, 143 const char *name, const char **parent_names, u8 num_parents, 144 void __iomem *base, int con_offset, int grf_lock_offset, 145 int lock_shift, int reg_mode, int mode_shift, 146 struct rockchip_pll_rate_table *rate_table, 147 u8 clk_pll_flags, spinlock_t *lock); 148 149 struct rockchip_cpuclk_clksel { 150 int reg; 151 u32 val; 152 }; 153 154 #define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2 155 struct rockchip_cpuclk_rate_table { 156 unsigned long prate; 157 struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS]; 158 }; 159 160 /** 161 * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock 162 * @core_reg: register offset of the core settings register 163 * @div_core_shift: core divider offset used to divide the pll value 164 * @div_core_mask: core divider mask 165 * @mux_core_shift: offset of the core multiplexer 166 */ 167 struct rockchip_cpuclk_reg_data { 168 int core_reg; 169 u8 div_core_shift; 170 u32 div_core_mask; 171 int mux_core_reg; 172 u8 mux_core_shift; 173 }; 174 175 struct clk *rockchip_clk_register_cpuclk(const char *name, 176 const char **parent_names, u8 num_parents, 177 const struct rockchip_cpuclk_reg_data *reg_data, 178 const struct rockchip_cpuclk_rate_table *rates, 179 int nrates, void __iomem *reg_base, spinlock_t *lock); 180 181 struct clk *rockchip_clk_register_mmc(const char *name, 182 const char **parent_names, u8 num_parents, 183 void __iomem *reg, int shift); 184 185 #define PNAME(x) static const char *x[] __initconst 186 187 enum rockchip_clk_branch_type { 188 branch_composite, 189 branch_mux, 190 branch_divider, 191 branch_fraction_divider, 192 branch_gate, 193 branch_mmc, 194 }; 195 196 struct rockchip_clk_branch { 197 unsigned int id; 198 enum rockchip_clk_branch_type branch_type; 199 const char *name; 200 const char **parent_names; 201 u8 num_parents; 202 unsigned long flags; 203 int muxdiv_offset; 204 u8 mux_shift; 205 u8 mux_width; 206 u8 mux_flags; 207 u8 div_shift; 208 u8 div_width; 209 u8 div_flags; 210 struct clk_div_table *div_table; 211 int gate_offset; 212 u8 gate_shift; 213 u8 gate_flags; 214 }; 215 216 #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\ 217 df, go, gs, gf) \ 218 { \ 219 .id = _id, \ 220 .branch_type = branch_composite, \ 221 .name = cname, \ 222 .parent_names = pnames, \ 223 .num_parents = ARRAY_SIZE(pnames), \ 224 .flags = f, \ 225 .muxdiv_offset = mo, \ 226 .mux_shift = ms, \ 227 .mux_width = mw, \ 228 .mux_flags = mf, \ 229 .div_shift = ds, \ 230 .div_width = dw, \ 231 .div_flags = df, \ 232 .gate_offset = go, \ 233 .gate_shift = gs, \ 234 .gate_flags = gf, \ 235 } 236 237 #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \ 238 go, gs, gf) \ 239 { \ 240 .id = _id, \ 241 .branch_type = branch_composite, \ 242 .name = cname, \ 243 .parent_names = (const char *[]){ pname }, \ 244 .num_parents = 1, \ 245 .flags = f, \ 246 .muxdiv_offset = mo, \ 247 .div_shift = ds, \ 248 .div_width = dw, \ 249 .div_flags = df, \ 250 .gate_offset = go, \ 251 .gate_shift = gs, \ 252 .gate_flags = gf, \ 253 } 254 255 #define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\ 256 df, dt, go, gs, gf) \ 257 { \ 258 .id = _id, \ 259 .branch_type = branch_composite, \ 260 .name = cname, \ 261 .parent_names = (const char *[]){ pname }, \ 262 .num_parents = 1, \ 263 .flags = f, \ 264 .muxdiv_offset = mo, \ 265 .div_shift = ds, \ 266 .div_width = dw, \ 267 .div_flags = df, \ 268 .div_table = dt, \ 269 .gate_offset = go, \ 270 .gate_shift = gs, \ 271 .gate_flags = gf, \ 272 } 273 274 #define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \ 275 go, gs, gf) \ 276 { \ 277 .id = _id, \ 278 .branch_type = branch_composite, \ 279 .name = cname, \ 280 .parent_names = pnames, \ 281 .num_parents = ARRAY_SIZE(pnames), \ 282 .flags = f, \ 283 .muxdiv_offset = mo, \ 284 .mux_shift = ms, \ 285 .mux_width = mw, \ 286 .mux_flags = mf, \ 287 .gate_offset = go, \ 288 .gate_shift = gs, \ 289 .gate_flags = gf, \ 290 } 291 292 #define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \ 293 ds, dw, df) \ 294 { \ 295 .id = _id, \ 296 .branch_type = branch_composite, \ 297 .name = cname, \ 298 .parent_names = pnames, \ 299 .num_parents = ARRAY_SIZE(pnames), \ 300 .flags = f, \ 301 .muxdiv_offset = mo, \ 302 .mux_shift = ms, \ 303 .mux_width = mw, \ 304 .mux_flags = mf, \ 305 .div_shift = ds, \ 306 .div_width = dw, \ 307 .div_flags = df, \ 308 .gate_offset = -1, \ 309 } 310 311 #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\ 312 { \ 313 .id = _id, \ 314 .branch_type = branch_fraction_divider, \ 315 .name = cname, \ 316 .parent_names = (const char *[]){ pname }, \ 317 .num_parents = 1, \ 318 .flags = f, \ 319 .muxdiv_offset = mo, \ 320 .div_shift = 16, \ 321 .div_width = 16, \ 322 .div_flags = df, \ 323 .gate_offset = go, \ 324 .gate_shift = gs, \ 325 .gate_flags = gf, \ 326 } 327 328 #define MUX(_id, cname, pnames, f, o, s, w, mf) \ 329 { \ 330 .id = _id, \ 331 .branch_type = branch_mux, \ 332 .name = cname, \ 333 .parent_names = pnames, \ 334 .num_parents = ARRAY_SIZE(pnames), \ 335 .flags = f, \ 336 .muxdiv_offset = o, \ 337 .mux_shift = s, \ 338 .mux_width = w, \ 339 .mux_flags = mf, \ 340 .gate_offset = -1, \ 341 } 342 343 #define DIV(_id, cname, pname, f, o, s, w, df) \ 344 { \ 345 .id = _id, \ 346 .branch_type = branch_divider, \ 347 .name = cname, \ 348 .parent_names = (const char *[]){ pname }, \ 349 .num_parents = 1, \ 350 .flags = f, \ 351 .muxdiv_offset = o, \ 352 .div_shift = s, \ 353 .div_width = w, \ 354 .div_flags = df, \ 355 .gate_offset = -1, \ 356 } 357 358 #define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \ 359 { \ 360 .id = _id, \ 361 .branch_type = branch_divider, \ 362 .name = cname, \ 363 .parent_names = (const char *[]){ pname }, \ 364 .num_parents = 1, \ 365 .flags = f, \ 366 .muxdiv_offset = o, \ 367 .div_shift = s, \ 368 .div_width = w, \ 369 .div_flags = df, \ 370 .div_table = dt, \ 371 } 372 373 #define GATE(_id, cname, pname, f, o, b, gf) \ 374 { \ 375 .id = _id, \ 376 .branch_type = branch_gate, \ 377 .name = cname, \ 378 .parent_names = (const char *[]){ pname }, \ 379 .num_parents = 1, \ 380 .flags = f, \ 381 .gate_offset = o, \ 382 .gate_shift = b, \ 383 .gate_flags = gf, \ 384 } 385 386 #define MMC(_id, cname, pname, offset, shift) \ 387 { \ 388 .id = _id, \ 389 .branch_type = branch_mmc, \ 390 .name = cname, \ 391 .parent_names = (const char *[]){ pname }, \ 392 .num_parents = 1, \ 393 .muxdiv_offset = offset, \ 394 .div_shift = shift, \ 395 } 396 397 void rockchip_clk_init(struct device_node *np, void __iomem *base, 398 unsigned long nr_clks); 399 struct regmap *rockchip_clk_get_grf(void); 400 void rockchip_clk_add_lookup(struct clk *clk, unsigned int id); 401 void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list, 402 unsigned int nr_clk); 403 void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, 404 unsigned int nr_pll, int grf_lock_offset); 405 void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name, 406 const char **parent_names, u8 num_parents, 407 const struct rockchip_cpuclk_reg_data *reg_data, 408 const struct rockchip_cpuclk_rate_table *rates, 409 int nrates); 410 void rockchip_clk_protect_critical(const char *clocks[], int nclocks); 411 void rockchip_register_restart_notifier(unsigned int reg); 412 413 #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) 414 415 #ifdef CONFIG_RESET_CONTROLLER 416 void rockchip_register_softrst(struct device_node *np, 417 unsigned int num_regs, 418 void __iomem *base, u8 flags); 419 #else 420 static inline void rockchip_register_softrst(struct device_node *np, 421 unsigned int num_regs, 422 void __iomem *base, u8 flags) 423 { 424 } 425 #endif 426 427 #endif 428