19c92ab61SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
2e9b93213SMaxime Ripard /*
3e9b93213SMaxime Ripard * Copyright (c) 2016 Maxime Ripard. All rights reserved.
4e9b93213SMaxime Ripard */
5e9b93213SMaxime Ripard
6e9b93213SMaxime Ripard #ifndef _CCU_DIV_H_
7e9b93213SMaxime Ripard #define _CCU_DIV_H_
8e9b93213SMaxime Ripard
9e9b93213SMaxime Ripard #include <linux/clk-provider.h>
10e9b93213SMaxime Ripard
11e9b93213SMaxime Ripard #include "ccu_common.h"
12e9b93213SMaxime Ripard #include "ccu_mux.h"
13e9b93213SMaxime Ripard
14e9c959a6SMaxime Ripard /**
15a501a14eSMaxime Ripard * struct ccu_div_internal - Internal divider description
16e9c959a6SMaxime Ripard * @shift: Bit offset of the divider in its register
17e9c959a6SMaxime Ripard * @width: Width of the divider field in its register
1887ba9e59SMaxime Ripard * @max: Maximum value allowed for that divider. This is the
1987ba9e59SMaxime Ripard * arithmetic value, not the maximum value to be set in the
2087ba9e59SMaxime Ripard * register.
21e9c959a6SMaxime Ripard * @flags: clk_divider flags to apply on this divider
22e9c959a6SMaxime Ripard * @table: Divider table pointer (if applicable)
23e9c959a6SMaxime Ripard *
24e9c959a6SMaxime Ripard * That structure represents a single divider, and is meant to be
25e9c959a6SMaxime Ripard * embedded in other structures representing the various clock
26e9c959a6SMaxime Ripard * classes.
27e9c959a6SMaxime Ripard *
28e9c959a6SMaxime Ripard * It is basically a wrapper around the clk_divider functions
29e9c959a6SMaxime Ripard * arguments.
30e9c959a6SMaxime Ripard */
31a501a14eSMaxime Ripard struct ccu_div_internal {
32e9b93213SMaxime Ripard u8 shift;
33e9b93213SMaxime Ripard u8 width;
34e9b93213SMaxime Ripard
3587ba9e59SMaxime Ripard u32 max;
36e66f81bbSMaxime Ripard u32 offset;
3787ba9e59SMaxime Ripard
38e9b93213SMaxime Ripard u32 flags;
39e9b93213SMaxime Ripard
40e9b93213SMaxime Ripard struct clk_div_table *table;
41e9b93213SMaxime Ripard };
42e9b93213SMaxime Ripard
43e9b93213SMaxime Ripard #define _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, _flags) \
44e9b93213SMaxime Ripard { \
45e9b93213SMaxime Ripard .shift = _shift, \
46e9b93213SMaxime Ripard .width = _width, \
47e9b93213SMaxime Ripard .flags = _flags, \
48e9b93213SMaxime Ripard .table = _table, \
49e9b93213SMaxime Ripard }
50e9b93213SMaxime Ripard
51e9b93213SMaxime Ripard #define _SUNXI_CCU_DIV_TABLE(_shift, _width, _table) \
52e9b93213SMaxime Ripard _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, 0)
53e9b93213SMaxime Ripard
54e66f81bbSMaxime Ripard #define _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _off, _max, _flags) \
5587ba9e59SMaxime Ripard { \
5687ba9e59SMaxime Ripard .shift = _shift, \
5787ba9e59SMaxime Ripard .width = _width, \
5887ba9e59SMaxime Ripard .flags = _flags, \
5987ba9e59SMaxime Ripard .max = _max, \
60e66f81bbSMaxime Ripard .offset = _off, \
6187ba9e59SMaxime Ripard }
6287ba9e59SMaxime Ripard
63e66f81bbSMaxime Ripard #define _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, _flags) \
64e66f81bbSMaxime Ripard _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, 1, _max, _flags)
65e66f81bbSMaxime Ripard
6687ba9e59SMaxime Ripard #define _SUNXI_CCU_DIV_FLAGS(_shift, _width, _flags) \
6787ba9e59SMaxime Ripard _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, 0, _flags)
6887ba9e59SMaxime Ripard
6987ba9e59SMaxime Ripard #define _SUNXI_CCU_DIV_MAX(_shift, _width, _max) \
7087ba9e59SMaxime Ripard _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, 0)
7187ba9e59SMaxime Ripard
72e66f81bbSMaxime Ripard #define _SUNXI_CCU_DIV_OFFSET(_shift, _width, _offset) \
73e66f81bbSMaxime Ripard _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _offset, 0, 0)
74e66f81bbSMaxime Ripard
75e9b93213SMaxime Ripard #define _SUNXI_CCU_DIV(_shift, _width) \
7687ba9e59SMaxime Ripard _SUNXI_CCU_DIV_FLAGS(_shift, _width, 0)
77e9b93213SMaxime Ripard
78e9b93213SMaxime Ripard struct ccu_div {
79e9b93213SMaxime Ripard u32 enable;
80e9b93213SMaxime Ripard
81a501a14eSMaxime Ripard struct ccu_div_internal div;
82e9b93213SMaxime Ripard struct ccu_mux_internal mux;
83e9b93213SMaxime Ripard struct ccu_common common;
84721353c0SPriit Laes unsigned int fixed_post_div;
85e9b93213SMaxime Ripard };
86e9b93213SMaxime Ripard
87e9b93213SMaxime Ripard #define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg, \
88e9b93213SMaxime Ripard _shift, _width, \
89e9b93213SMaxime Ripard _table, _gate, _flags) \
90e9b93213SMaxime Ripard struct ccu_div _struct = { \
91e9b93213SMaxime Ripard .div = _SUNXI_CCU_DIV_TABLE(_shift, _width, \
92e9b93213SMaxime Ripard _table), \
93e9b93213SMaxime Ripard .enable = _gate, \
94e9b93213SMaxime Ripard .common = { \
95e9b93213SMaxime Ripard .reg = _reg, \
96e9b93213SMaxime Ripard .hw.init = CLK_HW_INIT(_name, \
97e9b93213SMaxime Ripard _parent, \
98e9b93213SMaxime Ripard &ccu_div_ops, \
99e9b93213SMaxime Ripard _flags), \
100e9b93213SMaxime Ripard } \
101e9b93213SMaxime Ripard }
102e9b93213SMaxime Ripard
103e9b93213SMaxime Ripard
104e9b93213SMaxime Ripard #define SUNXI_CCU_DIV_TABLE(_struct, _name, _parent, _reg, \
105e9b93213SMaxime Ripard _shift, _width, \
106e9b93213SMaxime Ripard _table, _flags) \
107e9b93213SMaxime Ripard SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg, \
108e9b93213SMaxime Ripard _shift, _width, _table, 0, \
109e9b93213SMaxime Ripard _flags)
110e9b93213SMaxime Ripard
1113317cb17SSamuel Holland #define SUNXI_CCU_DIV_TABLE_HW(_struct, _name, _parent, _reg, \
1123317cb17SSamuel Holland _shift, _width, \
1133317cb17SSamuel Holland _table, _flags) \
1143317cb17SSamuel Holland struct ccu_div _struct = { \
1153317cb17SSamuel Holland .div = _SUNXI_CCU_DIV_TABLE(_shift, _width, \
1163317cb17SSamuel Holland _table), \
1173317cb17SSamuel Holland .common = { \
1183317cb17SSamuel Holland .reg = _reg, \
1193317cb17SSamuel Holland .hw.init = CLK_HW_INIT_HW(_name, \
1203317cb17SSamuel Holland _parent, \
1213317cb17SSamuel Holland &ccu_div_ops, \
1223317cb17SSamuel Holland _flags), \
1233317cb17SSamuel Holland } \
1243317cb17SSamuel Holland }
1253317cb17SSamuel Holland
1263317cb17SSamuel Holland
1276f91c601SMaxime Ripard #define SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \
1286f91c601SMaxime Ripard _parents, _table, \
1296f91c601SMaxime Ripard _reg, \
1306f91c601SMaxime Ripard _mshift, _mwidth, \
1316f91c601SMaxime Ripard _muxshift, _muxwidth, \
132e9b93213SMaxime Ripard _gate, _flags) \
133e9b93213SMaxime Ripard struct ccu_div _struct = { \
134e9b93213SMaxime Ripard .enable = _gate, \
135e9b93213SMaxime Ripard .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
1366f91c601SMaxime Ripard .mux = _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, _table), \
137e9b93213SMaxime Ripard .common = { \
138e9b93213SMaxime Ripard .reg = _reg, \
139e9b93213SMaxime Ripard .hw.init = CLK_HW_INIT_PARENTS(_name, \
140e9b93213SMaxime Ripard _parents, \
141e9b93213SMaxime Ripard &ccu_div_ops, \
142e9b93213SMaxime Ripard _flags), \
143e9b93213SMaxime Ripard }, \
144e9b93213SMaxime Ripard }
145e9b93213SMaxime Ripard
146*253795abSFrank Oltmanns #define SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(_struct, _name, \
147*253795abSFrank Oltmanns _parents, _table, \
148*253795abSFrank Oltmanns _reg, \
149*253795abSFrank Oltmanns _mshift, _mwidth, \
150*253795abSFrank Oltmanns _muxshift, _muxwidth, \
151*253795abSFrank Oltmanns _gate, _flags) \
152*253795abSFrank Oltmanns struct ccu_div _struct = { \
153*253795abSFrank Oltmanns .enable = _gate, \
154*253795abSFrank Oltmanns .div = _SUNXI_CCU_DIV_FLAGS(_mshift, _mwidth, CLK_DIVIDER_ROUND_CLOSEST), \
155*253795abSFrank Oltmanns .mux = _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, _table), \
156*253795abSFrank Oltmanns .common = { \
157*253795abSFrank Oltmanns .reg = _reg, \
158*253795abSFrank Oltmanns .hw.init = CLK_HW_INIT_PARENTS(_name, \
159*253795abSFrank Oltmanns _parents, \
160*253795abSFrank Oltmanns &ccu_div_ops, \
161*253795abSFrank Oltmanns _flags), \
162*253795abSFrank Oltmanns .features = CCU_FEATURE_CLOSEST_RATE, \
163*253795abSFrank Oltmanns }, \
164*253795abSFrank Oltmanns }
165*253795abSFrank Oltmanns
1666f91c601SMaxime Ripard #define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
1676f91c601SMaxime Ripard _mshift, _mwidth, _muxshift, _muxwidth, \
1686f91c601SMaxime Ripard _gate, _flags) \
1696f91c601SMaxime Ripard SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \
1706f91c601SMaxime Ripard _parents, NULL, \
1716f91c601SMaxime Ripard _reg, _mshift, _mwidth, \
1726f91c601SMaxime Ripard _muxshift, _muxwidth, \
1736f91c601SMaxime Ripard _gate, _flags)
1746f91c601SMaxime Ripard
175*253795abSFrank Oltmanns #define SUNXI_CCU_M_WITH_MUX_GATE_CLOSEST(_struct, _name, _parents, \
176*253795abSFrank Oltmanns _reg, _mshift, _mwidth, \
177*253795abSFrank Oltmanns _muxshift, _muxwidth, \
178*253795abSFrank Oltmanns _gate, _flags) \
179*253795abSFrank Oltmanns SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(_struct, _name, \
180*253795abSFrank Oltmanns _parents, NULL, \
181*253795abSFrank Oltmanns _reg, _mshift, _mwidth, \
182*253795abSFrank Oltmanns _muxshift, _muxwidth, \
183*253795abSFrank Oltmanns _gate, _flags)
184*253795abSFrank Oltmanns
185e9b93213SMaxime Ripard #define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg, \
186e9b93213SMaxime Ripard _mshift, _mwidth, _muxshift, _muxwidth, \
187e9b93213SMaxime Ripard _flags) \
1886f91c601SMaxime Ripard SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \
1896f91c601SMaxime Ripard _parents, NULL, \
1906f91c601SMaxime Ripard _reg, _mshift, _mwidth, \
1916f91c601SMaxime Ripard _muxshift, _muxwidth, \
192e9b93213SMaxime Ripard 0, _flags)
193e9b93213SMaxime Ripard
194e9b93213SMaxime Ripard
195e9b93213SMaxime Ripard #define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \
196e9b93213SMaxime Ripard _mshift, _mwidth, _gate, \
197e9b93213SMaxime Ripard _flags) \
198e9b93213SMaxime Ripard struct ccu_div _struct = { \
199e9b93213SMaxime Ripard .enable = _gate, \
200e9b93213SMaxime Ripard .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
201e9b93213SMaxime Ripard .common = { \
202e9b93213SMaxime Ripard .reg = _reg, \
203e9b93213SMaxime Ripard .hw.init = CLK_HW_INIT(_name, \
204e9b93213SMaxime Ripard _parent, \
205e9b93213SMaxime Ripard &ccu_div_ops, \
206e9b93213SMaxime Ripard _flags), \
207e9b93213SMaxime Ripard }, \
208e9b93213SMaxime Ripard }
209e9b93213SMaxime Ripard
210e9b93213SMaxime Ripard #define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth, \
211e9b93213SMaxime Ripard _flags) \
212e9b93213SMaxime Ripard SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \
213e9b93213SMaxime Ripard _mshift, _mwidth, 0, _flags)
214e9b93213SMaxime Ripard
2153317cb17SSamuel Holland #define SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
2163317cb17SSamuel Holland _mshift, _mwidth, \
2173317cb17SSamuel Holland _muxshift, _muxwidth, \
2183317cb17SSamuel Holland _gate, _flags) \
2193317cb17SSamuel Holland struct ccu_div _struct = { \
2203317cb17SSamuel Holland .enable = _gate, \
2213317cb17SSamuel Holland .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
2223317cb17SSamuel Holland .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
2233317cb17SSamuel Holland .common = { \
2243317cb17SSamuel Holland .reg = _reg, \
2253317cb17SSamuel Holland .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
2263317cb17SSamuel Holland _parents, \
2273317cb17SSamuel Holland &ccu_div_ops, \
2283317cb17SSamuel Holland _flags), \
2293317cb17SSamuel Holland }, \
2303317cb17SSamuel Holland }
2313317cb17SSamuel Holland
2323317cb17SSamuel Holland #define SUNXI_CCU_M_DATA_WITH_MUX(_struct, _name, _parents, _reg, \
2333317cb17SSamuel Holland _mshift, _mwidth, \
2343317cb17SSamuel Holland _muxshift, _muxwidth, \
2353317cb17SSamuel Holland _flags) \
2363317cb17SSamuel Holland SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
2373317cb17SSamuel Holland _mshift, _mwidth, \
2383317cb17SSamuel Holland _muxshift, _muxwidth, \
2393317cb17SSamuel Holland 0, _flags)
2403317cb17SSamuel Holland
2413317cb17SSamuel Holland #define SUNXI_CCU_M_HW_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
2423317cb17SSamuel Holland _mshift, _mwidth, _muxshift, _muxwidth, \
2433317cb17SSamuel Holland _gate, _flags) \
2443317cb17SSamuel Holland struct ccu_div _struct = { \
2453317cb17SSamuel Holland .enable = _gate, \
2463317cb17SSamuel Holland .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
2473317cb17SSamuel Holland .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
2483317cb17SSamuel Holland .common = { \
2493317cb17SSamuel Holland .reg = _reg, \
2503317cb17SSamuel Holland .hw.init = CLK_HW_INIT_PARENTS_HW(_name, \
2513317cb17SSamuel Holland _parents, \
2523317cb17SSamuel Holland &ccu_div_ops, \
2533317cb17SSamuel Holland _flags), \
2543317cb17SSamuel Holland }, \
2553317cb17SSamuel Holland }
2563317cb17SSamuel Holland
2573317cb17SSamuel Holland #define SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg, \
2583317cb17SSamuel Holland _mshift, _mwidth, _gate, \
2593317cb17SSamuel Holland _flags) \
2603317cb17SSamuel Holland struct ccu_div _struct = { \
2613317cb17SSamuel Holland .enable = _gate, \
2623317cb17SSamuel Holland .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
2633317cb17SSamuel Holland .common = { \
2643317cb17SSamuel Holland .reg = _reg, \
2653317cb17SSamuel Holland .hw.init = CLK_HW_INIT_HWS(_name, \
2663317cb17SSamuel Holland _parent, \
2673317cb17SSamuel Holland &ccu_div_ops, \
2683317cb17SSamuel Holland _flags), \
2693317cb17SSamuel Holland }, \
2703317cb17SSamuel Holland }
2713317cb17SSamuel Holland
2723317cb17SSamuel Holland #define SUNXI_CCU_M_HWS(_struct, _name, _parent, _reg, _mshift, \
2733317cb17SSamuel Holland _mwidth, _flags) \
2743317cb17SSamuel Holland SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg, \
2753317cb17SSamuel Holland _mshift, _mwidth, 0, _flags)
2763317cb17SSamuel Holland
hw_to_ccu_div(struct clk_hw * hw)277e9b93213SMaxime Ripard static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
278e9b93213SMaxime Ripard {
279e9b93213SMaxime Ripard struct ccu_common *common = hw_to_ccu_common(hw);
280e9b93213SMaxime Ripard
281e9b93213SMaxime Ripard return container_of(common, struct ccu_div, common);
282e9b93213SMaxime Ripard }
283e9b93213SMaxime Ripard
284e9b93213SMaxime Ripard extern const struct clk_ops ccu_div_ops;
285e9b93213SMaxime Ripard
286e9b93213SMaxime Ripard #endif /* _CCU_DIV_H_ */
287