Commit | Line | Data |
---|---|---|
e9b93213 MR |
1 | /* |
2 | * Copyright (c) 2016 Maxime Ripard. All rights reserved. | |
3 | * | |
4 | * This software is licensed under the terms of the GNU General Public | |
5 | * License version 2, as published by the Free Software Foundation, and | |
6 | * may be copied, distributed, and modified under those terms. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | */ | |
13 | ||
14 | #ifndef _CCU_DIV_H_ | |
15 | #define _CCU_DIV_H_ | |
16 | ||
17 | #include <linux/clk-provider.h> | |
18 | ||
19 | #include "ccu_common.h" | |
20 | #include "ccu_mux.h" | |
21 | ||
e9c959a6 MR |
22 | /** |
23 | * struct _ccu_div - Internal divider description | |
24 | * @shift: Bit offset of the divider in its register | |
25 | * @width: Width of the divider field in its register | |
87ba9e59 MR |
26 | * @max: Maximum value allowed for that divider. This is the |
27 | * arithmetic value, not the maximum value to be set in the | |
28 | * register. | |
e9c959a6 MR |
29 | * @flags: clk_divider flags to apply on this divider |
30 | * @table: Divider table pointer (if applicable) | |
31 | * | |
32 | * That structure represents a single divider, and is meant to be | |
33 | * embedded in other structures representing the various clock | |
34 | * classes. | |
35 | * | |
36 | * It is basically a wrapper around the clk_divider functions | |
37 | * arguments. | |
38 | */ | |
e9b93213 MR |
39 | struct _ccu_div { |
40 | u8 shift; | |
41 | u8 width; | |
42 | ||
87ba9e59 MR |
43 | u32 max; |
44 | ||
e9b93213 MR |
45 | u32 flags; |
46 | ||
47 | struct clk_div_table *table; | |
48 | }; | |
49 | ||
50 | #define _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, _flags) \ | |
51 | { \ | |
52 | .shift = _shift, \ | |
53 | .width = _width, \ | |
54 | .flags = _flags, \ | |
55 | .table = _table, \ | |
56 | } | |
57 | ||
e9b93213 MR |
58 | #define _SUNXI_CCU_DIV_TABLE(_shift, _width, _table) \ |
59 | _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, 0) | |
60 | ||
87ba9e59 MR |
61 | #define _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, _flags) \ |
62 | { \ | |
63 | .shift = _shift, \ | |
64 | .width = _width, \ | |
65 | .flags = _flags, \ | |
66 | .max = _max, \ | |
67 | } | |
68 | ||
69 | #define _SUNXI_CCU_DIV_FLAGS(_shift, _width, _flags) \ | |
70 | _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, 0, _flags) | |
71 | ||
72 | #define _SUNXI_CCU_DIV_MAX(_shift, _width, _max) \ | |
73 | _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, 0) | |
74 | ||
e9b93213 | 75 | #define _SUNXI_CCU_DIV(_shift, _width) \ |
87ba9e59 | 76 | _SUNXI_CCU_DIV_FLAGS(_shift, _width, 0) |
e9b93213 MR |
77 | |
78 | struct ccu_div { | |
79 | u32 enable; | |
80 | ||
81 | struct _ccu_div div; | |
82 | struct ccu_mux_internal mux; | |
83 | struct ccu_common common; | |
84 | }; | |
85 | ||
86 | #define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg, \ | |
87 | _shift, _width, \ | |
88 | _table, _gate, _flags) \ | |
89 | struct ccu_div _struct = { \ | |
90 | .div = _SUNXI_CCU_DIV_TABLE(_shift, _width, \ | |
91 | _table), \ | |
92 | .enable = _gate, \ | |
93 | .common = { \ | |
94 | .reg = _reg, \ | |
95 | .hw.init = CLK_HW_INIT(_name, \ | |
96 | _parent, \ | |
97 | &ccu_div_ops, \ | |
98 | _flags), \ | |
99 | } \ | |
100 | } | |
101 | ||
102 | ||
103 | #define SUNXI_CCU_DIV_TABLE(_struct, _name, _parent, _reg, \ | |
104 | _shift, _width, \ | |
105 | _table, _flags) \ | |
106 | SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg, \ | |
107 | _shift, _width, _table, 0, \ | |
108 | _flags) | |
109 | ||
6f91c601 MR |
110 | #define SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \ |
111 | _parents, _table, \ | |
112 | _reg, \ | |
113 | _mshift, _mwidth, \ | |
114 | _muxshift, _muxwidth, \ | |
115 | _gate, _flags) \ | |
e9b93213 MR |
116 | struct ccu_div _struct = { \ |
117 | .enable = _gate, \ | |
118 | .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \ | |
6f91c601 | 119 | .mux = _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, _table), \ |
e9b93213 MR |
120 | .common = { \ |
121 | .reg = _reg, \ | |
122 | .hw.init = CLK_HW_INIT_PARENTS(_name, \ | |
123 | _parents, \ | |
124 | &ccu_div_ops, \ | |
125 | _flags), \ | |
126 | }, \ | |
127 | } | |
128 | ||
6f91c601 MR |
129 | #define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg, \ |
130 | _mshift, _mwidth, _muxshift, _muxwidth, \ | |
131 | _gate, _flags) \ | |
132 | SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \ | |
133 | _parents, NULL, \ | |
134 | _reg, _mshift, _mwidth, \ | |
135 | _muxshift, _muxwidth, \ | |
136 | _gate, _flags) | |
137 | ||
e9b93213 MR |
138 | #define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg, \ |
139 | _mshift, _mwidth, _muxshift, _muxwidth, \ | |
140 | _flags) \ | |
6f91c601 MR |
141 | SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \ |
142 | _parents, NULL, \ | |
143 | _reg, _mshift, _mwidth, \ | |
144 | _muxshift, _muxwidth, \ | |
145 | 0, _flags) | |
e9b93213 MR |
146 | |
147 | ||
148 | #define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \ | |
149 | _mshift, _mwidth, _gate, \ | |
150 | _flags) \ | |
151 | struct ccu_div _struct = { \ | |
152 | .enable = _gate, \ | |
153 | .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \ | |
154 | .common = { \ | |
155 | .reg = _reg, \ | |
156 | .hw.init = CLK_HW_INIT(_name, \ | |
157 | _parent, \ | |
158 | &ccu_div_ops, \ | |
159 | _flags), \ | |
160 | }, \ | |
161 | } | |
162 | ||
163 | #define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth, \ | |
164 | _flags) \ | |
165 | SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \ | |
166 | _mshift, _mwidth, 0, _flags) | |
167 | ||
168 | static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw) | |
169 | { | |
170 | struct ccu_common *common = hw_to_ccu_common(hw); | |
171 | ||
172 | return container_of(common, struct ccu_div, common); | |
173 | } | |
174 | ||
175 | extern const struct clk_ops ccu_div_ops; | |
176 | ||
177 | #endif /* _CCU_DIV_H_ */ |