Linux-libre 5.3.12-gnu
[librecmc/linux-libre.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 static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw)
86 {
87         struct ccu_common *common = hw_to_ccu_common(hw);
88
89         return container_of(common, struct ccu_mp, common);
90 }
91
92 extern const struct clk_ops ccu_mp_ops;
93
94 /*
95  * Special class of M-P clock that supports MMC timing modes
96  *
97  * Since the MMC clock registers all follow the same layout, we can
98  * simplify the macro for this particular case. In addition, as
99  * switching modes also affects the output clock rate, we need to
100  * have CLK_GET_RATE_NOCACHE for all these types of clocks.
101  */
102
103 #define SUNXI_CCU_MP_MMC_WITH_MUX_GATE(_struct, _name, _parents, _reg,  \
104                                        _flags)                          \
105         struct ccu_mp _struct = {                                       \
106                 .enable = BIT(31),                                      \
107                 .m      = _SUNXI_CCU_DIV(0, 4),                         \
108                 .p      = _SUNXI_CCU_DIV(16, 2),                        \
109                 .mux    = _SUNXI_CCU_MUX(24, 2),                        \
110                 .common = {                                             \
111                         .reg            = _reg,                         \
112                         .features       = CCU_FEATURE_MMC_TIMING_SWITCH, \
113                         .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
114                                                               _parents, \
115                                                               &ccu_mp_mmc_ops, \
116                                                               CLK_GET_RATE_NOCACHE | \
117                                                               _flags),  \
118                 }                                                       \
119         }
120
121 extern const struct clk_ops ccu_mp_mmc_ops;
122
123 #endif /* _CCU_MP_H_ */