1 /* 2 * Copyright (c) 2020 Antmicro <www.antmicro.com> 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef LITEX_MMCM_H 8 #define LITEX_MMCM_H 9 10 #include <zephyr/sys/util.h> 11 #include <zephyr/types.h> 12 13 /* Common values */ 14 #define PICOS_IN_SEC 1000000000000 15 16 /* MMCM specific numbers */ 17 #define CLKOUT_MAX 7 18 #define DELAY_TIME_MAX 63 19 #define PHASE_MUX_MAX 7 20 #define HIGH_LOW_TIME_REG_MAX 63 21 #define PHASE_MUX_RES_FACTOR 8 22 23 /* DRP registers index */ 24 #define DRP_RESET 0 25 #define DRP_LOCKED 1 26 #define DRP_READ 2 27 #define DRP_WRITE 3 28 #define DRP_DRDY 4 29 #define DRP_ADR 5 30 #define DRP_DAT_W 6 31 #define DRP_DAT_R 7 32 33 /* Base address */ 34 #define DRP_BASE DT_REG_ADDR_BY_IDX(MMCM, 0) 35 /* Register address */ 36 #define DRP_ADDR_RESET DT_REG_ADDR_BY_NAME(MMCM, drp_reset) 37 #define DRP_ADDR_LOCKED DT_REG_ADDR_BY_NAME(MMCM, drp_locked) 38 #define DRP_ADDR_READ DT_REG_ADDR_BY_NAME(MMCM, drp_read) 39 #define DRP_ADDR_WRITE DT_REG_ADDR_BY_NAME(MMCM, drp_write) 40 #define DRP_ADDR_DRDY DT_REG_ADDR_BY_NAME(MMCM, drp_drdy) 41 #define DRP_ADDR_ADR DT_REG_ADDR_BY_NAME(MMCM, drp_adr) 42 #define DRP_ADDR_DAT_W DT_REG_ADDR_BY_NAME(MMCM, drp_dat_w) 43 #define DRP_ADDR_DAT_R DT_REG_ADDR_BY_NAME(MMCM, drp_dat_r) 44 45 /* Devicetree global defines */ 46 #define LOCK_TIMEOUT DT_PROP(MMCM, litex_lock_timeout) 47 #define DRDY_TIMEOUT DT_PROP(MMCM, litex_drdy_timeout) 48 #define DIVCLK_DIVIDE_MIN DT_PROP(MMCM, litex_divclk_divide_min) 49 #define DIVCLK_DIVIDE_MAX DT_PROP(MMCM, litex_divclk_divide_max) 50 #define CLKFBOUT_MULT_MIN DT_PROP(MMCM, litex_clkfbout_mult_min) 51 #define CLKFBOUT_MULT_MAX DT_PROP(MMCM, litex_clkfbout_mult_max) 52 #define VCO_FREQ_MIN DT_PROP(MMCM, litex_vco_freq_min) 53 #define VCO_FREQ_MAX DT_PROP(MMCM, litex_vco_freq_max) 54 #define CLKOUT_DIVIDE_MIN DT_PROP(MMCM, litex_clkout_divide_min) 55 #define CLKOUT_DIVIDE_MAX DT_PROP(MMCM, litex_clkout_divide_max) 56 #define VCO_MARGIN DT_PROP(MMCM, litex_vco_margin) 57 58 #define CLKOUT_INIT(N) \ 59 BUILD_ASSERT(CLKOUT_DUTY_DEN(N) > 0 && \ 60 CLKOUT_DUTY_NUM(N) > 0 && \ 61 CLKOUT_DUTY_NUM(N) <= CLKOUT_DUTY_DEN(N), \ 62 "Invalid default duty"); \ 63 BUILD_ASSERT(CLKOUT_ID(N) < NCLKOUT, "Invalid CLKOUT index"); \ 64 lcko = &ldev->clkouts[N]; \ 65 lcko->id = CLKOUT_ID(N); \ 66 \ 67 lcko->clkout_div = clkout_div; \ 68 lcko->def.freq = CLKOUT_FREQ(N); \ 69 lcko->def.phase = CLKOUT_PHASE(N); \ 70 lcko->def.duty.num = CLKOUT_DUTY_NUM(N); \ 71 lcko->def.duty.den = CLKOUT_DUTY_DEN(N); \ 72 lcko->margin.m = CLKOUT_MARGIN(N); \ 73 lcko->margin.exp = CLKOUT_MARGIN_EXP(N); 74 75 /* Devicetree clkout defines */ 76 #define CLKOUT_EXIST(N) DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(clk##N)) 77 #define CLKOUT_ID(N) DT_REG_ADDR(DT_NODELABEL(clk##N)) 78 #define CLKOUT_FREQ(N) DT_PROP(DT_NODELABEL(clk##N), \ 79 litex_clock_frequency) 80 #define CLKOUT_PHASE(N) DT_PROP(DT_NODELABEL(clk##N), \ 81 litex_clock_phase) 82 #define CLKOUT_DUTY_NUM(N) DT_PROP(DT_NODELABEL(clk##N), \ 83 litex_clock_duty_num) 84 #define CLKOUT_DUTY_DEN(N) DT_PROP(DT_NODELABEL(clk##N), \ 85 litex_clock_duty_den) 86 #define CLKOUT_MARGIN(N) DT_PROP(DT_NODELABEL(clk##N), \ 87 litex_clock_margin) 88 #define CLKOUT_MARGIN_EXP(N) DT_PROP(DT_NODELABEL(clk##N), \ 89 litex_clock_margin_exp) 90 91 /* Register values */ 92 #define FULL_REG_16 0xFFFF 93 #define ZERO_REG 0x0 94 #define KEEP_IN_MUL_REG1 0xF000 95 #define KEEP_IN_MUL_REG2 0xFF3F 96 #define KEEP_IN_DIV 0xC000 97 #define REG1_FREQ_MASK 0xF000 98 #define REG2_FREQ_MASK 0x803F 99 #define REG1_DUTY_MASK 0xF000 100 #define REG2_DUTY_MASK 0xFF7F 101 #define REG1_PHASE_MASK 0x1FFF 102 #define REG2_PHASE_MASK 0xFCC0 103 #define FILT1_MASK 0x66FF 104 #define FILT2_MASK 0x666F 105 #define LOCK1_MASK 0xFC00 106 #define LOCK23_MASK 0x8000 107 /* Control bits extraction masks */ 108 #define HL_TIME_MASK 0x3F 109 #define FRAC_MASK 0x7 110 #define EDGE_MASK 0x1 111 #define NO_CNT_MASK 0x1 112 #define FRAC_EN_MASK 0x1 113 #define PHASE_MUX_MASK 0x7 114 115 /* Bit groups start position in DRP registers */ 116 #define HIGH_TIME_POS 6 117 #define LOW_TIME_POS 0 118 #define PHASE_MUX_POS 13 119 #define FRAC_POS 12 120 #define FRAC_EN_POS 11 121 #define FRAC_WF_R_POS 10 122 #define EDGE_POS 7 123 #define NO_CNT_POS 6 124 #define EDGE_DIVREG_POS 13 125 #define NO_CNT_DIVREG_POS 12 126 #define DELAY_TIME_POS 0 127 128 /* MMCM Register addresses */ 129 #define POWER_REG 0x28 130 #define DIV_REG 0x16 131 #define LOCK_REG1 0x18 132 #define LOCK_REG2 0x19 133 #define LOCK_REG3 0x1A 134 #define FILT_REG1 0x4E 135 #define FILT_REG2 0x4F 136 #define CLKOUT0_REG1 0x08 137 #define CLKOUT0_REG2 0x09 138 #define CLKOUT1_REG1 0x0A 139 #define CLKOUT1_REG2 0x0B 140 #define CLKOUT2_REG1 0x0C 141 #define CLKOUT2_REG2 0x0D 142 #define CLKOUT3_REG1 0x0E 143 #define CLKOUT3_REG2 0x0F 144 #define CLKOUT4_REG1 0x10 145 #define CLKOUT4_REG2 0x11 146 #define CLKOUT5_REG1 0x06 147 #define CLKOUT5_REG2 0x07 148 #define CLKOUT6_REG1 0x12 149 #define CLKOUT6_REG2 0x13 150 #define CLKFBOUT_REG1 0x14 151 #define CLKFBOUT_REG2 0x15 152 153 /* Basic structure for DRP registers */ 154 struct litex_drp_reg { 155 uint32_t addr; 156 uint32_t size; 157 }; 158 159 struct litex_clk_range { 160 uint32_t min; 161 uint32_t max; 162 }; 163 164 struct clk_duty { 165 uint32_t num; 166 uint32_t den; 167 }; 168 169 struct litex_clk_default { 170 struct clk_duty duty; 171 int phase; 172 uint32_t freq; 173 }; 174 175 struct litex_clk_glob_params { 176 uint64_t freq; 177 uint32_t div; 178 uint32_t mul; 179 }; 180 181 /* Divider configuration bits group */ 182 struct litex_clk_div_params { 183 uint8_t high_time; 184 uint8_t low_time; 185 uint8_t no_cnt; 186 uint8_t edge; 187 }; 188 189 /* Phase configuration bits group */ 190 struct litex_clk_phase_params { 191 uint8_t phase_mux; 192 uint8_t delay_time; 193 uint8_t mx; 194 }; 195 196 /* Fractional configuration bits group */ 197 struct litex_clk_frac_params { 198 uint8_t frac_en; 199 uint8_t frac; 200 uint8_t phase_mux_f; 201 uint8_t frac_wf_r; 202 uint8_t frac_wf_f; 203 }; 204 205 struct litex_clk_params { 206 struct clk_duty duty; 207 int phase; 208 uint32_t freq; 209 uint32_t period_off; 210 uint8_t div; 211 }; 212 213 struct litex_clk_timeout { 214 uint32_t lock; 215 uint32_t drdy; 216 }; 217 218 /* Basic structure for MMCM reg addresses */ 219 struct litex_clk_clkout_addr { 220 uint8_t reg1; 221 uint8_t reg2; 222 }; 223 224 /* Structure for all MMCM regs */ 225 struct litex_clk_regs_addr { 226 struct litex_clk_clkout_addr clkout[CLKOUT_MAX]; 227 }; 228 229 struct litex_clk_clkout_margin { 230 uint32_t m; /* margin factor scaled to integer */ 231 uint32_t exp; 232 }; 233 234 struct litex_clk_device { 235 uint32_t *base; 236 /*struct clk_hw clk_hw;*/ 237 struct litex_clk_clkout *clkouts; /* array of clock outputs */ 238 struct litex_clk_timeout timeout; /* timeouts for wait functions*/ 239 struct litex_clk_glob_params g_config; /* general MMCM settings */ 240 struct litex_clk_glob_params ts_g_config;/* settings to set*/ 241 struct litex_clk_range divclk; /* divclk_divide_range */ 242 struct litex_clk_range clkfbout; /* clkfbout_mult_frange */ 243 struct litex_clk_range vco; /* vco_freq_range */ 244 uint8_t *update_clkout; /* which clkout needs update */ 245 uint32_t vco_margin; 246 uint32_t nclkout; 247 }; 248 249 struct litex_clk_clkout { 250 uint32_t *base; 251 struct litex_clk_device *ldev; /* global data */ 252 struct litex_clk_default def; /* DTS defaults */ 253 struct litex_clk_params config; /* real CLKOUT settings */ 254 struct litex_clk_params ts_config; /* CLKOUT settings to set */ 255 struct litex_clk_div_params div; /* CLKOUT configuration groups*/ 256 struct litex_clk_phase_params phase; 257 struct litex_clk_frac_params frac; 258 struct litex_clk_range clkout_div; /* clkout_divide_range */ 259 struct litex_clk_clkout_margin margin; 260 uint32_t id; 261 }; 262 263 #endif /* LITEX_MMCM_H */ 264