Gabriel Fernandez | 1308d75 | 2020-03-11 11:30:34 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2022, STMicroelectronics - All Rights Reserved |
| 3 | * |
| 4 | * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause |
| 5 | */ |
| 6 | |
| 7 | #ifndef CLK_STM32_CORE_H |
| 8 | #define CLK_STM32_CORE_H |
| 9 | |
| 10 | struct mux_cfg { |
| 11 | uint16_t offset; |
| 12 | uint8_t shift; |
| 13 | uint8_t width; |
| 14 | uint8_t bitrdy; |
| 15 | }; |
| 16 | |
| 17 | struct gate_cfg { |
| 18 | uint16_t offset; |
| 19 | uint8_t bit_idx; |
| 20 | uint8_t set_clr; |
| 21 | }; |
| 22 | |
| 23 | struct clk_div_table { |
| 24 | unsigned int val; |
| 25 | unsigned int div; |
| 26 | }; |
| 27 | |
| 28 | struct div_cfg { |
| 29 | uint16_t offset; |
| 30 | uint8_t shift; |
| 31 | uint8_t width; |
| 32 | uint8_t flags; |
| 33 | uint8_t bitrdy; |
| 34 | const struct clk_div_table *table; |
| 35 | }; |
| 36 | |
| 37 | struct parent_cfg { |
| 38 | uint8_t num_parents; |
| 39 | const uint16_t *id_parents; |
| 40 | struct mux_cfg *mux; |
| 41 | }; |
| 42 | |
| 43 | struct stm32_clk_priv; |
| 44 | |
| 45 | struct stm32_clk_ops { |
| 46 | unsigned long (*recalc_rate)(struct stm32_clk_priv *priv, int id, unsigned long rate); |
| 47 | int (*get_parent)(struct stm32_clk_priv *priv, int id); |
| 48 | int (*set_rate)(struct stm32_clk_priv *priv, int id, unsigned long rate, |
| 49 | unsigned long prate); |
| 50 | int (*enable)(struct stm32_clk_priv *priv, int id); |
| 51 | void (*disable)(struct stm32_clk_priv *priv, int id); |
| 52 | bool (*is_enabled)(struct stm32_clk_priv *priv, int id); |
| 53 | void (*init)(struct stm32_clk_priv *priv, int id); |
| 54 | }; |
| 55 | |
| 56 | struct clk_stm32 { |
| 57 | const char *name; |
| 58 | uint16_t binding; |
| 59 | uint16_t parent; |
| 60 | uint8_t flags; |
| 61 | void *clock_cfg; |
| 62 | const struct stm32_clk_ops *ops; |
| 63 | }; |
| 64 | |
| 65 | struct stm32_clk_priv { |
| 66 | uintptr_t base; |
| 67 | const uint32_t num; |
| 68 | const struct clk_stm32 *clks; |
| 69 | const struct parent_cfg *parents; |
| 70 | const uint32_t nb_parents; |
| 71 | const struct gate_cfg *gates; |
| 72 | const uint32_t nb_gates; |
| 73 | const struct div_cfg *div; |
| 74 | const uint32_t nb_div; |
| 75 | struct clk_oscillator_data *osci_data; |
| 76 | const uint32_t nb_osci_data; |
| 77 | uint32_t *gate_refcounts; |
| 78 | void *pdata; |
| 79 | }; |
| 80 | |
| 81 | struct stm32_clk_bypass { |
| 82 | uint16_t offset; |
| 83 | uint8_t bit_byp; |
| 84 | uint8_t bit_digbyp; |
| 85 | }; |
| 86 | |
| 87 | struct stm32_clk_css { |
| 88 | uint16_t offset; |
| 89 | uint8_t bit_css; |
| 90 | }; |
| 91 | |
| 92 | struct stm32_clk_drive { |
| 93 | uint16_t offset; |
| 94 | uint8_t drv_shift; |
| 95 | uint8_t drv_width; |
| 96 | uint8_t drv_default; |
| 97 | }; |
| 98 | |
| 99 | struct clk_oscillator_data { |
| 100 | const char *name; |
| 101 | uint16_t id_clk; |
| 102 | unsigned long frequency; |
| 103 | uint16_t gate_id; |
| 104 | uint16_t gate_rdy_id; |
| 105 | struct stm32_clk_bypass *bypass; |
| 106 | struct stm32_clk_css *css; |
| 107 | struct stm32_clk_drive *drive; |
| 108 | }; |
| 109 | |
| 110 | struct clk_fixed_rate { |
| 111 | const char *name; |
| 112 | unsigned long fixed_rate; |
| 113 | }; |
| 114 | |
| 115 | struct clk_gate_cfg { |
| 116 | uint32_t offset; |
| 117 | uint8_t bit_idx; |
| 118 | }; |
| 119 | |
| 120 | /* CLOCK FLAGS */ |
| 121 | #define CLK_IS_CRITICAL BIT(0) |
| 122 | #define CLK_IGNORE_UNUSED BIT(1) |
| 123 | #define CLK_SET_RATE_PARENT BIT(2) |
| 124 | |
| 125 | #define CLK_DIVIDER_ONE_BASED BIT(0) |
| 126 | #define CLK_DIVIDER_POWER_OF_TWO BIT(1) |
| 127 | #define CLK_DIVIDER_ALLOW_ZERO BIT(2) |
| 128 | #define CLK_DIVIDER_HIWORD_MASK BIT(3) |
| 129 | #define CLK_DIVIDER_ROUND_CLOSEST BIT(4) |
| 130 | #define CLK_DIVIDER_READ_ONLY BIT(5) |
| 131 | #define CLK_DIVIDER_MAX_AT_ZERO BIT(6) |
| 132 | #define CLK_DIVIDER_BIG_ENDIAN BIT(7) |
| 133 | |
| 134 | #define MUX_MAX_PARENTS U(0x8000) |
| 135 | #define MUX_PARENT_MASK GENMASK(14, 0) |
| 136 | #define MUX_FLAG U(0x8000) |
| 137 | #define MUX(mux) ((mux) | MUX_FLAG) |
| 138 | |
| 139 | #define NO_GATE 0 |
| 140 | #define _NO_ID UINT16_MAX |
| 141 | #define CLK_IS_ROOT UINT16_MAX |
| 142 | #define MUX_NO_BIT_RDY UINT8_MAX |
| 143 | #define DIV_NO_BIT_RDY UINT8_MAX |
| 144 | |
| 145 | #define MASK_WIDTH_SHIFT(_width, _shift) \ |
| 146 | GENMASK(((_width) + (_shift) - 1U), (_shift)) |
| 147 | |
| 148 | int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base); |
| 149 | void clk_stm32_enable_critical_clocks(void); |
| 150 | |
| 151 | struct stm32_clk_priv *clk_stm32_get_priv(void); |
| 152 | |
| 153 | int clk_get_index(struct stm32_clk_priv *priv, unsigned long binding_id); |
| 154 | const struct clk_stm32 *_clk_get(struct stm32_clk_priv *priv, int id); |
| 155 | |
| 156 | void clk_oscillator_set_bypass(struct stm32_clk_priv *priv, int id, bool digbyp, bool bypass); |
| 157 | void clk_oscillator_set_drive(struct stm32_clk_priv *priv, int id, uint8_t lsedrv); |
| 158 | void clk_oscillator_set_css(struct stm32_clk_priv *priv, int id, bool css); |
| 159 | |
| 160 | int _clk_stm32_gate_wait_ready(struct stm32_clk_priv *priv, uint16_t gate_id, bool ready_on); |
| 161 | |
| 162 | int clk_oscillator_wait_ready(struct stm32_clk_priv *priv, int id, bool ready_on); |
| 163 | int clk_oscillator_wait_ready_on(struct stm32_clk_priv *priv, int id); |
| 164 | int clk_oscillator_wait_ready_off(struct stm32_clk_priv *priv, int id); |
| 165 | |
| 166 | const char *_clk_stm32_get_name(struct stm32_clk_priv *priv, int id); |
| 167 | const char *clk_stm32_get_name(struct stm32_clk_priv *priv, unsigned long binding_id); |
| 168 | int clk_stm32_get_counter(unsigned long binding_id); |
| 169 | |
| 170 | void _clk_stm32_gate_disable(struct stm32_clk_priv *priv, uint16_t gate_id); |
| 171 | int _clk_stm32_gate_enable(struct stm32_clk_priv *priv, uint16_t gate_id); |
| 172 | |
| 173 | int _clk_stm32_set_parent(struct stm32_clk_priv *priv, int id, int src_id); |
| 174 | int _clk_stm32_set_parent_by_index(struct stm32_clk_priv *priv, int clk, int sel); |
| 175 | |
| 176 | int _clk_stm32_get_parent(struct stm32_clk_priv *priv, int id); |
| 177 | int _clk_stm32_get_parent_by_index(struct stm32_clk_priv *priv, int clk_id, int idx); |
| 178 | int _clk_stm32_get_parent_index(struct stm32_clk_priv *priv, int clk_id); |
| 179 | |
| 180 | unsigned long _clk_stm32_get_rate(struct stm32_clk_priv *priv, int id); |
| 181 | unsigned long _clk_stm32_get_parent_rate(struct stm32_clk_priv *priv, int id); |
| 182 | |
| 183 | bool _stm32_clk_is_flags(struct stm32_clk_priv *priv, int id, uint8_t flag); |
| 184 | |
| 185 | int _clk_stm32_enable(struct stm32_clk_priv *priv, int id); |
| 186 | void _clk_stm32_disable(struct stm32_clk_priv *priv, int id); |
| 187 | |
| 188 | int clk_stm32_enable_call_ops(struct stm32_clk_priv *priv, uint16_t id); |
| 189 | void clk_stm32_disable_call_ops(struct stm32_clk_priv *priv, uint16_t id); |
| 190 | |
| 191 | bool _clk_stm32_is_enabled(struct stm32_clk_priv *priv, int id); |
| 192 | |
| 193 | int _clk_stm32_divider_set_rate(struct stm32_clk_priv *priv, int div_id, |
| 194 | unsigned long rate, unsigned long parent_rate); |
| 195 | |
| 196 | int clk_stm32_divider_set_rate(struct stm32_clk_priv *priv, int id, unsigned long rate, |
| 197 | unsigned long prate); |
| 198 | |
| 199 | unsigned long _clk_stm32_divider_recalc(struct stm32_clk_priv *priv, |
| 200 | int div_id, |
| 201 | unsigned long prate); |
| 202 | |
| 203 | unsigned long clk_stm32_divider_recalc(struct stm32_clk_priv *priv, int idx, |
| 204 | unsigned long prate); |
| 205 | |
| 206 | int clk_stm32_gate_enable(struct stm32_clk_priv *priv, int idx); |
| 207 | void clk_stm32_gate_disable(struct stm32_clk_priv *priv, int idx); |
| 208 | |
| 209 | bool _clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int gate_id); |
| 210 | bool clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int idx); |
| 211 | |
| 212 | uint32_t clk_stm32_div_get_value(struct stm32_clk_priv *priv, int div_id); |
| 213 | int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value); |
| 214 | int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel); |
| 215 | int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id); |
| 216 | |
| 217 | int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb); |
| 218 | |
| 219 | #ifdef CFG_STM32_CLK_DEBUG |
| 220 | void clk_stm32_display_clock_info(void); |
| 221 | #endif |
| 222 | |
| 223 | struct clk_stm32_div_cfg { |
| 224 | int id; |
| 225 | }; |
| 226 | |
| 227 | #define STM32_DIV(idx, _binding, _parent, _flags, _div_id) \ |
| 228 | [(idx)] = (struct clk_stm32){ \ |
| 229 | .name = #idx,\ |
| 230 | .binding = (_binding),\ |
| 231 | .parent = (_parent),\ |
| 232 | .flags = (_flags),\ |
| 233 | .clock_cfg = &(struct clk_stm32_div_cfg){\ |
| 234 | .id = (_div_id),\ |
| 235 | },\ |
| 236 | .ops = &clk_stm32_divider_ops,\ |
| 237 | } |
| 238 | |
| 239 | struct clk_stm32_gate_cfg { |
| 240 | int id; |
| 241 | }; |
| 242 | |
| 243 | #define STM32_GATE(idx, _binding, _parent, _flags, _gate_id) \ |
| 244 | [(idx)] = (struct clk_stm32){ \ |
| 245 | .name = #idx,\ |
| 246 | .binding = (_binding),\ |
| 247 | .parent = (_parent),\ |
| 248 | .flags = (_flags),\ |
| 249 | .clock_cfg = &(struct clk_stm32_gate_cfg){\ |
| 250 | .id = (_gate_id),\ |
| 251 | },\ |
| 252 | .ops = &clk_stm32_gate_ops,\ |
| 253 | } |
| 254 | |
| 255 | struct fixed_factor_cfg { |
| 256 | unsigned int mult; |
| 257 | unsigned int div; |
| 258 | }; |
| 259 | |
| 260 | unsigned long fixed_factor_recalc_rate(struct stm32_clk_priv *priv, |
| 261 | int _idx, unsigned long prate); |
| 262 | |
| 263 | #define FIXED_FACTOR(idx, _idx, _parent, _mult, _div) \ |
| 264 | [(idx)] = (struct clk_stm32){ \ |
| 265 | .name = #idx,\ |
| 266 | .binding = (_idx),\ |
| 267 | .parent = (_parent),\ |
| 268 | .clock_cfg = &(struct fixed_factor_cfg){\ |
| 269 | .mult = (_mult),\ |
| 270 | .div = (_div),\ |
| 271 | },\ |
| 272 | .ops = &clk_fixed_factor_ops,\ |
| 273 | } |
| 274 | |
| 275 | #define GATE(idx, _binding, _parent, _flags, _offset, _bit_idx) \ |
| 276 | [(idx)] = (struct clk_stm32){ \ |
| 277 | .name = #idx,\ |
| 278 | .binding = (_binding),\ |
| 279 | .parent = (_parent),\ |
| 280 | .flags = (_flags),\ |
| 281 | .clock_cfg = &(struct clk_gate_cfg){\ |
| 282 | .offset = (_offset),\ |
| 283 | .bit_idx = (_bit_idx),\ |
| 284 | },\ |
| 285 | .ops = &clk_gate_ops,\ |
| 286 | } |
| 287 | |
| 288 | #define STM32_MUX(idx, _binding, _mux_id, _flags) \ |
| 289 | [(idx)] = (struct clk_stm32){ \ |
| 290 | .name = #idx,\ |
| 291 | .binding = (_binding),\ |
| 292 | .parent = (MUX(_mux_id)),\ |
| 293 | .flags = (_flags),\ |
| 294 | .clock_cfg = NULL,\ |
| 295 | .ops = (&clk_mux_ops),\ |
| 296 | } |
| 297 | |
| 298 | struct clk_timer_cfg { |
| 299 | uint32_t apbdiv; |
| 300 | uint32_t timpre; |
| 301 | }; |
| 302 | |
| 303 | #define CK_TIMER(idx, _idx, _parent, _flags, _apbdiv, _timpre) \ |
| 304 | [(idx)] = (struct clk_stm32){ \ |
| 305 | .name = #idx,\ |
| 306 | .binding = (_idx),\ |
| 307 | .parent = (_parent),\ |
| 308 | .flags = (CLK_SET_RATE_PARENT | (_flags)),\ |
| 309 | .clock_cfg = &(struct clk_timer_cfg){\ |
| 310 | .apbdiv = (_apbdiv),\ |
| 311 | .timpre = (_timpre),\ |
| 312 | },\ |
| 313 | .ops = &clk_timer_ops,\ |
| 314 | } |
| 315 | |
| 316 | struct clk_stm32_fixed_rate_cfg { |
| 317 | unsigned long rate; |
| 318 | }; |
| 319 | |
| 320 | #define CLK_FIXED_RATE(idx, _binding, _rate) \ |
| 321 | [(idx)] = (struct clk_stm32){ \ |
| 322 | .name = #idx,\ |
| 323 | .binding = (_binding),\ |
| 324 | .parent = (CLK_IS_ROOT),\ |
| 325 | .clock_cfg = &(struct clk_stm32_fixed_rate_cfg){\ |
| 326 | .rate = (_rate),\ |
| 327 | },\ |
| 328 | .ops = &clk_stm32_fixed_rate_ops,\ |
| 329 | } |
| 330 | |
| 331 | #define BYPASS(_offset, _bit_byp, _bit_digbyp) &(struct stm32_clk_bypass){\ |
| 332 | .offset = (_offset),\ |
| 333 | .bit_byp = (_bit_byp),\ |
| 334 | .bit_digbyp = (_bit_digbyp),\ |
| 335 | } |
| 336 | |
| 337 | #define CSS(_offset, _bit_css) &(struct stm32_clk_css){\ |
| 338 | .offset = (_offset),\ |
| 339 | .bit_css = (_bit_css),\ |
| 340 | } |
| 341 | |
| 342 | #define DRIVE(_offset, _shift, _width, _default) &(struct stm32_clk_drive){\ |
| 343 | .offset = (_offset),\ |
| 344 | .drv_shift = (_shift),\ |
| 345 | .drv_width = (_width),\ |
| 346 | .drv_default = (_default),\ |
| 347 | } |
| 348 | |
| 349 | #define OSCILLATOR(idx_osc, _id, _name, _gate_id, _gate_rdy_id, _bypass, _css, _drive) \ |
| 350 | [(idx_osc)] = (struct clk_oscillator_data){\ |
| 351 | .name = (_name),\ |
| 352 | .id_clk = (_id),\ |
| 353 | .gate_id = (_gate_id),\ |
| 354 | .gate_rdy_id = (_gate_rdy_id),\ |
| 355 | .bypass = (_bypass),\ |
| 356 | .css = (_css),\ |
| 357 | .drive = (_drive),\ |
| 358 | } |
| 359 | |
| 360 | struct clk_oscillator_data *clk_oscillator_get_data(struct stm32_clk_priv *priv, int id); |
| 361 | |
| 362 | void clk_stm32_osc_init(struct stm32_clk_priv *priv, int id); |
| 363 | bool clk_stm32_osc_gate_is_enabled(struct stm32_clk_priv *priv, int id); |
| 364 | int clk_stm32_osc_gate_enable(struct stm32_clk_priv *priv, int id); |
| 365 | void clk_stm32_osc_gate_disable(struct stm32_clk_priv *priv, int id); |
| 366 | |
| 367 | struct stm32_osc_cfg { |
| 368 | int osc_id; |
| 369 | }; |
| 370 | |
| 371 | #define CLK_OSC(idx, _idx, _parent, _osc_id) \ |
| 372 | [(idx)] = (struct clk_stm32){ \ |
| 373 | .name = #idx,\ |
| 374 | .binding = (_idx),\ |
| 375 | .parent = (_parent),\ |
| 376 | .flags = CLK_IS_CRITICAL,\ |
| 377 | .clock_cfg = &(struct stm32_osc_cfg){\ |
| 378 | .osc_id = (_osc_id),\ |
| 379 | },\ |
| 380 | .ops = &clk_stm32_osc_ops,\ |
| 381 | } |
| 382 | |
| 383 | #define CLK_OSC_FIXED(idx, _idx, _parent, _osc_id) \ |
| 384 | [(idx)] = (struct clk_stm32){ \ |
| 385 | .name = #idx,\ |
| 386 | .binding = (_idx),\ |
| 387 | .parent = (_parent),\ |
| 388 | .flags = CLK_IS_CRITICAL,\ |
| 389 | .clock_cfg = &(struct stm32_osc_cfg){\ |
| 390 | .osc_id = (_osc_id),\ |
| 391 | },\ |
| 392 | .ops = &clk_stm32_osc_nogate_ops,\ |
| 393 | } |
| 394 | |
| 395 | extern const struct stm32_clk_ops clk_mux_ops; |
| 396 | extern const struct stm32_clk_ops clk_stm32_divider_ops; |
| 397 | extern const struct stm32_clk_ops clk_stm32_gate_ops; |
| 398 | extern const struct stm32_clk_ops clk_fixed_factor_ops; |
| 399 | extern const struct stm32_clk_ops clk_gate_ops; |
| 400 | extern const struct stm32_clk_ops clk_timer_ops; |
| 401 | extern const struct stm32_clk_ops clk_stm32_fixed_rate_ops; |
| 402 | extern const struct stm32_clk_ops clk_stm32_osc_ops; |
| 403 | extern const struct stm32_clk_ops clk_stm32_osc_nogate_ops; |
| 404 | |
| 405 | #endif /* CLK_STM32_CORE_H */ |