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