1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _CCU_MUX_H_
3 #define _CCU_MUX_H_
4 
5 #include "ccu.h"
6 #include "ccu_common.h"
7 
8 /*
9  * Create a contiguous bitmask starting at bit position @l and ending at
10  * position @h. For example
11  * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
12  */
13 
14 struct ccu_mux_fixed_prediv
15 {
16     u8  index;
17     u16 div;
18 };
19 
20 struct ccu_mux_var_prediv
21 {
22     u8  index;
23     u8  shift;
24     u8  width;
25 };
26 
27 struct ccu_mux_internal
28 {
29     u8      shift;
30     u8      width;
31     const u8    *table;
32 
33     const struct ccu_mux_fixed_prediv   *fixed_predivs;
34     u8      n_predivs;
35 
36     const struct ccu_mux_var_prediv     *var_predivs;
37     u8      n_var_predivs;
38 };
39 
40 #define _SUNXI_CCU_MUX_TABLE(_shift, _width, _table)    \
41     {                       \
42         .shift  = _shift,           \
43                   .width  = _width,           \
44                             .table  = _table,           \
45     }
46 
47 #define _SUNXI_CCU_MUX(_shift, _width) \
48     _SUNXI_CCU_MUX_TABLE(_shift, _width, NULL)
49 
50 struct ccu_mux
51 {
52     u32         reg;
53     u32         enable;
54 
55     struct ccu_mux_internal mux;
56     struct ccu_common   common;
57 };
58 
59 #define SUNXI_CCU_MUX_WITH_GATE_KEY(_struct, _name, _parents,       \
60                                     _reg, _shift, _width,       \
61                                     _key_value, _gate, _flags)      \
62 struct ccu_mux _struct = {                  \
63     .enable = _gate,                    \
64               .mux    = _SUNXI_CCU_MUX(_shift, _width),       \
65                         .common = {                     \
66                                                         .reg        = _reg,             \
67                                                         .features   = CCU_FEATURE_KEY_FIELD_MOD,    \
68                                                         .key_value  = _key_value,           \
69                                                         .hw.init    = CLK_HW_INIT_PARENTS(_name,    \
70                                                                 _parents, \
71                                                                 &ccu_mux_ops, \
72                                                                 _flags),  \
73                                   }                           \
74 }
75 
76 #define SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, _table, \
77                                       _reg, _shift, _width, _gate,   \
78                                       _flags)                \
79 struct ccu_mux _struct = {                  \
80     .enable = _gate,                    \
81               .mux    = _SUNXI_CCU_MUX_TABLE(_shift, _width, _table), \
82                         .common = {                     \
83                                                         .reg        = _reg,             \
84                                                         .hw.init    = CLK_HW_INIT_PARENTS(_name,    \
85                                                                 _parents, \
86                                                                 &ccu_mux_ops, \
87                                                                 _flags),  \
88                                   }                           \
89 }
90 
91 #define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg,     \
92                                 _shift, _width, _gate, _flags)      \
93 SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL,   \
94                               _reg, _shift, _width, _gate,  \
95                               _flags)
96 
97 #define SUNXI_CCU_MUX(_struct, _name, _parents, _reg, _shift, _width,   \
98                       _flags)                       \
99 SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL,   \
100                               _reg, _shift, _width, 0, _flags)
101 
hw_to_ccu_mux(struct clk_hw * hw)102 static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)
103 {
104     struct ccu_common *common = hw_to_ccu_common(hw);
105 
106     return container_of(common, struct ccu_mux, common);
107 }
108 
109 extern const struct clk_ops ccu_mux_ops;
110 
111 unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common,
112         struct ccu_mux_internal *cm,
113         int parent_index,
114         unsigned long parent_rate);
115 int ccu_mux_helper_determine_rate(struct ccu_common *common,
116                                   struct ccu_mux_internal *cm,
117                                   struct clk_rate_request *req,
118                                   unsigned long (*round)(struct ccu_mux_internal *,
119                                           struct clk_hw *,
120                                           unsigned long *,
121                                           unsigned long,
122                                           void *),
123                                   void *data);
124 u8 ccu_mux_helper_get_parent(struct ccu_common *common,
125                              struct ccu_mux_internal *cm);
126 int ccu_mux_helper_set_parent(struct ccu_common *common,
127                               struct ccu_mux_internal *cm,
128                               u8 index);
129 
130 #endif /* _CCU_MUX_H_ */
131