GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / clk / sunxi-ng / ccu_mux.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _CCU_MUX_H_
3 #define _CCU_MUX_H_
4
5 #include <linux/clk-provider.h>
6
7 #include "ccu_common.h"
8
9 struct ccu_mux_fixed_prediv {
10         u8      index;
11         u16     div;
12 };
13
14 struct ccu_mux_var_prediv {
15         u8      index;
16         u8      shift;
17         u8      width;
18 };
19
20 struct ccu_mux_internal {
21         u8              shift;
22         u8              width;
23         const u8        *table;
24
25         const struct ccu_mux_fixed_prediv       *fixed_predivs;
26         u8              n_predivs;
27
28         const struct ccu_mux_var_prediv         *var_predivs;
29         u8              n_var_predivs;
30 };
31
32 #define _SUNXI_CCU_MUX_TABLE(_shift, _width, _table)    \
33         {                                               \
34                 .shift  = _shift,                       \
35                 .width  = _width,                       \
36                 .table  = _table,                       \
37         }
38
39 #define _SUNXI_CCU_MUX(_shift, _width) \
40         _SUNXI_CCU_MUX_TABLE(_shift, _width, NULL)
41
42 struct ccu_mux {
43         u32                     enable;
44
45         struct ccu_mux_internal mux;
46         struct ccu_common       common;
47 };
48
49 #define SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents, _table,    \
50                                      _reg, _shift, _width, _gate,               \
51                                      _flags, _features)                         \
52         struct ccu_mux _struct = {                                              \
53                 .enable = _gate,                                                \
54                 .mux    = _SUNXI_CCU_MUX_TABLE(_shift, _width, _table),         \
55                 .common = {                                                     \
56                         .reg            = _reg,                                 \
57                         .hw.init        = CLK_HW_INIT_PARENTS(_name,            \
58                                                               _parents,         \
59                                                               &ccu_mux_ops,     \
60                                                               _flags),          \
61                         .features       = _features,                            \
62                 }                                                               \
63         }
64
65 #define SUNXI_CCU_MUX_TABLE_WITH_GATE_CLOSEST(_struct, _name, _parents, \
66                                               _table, _reg, _shift,     \
67                                               _width, _gate, _flags)    \
68         SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents,    \
69                                            _table, _reg, _shift,        \
70                                            _width, _gate, _flags,       \
71                                            CCU_FEATURE_CLOSEST_RATE)
72
73 #define SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, _table, \
74                                      _reg, _shift, _width, _gate,       \
75                                      _flags)                            \
76         SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents,    \
77                                            _table, _reg, _shift,        \
78                                            _width, _gate, _flags, 0)
79
80 #define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg,         \
81                                 _shift, _width, _gate, _flags)          \
82         SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL,   \
83                                       _reg, _shift, _width, _gate,      \
84                                       _flags)
85
86 #define SUNXI_CCU_MUX(_struct, _name, _parents, _reg, _shift, _width,   \
87                       _flags)                                           \
88         SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL,   \
89                                       _reg, _shift, _width, 0, _flags)
90
91 #define SUNXI_CCU_MUX_DATA_WITH_GATE(_struct, _name, _parents, _reg,    \
92                                      _shift, _width, _gate, _flags)     \
93         struct ccu_mux _struct = {                                      \
94                 .enable = _gate,                                        \
95                 .mux    = _SUNXI_CCU_MUX(_shift, _width),               \
96                 .common = {                                             \
97                         .reg            = _reg,                         \
98                         .hw.init        = CLK_HW_INIT_PARENTS_DATA(_name, \
99                                                                    _parents, \
100                                                                    &ccu_mux_ops, \
101                                                                    _flags), \
102                 }                                                       \
103         }
104
105 #define SUNXI_CCU_MUX_DATA(_struct, _name, _parents, _reg,              \
106                       _shift, _width, _flags)                           \
107         SUNXI_CCU_MUX_DATA_WITH_GATE(_struct, _name, _parents, _reg,    \
108                                      _shift, _width, 0, _flags)
109
110 #define SUNXI_CCU_MUX_HW_WITH_GATE(_struct, _name, _parents, _reg,      \
111                                    _shift, _width, _gate, _flags)       \
112         struct ccu_mux _struct = {                                      \
113                 .enable = _gate,                                        \
114                 .mux    = _SUNXI_CCU_MUX(_shift, _width),               \
115                 .common = {                                             \
116                         .reg            = _reg,                         \
117                         .hw.init        = CLK_HW_INIT_PARENTS_HW(_name, \
118                                                                  _parents, \
119                                                                  &ccu_mux_ops, \
120                                                                  _flags), \
121                 }                                                       \
122         }
123
124 static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)
125 {
126         struct ccu_common *common = hw_to_ccu_common(hw);
127
128         return container_of(common, struct ccu_mux, common);
129 }
130
131 extern const struct clk_ops ccu_mux_ops;
132
133 unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common,
134                                           struct ccu_mux_internal *cm,
135                                           int parent_index,
136                                           unsigned long parent_rate);
137 int ccu_mux_helper_determine_rate(struct ccu_common *common,
138                                   struct ccu_mux_internal *cm,
139                                   struct clk_rate_request *req,
140                                   unsigned long (*round)(struct ccu_mux_internal *,
141                                                          struct clk_hw *,
142                                                          unsigned long *,
143                                                          unsigned long,
144                                                          void *),
145                                   void *data);
146 u8 ccu_mux_helper_get_parent(struct ccu_common *common,
147                              struct ccu_mux_internal *cm);
148 int ccu_mux_helper_set_parent(struct ccu_common *common,
149                               struct ccu_mux_internal *cm,
150                               u8 index);
151
152 struct ccu_mux_nb {
153         struct notifier_block   clk_nb;
154         struct ccu_common       *common;
155         struct ccu_mux_internal *cm;
156
157         u32     delay_us;       /* How many us to wait after reparenting */
158         u8      bypass_index;   /* Which parent to temporarily use */
159         u8      original_index; /* This is set by the notifier callback */
160 };
161
162 #define to_ccu_mux_nb(_nb) container_of(_nb, struct ccu_mux_nb, clk_nb)
163
164 int ccu_mux_notifier_register(struct clk *clk, struct ccu_mux_nb *mux_nb);
165
166 #endif /* _CCU_MUX_H_ */