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