GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / clk / sunxi-ng / ccu_mp.h
1 /*
2  * Copyright (c) 2016 Maxime Ripard. All rights reserved.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #ifndef _CCU_MP_H_
15 #define _CCU_MP_H_
16
17 #include <linux/bitops.h>
18 #include <linux/clk-provider.h>
19
20 #include "ccu_common.h"
21 #include "ccu_div.h"
22 #include "ccu_mult.h"
23 #include "ccu_mux.h"
24
25 /*
26  * struct ccu_mp - Definition of an M-P clock
27  *
28  * Clocks based on the formula parent >> P / M
29  */
30 struct ccu_mp {
31         u32                     enable;
32
33         struct ccu_div_internal         m;
34         struct ccu_div_internal         p;
35         struct ccu_mux_internal mux;
36
37         unsigned int            fixed_post_div;
38
39         struct ccu_common       common;
40 };
41
42 #define SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(_struct, _name, _parents, _reg, \
43                                            _mshift, _mwidth,            \
44                                            _pshift, _pwidth,            \
45                                            _muxshift, _muxwidth,        \
46                                            _gate, _postdiv, _flags)     \
47         struct ccu_mp _struct = {                                       \
48                 .enable = _gate,                                        \
49                 .m      = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
50                 .p      = _SUNXI_CCU_DIV(_pshift, _pwidth),             \
51                 .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),         \
52                 .fixed_post_div = _postdiv,                             \
53                 .common = {                                             \
54                         .reg            = _reg,                         \
55                         .features       = CCU_FEATURE_FIXED_POSTDIV,    \
56                         .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
57                                                               _parents, \
58                                                               &ccu_mp_ops, \
59                                                               _flags),  \
60                 }                                                       \
61         }
62
63 #define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,      \
64                                    _mshift, _mwidth,                    \
65                                    _pshift, _pwidth,                    \
66                                    _muxshift, _muxwidth,                \
67                                    _gate, _flags)                       \
68         struct ccu_mp _struct = {                                       \
69                 .enable = _gate,                                        \
70                 .m      = _SUNXI_CCU_DIV(_mshift, _mwidth),             \
71                 .p      = _SUNXI_CCU_DIV(_pshift, _pwidth),             \
72                 .mux    = _SUNXI_CCU_MUX(_muxshift, _muxwidth),         \
73                 .common = {                                             \
74                         .reg            = _reg,                         \
75                         .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
76                                                               _parents, \
77                                                               &ccu_mp_ops, \
78                                                               _flags),  \
79                 }                                                       \
80         }
81
82 #define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg,           \
83                               _mshift, _mwidth,                         \
84                               _pshift, _pwidth,                         \
85                               _muxshift, _muxwidth,                     \
86                               _flags)                                   \
87         SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,      \
88                                    _mshift, _mwidth,                    \
89                                    _pshift, _pwidth,                    \
90                                    _muxshift, _muxwidth,                \
91                                    0, _flags)
92
93 static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw)
94 {
95         struct ccu_common *common = hw_to_ccu_common(hw);
96
97         return container_of(common, struct ccu_mp, common);
98 }
99
100 extern const struct clk_ops ccu_mp_ops;
101
102 /*
103  * Special class of M-P clock that supports MMC timing modes
104  *
105  * Since the MMC clock registers all follow the same layout, we can
106  * simplify the macro for this particular case. In addition, as
107  * switching modes also affects the output clock rate, we need to
108  * have CLK_GET_RATE_NOCACHE for all these types of clocks.
109  */
110
111 #define SUNXI_CCU_MP_MMC_WITH_MUX_GATE(_struct, _name, _parents, _reg,  \
112                                        _flags)                          \
113         struct ccu_mp _struct = {                                       \
114                 .enable = BIT(31),                                      \
115                 .m      = _SUNXI_CCU_DIV(0, 4),                         \
116                 .p      = _SUNXI_CCU_DIV(16, 2),                        \
117                 .mux    = _SUNXI_CCU_MUX(24, 2),                        \
118                 .common = {                                             \
119                         .reg            = _reg,                         \
120                         .features       = CCU_FEATURE_MMC_TIMING_SWITCH, \
121                         .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
122                                                               _parents, \
123                                                               &ccu_mp_mmc_ops, \
124                                                               CLK_GET_RATE_NOCACHE | \
125                                                               _flags),  \
126                 }                                                       \
127         }
128
129 extern const struct clk_ops ccu_mp_mmc_ops;
130
131 #endif /* _CCU_MP_H_ */