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