Merge tag 'devicetree-fixes-for-6.2-3' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / drivers / clk / sunxi-ng / ccu_div.h
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (c) 2016 Maxime Ripard. All rights reserved.
4  */
5
6 #ifndef _CCU_DIV_H_
7 #define _CCU_DIV_H_
8
9 #include <linux/clk-provider.h>
10
11 #include "ccu_common.h"
12 #include "ccu_mux.h"
13
14 /**
15  * struct ccu_div_internal - Internal divider description
16  * @shift: Bit offset of the divider in its register
17  * @width: Width of the divider field in its register
18  * @max: Maximum value allowed for that divider. This is the
19  *       arithmetic value, not the maximum value to be set in the
20  *       register.
21  * @flags: clk_divider flags to apply on this divider
22  * @table: Divider table pointer (if applicable)
23  *
24  * That structure represents a single divider, and is meant to be
25  * embedded in other structures representing the various clock
26  * classes.
27  *
28  * It is basically a wrapper around the clk_divider functions
29  * arguments.
30  */
31 struct ccu_div_internal {
32         u8                      shift;
33         u8                      width;
34
35         u32                     max;
36         u32                     offset;
37
38         u32                     flags;
39
40         struct clk_div_table    *table;
41 };
42
43 #define _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, _flags)      \
44         {                                                               \
45                 .shift  = _shift,                                       \
46                 .width  = _width,                                       \
47                 .flags  = _flags,                                       \
48                 .table  = _table,                                       \
49         }
50
51 #define _SUNXI_CCU_DIV_TABLE(_shift, _width, _table)                    \
52         _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, 0)
53
54 #define _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _off, _max, _flags) \
55         {                                                               \
56                 .shift  = _shift,                                       \
57                 .width  = _width,                                       \
58                 .flags  = _flags,                                       \
59                 .max    = _max,                                         \
60                 .offset = _off,                                         \
61         }
62
63 #define _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, _flags)          \
64         _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, 1, _max, _flags)
65
66 #define _SUNXI_CCU_DIV_FLAGS(_shift, _width, _flags)                    \
67         _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, 0, _flags)
68
69 #define _SUNXI_CCU_DIV_MAX(_shift, _width, _max)                        \
70         _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, 0)
71
72 #define _SUNXI_CCU_DIV_OFFSET(_shift, _width, _offset)                  \
73         _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _offset, 0, 0)
74
75 #define _SUNXI_CCU_DIV(_shift, _width)                                  \
76         _SUNXI_CCU_DIV_FLAGS(_shift, _width, 0)
77
78 struct ccu_div {
79         u32                     enable;
80
81         struct ccu_div_internal div;
82         struct ccu_mux_internal mux;
83         struct ccu_common       common;
84         unsigned int            fixed_post_div;
85 };
86
87 #define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,    \
88                                       _shift, _width,                   \
89                                       _table, _gate, _flags)            \
90         struct ccu_div _struct = {                                      \
91                 .div            = _SUNXI_CCU_DIV_TABLE(_shift, _width,  \
92                                                        _table),         \
93                 .enable         = _gate,                                \
94                 .common = {                                             \
95                         .reg            = _reg,                         \
96                         .hw.init        = CLK_HW_INIT(_name,            \
97                                                       _parent,          \
98                                                       &ccu_div_ops,     \
99                                                       _flags),          \
100                 }                                                       \
101         }
102
103
104 #define SUNXI_CCU_DIV_TABLE(_struct, _name, _parent, _reg,              \
105                             _shift, _width,                             \
106                             _table, _flags)                             \
107         SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,    \
108                                       _shift, _width, _table, 0,        \
109                                       _flags)
110
111 #define SUNXI_CCU_DIV_TABLE_HW(_struct, _name, _parent, _reg,           \
112                                _shift, _width,                          \
113                                _table, _flags)                          \
114         struct ccu_div _struct = {                                      \
115                 .div            = _SUNXI_CCU_DIV_TABLE(_shift, _width,  \
116                                                        _table),         \
117                 .common = {                                             \
118                         .reg            = _reg,                         \
119                         .hw.init        = CLK_HW_INIT_HW(_name,         \
120                                                          _parent,       \
121                                                          &ccu_div_ops,  \
122                                                          _flags),       \
123                 }                                                       \
124         }
125
126
127 #define SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,                 \
128                                         _parents, _table,               \
129                                         _reg,                           \
130                                         _mshift, _mwidth,               \
131                                         _muxshift, _muxwidth,           \
132                                         _gate, _flags)                  \
133         struct ccu_div _struct = {                                      \
134                 .enable = _gate,                                        \
135                 .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
136                 .mux    = _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, _table), \
137                 .common = {                                             \
138                         .reg            = _reg,                         \
139                         .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
140                                                               _parents, \
141                                                               &ccu_div_ops, \
142                                                               _flags),  \
143                 },                                                      \
144         }
145
146 #define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg,       \
147                                   _mshift, _mwidth, _muxshift, _muxwidth, \
148                                   _gate, _flags)                        \
149         SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,                 \
150                                         _parents, NULL,                 \
151                                         _reg, _mshift, _mwidth,         \
152                                         _muxshift, _muxwidth,           \
153                                         _gate, _flags)
154
155 #define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg,            \
156                              _mshift, _mwidth, _muxshift, _muxwidth,    \
157                              _flags)                                    \
158         SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name,                 \
159                                         _parents, NULL,                 \
160                                         _reg, _mshift, _mwidth,         \
161                                         _muxshift, _muxwidth,           \
162                                         0, _flags)
163
164
165 #define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,            \
166                               _mshift, _mwidth, _gate,                  \
167                               _flags)                                   \
168         struct ccu_div _struct = {                                      \
169                 .enable = _gate,                                        \
170                 .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
171                 .common = {                                             \
172                         .reg            = _reg,                         \
173                         .hw.init        = CLK_HW_INIT(_name,            \
174                                                       _parent,          \
175                                                       &ccu_div_ops,     \
176                                                       _flags),          \
177                 },                                                      \
178         }
179
180 #define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth,    \
181                     _flags)                                             \
182         SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,            \
183                               _mshift, _mwidth, 0, _flags)
184
185 #define SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg,  \
186                                        _mshift, _mwidth,                \
187                                        _muxshift, _muxwidth,            \
188                                        _gate, _flags)                   \
189         struct ccu_div _struct = {                                      \
190                 .enable = _gate,                                        \
191                 .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
192                 .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),         \
193                 .common = {                                             \
194                         .reg            = _reg,                         \
195                         .hw.init        = CLK_HW_INIT_PARENTS_DATA(_name, \
196                                                                    _parents, \
197                                                                    &ccu_div_ops, \
198                                                                    _flags), \
199                 },                                                      \
200         }
201
202 #define SUNXI_CCU_M_DATA_WITH_MUX(_struct, _name, _parents, _reg,       \
203                                   _mshift, _mwidth,                     \
204                                   _muxshift, _muxwidth,                 \
205                                   _flags)                               \
206         SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg,  \
207                                        _mshift, _mwidth,                \
208                                        _muxshift, _muxwidth,            \
209                                        0, _flags)
210
211 #define SUNXI_CCU_M_HW_WITH_MUX_GATE(_struct, _name, _parents, _reg,    \
212                                      _mshift, _mwidth, _muxshift, _muxwidth, \
213                                      _gate, _flags)                     \
214         struct ccu_div _struct = {                                      \
215                 .enable = _gate,                                        \
216                 .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
217                 .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),         \
218                 .common = {                                             \
219                         .reg            = _reg,                         \
220                         .hw.init        = CLK_HW_INIT_PARENTS_HW(_name, \
221                                                                  _parents, \
222                                                                  &ccu_div_ops, \
223                                                                  _flags), \
224                 },                                                      \
225         }
226
227 #define SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg,        \
228                                   _mshift, _mwidth, _gate,              \
229                                   _flags)                               \
230         struct ccu_div _struct = {                                      \
231                 .enable = _gate,                                        \
232                 .div    = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
233                 .common = {                                             \
234                         .reg            = _reg,                         \
235                         .hw.init        = CLK_HW_INIT_HWS(_name,        \
236                                                           _parent,      \
237                                                           &ccu_div_ops, \
238                                                           _flags),      \
239                 },                                                      \
240         }
241
242 #define SUNXI_CCU_M_HWS(_struct, _name, _parent, _reg, _mshift,         \
243                         _mwidth, _flags)                                \
244         SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg,        \
245                                   _mshift, _mwidth, 0, _flags)
246
247 static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
248 {
249         struct ccu_common *common = hw_to_ccu_common(hw);
250
251         return container_of(common, struct ccu_div, common);
252 }
253
254 extern const struct clk_ops ccu_div_ops;
255
256 #endif /* _CCU_DIV_H_ */