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_FACTORS_H__
33 #define __CLK_FACTORS_H__
34 
35 #include "clk.h"
36 
37 struct sunxi_clk_factor_freq
38 {
39     u32 factor;
40     u32 freq;
41 };
42 
43 #define FACTOR_ALL(nv, ns, nw, kv, ks, kw, mv, ms, mw, \
44                    pv, ps, pw, d1v, d1s, d1w, d2v, d2s, d2w) \
45 ((((nv & ((1 << nw) - 1)) << ns) | \
46   ((kv & ((1 << kw) - 1)) << ks) | \
47   ((mv & ((1 << mw) - 1)) << ms) | \
48   ((pv & ((1 << pw) - 1)) << ps) | \
49   ((d1v & ((1 << d1w) - 1)) << d1s) | \
50   ((d2v & ((1 << d2w) - 1)) << d2s)))
51 
52 #define F_N8X8_P16x2(nv, pv)      (FACTOR_ALL(nv, 8, 8, 0, 0, 0, 0, 0, 0, pv, 16, 2, 0, 0, 0, 0, 0, 0))
53 #define F_N8X8_D1V1X1_D2V0X1(nv, d1v, d2v) (FACTOR_ALL(nv, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, d1v, 1, 1, d2v, 0, 1))
54 #define F_N8X8_D1V1X1(nv, d1v)             (FACTOR_ALL(nv, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, d1v, 1, 1, 0, 0, 0))
55 #define F_N8X8_D1V4X2_D2V0X2(nv, d1v, d2v) (FACTOR_ALL(nv, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, d1v, 4, 2, d2v, 0, 2))
56 #define F_N8X8_P16X6_D1V1X1_D2V0X1(nv, pv, d1v, d2v) (FACTOR_ALL(nv, 8, 8, 0, 0, 0, 0, 0, 0, pv, 16, 6, d1v, 1, 1, d2v, 0, 1))
57 
58 #define PLLCPU(n, p, freq)          {F_N8X8_P16x2(n, p), freq}
59 #define PLLDDR(n, d1, d2, freq)     {F_N8X8_D1V1X1_D2V0X1(n, d1, d2), freq}
60 #define PLLPERIPH0(n, d1, d2, freq)  {F_N8X8_D1V1X1_D2V0X1(n, d1, d2), freq}
61 #define PLLPERIPH1(n, d1, d2, freq)  {F_N8X8_D1V1X1_D2V0X1(n, d1, d2), freq}
62 #define PLLVIDEO0(n, d1, freq)       {F_N8X8_D1V1X1(n, d1), freq}
63 #define PLLAUDIO(n, p, d1, d2, freq) {F_N8X8_P16X6_D1V1X1_D2V0X1(n, p, d1, d2), freq}
64 
65 #define SUNXI_CLK_FACTORS_CONFIG(name, _nshift, _nwidth, _kshift, _kwidth, \
66                                  _mshift, _mwidth, _pshift, _pwidth, _d1shift, _d1width, \
67                                  _d2shift, _d2width, _frac, _outshift, _modeshift, \
68                                  _enshift, _sdmshift, _sdmwidth, _sdmpat, _sdmval, \
69                                  _mux_inshift, _out_enshift)                        \
70 struct sunxi_clk_factors_config sunxi_clk_factor_config_##name = { \
71     .nshift = _nshift,  \
72               .nwidth = _nwidth,  \
73                         .kshift = _kshift,  \
74                                   .kwidth = _kwidth,  \
75                                             .mshift = _mshift,  \
76                                                     .mwidth = _mwidth,  \
77                                                             .pshift = _pshift,  \
78                                                                     .pwidth = _pwidth,  \
79                                                                             .d1shift = _d1shift,    \
80                                                                                     .d1width = _d1width,    \
81                                                                                             .d2shift = _d2shift,    \
82                                                                                                     .d2width = _d2width,    \
83                                                                                                             .frac = _frac,  \
84                                                                                                                     .outshift = _outshift,  \
85                                                                                                                             .modeshift = _modeshift,     \
86                                                                                                                                     .enshift = _enshift,    \
87                                                                                                                                             .sdmshift = _sdmshift,    \
88                                                                                                                                                     .sdmwidth = _sdmwidth,    \
89                                                                                                                                                             .sdmpat  = _sdmpat,    \
90                                                                                                                                                                     .sdmval  = _sdmval,    \
91                                                                                                                                                                             .updshift = 0,         \
92                                                                                                                                                                                     .mux_inshift = _mux_inshift, \
93                                                                                                                                                                                             .out_enshift = _out_enshift, \
94 }
95 
96 #define SUNXI_CLK_FACTORS_INIT(_name, _reg, _lock_reg, _lock_bit, _pll_lock_ctrl_reg, _lock_en_bit )   \
97     struct factor_init_data sunxi_clk_factor_init_##_name = {    \
98         .reg =_reg,     \
99               .lock_reg = _lock_reg,  \
100                           .pll_lock_ctrl_reg = _pll_lock_ctrl_reg,    \
101                                                .lock_bit = _lock_bit,  \
102                                                        .lock_en_bit = _lock_en_bit,    \
103                                                                .lock_mode = PLL_LOCK_NEW_MODE, \
104                                                                        .config = &sunxi_clk_factor_config_##_name,     \
105                                                                                .get_factors = &get_factors_##_name,    \
106                                                                                        .calc_rate = &calc_rate_##_name,    \
107     }
108 
109 #define SUNXI_CLK_FACTOR(_name, _clk, _current_parent, _current_parent_type, _clk_rate,  _parent_rate ) \
110     clk_factor_t sunxi_clk_factor_##_name  = {  \
111                                                 .clk_core = {   \
112                                                                 .clk = _clk,    \
113                                                                 .clk_type = HAL_CLK_FACTOR, \
114                                                                 .current_parent = _current_parent,  \
115                                                                 .current_parent_type = _current_parent_type, \
116                                                                 .clk_rate = _clk_rate,      \
117                                                                 .parent_rate = _parent_rate,        \
118                                                                 .clk_enbale = HAL_CLK_STATUS_DISABLED,   \
119                                                             },  \
120                                                 .factor_data = &sunxi_clk_factor_init_##_name,   \
121                                              }
122 
123 
124 /*no-change-from-linux*/
125 typedef enum pll_lock_mode
126 {
127     PLL_LOCK_NEW_MODE = 0x0,
128     PLL_LOCK_OLD_MODE,
129     PLL_LOCK_NONE_MODE,
130     PLL_LOCK_MODE_MAX,
131 } pll_lock_mode_e;
132 
133 /**
134  * struct clk_factors_value - factor value
135  *
136  * @factorn:    factor-n value
137  * @factork:    factor-k value
138  * @factorm:    factor-m value
139  * @factorp:    factor-p value
140  * @factord1:   factor-d1 value
141  * @factord2:   factor-d2 value
142  * @frac_mode:  fraction mode value
143  * @frac_freq:  fraction frequnecy value
144  */
145 
146 /*no-change-from-linux*/
147 struct clk_factors_value
148 {
149     u16 factorn;
150     u16 factork;
151 
152     u16 factorm;
153     u16 factorp;
154 
155     u16 factord1;
156     u16 factord2;
157 
158     u16 frac_mode;
159     u16 frac_freq;
160 };
161 
162 
163 /**
164  * struct sunxi_clk_factors_config - factor config
165  *
166  * @nshift:     shift to factor-n bit field
167  * @nwidth:     width of factor-n bit field
168  * @kshift:     shift to factor-k bit field
169  * @kwidth:     width of factor-k bit field
170  * @mshift:     shift to factor-m bit field
171  * @mwidth:     width of factor-m bit field
172  * @pshift:     shift to factor-p bit field
173  * @pwidth:     width of factor-p bit field
174  * @d1shift:    shift to factor-d1 bit field
175  * @d1width:    width of factor-d1 bit field
176  * @d2shift:    shift to factor-d2 bit field
177  * @d2width:    width of factor-d2 bit field
178  * @frac:       flag of fraction
179  * @outshift:   shift to frequency select bit field
180  * @modeshift:  shift to fraction/integer mode select
181  * @enshift:    shift to factor enable bit field
182  * @lockshift:  shift to factor lock status bit filed
183  * @sdmshift:   shift to factor sdm enable bit filed
184  * @sdmwidth    shift to factor sdm width bit filed
185  * @sdmpat      sdmpat reg address offset
186  * @sdmval      sdm default value
187  * @updshift    shift to update bit (especial for ddr/ddr0/ddr1)
188  * @delay       for flat factors delay.
189  * @mux_inshift shift to multiplexer(multiple 24M source clocks) bit field
190  * @out_enshift shift to enable pll clock output bit field
191  */
192 /*no-change-from-linux*/
193 struct sunxi_clk_factors_config
194 {
195     u8 nshift;
196     u8 nwidth;
197     u8 kshift;
198     u8 kwidth;
199 
200     u8 mshift;
201     u8 mwidth;
202     u8 pshift;
203     u8 pwidth;
204 
205     u8 d1shift;
206     u8 d1width;
207     u8 d2shift;
208     u8 d2width;
209 
210     u8 frac;
211     u8 outshift;
212     u8 modeshift;
213     u8 enshift;
214 
215     u8 lockshift;
216     u8 sdmshift;
217     u8 sdmwidth;
218 
219     volatile uint32_t *sdmpat;
220     u32 sdmval;
221 
222     u32 updshift;
223     u32 delay;
224 
225     u32 mux_inshift;
226     u32 out_enshift;
227 };
228 
229 /**
230  * struct factor_init_data - factor init data
231  *
232  * @name:       name of the clock
233  * @parent_name:name of the parent
234  * @num_parents:counter of the parents
235  * @flags:      factor optimal configurations
236  * @reg:        register address for the factor
237  * @lock_reg:   register address for check if the pll has locked
238  * @lock_bit:   bit offset of the lock_reg, to check if the the pll has locked
239  * @pll_lock_ctrl_reg: pll lock control register, this function is first used on
240  *              the sun50i, to enable the function of pll hardlock
241  * @lock_en_bit:bit offset of the pll_lock_ctrl_reg, to enable the function
242  * @config:     configuration of the factor
243  * @get_factors:function for get factors parameter under a given frequency
244  * @calc_rate:  function for calculate the factor frequency
245  * @priv_ops:   private operations hook for the special factor
246  * @priv_regops:register operation hook for read/write the register
247  *
248  */
249 struct factor_init_data
250 {
251     //const char          *name;
252     //const char          **parent_names;
253     //int                 num_parents;
254     //unsigned long       flags;
255     volatile uint32_t   *reg;
256     volatile uint32_t   *lock_reg;
257     volatile uint32_t   *pll_lock_ctrl_reg;
258     u8 lock_bit;
259     u8 lock_en_bit;
260     pll_lock_mode_e     lock_mode;
261     struct sunxi_clk_factors_config *config;
262     int (*get_factors)(u32 rate, u32 parent_rate, struct clk_factors_value *factor);
263     int (*calc_rate)(u32 parent_rate, struct clk_factors_value *factor);
264 
265     //struct clk_ops *priv_ops;
266     //struct sunxi_reg_ops *priv_regops;
267 };
268 
269 hal_clk_status_t sunxi_clk_fators_enable(clk_factor_pt clk);
270 hal_clk_status_t sunxi_clk_fators_disable(clk_factor_pt clk);
271 hal_clk_status_t sunxi_clk_fators_is_enabled(clk_factor_pt clk);
272 hal_clk_status_t sunxi_clk_factors_recalc_rate(clk_factor_pt clk, u32 *rate);
273 hal_clk_status_t sunxi_clk_factors_set_rate(clk_factor_pt clk, u32 rate);
274 u32 sunxi_clk_factors_round_rate(clk_factor_pt clk, u32 rate);
275 int sunxi_clk_com_ftr_sr(struct sunxi_clk_factors_config *f_config,
276                          struct clk_factors_value *factor,
277                          struct sunxi_clk_factor_freq table[],
278                          unsigned long index, unsigned long tbl_count);
279 
280 #endif
281