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 52 enum rockchip_pll_type { 53 pll_rk3066, 54 }; 55 56 #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \ 57 { \ 58 .rate = _rate##U, \ 59 .nr = _nr, \ 60 .nf = _nf, \ 61 .no = _no, \ 62 .bwadj = (_nf >> 1), \ 63 } 64 65 struct rockchip_pll_rate_table { 66 unsigned long rate; 67 unsigned int nr; 68 unsigned int nf; 69 unsigned int no; 70 unsigned int bwadj; 71 }; 72 73 /** 74 * struct rockchip_pll_clock: information about pll clock 75 * @id: platform specific id of the clock. 76 * @name: name of this pll clock. 77 * @parent_name: name of the parent clock. 78 * @flags: optional flags for basic clock. 79 * @con_offset: offset of the register for configuring the PLL. 80 * @mode_offset: offset of the register for configuring the PLL-mode. 81 * @mode_shift: offset inside the mode-register for the mode of this pll. 82 * @lock_shift: offset inside the lock register for the lock status. 83 * @type: Type of PLL to be registered. 84 * @rate_table: Table of usable pll rates 85 */ 86 struct rockchip_pll_clock { 87 unsigned int id; 88 const char *name; 89 const char **parent_names; 90 u8 num_parents; 91 unsigned long flags; 92 int con_offset; 93 int mode_offset; 94 int mode_shift; 95 int lock_shift; 96 enum rockchip_pll_type type; 97 struct rockchip_pll_rate_table *rate_table; 98 }; 99 100 #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ 101 _lshift, _rtable) \ 102 { \ 103 .id = _id, \ 104 .type = _type, \ 105 .name = _name, \ 106 .parent_names = _pnames, \ 107 .num_parents = ARRAY_SIZE(_pnames), \ 108 .flags = CLK_GET_RATE_NOCACHE | _flags, \ 109 .con_offset = _con, \ 110 .mode_offset = _mode, \ 111 .mode_shift = _mshift, \ 112 .lock_shift = _lshift, \ 113 .rate_table = _rtable, \ 114 } 115 116 struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, 117 const char *name, const char **parent_names, u8 num_parents, 118 void __iomem *base, int con_offset, int grf_lock_offset, 119 int lock_shift, int reg_mode, int mode_shift, 120 struct rockchip_pll_rate_table *rate_table, 121 spinlock_t *lock); 122 123 #define PNAME(x) static const char *x[] __initconst 124 125 enum rockchip_clk_branch_type { 126 branch_composite, 127 branch_mux, 128 branch_divider, 129 branch_fraction_divider, 130 branch_gate, 131 }; 132 133 struct rockchip_clk_branch { 134 unsigned int id; 135 enum rockchip_clk_branch_type branch_type; 136 const char *name; 137 const char **parent_names; 138 u8 num_parents; 139 unsigned long flags; 140 int muxdiv_offset; 141 u8 mux_shift; 142 u8 mux_width; 143 u8 mux_flags; 144 u8 div_shift; 145 u8 div_width; 146 u8 div_flags; 147 struct clk_div_table *div_table; 148 int gate_offset; 149 u8 gate_shift; 150 u8 gate_flags; 151 }; 152 153 #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\ 154 df, go, gs, gf) \ 155 { \ 156 .id = _id, \ 157 .branch_type = branch_composite, \ 158 .name = cname, \ 159 .parent_names = pnames, \ 160 .num_parents = ARRAY_SIZE(pnames), \ 161 .flags = f, \ 162 .muxdiv_offset = mo, \ 163 .mux_shift = ms, \ 164 .mux_width = mw, \ 165 .mux_flags = mf, \ 166 .div_shift = ds, \ 167 .div_width = dw, \ 168 .div_flags = df, \ 169 .gate_offset = go, \ 170 .gate_shift = gs, \ 171 .gate_flags = gf, \ 172 } 173 174 #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \ 175 go, gs, gf) \ 176 { \ 177 .id = _id, \ 178 .branch_type = branch_composite, \ 179 .name = cname, \ 180 .parent_names = (const char *[]){ pname }, \ 181 .num_parents = 1, \ 182 .flags = f, \ 183 .muxdiv_offset = mo, \ 184 .div_shift = ds, \ 185 .div_width = dw, \ 186 .div_flags = df, \ 187 .gate_offset = go, \ 188 .gate_shift = gs, \ 189 .gate_flags = gf, \ 190 } 191 192 #define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\ 193 df, dt, go, gs, gf) \ 194 { \ 195 .id = _id, \ 196 .branch_type = branch_composite, \ 197 .name = cname, \ 198 .parent_names = (const char *[]){ pname }, \ 199 .num_parents = 1, \ 200 .flags = f, \ 201 .muxdiv_offset = mo, \ 202 .div_shift = ds, \ 203 .div_width = dw, \ 204 .div_flags = df, \ 205 .div_table = dt, \ 206 .gate_offset = go, \ 207 .gate_shift = gs, \ 208 .gate_flags = gf, \ 209 } 210 211 #define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \ 212 go, gs, gf) \ 213 { \ 214 .id = _id, \ 215 .branch_type = branch_composite, \ 216 .name = cname, \ 217 .parent_names = pnames, \ 218 .num_parents = ARRAY_SIZE(pnames), \ 219 .flags = f, \ 220 .muxdiv_offset = mo, \ 221 .mux_shift = ms, \ 222 .mux_width = mw, \ 223 .mux_flags = mf, \ 224 .gate_offset = go, \ 225 .gate_shift = gs, \ 226 .gate_flags = gf, \ 227 } 228 229 #define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \ 230 ds, dw, df) \ 231 { \ 232 .id = _id, \ 233 .branch_type = branch_composite, \ 234 .name = cname, \ 235 .parent_names = pnames, \ 236 .num_parents = ARRAY_SIZE(pnames), \ 237 .flags = f, \ 238 .muxdiv_offset = mo, \ 239 .mux_shift = ms, \ 240 .mux_width = mw, \ 241 .mux_flags = mf, \ 242 .div_shift = ds, \ 243 .div_width = dw, \ 244 .div_flags = df, \ 245 .gate_offset = -1, \ 246 } 247 248 #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\ 249 { \ 250 .id = _id, \ 251 .branch_type = branch_fraction_divider, \ 252 .name = cname, \ 253 .parent_names = (const char *[]){ pname }, \ 254 .num_parents = 1, \ 255 .flags = f, \ 256 .muxdiv_offset = mo, \ 257 .div_shift = 16, \ 258 .div_width = 16, \ 259 .div_flags = df, \ 260 .gate_offset = go, \ 261 .gate_shift = gs, \ 262 .gate_flags = gf, \ 263 } 264 265 #define MUX(_id, cname, pnames, f, o, s, w, mf) \ 266 { \ 267 .id = _id, \ 268 .branch_type = branch_mux, \ 269 .name = cname, \ 270 .parent_names = pnames, \ 271 .num_parents = ARRAY_SIZE(pnames), \ 272 .flags = f, \ 273 .muxdiv_offset = o, \ 274 .mux_shift = s, \ 275 .mux_width = w, \ 276 .mux_flags = mf, \ 277 .gate_offset = -1, \ 278 } 279 280 #define DIV(_id, cname, pname, f, o, s, w, df) \ 281 { \ 282 .id = _id, \ 283 .branch_type = branch_divider, \ 284 .name = cname, \ 285 .parent_names = (const char *[]){ pname }, \ 286 .num_parents = 1, \ 287 .flags = f, \ 288 .muxdiv_offset = o, \ 289 .div_shift = s, \ 290 .div_width = w, \ 291 .div_flags = df, \ 292 .gate_offset = -1, \ 293 } 294 295 #define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \ 296 { \ 297 .id = _id, \ 298 .branch_type = branch_divider, \ 299 .name = cname, \ 300 .parent_names = (const char *[]){ pname }, \ 301 .num_parents = 1, \ 302 .flags = f, \ 303 .muxdiv_offset = o, \ 304 .div_shift = s, \ 305 .div_width = w, \ 306 .div_flags = df, \ 307 .div_table = dt, \ 308 } 309 310 #define GATE(_id, cname, pname, f, o, b, gf) \ 311 { \ 312 .id = _id, \ 313 .branch_type = branch_gate, \ 314 .name = cname, \ 315 .parent_names = (const char *[]){ pname }, \ 316 .num_parents = 1, \ 317 .flags = f, \ 318 .gate_offset = o, \ 319 .gate_shift = b, \ 320 .gate_flags = gf, \ 321 } 322 323 324 void rockchip_clk_init(struct device_node *np, void __iomem *base, 325 unsigned long nr_clks); 326 struct regmap *rockchip_clk_get_grf(void); 327 void rockchip_clk_add_lookup(struct clk *clk, unsigned int id); 328 void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list, 329 unsigned int nr_clk); 330 void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, 331 unsigned int nr_pll, int grf_lock_offset); 332 333 #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) 334 335 #ifdef CONFIG_RESET_CONTROLLER 336 void rockchip_register_softrst(struct device_node *np, 337 unsigned int num_regs, 338 void __iomem *base, u8 flags); 339 #else 340 static inline void rockchip_register_softrst(struct device_node *np, 341 unsigned int num_regs, 342 void __iomem *base, u8 flags) 343 { 344 } 345 #endif 346 347 #endif 348