1 /* 2 * Copyright (c) 2017 Rockchip Electronics Co. Ltd. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15 #ifndef __CLK_REGMAP_H__ 16 #define __CLK_REGMAP_H__ 17 18 #include <linux/regmap.h> 19 #include <linux/kernel.h> 20 #include <linux/module.h> 21 #include <linux/platform_device.h> 22 #include <linux/clk-provider.h> 23 #include <linux/device.h> 24 #include <linux/delay.h> 25 26 #define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l))) 27 #define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK((h), (l)) << 16)) 28 29 struct clk_pll_data { 30 unsigned int id; 31 const char *name; 32 const char *parent_name; 33 u32 reg; 34 u8 pd_shift; 35 u8 dsmpd_shift; 36 u8 lock_shift; 37 unsigned long flags; 38 }; 39 40 #define PLL(_id, _name, _parent_name, _reg, _pd_shift, _dsmpd_shift, \ 41 _lock_shift, _flags) \ 42 { \ 43 .id = _id, \ 44 .name = _name, \ 45 .parent_name = _parent_name, \ 46 .reg = _reg, \ 47 .pd_shift = _pd_shift, \ 48 .dsmpd_shift = _dsmpd_shift, \ 49 .lock_shift = _lock_shift, \ 50 .flags = _flags, \ 51 } 52 53 #define RK618_PLL(_id, _name, _parent_name, _reg, _flags) \ 54 PLL(_id, _name, _parent_name, _reg, 10, 9, 15, _flags) 55 56 struct clk_mux_data { 57 unsigned int id; 58 const char *name; 59 const char *const *parent_names; 60 u8 num_parents; 61 u32 reg; 62 u8 shift; 63 u8 width; 64 unsigned long flags; 65 }; 66 67 #define MUX(_id, _name, _parent_names, _reg, _shift, _width, _flags) \ 68 { \ 69 .id = _id, \ 70 .name = _name, \ 71 .parent_names = _parent_names, \ 72 .num_parents = ARRAY_SIZE(_parent_names), \ 73 .reg = _reg, \ 74 .shift = _shift, \ 75 .width = _width, \ 76 .flags = _flags, \ 77 } 78 79 struct clk_gate_data { 80 unsigned int id; 81 const char *name; 82 const char *parent_name; 83 u32 reg; 84 u8 shift; 85 unsigned long flags; 86 }; 87 88 #define GATE(_id, _name, _parent_name, _reg, _shift, _flags) \ 89 { \ 90 .id = _id, \ 91 .name = _name, \ 92 .parent_name = _parent_name, \ 93 .reg = _reg, \ 94 .shift = _shift, \ 95 .flags = _flags, \ 96 } 97 98 struct clk_divider_data { 99 unsigned int id; 100 const char *name; 101 const char *parent_name; 102 u32 reg; 103 u8 shift; 104 u8 width; 105 unsigned long flags; 106 }; 107 108 #define DIV(_id, _name, _parent_name, _reg, _shift, _width, _flags) \ 109 { \ 110 .id = _id, \ 111 .name = _name, \ 112 .parent_name = _parent_name, \ 113 .reg = _reg, \ 114 .shift = _shift, \ 115 .width = _width, \ 116 .flags = _flags, \ 117 } 118 119 struct clk_composite_data { 120 unsigned int id; 121 const char *name; 122 const char *const *parent_names; 123 u8 num_parents; 124 u32 mux_reg; 125 u8 mux_shift; 126 u8 mux_width; 127 u32 div_reg; 128 u8 div_shift; 129 u8 div_width; 130 u8 div_flags; 131 u32 gate_reg; 132 u8 gate_shift; 133 unsigned long flags; 134 }; 135 136 #define COMPOSITE(_id, _name, _parent_names, \ 137 _mux_reg, _mux_shift, _mux_width, \ 138 _div_reg, _div_shift, _div_width, \ 139 _gate_reg, _gate_shift, _flags) \ 140 { \ 141 .id = _id, \ 142 .name = _name, \ 143 .parent_names = _parent_names, \ 144 .num_parents = ARRAY_SIZE(_parent_names), \ 145 .mux_reg = _mux_reg, \ 146 .mux_shift = _mux_shift, \ 147 .mux_width = _mux_width, \ 148 .div_reg = _div_reg, \ 149 .div_shift = _div_shift, \ 150 .div_width = _div_width, \ 151 .div_flags = CLK_DIVIDER_HIWORD_MASK, \ 152 .gate_reg = _gate_reg, \ 153 .gate_shift = _gate_shift, \ 154 .flags = _flags, \ 155 } 156 157 #define COMPOSITE_NOMUX(_id, _name, _parent_name, \ 158 _div_reg, _div_shift, _div_width, \ 159 _gate_reg, _gate_shift, _flags) \ 160 { \ 161 .id = _id, \ 162 .name = _name, \ 163 .parent_names = (const char *[]){ _parent_name }, \ 164 .num_parents = 1, \ 165 .div_reg = _div_reg, \ 166 .div_shift = _div_shift, \ 167 .div_width = _div_width, \ 168 .div_flags = CLK_DIVIDER_HIWORD_MASK, \ 169 .gate_reg = _gate_reg, \ 170 .gate_shift = _gate_shift, \ 171 .flags = _flags, \ 172 } 173 174 #define COMPOSITE_NODIV(_id, _name, _parent_names, \ 175 _mux_reg, _mux_shift, _mux_width, \ 176 _gate_reg, _gate_shift, _flags) \ 177 COMPOSITE(_id, _name, _parent_names, \ 178 _mux_reg, _mux_shift, _mux_width, \ 179 0, 0, 0, \ 180 _gate_reg, _gate_shift, _flags) 181 182 #define COMPOSITE_FRAC(_id, _name, _parent_names, \ 183 _mux_reg, _mux_shift, _mux_width, \ 184 _div_reg, \ 185 _gate_reg, _gate_shift, _flags) \ 186 { \ 187 .id = _id, \ 188 .name = _name, \ 189 .parent_names = _parent_names, \ 190 .num_parents = ARRAY_SIZE(_parent_names), \ 191 .mux_reg = _mux_reg, \ 192 .mux_shift = _mux_shift, \ 193 .mux_width = _mux_width, \ 194 .div_reg = _div_reg, \ 195 .gate_reg = _gate_reg, \ 196 .gate_shift = _gate_shift, \ 197 .flags = _flags, \ 198 } 199 200 #define COMPOSITE_FRAC_NOMUX(_id, _name, _parent_name, \ 201 _div_reg, \ 202 _gate_reg, _gate_shift, _flags) \ 203 { \ 204 .id = _id, \ 205 .name = _name, \ 206 .parent_names = (const char *[]){ _parent_name }, \ 207 .num_parents = 1, \ 208 .div_reg = _div_reg, \ 209 .gate_reg = _gate_reg, \ 210 .gate_shift = _gate_shift, \ 211 .flags = _flags, \ 212 } 213 214 #define COMPOSITE_FRAC_NOGATE(_id, _name, _parent_names, \ 215 _mux_reg, _mux_shift, _mux_width, \ 216 _div_reg, \ 217 _flags) \ 218 COMPOSITE_FRAC(_id, _name, _parent_names, \ 219 _mux_reg, _mux_shift, _mux_width, \ 220 _div_reg, 0, 0, _flags) 221 222 struct clk_regmap_fractional_divider { 223 struct clk_hw hw; 224 struct device *dev; 225 struct regmap *regmap; 226 u32 reg; 227 u8 mshift; 228 u8 mwidth; 229 u32 mmask; 230 u8 nshift; 231 u8 nwidth; 232 u32 nmask; 233 }; 234 235 struct clk_regmap_divider { 236 struct clk_hw hw; 237 struct device *dev; 238 struct regmap *regmap; 239 u32 reg; 240 u8 shift; 241 u8 width; 242 }; 243 244 struct clk_regmap_gate { 245 struct clk_hw hw; 246 struct device *dev; 247 struct regmap *regmap; 248 u32 reg; 249 u8 shift; 250 }; 251 252 struct clk_regmap_mux { 253 struct clk_hw hw; 254 struct device *dev; 255 struct regmap *regmap; 256 u32 reg; 257 u32 mask; 258 u8 shift; 259 }; 260 261 extern const struct clk_ops clk_regmap_mux_ops; 262 extern const struct clk_ops clk_regmap_divider_ops; 263 extern const struct clk_ops clk_regmap_gate_ops; 264 extern const struct clk_ops clk_regmap_fractional_divider_ops; 265 266 struct clk * 267 devm_clk_regmap_register_pll(struct device *dev, const char *name, 268 const char *parent_name, 269 struct regmap *regmap, u32 reg, u8 pd_shift, 270 u8 dsmpd_shift, u8 lock_shift, 271 unsigned long flags); 272 273 struct clk * 274 devm_clk_regmap_register_mux(struct device *dev, const char *name, 275 const char * const *parent_names, u8 num_parents, 276 struct regmap *regmap, u32 reg, u8 shift, u8 width, 277 unsigned long flags); 278 279 struct clk * 280 devm_clk_regmap_register_divider(struct device *dev, const char *name, 281 const char *parent_name, struct regmap *regmap, 282 u32 reg, u8 shift, u8 width, 283 unsigned long flags); 284 285 struct clk * 286 devm_clk_regmap_register_gate(struct device *dev, const char *name, 287 const char *parent_name, 288 struct regmap *regmap, u32 reg, u8 shift, 289 unsigned long flags); 290 291 struct clk * 292 devm_clk_regmap_register_fractional_divider(struct device *dev, 293 const char *name, 294 const char *parent_name, 295 struct regmap *regmap, 296 u32 reg, unsigned long flags); 297 298 struct clk * 299 devm_clk_regmap_register_composite(struct device *dev, const char *name, 300 const char *const *parent_names, 301 u8 num_parents, struct regmap *regmap, 302 u32 mux_reg, u8 mux_shift, u8 mux_width, 303 u32 div_reg, u8 div_shift, u8 div_width, 304 u8 div_flags, 305 u32 gate_reg, u8 gate_shift, 306 unsigned long flags); 307 308 #endif 309