GNU Linux-libre 4.9.330-gnu1
[releases.git] / drivers / clk / sunxi-ng / ccu_mux.h
1 #ifndef _CCU_MUX_H_
2 #define _CCU_MUX_H_
3
4 #include <linux/clk-provider.h>
5
6 #include "ccu_common.h"
7
8 struct ccu_mux_fixed_prediv {
9         u8      index;
10         u16     div;
11 };
12
13 struct ccu_mux_internal {
14         u8              shift;
15         u8              width;
16         const u8        *table;
17
18         const struct ccu_mux_fixed_prediv       *fixed_predivs;
19         u8              n_predivs;
20
21         struct {
22                 u8      index;
23                 u8      shift;
24                 u8      width;
25         } variable_prediv;
26 };
27
28 #define _SUNXI_CCU_MUX_TABLE(_shift, _width, _table)    \
29         {                                               \
30                 .shift  = _shift,                       \
31                 .width  = _width,                       \
32                 .table  = _table,                       \
33         }
34
35 #define _SUNXI_CCU_MUX(_shift, _width) \
36         _SUNXI_CCU_MUX_TABLE(_shift, _width, NULL)
37
38 struct ccu_mux {
39         u16                     reg;
40         u32                     enable;
41
42         struct ccu_mux_internal mux;
43         struct ccu_common       common;
44 };
45
46 #define SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, _table, \
47                                      _reg, _shift, _width, _gate,       \
48                                      _flags)                            \
49         struct ccu_mux _struct = {                                      \
50                 .enable = _gate,                                        \
51                 .mux    = _SUNXI_CCU_MUX_TABLE(_shift, _width, _table), \
52                 .common = {                                             \
53                         .reg            = _reg,                         \
54                         .hw.init        = CLK_HW_INIT_PARENTS(_name,    \
55                                                               _parents, \
56                                                               &ccu_mux_ops, \
57                                                               _flags),  \
58                 }                                                       \
59         }
60
61 #define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg,         \
62                                 _shift, _width, _gate, _flags)          \
63         SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL,   \
64                                       _reg, _shift, _width, _gate,      \
65                                       _flags)
66
67 #define SUNXI_CCU_MUX(_struct, _name, _parents, _reg, _shift, _width,   \
68                       _flags)                                           \
69         SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL,   \
70                                       _reg, _shift, _width, 0, _flags)
71
72 static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)
73 {
74         struct ccu_common *common = hw_to_ccu_common(hw);
75
76         return container_of(common, struct ccu_mux, common);
77 }
78
79 extern const struct clk_ops ccu_mux_ops;
80
81 void ccu_mux_helper_adjust_parent_for_prediv(struct ccu_common *common,
82                                              struct ccu_mux_internal *cm,
83                                              int parent_index,
84                                              unsigned long *parent_rate);
85 int ccu_mux_helper_determine_rate(struct ccu_common *common,
86                                   struct ccu_mux_internal *cm,
87                                   struct clk_rate_request *req,
88                                   unsigned long (*round)(struct ccu_mux_internal *,
89                                                          unsigned long,
90                                                          unsigned long,
91                                                          void *),
92                                   void *data);
93 u8 ccu_mux_helper_get_parent(struct ccu_common *common,
94                              struct ccu_mux_internal *cm);
95 int ccu_mux_helper_set_parent(struct ccu_common *common,
96                               struct ccu_mux_internal *cm,
97                               u8 index);
98
99 struct ccu_mux_nb {
100         struct notifier_block   clk_nb;
101         struct ccu_common       *common;
102         struct ccu_mux_internal *cm;
103
104         u32     delay_us;       /* How many us to wait after reparenting */
105         u8      bypass_index;   /* Which parent to temporarily use */
106         u8      original_index; /* This is set by the notifier callback */
107 };
108
109 #define to_ccu_mux_nb(_nb) container_of(_nb, struct ccu_mux_nb, clk_nb)
110
111 int ccu_mux_notifier_register(struct clk *clk, struct ccu_mux_nb *mux_nb);
112
113 #endif /* _CCU_MUX_H_ */