1 /* Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
2  *
3  * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
4  *the the People's Republic of China and other countries.
5  * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
6  *
7  * DISCLAIMER
8  * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
9  * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
10  * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
11  * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
12  * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
13  * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
14  * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
15  *
16  *
17  * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
18  * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
19  * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
20  * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
21  * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29  * OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef __CLK_PERIPH_H__
33 #define __CLK_PERIPH_H__
34 
35 #include "clk.h"
36 
37 #define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])
38 
39 #define SUNXI_CLK_PERIPH_CONFIG(name, _mux_reg, _mux_shift, _mux_width,  \
40                                 _div_reg, _div_mshift, _div_mwidth, _div_nshift, _div_nwidth,   \
41                                 _gate_flags, _enable_reg, _reset_reg, _bus_gate_reg, _drm_gate_reg, \
42                                 _enable_shift, _reset_shift, _bus_gate_shift, _dram_gate_shift,  _com_gate, _com_gate_off) \
43 struct sunxi_clk_periph sunxi_clk_periph_config_##name = {      \
44     .mux = {                                                \
45                                                             .reg = (volatile uint32_t   *)_mux_reg,             \
46                                                             .shift = _mux_shift,                                \
47                                                             .width = _mux_width,                                \
48            },                                                      \
49            .divider = {                                            \
50                                                                    .reg = (volatile uint32_t   *)_div_reg,                   \
51                                                                    .mshift = _div_mshift,                              \
52                                                                    .mwidth = _div_mwidth,                              \
53                                                                    .nshift = _div_nshift,                              \
54                                                                    .nwidth = _div_nwidth,                              \
55                       },                                                      \
56                       .gate = {                                               \
57                                                                               .flags = _gate_flags,                               \
58                                                                               .enable = (volatile uint32_t   *)_enable_reg,             \
59                                                                               .reset = (volatile uint32_t   *)_reset_reg,               \
60                                                                               .bus = (volatile uint32_t   *)_bus_gate_reg,              \
61                                                                               .dram = (volatile uint32_t   *)_drm_gate_reg,             \
62                                                                               .enb_shift = _enable_shift,                         \
63                                                                               .rst_shift = _reset_shift,                          \
64                                                                               .bus_shift = _bus_gate_shift,                       \
65                                                                               .ddr_shift = _dram_gate_shift,                      \
66                               },                                                      \
67                               .com_gate = _com_gate,                                  \
68                                           .com_gate_off = _com_gate_off,                          \
69 }
70 
71 #define SUNXI_CLK_PERIPH(_name, _clk,  _parent_arry) \
72     clk_periph_t sunxi_clk_periph_##_name  = {  \
73                                                 .clk_core = {   \
74                                                                 .clk = _clk,    \
75                                                                 .clk_type = HAL_CLK_PERIPH, \
76                                                                 .current_parent = HAL_CLK_UNINITIALIZED,    \
77                                                                 .current_parent_type = 0, \
78                                                                 .clk_rate = 0,     \
79                                                                 .parent_rate = 0,      \
80                                                                 .clk_enbale = HAL_CLK_STATUS_DISABLED,   \
81                                                             },  \
82                                                 .parent_arry = _parent_arry,    \
83                                                 .parent_arry_size = ARRAY_SIZE(_parent_arry), \
84                                                 .config = &sunxi_clk_periph_config_##_name,     \
85                                              }
86 
87 #define SUNXI_PERIPH_INIT(_name, _clk, _parent_clk, _clk_rate) \
88     clk_base_t sunxi_periph_clk_init_##_name = {    \
89                                                     .clk = _clk,    \
90                                                     .parent = _parent_clk,  \
91                                                     .clk_rate = _clk_rate,  \
92                                                }
93 
94 
95 /**
96  * struct sunxi_clk_periph_gate - peripheral gate clock
97  *
98  * @flags:      hardware-specific flags
99  * @enable:     enable register
100  * @reset:      reset register
101  * @bus:        bus gating resiter
102  * @dram:       dram gating register
103  * @enb_shift:  enable gate bit shift
104  * @rst_shift:  reset gate bit shift
105  * @bus_shift:  bus gate bit shift
106  * @ddr_shift:  dram gate bit shift
107  *
108  * Flags:
109  * SUNXI_PERIPH_NO_GATE - this flag indicates that module gate is not allowed for this module.
110  * SUNXI_PERIPH_NO_RESET - This flag indicates that reset is not allowed for this module.
111  * SUNXI_PERIPH_NO_BUS_GATE - This flag indicates that bus gate is not allowed for this module.
112  * SUNXI_PERIPH_NO_DDR_GATE - This flag indicates that dram gate is not allowed for this module.
113  */
114 struct sunxi_clk_periph_gate
115 {
116     u32             flags;
117     volatile uint32_t   *enable;
118     volatile uint32_t   *reset;
119     volatile uint32_t   *bus;
120     volatile uint32_t   *dram;
121     u8              enb_shift;
122     u8              rst_shift;
123     u8              bus_shift;
124     u8              ddr_shift;
125 };
126 
127 /**
128  * struct sunxi_clk_periph_div - periph divider clock
129  *
130  * @reg:        register containing divider
131  * @mshift:     shift to the divider-m bit field, div = (m+1)
132  * @mwidth:     width of the divider-m bit field
133  * @nshift:     shift to the divider-n bit field, div = (1<<n)
134  * @nwidth:     width of the divider-n bit field
135  * @lock:       register lock
136  *
137  * Flags:
138  */
139 struct sunxi_clk_periph_div
140 {
141     volatile uint32_t   *reg;
142     u8              mshift;
143     u8              mwidth;
144     u8              nshift;
145     u8              nwidth;
146     //spinlock_t      *lock;
147 };
148 
149 
150 /**
151  * struct sunxi_clk_periph_mux - multiplexer clock
152  *
153  * @reg:        register controlling multiplexer
154  * @shift:      shift to multiplexer bit field
155  * @width:      width of mutliplexer bit field
156  * @lock:       register lock
157  *
158  * Clock with multiple selectable parents.  Implements .get_parent, .set_parent
159  * and .recalc_rate
160  *
161  */
162 struct sunxi_clk_periph_mux
163 {
164     volatile uint32_t   *reg;
165     u8              shift;
166     u8              width;
167     //spinlock_t      *lock;
168 };
169 
170 struct sunxi_clk_comgate
171 {
172     const u8        *name;
173     u16             val;
174     u16             mask;
175     u8              share;
176     u8              res;
177 };
178 
179 #define BUS_GATE_SHARE  0x01
180 #define RST_GATE_SHARE  0x02
181 #define MBUS_GATE_SHARE 0x04
182 #define MOD_GATE_SHARE  0x08
183 
184 #define IS_SHARE_BUS_GATE(x)  (x->com_gate?((x->com_gate->share & BUS_GATE_SHARE)?1:0):0)
185 #define IS_SHARE_RST_GATE(x)  (x->com_gate?((x->com_gate->share & RST_GATE_SHARE)?1:0):0)
186 #define IS_SHARE_MBUS_GATE(x) (x->com_gate?((x->com_gate->share & MBUS_GATE_SHARE)?1:0):0)
187 #define IS_SHARE_MOD_GATE(x)  (x->com_gate?((x->com_gate->share & MOD_GATE_SHARE)?1:0):0)
188 
189 /**
190  * struct sunxi-clk-periph - peripheral clock
191  *
192  * @hw:         handle between common and hardware-specific interfaces
193  * @flags:      flags used across common struct clk, please take refference of the clk-provider.h
194  * @lock:       lock for protecting the periph clock operations
195  * @mux:        mux clock
196  * @gate:       gate clock
197  * @divider:    divider clock
198  * @com_gate:       the shared clock
199  * @com_gate_off:   bit shift to mark the flag in the com_gate
200  * @priv_clkops:    divider clock ops
201  * @priv_regops:    gate clock ops
202  */
203 struct sunxi_clk_periph
204 {
205     //struct clk_hw                   hw;
206     //unsigned long                   flags;
207     //spinlock_t                      *lock;
208 
209     struct sunxi_clk_periph_mux     mux;
210     struct sunxi_clk_periph_gate    gate;
211     struct sunxi_clk_periph_div     divider;
212     struct sunxi_clk_comgate       *com_gate;
213     u8                              com_gate_off;
214     //struct clk_ops                 *priv_clkops;
215     //struct sunxi_reg_ops           *priv_regops;
216 };
217 
218 
219 hal_clk_status_t sunxi_clk_periph_get_parent(clk_periph_pt clk, u8 *parent_index);
220 hal_clk_status_t sunxi_clk_periph_set_parent(clk_periph_pt clk, u8 index);
221 hal_clk_status_t sunxi_clk_periph_enable(clk_periph_pt clk);
222 hal_clk_status_t sunxi_clk_periph_is_enabled(clk_periph_pt clk);
223 hal_clk_status_t sunxi_clk_periph_disable(clk_periph_pt clk);
224 hal_clk_status_t sunxi_clk_periph_recalc_rate(clk_periph_pt clk, u32 *rate);
225 u32 sunxi_clk_periph_round_rate(clk_periph_pt clk, u32 rate, u32 prate);
226 hal_clk_status_t sunxi_clk_periph_set_rate(clk_periph_pt clk, u32 rate);
227 
228 
229 #endif /* __MACH_SUNXI_CLK_PERIPH_H */
230