1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Copyright (C) STMicroelectronics 2022 - All Rights Reserved |
4 | * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics. |
5 | */ |
6 | |
7 | #include <linux/clk-provider.h> |
8 | |
9 | struct stm32_rcc_match_data; |
10 | |
11 | struct stm32_mux_cfg { |
12 | u16 offset; |
13 | u8 shift; |
14 | u8 width; |
15 | u8 flags; |
16 | u32 *table; |
17 | u8 ready; |
18 | }; |
19 | |
20 | struct stm32_gate_cfg { |
21 | u16 offset; |
22 | u8 bit_idx; |
23 | u8 set_clr; |
24 | }; |
25 | |
26 | struct stm32_div_cfg { |
27 | u16 offset; |
28 | u8 shift; |
29 | u8 width; |
30 | u8 flags; |
31 | u8 ready; |
32 | const struct clk_div_table *table; |
33 | }; |
34 | |
35 | struct stm32_composite_cfg { |
36 | int mux; |
37 | int gate; |
38 | int div; |
39 | }; |
40 | |
41 | #define NO_ID 0xFFFFFFFF |
42 | |
43 | #define NO_STM32_MUX 0xFFFF |
44 | #define NO_STM32_DIV 0xFFFF |
45 | #define NO_STM32_GATE 0xFFFF |
46 | |
47 | struct clock_config { |
48 | unsigned long id; |
49 | int sec_id; |
50 | void *clock_cfg; |
51 | |
52 | struct clk_hw *(*func)(struct device *dev, |
53 | const struct stm32_rcc_match_data *data, |
54 | void __iomem *base, |
55 | spinlock_t *lock, |
56 | const struct clock_config *cfg); |
57 | }; |
58 | |
59 | struct clk_stm32_clock_data { |
60 | u16 *gate_cpt; |
61 | const struct stm32_gate_cfg *gates; |
62 | const struct stm32_mux_cfg *muxes; |
63 | const struct stm32_div_cfg *dividers; |
64 | struct clk_hw *(*is_multi_mux)(struct clk_hw *hw); |
65 | }; |
66 | |
67 | struct stm32_rcc_match_data { |
68 | struct clk_hw_onecell_data *hw_clks; |
69 | unsigned int num_clocks; |
70 | const struct clock_config *tab_clocks; |
71 | unsigned int maxbinding; |
72 | struct clk_stm32_clock_data *clock_data; |
73 | struct clk_stm32_reset_data *reset_data; |
74 | int (*check_security)(void __iomem *base, |
75 | const struct clock_config *cfg); |
76 | int (*multi_mux)(void __iomem *base, const struct clock_config *cfg); |
77 | }; |
78 | |
79 | int stm32_rcc_init(struct device *dev, const struct of_device_id *match_data, |
80 | void __iomem *base); |
81 | |
82 | /* MUX define */ |
83 | #define MUX_NO_RDY 0xFF |
84 | #define MUX_SAFE BIT(7) |
85 | |
86 | /* DIV define */ |
87 | #define DIV_NO_RDY 0xFF |
88 | |
89 | /* Definition of clock structure */ |
90 | struct clk_stm32_mux { |
91 | u16 mux_id; |
92 | struct clk_hw hw; |
93 | void __iomem *base; |
94 | struct clk_stm32_clock_data *clock_data; |
95 | spinlock_t *lock; /* spin lock */ |
96 | }; |
97 | |
98 | #define to_clk_stm32_mux(_hw) container_of(_hw, struct clk_stm32_mux, hw) |
99 | |
100 | struct clk_stm32_gate { |
101 | u16 gate_id; |
102 | struct clk_hw hw; |
103 | void __iomem *base; |
104 | struct clk_stm32_clock_data *clock_data; |
105 | spinlock_t *lock; /* spin lock */ |
106 | }; |
107 | |
108 | #define to_clk_stm32_gate(_hw) container_of(_hw, struct clk_stm32_gate, hw) |
109 | |
110 | struct clk_stm32_div { |
111 | u16 div_id; |
112 | struct clk_hw hw; |
113 | void __iomem *base; |
114 | struct clk_stm32_clock_data *clock_data; |
115 | spinlock_t *lock; /* spin lock */ |
116 | }; |
117 | |
118 | #define to_clk_stm32_divider(_hw) container_of(_hw, struct clk_stm32_div, hw) |
119 | |
120 | struct clk_stm32_composite { |
121 | u16 gate_id; |
122 | u16 mux_id; |
123 | u16 div_id; |
124 | struct clk_hw hw; |
125 | void __iomem *base; |
126 | struct clk_stm32_clock_data *clock_data; |
127 | spinlock_t *lock; /* spin lock */ |
128 | }; |
129 | |
130 | #define to_clk_stm32_composite(_hw) container_of(_hw, struct clk_stm32_composite, hw) |
131 | |
132 | /* Clock operators */ |
133 | extern const struct clk_ops clk_stm32_mux_ops; |
134 | extern const struct clk_ops clk_stm32_gate_ops; |
135 | extern const struct clk_ops clk_stm32_divider_ops; |
136 | extern const struct clk_ops clk_stm32_composite_ops; |
137 | |
138 | /* Clock registering */ |
139 | struct clk_hw *clk_stm32_mux_register(struct device *dev, |
140 | const struct stm32_rcc_match_data *data, |
141 | void __iomem *base, |
142 | spinlock_t *lock, |
143 | const struct clock_config *cfg); |
144 | |
145 | struct clk_hw *clk_stm32_gate_register(struct device *dev, |
146 | const struct stm32_rcc_match_data *data, |
147 | void __iomem *base, |
148 | spinlock_t *lock, |
149 | const struct clock_config *cfg); |
150 | |
151 | struct clk_hw *clk_stm32_div_register(struct device *dev, |
152 | const struct stm32_rcc_match_data *data, |
153 | void __iomem *base, |
154 | spinlock_t *lock, |
155 | const struct clock_config *cfg); |
156 | |
157 | struct clk_hw *clk_stm32_composite_register(struct device *dev, |
158 | const struct stm32_rcc_match_data *data, |
159 | void __iomem *base, |
160 | spinlock_t *lock, |
161 | const struct clock_config *cfg); |
162 | |
163 | #define STM32_CLOCK_CFG(_binding, _clk, _sec_id, _struct, _register)\ |
164 | {\ |
165 | .id = (_binding),\ |
166 | .sec_id = (_sec_id),\ |
167 | .clock_cfg = (_struct) {_clk},\ |
168 | .func = (_register),\ |
169 | } |
170 | |
171 | #define STM32_MUX_CFG(_binding, _clk, _sec_id)\ |
172 | STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_mux *,\ |
173 | &clk_stm32_mux_register) |
174 | |
175 | #define STM32_GATE_CFG(_binding, _clk, _sec_id)\ |
176 | STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_gate *,\ |
177 | &clk_stm32_gate_register) |
178 | |
179 | #define STM32_DIV_CFG(_binding, _clk, _sec_id)\ |
180 | STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_div *,\ |
181 | &clk_stm32_div_register) |
182 | |
183 | #define STM32_COMPOSITE_CFG(_binding, _clk, _sec_id)\ |
184 | STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_composite *,\ |
185 | &clk_stm32_composite_register) |
186 | |