GNU Linux-libre 4.19.286-gnu1
[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         u16                     reg;
44         u32                     enable;
45
46         struct ccu_mux_internal mux;
47         struct ccu_common       common;
48 };
49
50 #define SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, _table, \
51                                      _reg, _shift, _width, _gate,       \
52                                      _flags)                            \
53         struct ccu_mux _struct = {                                      \
54                 .enable = _gate,                                        \
55                 .mux    = _SUNXI_CCU_MUX_TABLE(_shift, _width, _table), \
56                 .common = {                                             \
57                         .reg            = _reg,                         \
58                         .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
59                                                               _parents, \
60                                                               &ccu_mux_ops, \
61                                                               _flags),  \
62                 }                                                       \
63         }
64
65 #define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg,         \
66                                 _shift, _width, _gate, _flags)          \
67         SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL,   \
68                                       _reg, _shift, _width, _gate,      \
69                                       _flags)
70
71 #define SUNXI_CCU_MUX(_struct, _name, _parents, _reg, _shift, _width,   \
72                       _flags)                                           \
73         SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL,   \
74                                       _reg, _shift, _width, 0, _flags)
75
76 static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)
77 {
78         struct ccu_common *common = hw_to_ccu_common(hw);
79
80         return container_of(common, struct ccu_mux, common);
81 }
82
83 extern const struct clk_ops ccu_mux_ops;
84
85 unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common,
86                                           struct ccu_mux_internal *cm,
87                                           int parent_index,
88                                           unsigned long parent_rate);
89 int ccu_mux_helper_determine_rate(struct ccu_common *common,
90                                   struct ccu_mux_internal *cm,
91                                   struct clk_rate_request *req,
92                                   unsigned long (*round)(struct ccu_mux_internal *,
93                                                          struct clk_hw *,
94                                                          unsigned long *,
95                                                          unsigned long,
96                                                          void *),
97                                   void *data);
98 u8 ccu_mux_helper_get_parent(struct ccu_common *common,
99                              struct ccu_mux_internal *cm);
100 int ccu_mux_helper_set_parent(struct ccu_common *common,
101                               struct ccu_mux_internal *cm,
102                               u8 index);
103
104 struct ccu_mux_nb {
105         struct notifier_block   clk_nb;
106         struct ccu_common       *common;
107         struct ccu_mux_internal *cm;
108
109         u32     delay_us;       /* How many us to wait after reparenting */
110         u8      bypass_index;   /* Which parent to temporarily use */
111         u8      original_index; /* This is set by the notifier callback */
112 };
113
114 #define to_ccu_mux_nb(_nb) container_of(_nb, struct ccu_mux_nb, clk_nb)
115
116 int ccu_mux_notifier_register(struct clk *clk, struct ccu_mux_nb *mux_nb);
117
118 #endif /* _CCU_MUX_H_ */