GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / clk / sunxi-ng / ccu_mp.h
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (c) 2016 Maxime Ripard. All rights reserved.
4  */
5
6 #ifndef _CCU_MP_H_
7 #define _CCU_MP_H_
8
9 #include <linux/bitops.h>
10 #include <linux/clk-provider.h>
11
12 #include "ccu_common.h"
13 #include "ccu_div.h"
14 #include "ccu_mult.h"
15 #include "ccu_mux.h"
16
17 /*
18  * struct ccu_mp - Definition of an M-P clock
19  *
20  * Clocks based on the formula parent >> P / M
21  */
22 struct ccu_mp {
23         u32                     enable;
24
25         struct ccu_div_internal         m;
26         struct ccu_div_internal         p;
27         struct ccu_mux_internal mux;
28
29         unsigned int            fixed_post_div;
30
31         struct ccu_common       common;
32 };
33
34 #define SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(_struct, _name, _parents, _reg, \
35                                            _mshift, _mwidth,            \
36                                            _pshift, _pwidth,            \
37                                            _muxshift, _muxwidth,        \
38                                            _gate, _postdiv, _flags)     \
39         struct ccu_mp _struct = {                                       \
40                 .enable = _gate,                                        \
41                 .m      = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
42                 .p      = _SUNXI_CCU_DIV(_pshift, _pwidth),             \
43                 .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),         \
44                 .fixed_post_div = _postdiv,                             \
45                 .common = {                                             \
46                         .reg            = _reg,                         \
47                         .features       = CCU_FEATURE_FIXED_POSTDIV,    \
48                         .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
49                                                               _parents, \
50                                                               &ccu_mp_ops, \
51                                                               _flags),  \
52                 }                                                       \
53         }
54
55 #define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,      \
56                                    _mshift, _mwidth,                    \
57                                    _pshift, _pwidth,                    \
58                                    _muxshift, _muxwidth,                \
59                                    _gate, _flags)                       \
60         struct ccu_mp _struct = {                                       \
61                 .enable = _gate,                                        \
62                 .m      = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
63                 .p      = _SUNXI_CCU_DIV(_pshift, _pwidth),             \
64                 .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),         \
65                 .common = {                                             \
66                         .reg            = _reg,                         \
67                         .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
68                                                               _parents, \
69                                                               &ccu_mp_ops, \
70                                                               _flags),  \
71                 }                                                       \
72         }
73
74 #define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg,           \
75                               _mshift, _mwidth,                         \
76                               _pshift, _pwidth,                         \
77                               _muxshift, _muxwidth,                     \
78                               _flags)                                   \
79         SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,      \
80                                    _mshift, _mwidth,                    \
81                                    _pshift, _pwidth,                    \
82                                    _muxshift, _muxwidth,                \
83                                    0, _flags)
84
85 #define SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
86                                         _mshift, _mwidth,               \
87                                         _pshift, _pwidth,               \
88                                         _muxshift, _muxwidth,           \
89                                         _gate, _flags)                  \
90         struct ccu_mp _struct = {                                       \
91                 .enable = _gate,                                        \
92                 .m      = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
93                 .p      = _SUNXI_CCU_DIV(_pshift, _pwidth),             \
94                 .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),         \
95                 .common = {                                             \
96                         .reg            = _reg,                         \
97                         .hw.init        = CLK_HW_INIT_PARENTS_DATA(_name, \
98                                                                    _parents, \
99                                                                    &ccu_mp_ops, \
100                                                                    _flags), \
101                 }                                                       \
102         }
103
104 #define SUNXI_CCU_MP_DATA_WITH_MUX(_struct, _name, _parents, _reg,      \
105                                    _mshift, _mwidth,                    \
106                                    _pshift, _pwidth,                    \
107                                    _muxshift, _muxwidth,                \
108                                    _flags)                              \
109         SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
110                                         _mshift, _mwidth,               \
111                                         _pshift, _pwidth,               \
112                                         _muxshift, _muxwidth,           \
113                                         0, _flags)
114
115 #define SUNXI_CCU_MP_HW_WITH_MUX_GATE(_struct, _name, _parents, _reg,   \
116                                       _mshift, _mwidth,                 \
117                                       _pshift, _pwidth,                 \
118                                       _muxshift, _muxwidth,             \
119                                       _gate, _flags)                    \
120         struct ccu_mp _struct = {                                       \
121                 .enable = _gate,                                        \
122                 .m      = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
123                 .p      = _SUNXI_CCU_DIV(_pshift, _pwidth),             \
124                 .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),         \
125                 .common = {                                             \
126                         .reg            = _reg,                         \
127                         .hw.init        = CLK_HW_INIT_PARENTS_HW(_name, \
128                                                                  _parents, \
129                                                                  &ccu_mp_ops, \
130                                                                  _flags), \
131                 }                                                       \
132         }
133
134 static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw)
135 {
136         struct ccu_common *common = hw_to_ccu_common(hw);
137
138         return container_of(common, struct ccu_mp, common);
139 }
140
141 extern const struct clk_ops ccu_mp_ops;
142
143 /*
144  * Special class of M-P clock that supports MMC timing modes
145  *
146  * Since the MMC clock registers all follow the same layout, we can
147  * simplify the macro for this particular case. In addition, as
148  * switching modes also affects the output clock rate, we need to
149  * have CLK_GET_RATE_NOCACHE for all these types of clocks.
150  */
151
152 #define SUNXI_CCU_MP_MMC_WITH_MUX_GATE(_struct, _name, _parents, _reg,  \
153                                        _flags)                          \
154         struct ccu_mp _struct = {                                       \
155                 .enable = BIT(31),                                      \
156                 .m      = _SUNXI_CCU_DIV(0, 4),                         \
157                 .p      = _SUNXI_CCU_DIV(16, 2),                        \
158                 .mux    = _SUNXI_CCU_MUX(24, 2),                        \
159                 .common = {                                             \
160                         .reg            = _reg,                         \
161                         .features       = CCU_FEATURE_MMC_TIMING_SWITCH, \
162                         .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
163                                                               _parents, \
164                                                               &ccu_mp_mmc_ops, \
165                                                               CLK_GET_RATE_NOCACHE | \
166                                                               _flags),  \
167                 }                                                       \
168         }
169
170 extern const struct clk_ops ccu_mp_mmc_ops;
171
172 #endif /* _CCU_MP_H_ */