]>
Commit | Line | Data |
---|---|---|
d382025d SG |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * (C) Copyright 2022-2023 Sumit Garg <sumit.garg@linaro.org> | |
4 | * | |
5 | * Qcom DWMAC specific glue layer | |
6 | */ | |
7 | ||
d678a59d | 8 | #include <common.h> |
d382025d SG |
9 | #include <asm/global_data.h> |
10 | #include <asm/gpio.h> | |
11 | #include <asm/io.h> | |
12 | #include <clk.h> | |
13 | #include <dm.h> | |
14 | #include <dm/device_compat.h> | |
15 | #include <phy.h> | |
16 | #include <reset.h> | |
17 | #include <syscon.h> | |
18 | #include <linux/bitops.h> | |
19 | #include <linux/delay.h> | |
20 | ||
21 | #include "dwc_eth_qos.h" | |
22 | ||
23 | /* RGMII_IO_MACRO_CONFIG fields */ | |
24 | #define RGMII_CONFIG_FUNC_CLK_EN BIT(30) | |
25 | #define RGMII_CONFIG_POS_NEG_DATA_SEL BIT(23) | |
26 | #define RGMII_CONFIG_GPIO_CFG_RX_INT GENMASK(21, 20) | |
27 | #define RGMII_CONFIG_GPIO_CFG_TX_INT GENMASK(19, 17) | |
28 | #define RGMII_CONFIG_MAX_SPD_PRG_9 GENMASK(16, 8) | |
29 | #define RGMII_CONFIG_MAX_SPD_PRG_2 GENMASK(7, 6) | |
30 | #define RGMII_CONFIG_INTF_SEL GENMASK(5, 4) | |
31 | #define RGMII_CONFIG_BYPASS_TX_ID_EN BIT(3) | |
32 | #define RGMII_CONFIG_LOOPBACK_EN BIT(2) | |
33 | #define RGMII_CONFIG_PROG_SWAP BIT(1) | |
34 | #define RGMII_CONFIG_DDR_MODE BIT(0) | |
35 | ||
36 | /* SDCC_HC_REG_DLL_CONFIG fields */ | |
37 | #define SDCC_DLL_CONFIG_DLL_RST BIT(30) | |
38 | #define SDCC_DLL_CONFIG_PDN BIT(29) | |
39 | #define SDCC_DLL_CONFIG_MCLK_FREQ GENMASK(26, 24) | |
40 | #define SDCC_DLL_CONFIG_CDR_SELEXT GENMASK(23, 20) | |
41 | #define SDCC_DLL_CONFIG_CDR_EXT_EN BIT(19) | |
42 | #define SDCC_DLL_CONFIG_CK_OUT_EN BIT(18) | |
43 | #define SDCC_DLL_CONFIG_CDR_EN BIT(17) | |
44 | #define SDCC_DLL_CONFIG_DLL_EN BIT(16) | |
45 | #define SDCC_DLL_MCLK_GATING_EN BIT(5) | |
46 | #define SDCC_DLL_CDR_FINE_PHASE GENMASK(3, 2) | |
47 | ||
48 | /* SDCC_HC_REG_DDR_CONFIG fields */ | |
49 | #define SDCC_DDR_CONFIG_PRG_DLY_EN BIT(31) | |
50 | #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY GENMASK(26, 21) | |
51 | #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE GENMASK(29, 27) | |
52 | #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN BIT(30) | |
53 | #define SDCC_DDR_CONFIG_PRG_RCLK_DLY GENMASK(8, 0) | |
54 | ||
55 | /* SDCC_HC_REG_DLL_CONFIG2 fields */ | |
56 | #define SDCC_DLL_CONFIG2_DLL_CLOCK_DIS BIT(21) | |
57 | #define SDCC_DLL_CONFIG2_MCLK_FREQ_CALC GENMASK(17, 10) | |
58 | #define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL GENMASK(3, 2) | |
59 | #define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW BIT(1) | |
60 | #define SDCC_DLL_CONFIG2_DDR_CAL_EN BIT(0) | |
61 | ||
62 | /* SDC4_STATUS bits */ | |
63 | #define SDC4_STATUS_DLL_LOCK BIT(7) | |
64 | ||
65 | /* RGMII_IO_MACRO_CONFIG2 fields */ | |
66 | #define RGMII_CONFIG2_RSVD_CONFIG15 GENMASK(31, 17) | |
67 | #define RGMII_CONFIG2_RGMII_CLK_SEL_CFG BIT(16) | |
68 | #define RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN BIT(13) | |
69 | #define RGMII_CONFIG2_CLK_DIVIDE_SEL BIT(12) | |
70 | #define RGMII_CONFIG2_RX_PROG_SWAP BIT(7) | |
71 | #define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6) | |
72 | #define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5) | |
73 | ||
74 | struct dwmac_rgmii_regs { | |
75 | u32 io_macro_config; /* 0x00 */ | |
76 | u32 sdcc_hc_dll_config; /* 0x04 */ | |
77 | u32 reserved_1; /* 0x08 */ | |
78 | u32 sdcc_hc_ddr_config; /* 0x0c */ | |
79 | u32 sdcc_hc_dll_config2; /* 0x10 */ | |
80 | u32 sdc4_status; /* 0x14 */ | |
81 | u32 sdcc_usr_ctl; /* 0x18 */ | |
82 | u32 io_macro_config2; /* 0x1c */ | |
83 | u32 io_macro_debug1; /* 0x20 */ | |
84 | u32 reserved_2; /* 0x24 */ | |
85 | u32 emac_sys_low_power_dbg; /* 0x28 */ | |
86 | u32 reserved_3[53]; /* upto 0x100 */ | |
87 | }; | |
88 | ||
89 | static struct dwmac_rgmii_regs emac_v2_3_0_por = { | |
90 | .io_macro_config = 0x00C01343, | |
91 | .sdcc_hc_dll_config = 0x2004642C, | |
92 | .sdcc_hc_ddr_config = 0x00000000, | |
93 | .sdcc_hc_dll_config2 = 0x00200000, | |
94 | .sdcc_usr_ctl = 0x00010800, | |
95 | .io_macro_config2 = 0x00002060 | |
96 | }; | |
97 | ||
98 | static void ethqos_set_func_clk_en(struct dwmac_rgmii_regs *regs) | |
99 | { | |
100 | setbits_le32(®s->io_macro_config, RGMII_CONFIG_FUNC_CLK_EN); | |
101 | } | |
102 | ||
103 | static int ethqos_dll_configure(struct udevice *dev, | |
104 | struct dwmac_rgmii_regs *regs) | |
105 | { | |
106 | unsigned int val; | |
107 | int retry = 1000; | |
108 | ||
109 | /* Set CDR_EN */ | |
110 | setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CDR_EN); | |
111 | ||
112 | /* Set CDR_EXT_EN */ | |
113 | setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CDR_EXT_EN); | |
114 | ||
115 | /* Clear CK_OUT_EN */ | |
116 | clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CK_OUT_EN); | |
117 | ||
118 | /* Set DLL_EN */ | |
119 | setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_EN); | |
120 | ||
121 | clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_MCLK_GATING_EN); | |
122 | ||
123 | clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CDR_FINE_PHASE); | |
124 | ||
125 | /* Wait for CK_OUT_EN clear */ | |
126 | do { | |
127 | val = readl(®s->sdcc_hc_dll_config); | |
128 | val &= SDCC_DLL_CONFIG_CK_OUT_EN; | |
129 | if (!val) | |
130 | break; | |
131 | mdelay(1); | |
132 | retry--; | |
133 | } while (retry > 0); | |
134 | if (!retry) | |
135 | dev_err(dev, "Clear CK_OUT_EN timedout\n"); | |
136 | ||
137 | /* Set CK_OUT_EN */ | |
138 | setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_CK_OUT_EN); | |
139 | ||
140 | /* Wait for CK_OUT_EN set */ | |
141 | retry = 1000; | |
142 | do { | |
143 | val = readl(®s->sdcc_hc_dll_config); | |
144 | val &= SDCC_DLL_CONFIG_CK_OUT_EN; | |
145 | if (val) | |
146 | break; | |
147 | mdelay(1); | |
148 | retry--; | |
149 | } while (retry > 0); | |
150 | if (!retry) | |
151 | dev_err(dev, "Set CK_OUT_EN timedout\n"); | |
152 | ||
153 | /* Set DDR_CAL_EN */ | |
154 | setbits_le32(®s->sdcc_hc_dll_config2, SDCC_DLL_CONFIG2_DDR_CAL_EN); | |
155 | ||
156 | clrbits_le32(®s->sdcc_hc_dll_config2, | |
157 | SDCC_DLL_CONFIG2_DLL_CLOCK_DIS); | |
158 | ||
159 | clrsetbits_le32(®s->sdcc_hc_dll_config2, | |
160 | SDCC_DLL_CONFIG2_MCLK_FREQ_CALC, 0x1A << 10); | |
161 | ||
162 | clrsetbits_le32(®s->sdcc_hc_dll_config2, | |
163 | SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL, BIT(2)); | |
164 | ||
165 | setbits_le32(®s->sdcc_hc_dll_config2, | |
166 | SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW); | |
167 | ||
168 | return 0; | |
169 | } | |
170 | ||
171 | static int ethqos_rgmii_macro_init(struct udevice *dev, | |
172 | struct dwmac_rgmii_regs *regs, | |
173 | unsigned long speed) | |
174 | { | |
175 | /* Disable loopback mode */ | |
176 | clrbits_le32(®s->io_macro_config2, | |
177 | RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN); | |
178 | ||
179 | /* Select RGMII, write 0 to interface select */ | |
180 | clrbits_le32(®s->io_macro_config, RGMII_CONFIG_INTF_SEL); | |
181 | ||
182 | switch (speed) { | |
183 | case SPEED_1000: | |
184 | setbits_le32(®s->io_macro_config, RGMII_CONFIG_DDR_MODE); | |
185 | clrbits_le32(®s->io_macro_config, | |
186 | RGMII_CONFIG_BYPASS_TX_ID_EN); | |
187 | setbits_le32(®s->io_macro_config, | |
188 | RGMII_CONFIG_POS_NEG_DATA_SEL); | |
189 | setbits_le32(®s->io_macro_config, RGMII_CONFIG_PROG_SWAP); | |
190 | ||
191 | clrbits_le32(®s->io_macro_config2, | |
192 | RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL); | |
193 | setbits_le32(®s->io_macro_config2, | |
194 | RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN); | |
195 | clrbits_le32(®s->io_macro_config2, | |
196 | RGMII_CONFIG2_RSVD_CONFIG15); | |
197 | setbits_le32(®s->io_macro_config2, | |
198 | RGMII_CONFIG2_RX_PROG_SWAP); | |
199 | ||
200 | /* Set PRG_RCLK_DLY to 57 for 1.8 ns delay */ | |
201 | clrsetbits_le32(®s->sdcc_hc_ddr_config, | |
202 | SDCC_DDR_CONFIG_PRG_RCLK_DLY, 57); | |
203 | setbits_le32(®s->sdcc_hc_ddr_config, SDCC_DDR_CONFIG_PRG_DLY_EN); | |
204 | ||
205 | setbits_le32(®s->io_macro_config, RGMII_CONFIG_LOOPBACK_EN); | |
206 | break; | |
207 | ||
208 | case SPEED_100: | |
209 | setbits_le32(®s->io_macro_config, RGMII_CONFIG_DDR_MODE); | |
210 | setbits_le32(®s->io_macro_config, | |
211 | RGMII_CONFIG_BYPASS_TX_ID_EN); | |
212 | clrbits_le32(®s->io_macro_config, | |
213 | RGMII_CONFIG_POS_NEG_DATA_SEL); | |
214 | clrbits_le32(®s->io_macro_config, RGMII_CONFIG_PROG_SWAP); | |
215 | clrsetbits_le32(®s->io_macro_config, | |
216 | RGMII_CONFIG_MAX_SPD_PRG_2, BIT(6)); | |
217 | ||
218 | clrbits_le32(®s->io_macro_config2, | |
219 | RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL); | |
220 | setbits_le32(®s->io_macro_config2, | |
221 | RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN); | |
222 | clrbits_le32(®s->io_macro_config2, | |
223 | RGMII_CONFIG2_RSVD_CONFIG15); | |
224 | clrbits_le32(®s->io_macro_config2, | |
225 | RGMII_CONFIG2_RX_PROG_SWAP); | |
226 | ||
227 | /* Write 0x5 to PRG_RCLK_DLY_CODE */ | |
228 | clrsetbits_le32(®s->sdcc_hc_ddr_config, | |
229 | SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, | |
230 | (BIT(29) | BIT(27))); | |
231 | setbits_le32(®s->sdcc_hc_ddr_config, | |
232 | SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY); | |
233 | setbits_le32(®s->sdcc_hc_ddr_config, | |
234 | SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN); | |
235 | ||
236 | setbits_le32(®s->io_macro_config, RGMII_CONFIG_LOOPBACK_EN); | |
237 | break; | |
238 | ||
239 | case SPEED_10: | |
240 | setbits_le32(®s->io_macro_config, RGMII_CONFIG_DDR_MODE); | |
241 | setbits_le32(®s->io_macro_config, | |
242 | RGMII_CONFIG_BYPASS_TX_ID_EN); | |
243 | clrbits_le32(®s->io_macro_config, | |
244 | RGMII_CONFIG_POS_NEG_DATA_SEL); | |
245 | clrbits_le32(®s->io_macro_config, RGMII_CONFIG_PROG_SWAP); | |
246 | clrsetbits_le32(®s->io_macro_config, | |
247 | RGMII_CONFIG_MAX_SPD_PRG_9, | |
248 | BIT(12) | GENMASK(9, 8)); | |
249 | ||
250 | clrbits_le32(®s->io_macro_config2, | |
251 | RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL); | |
252 | clrbits_le32(®s->io_macro_config2, | |
253 | RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN); | |
254 | clrbits_le32(®s->io_macro_config2, | |
255 | RGMII_CONFIG2_RSVD_CONFIG15); | |
256 | clrbits_le32(®s->io_macro_config2, | |
257 | RGMII_CONFIG2_RX_PROG_SWAP); | |
258 | ||
259 | /* Write 0x5 to PRG_RCLK_DLY_CODE */ | |
260 | clrsetbits_le32(®s->sdcc_hc_ddr_config, | |
261 | SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, | |
262 | (BIT(29) | BIT(27))); | |
263 | setbits_le32(®s->sdcc_hc_ddr_config, | |
264 | SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY); | |
265 | setbits_le32(®s->sdcc_hc_ddr_config, | |
266 | SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN); | |
267 | ||
268 | setbits_le32(®s->io_macro_config, RGMII_CONFIG_LOOPBACK_EN); | |
269 | break; | |
270 | ||
271 | default: | |
272 | dev_err(dev, "Invalid speed %ld\n", speed); | |
273 | return -EINVAL; | |
274 | } | |
275 | ||
276 | return 0; | |
277 | } | |
278 | ||
279 | static int ethqos_configure(struct udevice *dev, | |
280 | struct dwmac_rgmii_regs *regs, | |
281 | unsigned long speed) | |
282 | { | |
283 | unsigned int retry = 1000; | |
284 | ||
285 | /* Reset to POR values and enable clk */ | |
286 | writel(emac_v2_3_0_por.io_macro_config, ®s->io_macro_config); | |
287 | writel(emac_v2_3_0_por.sdcc_hc_dll_config, ®s->sdcc_hc_dll_config); | |
288 | writel(emac_v2_3_0_por.sdcc_hc_ddr_config, ®s->sdcc_hc_ddr_config); | |
289 | writel(emac_v2_3_0_por.sdcc_hc_dll_config2, ®s->sdcc_hc_dll_config2); | |
290 | writel(emac_v2_3_0_por.sdcc_usr_ctl, ®s->sdcc_usr_ctl); | |
291 | writel(emac_v2_3_0_por.io_macro_config2, ®s->io_macro_config2); | |
292 | ||
293 | ethqos_set_func_clk_en(regs); | |
294 | ||
295 | /* Initialize the DLL first */ | |
296 | ||
297 | /* Set DLL_RST */ | |
298 | setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_RST); | |
299 | ||
300 | /* Set PDN */ | |
301 | setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_PDN); | |
302 | ||
303 | /* Clear DLL_RST */ | |
304 | clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_RST); | |
305 | ||
306 | /* Clear PDN */ | |
307 | clrbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_PDN); | |
308 | ||
309 | if (speed == SPEED_1000) { | |
310 | /* Set DLL_EN */ | |
311 | setbits_le32(®s->sdcc_hc_dll_config, SDCC_DLL_CONFIG_DLL_EN); | |
312 | ||
313 | /* Set CK_OUT_EN */ | |
314 | setbits_le32(®s->sdcc_hc_dll_config, | |
315 | SDCC_DLL_CONFIG_CK_OUT_EN); | |
316 | ||
317 | /* Set USR_CTL bit 26 with mask of 3 bits */ | |
318 | clrsetbits_le32(®s->sdcc_usr_ctl, GENMASK(26, 24), BIT(26)); | |
319 | ||
320 | /* wait for DLL LOCK */ | |
321 | do { | |
322 | mdelay(1); | |
323 | if (readl(®s->sdc4_status) & SDC4_STATUS_DLL_LOCK) | |
324 | break; | |
325 | retry--; | |
326 | } while (retry > 0); | |
327 | if (!retry) | |
328 | dev_err(dev, "Timeout while waiting for DLL lock\n"); | |
329 | ||
330 | ethqos_dll_configure(dev, regs); | |
331 | } | |
332 | ||
333 | ethqos_rgmii_macro_init(dev, regs, speed); | |
334 | ||
335 | return 0; | |
336 | } | |
337 | ||
338 | static void ethqos_rgmii_dump(struct udevice *dev, | |
339 | struct dwmac_rgmii_regs *regs) | |
340 | { | |
341 | dev_dbg(dev, "Rgmii register dump\n"); | |
342 | dev_dbg(dev, "RGMII_IO_MACRO_CONFIG: %08x\n", | |
343 | readl(®s->io_macro_config)); | |
344 | dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG: %08x\n", | |
345 | readl(®s->sdcc_hc_dll_config)); | |
346 | dev_dbg(dev, "SDCC_HC_REG_DDR_CONFIG: %08x\n", | |
347 | readl(®s->sdcc_hc_ddr_config)); | |
348 | dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG2: %08x\n", | |
349 | readl(®s->sdcc_hc_dll_config2)); | |
350 | dev_dbg(dev, "SDC4_STATUS: %08x\n", | |
351 | readl(®s->sdc4_status)); | |
352 | dev_dbg(dev, "SDCC_USR_CTL: %08x\n", | |
353 | readl(®s->sdcc_usr_ctl)); | |
354 | dev_dbg(dev, "RGMII_IO_MACRO_CONFIG2: %08x\n", | |
355 | readl(®s->io_macro_config2)); | |
356 | dev_dbg(dev, "RGMII_IO_MACRO_DEBUG1: %08x\n", | |
357 | readl(®s->io_macro_debug1)); | |
358 | dev_dbg(dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %08x\n", | |
359 | readl(®s->emac_sys_low_power_dbg)); | |
360 | } | |
361 | ||
362 | static int qcom_eqos_rgmii_set_speed(struct udevice *dev, | |
363 | void *rgmii_regs, | |
364 | unsigned long speed) | |
365 | { | |
366 | int ret; | |
367 | ||
368 | ethqos_rgmii_dump(dev, rgmii_regs); | |
369 | ||
370 | ret = ethqos_configure(dev, rgmii_regs, speed); | |
371 | if (ret) | |
372 | return ret; | |
373 | ||
374 | ethqos_rgmii_dump(dev, rgmii_regs); | |
375 | ||
376 | return 0; | |
377 | } | |
378 | ||
379 | static int qcom_eqos_rgmii_reset(struct udevice *dev, void *rgmii_regs) | |
380 | { | |
381 | ethqos_set_func_clk_en(rgmii_regs); | |
382 | ||
383 | return 0; | |
384 | } | |
385 | ||
386 | static int eqos_start_clks_qcom(struct udevice *dev) | |
387 | { | |
388 | if (IS_ENABLED(CONFIG_CLK)) { | |
389 | struct clk_bulk clocks; | |
390 | int ret; | |
391 | ||
392 | ret = clk_get_bulk(dev, &clocks); | |
393 | if (ret) | |
394 | return ret; | |
395 | ||
396 | ret = clk_enable_bulk(&clocks); | |
397 | if (ret) | |
398 | return ret; | |
399 | } | |
400 | ||
401 | debug("%s: OK\n", __func__); | |
402 | return 0; | |
403 | } | |
404 | ||
405 | static int eqos_stop_clks_qcom(struct udevice *dev) | |
406 | { | |
407 | if (IS_ENABLED(CONFIG_CLK)) { | |
408 | struct clk_bulk clocks; | |
409 | int ret; | |
410 | ||
411 | ret = clk_get_bulk(dev, &clocks); | |
412 | if (ret) | |
413 | return ret; | |
414 | ||
415 | ret = clk_disable_bulk(&clocks); | |
416 | if (ret) | |
417 | return ret; | |
418 | } | |
419 | ||
420 | debug("%s: OK\n", __func__); | |
421 | return 0; | |
422 | } | |
423 | ||
424 | static int eqos_start_resets_qcom(struct udevice *dev) | |
425 | { | |
426 | struct eqos_priv *eqos = dev_get_priv(dev); | |
427 | int ret; | |
428 | ||
429 | debug("%s(dev=%p):\n", __func__, dev); | |
430 | ||
431 | if (!eqos->phy) { | |
432 | ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); | |
433 | if (ret < 0) { | |
434 | pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", ret); | |
435 | return ret; | |
436 | } | |
437 | ||
438 | udelay(eqos->reset_delays[0]); | |
439 | ||
440 | ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); | |
441 | if (ret < 0) { | |
442 | pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret); | |
443 | return ret; | |
444 | } | |
445 | ||
446 | udelay(eqos->reset_delays[1]); | |
447 | ||
448 | ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); | |
449 | if (ret < 0) { | |
450 | pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret); | |
451 | return ret; | |
452 | } | |
453 | ||
454 | udelay(eqos->reset_delays[2]); | |
455 | } | |
456 | ||
457 | ret = reset_deassert(&eqos->reset_ctl); | |
458 | if (ret < 0) { | |
459 | pr_err("reset_deassert() failed: %d", ret); | |
460 | return ret; | |
461 | } | |
462 | ||
463 | ret = qcom_eqos_rgmii_reset(dev, eqos->eqos_qcom_rgmii_regs); | |
464 | if (ret < 0) { | |
465 | pr_err("qcom rgmii_reset failed: %d", ret); | |
466 | return ret; | |
467 | } | |
468 | ||
469 | debug("%s: OK\n", __func__); | |
470 | return 0; | |
471 | } | |
472 | ||
473 | /* Clock rates */ | |
474 | #define RGMII_1000_NOM_CLK_FREQ (250 * 1000 * 1000UL) | |
475 | #define RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ (50 * 1000 * 1000UL) | |
476 | #define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ (5 * 1000 * 1000UL) | |
477 | ||
478 | static int eqos_set_tx_clk_speed_qcom(struct udevice *dev) | |
479 | { | |
480 | struct eqos_priv *eqos = dev_get_priv(dev); | |
481 | ulong rate; | |
482 | int ret; | |
483 | ||
484 | debug("%s(dev=%p):\n", __func__, dev); | |
485 | ||
486 | switch (eqos->phy->speed) { | |
487 | case SPEED_1000: | |
488 | rate = RGMII_1000_NOM_CLK_FREQ; | |
489 | break; | |
490 | case SPEED_100: | |
491 | rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ; | |
492 | break; | |
493 | case SPEED_10: | |
494 | rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ; | |
495 | break; | |
496 | default: | |
497 | pr_err("invalid speed %d", eqos->phy->speed); | |
498 | return -EINVAL; | |
499 | } | |
500 | ||
501 | ret = clk_set_rate(&eqos->clk_tx, rate); | |
502 | if (ret < 0) { | |
503 | pr_err("clk_set_rate(tx_clk, %lu) failed: %d", rate, ret); | |
504 | return ret; | |
505 | } | |
506 | ||
507 | ret = qcom_eqos_rgmii_set_speed(dev, eqos->eqos_qcom_rgmii_regs, | |
508 | eqos->phy->speed); | |
509 | if (ret < 0) { | |
510 | pr_err("qcom set_speed: %d, failed: %d", eqos->phy->speed, ret); | |
511 | return ret; | |
512 | } | |
513 | ||
514 | return 0; | |
515 | } | |
516 | ||
517 | static int eqos_probe_resources_qcom(struct udevice *dev) | |
518 | { | |
519 | struct eqos_priv *eqos = dev_get_priv(dev); | |
520 | phy_interface_t interface; | |
521 | int reset_flags = GPIOD_IS_OUT; | |
522 | int ret; | |
523 | ||
524 | debug("%s(dev=%p):\n", __func__, dev); | |
525 | ||
526 | interface = eqos->config->interface(dev); | |
527 | ||
528 | if (interface == PHY_INTERFACE_MODE_NA) { | |
529 | pr_err("Invalid PHY interface\n"); | |
530 | return -EINVAL; | |
531 | } | |
532 | ||
533 | eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0); | |
534 | ||
535 | eqos->tx_fifo_sz = dev_read_u32_default(dev, "tx-fifo-depth", 0); | |
536 | eqos->rx_fifo_sz = dev_read_u32_default(dev, "rx-fifo-depth", 0); | |
537 | ||
538 | ret = reset_get_by_name(dev, "emac", &eqos->reset_ctl); | |
539 | if (ret) { | |
540 | pr_err("reset_get_by_name(rst) failed: %d", ret); | |
541 | return ret; | |
542 | } | |
543 | ||
544 | if (dev_read_bool(dev, "snps,reset-active-low")) | |
545 | reset_flags |= GPIOD_ACTIVE_LOW; | |
546 | ||
547 | ret = gpio_request_by_name(dev, "snps,reset-gpio", 0, | |
548 | &eqos->phy_reset_gpio, reset_flags); | |
549 | if (ret == 0) { | |
550 | ret = dev_read_u32_array(dev, "snps,reset-delays-us", | |
551 | eqos->reset_delays, 3); | |
552 | } else if (ret == -ENOENT) { | |
553 | ret = 0; | |
554 | } | |
555 | ||
556 | eqos->eqos_qcom_rgmii_regs = (void *)dev_read_addr_name(dev, "rgmii"); | |
557 | if ((fdt_addr_t)eqos->eqos_qcom_rgmii_regs == FDT_ADDR_T_NONE) { | |
558 | pr_err("Invalid RGMII address\n"); | |
559 | return -EINVAL; | |
560 | } | |
561 | ||
562 | ret = clk_get_by_name(dev, "rgmii", &eqos->clk_tx); | |
563 | if (ret) { | |
564 | pr_err("clk_get_by_name(tx) failed: %d", ret); | |
565 | return -EINVAL; | |
566 | } | |
567 | ||
568 | debug("%s: OK\n", __func__); | |
569 | return 0; | |
570 | } | |
571 | ||
572 | static int eqos_remove_resources_qcom(struct udevice *dev) | |
573 | { | |
574 | struct eqos_priv *eqos = dev_get_priv(dev); | |
575 | ||
576 | debug("%s(dev=%p):\n", __func__, dev); | |
577 | ||
d382025d SG |
578 | dm_gpio_free(dev, &eqos->phy_reset_gpio); |
579 | reset_free(&eqos->reset_ctl); | |
580 | ||
581 | debug("%s: OK\n", __func__); | |
582 | return 0; | |
583 | } | |
584 | ||
585 | static struct eqos_ops eqos_qcom_ops = { | |
586 | .eqos_inval_desc = eqos_inval_desc_generic, | |
587 | .eqos_flush_desc = eqos_flush_desc_generic, | |
588 | .eqos_inval_buffer = eqos_inval_buffer_generic, | |
589 | .eqos_flush_buffer = eqos_flush_buffer_generic, | |
590 | .eqos_probe_resources = eqos_probe_resources_qcom, | |
591 | .eqos_remove_resources = eqos_remove_resources_qcom, | |
592 | .eqos_stop_resets = eqos_null_ops, | |
593 | .eqos_start_resets = eqos_start_resets_qcom, | |
594 | .eqos_stop_clks = eqos_stop_clks_qcom, | |
595 | .eqos_start_clks = eqos_start_clks_qcom, | |
596 | .eqos_calibrate_pads = eqos_null_ops, | |
597 | .eqos_disable_calibration = eqos_null_ops, | |
598 | .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_qcom, | |
599 | .eqos_get_enetaddr = eqos_null_ops, | |
600 | }; | |
601 | ||
602 | struct eqos_config __maybe_unused eqos_qcom_config = { | |
603 | .reg_access_always_ok = false, | |
604 | .mdio_wait = 10, | |
605 | .swr_wait = 50, | |
606 | .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, | |
607 | .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, | |
608 | .axi_bus_width = EQOS_AXI_WIDTH_64, | |
609 | .interface = dev_read_phy_mode, | |
610 | .ops = &eqos_qcom_ops | |
611 | }; |