1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (c) 2018-19, Linaro Limited |
3 | |
4 | #include <linux/module.h> |
5 | #include <linux/of.h> |
6 | #include <linux/of_net.h> |
7 | #include <linux/platform_device.h> |
8 | #include <linux/phy.h> |
9 | #include <linux/phy/phy.h> |
10 | |
11 | #include "stmmac.h" |
12 | #include "stmmac_platform.h" |
13 | |
14 | #define RGMII_IO_MACRO_CONFIG 0x0 |
15 | #define SDCC_HC_REG_DLL_CONFIG 0x4 |
16 | #define SDCC_TEST_CTL 0x8 |
17 | #define SDCC_HC_REG_DDR_CONFIG 0xC |
18 | #define SDCC_HC_REG_DLL_CONFIG2 0x10 |
19 | #define SDC4_STATUS 0x14 |
20 | #define SDCC_USR_CTL 0x18 |
21 | #define RGMII_IO_MACRO_CONFIG2 0x1C |
22 | #define RGMII_IO_MACRO_DEBUG1 0x20 |
23 | #define EMAC_SYSTEM_LOW_POWER_DEBUG 0x28 |
24 | |
25 | /* RGMII_IO_MACRO_CONFIG fields */ |
26 | #define RGMII_CONFIG_FUNC_CLK_EN BIT(30) |
27 | #define RGMII_CONFIG_POS_NEG_DATA_SEL BIT(23) |
28 | #define RGMII_CONFIG_GPIO_CFG_RX_INT GENMASK(21, 20) |
29 | #define RGMII_CONFIG_GPIO_CFG_TX_INT GENMASK(19, 17) |
30 | #define RGMII_CONFIG_MAX_SPD_PRG_9 GENMASK(16, 8) |
31 | #define RGMII_CONFIG_MAX_SPD_PRG_2 GENMASK(7, 6) |
32 | #define RGMII_CONFIG_INTF_SEL GENMASK(5, 4) |
33 | #define RGMII_CONFIG_BYPASS_TX_ID_EN BIT(3) |
34 | #define RGMII_CONFIG_LOOPBACK_EN BIT(2) |
35 | #define RGMII_CONFIG_PROG_SWAP BIT(1) |
36 | #define RGMII_CONFIG_DDR_MODE BIT(0) |
37 | #define RGMII_CONFIG_SGMII_CLK_DVDR GENMASK(18, 10) |
38 | |
39 | /* SDCC_HC_REG_DLL_CONFIG fields */ |
40 | #define SDCC_DLL_CONFIG_DLL_RST BIT(30) |
41 | #define SDCC_DLL_CONFIG_PDN BIT(29) |
42 | #define SDCC_DLL_CONFIG_MCLK_FREQ GENMASK(26, 24) |
43 | #define SDCC_DLL_CONFIG_CDR_SELEXT GENMASK(23, 20) |
44 | #define SDCC_DLL_CONFIG_CDR_EXT_EN BIT(19) |
45 | #define SDCC_DLL_CONFIG_CK_OUT_EN BIT(18) |
46 | #define SDCC_DLL_CONFIG_CDR_EN BIT(17) |
47 | #define SDCC_DLL_CONFIG_DLL_EN BIT(16) |
48 | #define SDCC_DLL_MCLK_GATING_EN BIT(5) |
49 | #define SDCC_DLL_CDR_FINE_PHASE GENMASK(3, 2) |
50 | |
51 | /* SDCC_HC_REG_DDR_CONFIG fields */ |
52 | #define SDCC_DDR_CONFIG_PRG_DLY_EN BIT(31) |
53 | #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY GENMASK(26, 21) |
54 | #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE GENMASK(29, 27) |
55 | #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN BIT(30) |
56 | #define SDCC_DDR_CONFIG_TCXO_CYCLES_CNT GENMASK(11, 9) |
57 | #define SDCC_DDR_CONFIG_PRG_RCLK_DLY GENMASK(8, 0) |
58 | |
59 | /* SDCC_HC_REG_DLL_CONFIG2 fields */ |
60 | #define SDCC_DLL_CONFIG2_DLL_CLOCK_DIS BIT(21) |
61 | #define SDCC_DLL_CONFIG2_MCLK_FREQ_CALC GENMASK(17, 10) |
62 | #define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL GENMASK(3, 2) |
63 | #define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW BIT(1) |
64 | #define SDCC_DLL_CONFIG2_DDR_CAL_EN BIT(0) |
65 | |
66 | /* SDC4_STATUS bits */ |
67 | #define SDC4_STATUS_DLL_LOCK BIT(7) |
68 | |
69 | /* RGMII_IO_MACRO_CONFIG2 fields */ |
70 | #define RGMII_CONFIG2_RSVD_CONFIG15 GENMASK(31, 17) |
71 | #define RGMII_CONFIG2_RGMII_CLK_SEL_CFG BIT(16) |
72 | #define RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN BIT(13) |
73 | #define RGMII_CONFIG2_CLK_DIVIDE_SEL BIT(12) |
74 | #define RGMII_CONFIG2_RX_PROG_SWAP BIT(7) |
75 | #define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6) |
76 | #define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5) |
77 | |
78 | /* MAC_CTRL_REG bits */ |
79 | #define ETHQOS_MAC_CTRL_SPEED_MODE BIT(14) |
80 | #define ETHQOS_MAC_CTRL_PORT_SEL BIT(15) |
81 | |
82 | #define SGMII_10M_RX_CLK_DVDR 0x31 |
83 | |
84 | struct ethqos_emac_por { |
85 | unsigned int offset; |
86 | unsigned int value; |
87 | }; |
88 | |
89 | struct ethqos_emac_driver_data { |
90 | const struct ethqos_emac_por *por; |
91 | unsigned int num_por; |
92 | bool rgmii_config_loopback_en; |
93 | bool has_emac_ge_3; |
94 | const char *link_clk_name; |
95 | bool has_integrated_pcs; |
96 | struct dwmac4_addrs dwmac4_addrs; |
97 | }; |
98 | |
99 | struct qcom_ethqos { |
100 | struct platform_device *pdev; |
101 | void __iomem *rgmii_base; |
102 | void __iomem *mac_base; |
103 | int (*configure_func)(struct qcom_ethqos *ethqos); |
104 | |
105 | unsigned int link_clk_rate; |
106 | struct clk *link_clk; |
107 | struct phy *serdes_phy; |
108 | unsigned int speed; |
109 | int serdes_speed; |
110 | phy_interface_t phy_mode; |
111 | |
112 | const struct ethqos_emac_por *por; |
113 | unsigned int num_por; |
114 | bool rgmii_config_loopback_en; |
115 | bool has_emac_ge_3; |
116 | }; |
117 | |
118 | static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset) |
119 | { |
120 | return readl(addr: ethqos->rgmii_base + offset); |
121 | } |
122 | |
123 | static void rgmii_writel(struct qcom_ethqos *ethqos, |
124 | int value, unsigned int offset) |
125 | { |
126 | writel(val: value, addr: ethqos->rgmii_base + offset); |
127 | } |
128 | |
129 | static void rgmii_updatel(struct qcom_ethqos *ethqos, |
130 | int mask, int val, unsigned int offset) |
131 | { |
132 | unsigned int temp; |
133 | |
134 | temp = rgmii_readl(ethqos, offset); |
135 | temp = (temp & ~(mask)) | val; |
136 | rgmii_writel(ethqos, value: temp, offset); |
137 | } |
138 | |
139 | static void rgmii_dump(void *priv) |
140 | { |
141 | struct qcom_ethqos *ethqos = priv; |
142 | struct device *dev = ðqos->pdev->dev; |
143 | |
144 | dev_dbg(dev, "Rgmii register dump\n" ); |
145 | dev_dbg(dev, "RGMII_IO_MACRO_CONFIG: %x\n" , |
146 | rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG)); |
147 | dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG: %x\n" , |
148 | rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG)); |
149 | dev_dbg(dev, "SDCC_HC_REG_DDR_CONFIG: %x\n" , |
150 | rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG)); |
151 | dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n" , |
152 | rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2)); |
153 | dev_dbg(dev, "SDC4_STATUS: %x\n" , |
154 | rgmii_readl(ethqos, SDC4_STATUS)); |
155 | dev_dbg(dev, "SDCC_USR_CTL: %x\n" , |
156 | rgmii_readl(ethqos, SDCC_USR_CTL)); |
157 | dev_dbg(dev, "RGMII_IO_MACRO_CONFIG2: %x\n" , |
158 | rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2)); |
159 | dev_dbg(dev, "RGMII_IO_MACRO_DEBUG1: %x\n" , |
160 | rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1)); |
161 | dev_dbg(dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n" , |
162 | rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG)); |
163 | } |
164 | |
165 | /* Clock rates */ |
166 | #define RGMII_1000_NOM_CLK_FREQ (250 * 1000 * 1000UL) |
167 | #define RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ (50 * 1000 * 1000UL) |
168 | #define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ (5 * 1000 * 1000UL) |
169 | |
170 | static void |
171 | ethqos_update_link_clk(struct qcom_ethqos *ethqos, unsigned int speed) |
172 | { |
173 | if (!phy_interface_mode_is_rgmii(mode: ethqos->phy_mode)) |
174 | return; |
175 | |
176 | switch (speed) { |
177 | case SPEED_1000: |
178 | ethqos->link_clk_rate = RGMII_1000_NOM_CLK_FREQ; |
179 | break; |
180 | |
181 | case SPEED_100: |
182 | ethqos->link_clk_rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ; |
183 | break; |
184 | |
185 | case SPEED_10: |
186 | ethqos->link_clk_rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ; |
187 | break; |
188 | } |
189 | |
190 | clk_set_rate(clk: ethqos->link_clk, rate: ethqos->link_clk_rate); |
191 | } |
192 | |
193 | static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos) |
194 | { |
195 | rgmii_updatel(ethqos, RGMII_CONFIG_FUNC_CLK_EN, |
196 | RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG); |
197 | } |
198 | |
199 | static const struct ethqos_emac_por emac_v2_3_0_por[] = { |
200 | { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x00C01343 }, |
201 | { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642C }, |
202 | { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x00000000 }, |
203 | { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 }, |
204 | { .offset = SDCC_USR_CTL, .value = 0x00010800 }, |
205 | { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 }, |
206 | }; |
207 | |
208 | static const struct ethqos_emac_driver_data emac_v2_3_0_data = { |
209 | .por = emac_v2_3_0_por, |
210 | .num_por = ARRAY_SIZE(emac_v2_3_0_por), |
211 | .rgmii_config_loopback_en = true, |
212 | .has_emac_ge_3 = false, |
213 | }; |
214 | |
215 | static const struct ethqos_emac_por emac_v2_1_0_por[] = { |
216 | { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x40C01343 }, |
217 | { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642C }, |
218 | { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x00000000 }, |
219 | { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 }, |
220 | { .offset = SDCC_USR_CTL, .value = 0x00010800 }, |
221 | { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 }, |
222 | }; |
223 | |
224 | static const struct ethqos_emac_driver_data emac_v2_1_0_data = { |
225 | .por = emac_v2_1_0_por, |
226 | .num_por = ARRAY_SIZE(emac_v2_1_0_por), |
227 | .rgmii_config_loopback_en = false, |
228 | .has_emac_ge_3 = false, |
229 | }; |
230 | |
231 | static const struct ethqos_emac_por emac_v3_0_0_por[] = { |
232 | { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x40c01343 }, |
233 | { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642c }, |
234 | { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x80040800 }, |
235 | { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 }, |
236 | { .offset = SDCC_USR_CTL, .value = 0x00010800 }, |
237 | { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 }, |
238 | }; |
239 | |
240 | static const struct ethqos_emac_driver_data emac_v3_0_0_data = { |
241 | .por = emac_v3_0_0_por, |
242 | .num_por = ARRAY_SIZE(emac_v3_0_0_por), |
243 | .rgmii_config_loopback_en = false, |
244 | .has_emac_ge_3 = true, |
245 | .dwmac4_addrs = { |
246 | .dma_chan = 0x00008100, |
247 | .dma_chan_offset = 0x1000, |
248 | .mtl_chan = 0x00008000, |
249 | .mtl_chan_offset = 0x1000, |
250 | .mtl_ets_ctrl = 0x00008010, |
251 | .mtl_ets_ctrl_offset = 0x1000, |
252 | .mtl_txq_weight = 0x00008018, |
253 | .mtl_txq_weight_offset = 0x1000, |
254 | .mtl_send_slp_cred = 0x0000801c, |
255 | .mtl_send_slp_cred_offset = 0x1000, |
256 | .mtl_high_cred = 0x00008020, |
257 | .mtl_high_cred_offset = 0x1000, |
258 | .mtl_low_cred = 0x00008024, |
259 | .mtl_low_cred_offset = 0x1000, |
260 | }, |
261 | }; |
262 | |
263 | static const struct ethqos_emac_por emac_v4_0_0_por[] = { |
264 | { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x40c01343 }, |
265 | { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642c }, |
266 | { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x80040800 }, |
267 | { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 }, |
268 | { .offset = SDCC_USR_CTL, .value = 0x00010800 }, |
269 | { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 }, |
270 | }; |
271 | |
272 | static const struct ethqos_emac_driver_data emac_v4_0_0_data = { |
273 | .por = emac_v4_0_0_por, |
274 | .num_por = ARRAY_SIZE(emac_v3_0_0_por), |
275 | .rgmii_config_loopback_en = false, |
276 | .has_emac_ge_3 = true, |
277 | .link_clk_name = "phyaux" , |
278 | .has_integrated_pcs = true, |
279 | .dwmac4_addrs = { |
280 | .dma_chan = 0x00008100, |
281 | .dma_chan_offset = 0x1000, |
282 | .mtl_chan = 0x00008000, |
283 | .mtl_chan_offset = 0x1000, |
284 | .mtl_ets_ctrl = 0x00008010, |
285 | .mtl_ets_ctrl_offset = 0x1000, |
286 | .mtl_txq_weight = 0x00008018, |
287 | .mtl_txq_weight_offset = 0x1000, |
288 | .mtl_send_slp_cred = 0x0000801c, |
289 | .mtl_send_slp_cred_offset = 0x1000, |
290 | .mtl_high_cred = 0x00008020, |
291 | .mtl_high_cred_offset = 0x1000, |
292 | .mtl_low_cred = 0x00008024, |
293 | .mtl_low_cred_offset = 0x1000, |
294 | }, |
295 | }; |
296 | |
297 | static int ethqos_dll_configure(struct qcom_ethqos *ethqos) |
298 | { |
299 | struct device *dev = ðqos->pdev->dev; |
300 | unsigned int val; |
301 | int retry = 1000; |
302 | |
303 | /* Set CDR_EN */ |
304 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EN, |
305 | SDCC_DLL_CONFIG_CDR_EN, SDCC_HC_REG_DLL_CONFIG); |
306 | |
307 | /* Set CDR_EXT_EN */ |
308 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EXT_EN, |
309 | SDCC_DLL_CONFIG_CDR_EXT_EN, SDCC_HC_REG_DLL_CONFIG); |
310 | |
311 | /* Clear CK_OUT_EN */ |
312 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN, |
313 | val: 0, SDCC_HC_REG_DLL_CONFIG); |
314 | |
315 | /* Set DLL_EN */ |
316 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN, |
317 | SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG); |
318 | |
319 | if (!ethqos->has_emac_ge_3) { |
320 | rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN, |
321 | val: 0, SDCC_HC_REG_DLL_CONFIG); |
322 | |
323 | rgmii_updatel(ethqos, SDCC_DLL_CDR_FINE_PHASE, |
324 | val: 0, SDCC_HC_REG_DLL_CONFIG); |
325 | } |
326 | |
327 | /* Wait for CK_OUT_EN clear */ |
328 | do { |
329 | val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG); |
330 | val &= SDCC_DLL_CONFIG_CK_OUT_EN; |
331 | if (!val) |
332 | break; |
333 | mdelay(1); |
334 | retry--; |
335 | } while (retry > 0); |
336 | if (!retry) |
337 | dev_err(dev, "Clear CK_OUT_EN timedout\n" ); |
338 | |
339 | /* Set CK_OUT_EN */ |
340 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN, |
341 | SDCC_DLL_CONFIG_CK_OUT_EN, SDCC_HC_REG_DLL_CONFIG); |
342 | |
343 | /* Wait for CK_OUT_EN set */ |
344 | retry = 1000; |
345 | do { |
346 | val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG); |
347 | val &= SDCC_DLL_CONFIG_CK_OUT_EN; |
348 | if (val) |
349 | break; |
350 | mdelay(1); |
351 | retry--; |
352 | } while (retry > 0); |
353 | if (!retry) |
354 | dev_err(dev, "Set CK_OUT_EN timedout\n" ); |
355 | |
356 | /* Set DDR_CAL_EN */ |
357 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN, |
358 | SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_HC_REG_DLL_CONFIG2); |
359 | |
360 | if (!ethqos->has_emac_ge_3) { |
361 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS, |
362 | val: 0, SDCC_HC_REG_DLL_CONFIG2); |
363 | |
364 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_MCLK_FREQ_CALC, |
365 | val: 0x1A << 10, SDCC_HC_REG_DLL_CONFIG2); |
366 | |
367 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL, |
368 | BIT(2), SDCC_HC_REG_DLL_CONFIG2); |
369 | |
370 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW, |
371 | SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW, |
372 | SDCC_HC_REG_DLL_CONFIG2); |
373 | } |
374 | |
375 | return 0; |
376 | } |
377 | |
378 | static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) |
379 | { |
380 | struct device *dev = ðqos->pdev->dev; |
381 | int phase_shift; |
382 | int loopback; |
383 | |
384 | /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */ |
385 | if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID || |
386 | ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID) |
387 | phase_shift = 0; |
388 | else |
389 | phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN; |
390 | |
391 | /* Disable loopback mode */ |
392 | rgmii_updatel(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN, |
393 | val: 0, RGMII_IO_MACRO_CONFIG2); |
394 | |
395 | /* Determine if this platform wants loopback enabled after programming */ |
396 | if (ethqos->rgmii_config_loopback_en) |
397 | loopback = RGMII_CONFIG_LOOPBACK_EN; |
398 | else |
399 | loopback = 0; |
400 | |
401 | /* Select RGMII, write 0 to interface select */ |
402 | rgmii_updatel(ethqos, RGMII_CONFIG_INTF_SEL, |
403 | val: 0, RGMII_IO_MACRO_CONFIG); |
404 | |
405 | switch (ethqos->speed) { |
406 | case SPEED_1000: |
407 | rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE, |
408 | RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); |
409 | rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, |
410 | val: 0, RGMII_IO_MACRO_CONFIG); |
411 | rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, |
412 | RGMII_CONFIG_POS_NEG_DATA_SEL, |
413 | RGMII_IO_MACRO_CONFIG); |
414 | rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP, |
415 | RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG); |
416 | rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, |
417 | val: 0, RGMII_IO_MACRO_CONFIG2); |
418 | |
419 | rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, |
420 | val: phase_shift, RGMII_IO_MACRO_CONFIG2); |
421 | rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, |
422 | val: 0, RGMII_IO_MACRO_CONFIG2); |
423 | rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, |
424 | RGMII_CONFIG2_RX_PROG_SWAP, |
425 | RGMII_IO_MACRO_CONFIG2); |
426 | |
427 | /* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT / 2 * RX delay ns, |
428 | * in practice this becomes PRG_RCLK_DLY = 52 * 4 / 2 * RX delay ns |
429 | */ |
430 | if (ethqos->has_emac_ge_3) { |
431 | /* 0.9 ns */ |
432 | rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, |
433 | val: 115, SDCC_HC_REG_DDR_CONFIG); |
434 | } else { |
435 | /* 1.8 ns */ |
436 | rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, |
437 | val: 57, SDCC_HC_REG_DDR_CONFIG); |
438 | } |
439 | rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN, |
440 | SDCC_DDR_CONFIG_PRG_DLY_EN, |
441 | SDCC_HC_REG_DDR_CONFIG); |
442 | rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, |
443 | val: loopback, RGMII_IO_MACRO_CONFIG); |
444 | break; |
445 | |
446 | case SPEED_100: |
447 | rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE, |
448 | RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); |
449 | rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, |
450 | RGMII_CONFIG_BYPASS_TX_ID_EN, |
451 | RGMII_IO_MACRO_CONFIG); |
452 | rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, |
453 | val: 0, RGMII_IO_MACRO_CONFIG); |
454 | rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP, |
455 | val: 0, RGMII_IO_MACRO_CONFIG); |
456 | rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, |
457 | val: 0, RGMII_IO_MACRO_CONFIG2); |
458 | rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, |
459 | val: phase_shift, RGMII_IO_MACRO_CONFIG2); |
460 | rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2, |
461 | BIT(6), RGMII_IO_MACRO_CONFIG); |
462 | rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, |
463 | val: 0, RGMII_IO_MACRO_CONFIG2); |
464 | |
465 | if (ethqos->has_emac_ge_3) |
466 | rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, |
467 | RGMII_CONFIG2_RX_PROG_SWAP, |
468 | RGMII_IO_MACRO_CONFIG2); |
469 | else |
470 | rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, |
471 | val: 0, RGMII_IO_MACRO_CONFIG2); |
472 | |
473 | /* Write 0x5 to PRG_RCLK_DLY_CODE */ |
474 | rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, |
475 | val: (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG); |
476 | rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, |
477 | SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, |
478 | SDCC_HC_REG_DDR_CONFIG); |
479 | rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, |
480 | SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, |
481 | SDCC_HC_REG_DDR_CONFIG); |
482 | rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, |
483 | val: loopback, RGMII_IO_MACRO_CONFIG); |
484 | break; |
485 | |
486 | case SPEED_10: |
487 | rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE, |
488 | RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); |
489 | rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, |
490 | RGMII_CONFIG_BYPASS_TX_ID_EN, |
491 | RGMII_IO_MACRO_CONFIG); |
492 | rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, |
493 | val: 0, RGMII_IO_MACRO_CONFIG); |
494 | rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP, |
495 | val: 0, RGMII_IO_MACRO_CONFIG); |
496 | rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, |
497 | val: 0, RGMII_IO_MACRO_CONFIG2); |
498 | rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, |
499 | val: phase_shift, RGMII_IO_MACRO_CONFIG2); |
500 | rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9, |
501 | BIT(12) | GENMASK(9, 8), |
502 | RGMII_IO_MACRO_CONFIG); |
503 | rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, |
504 | val: 0, RGMII_IO_MACRO_CONFIG2); |
505 | if (ethqos->has_emac_ge_3) |
506 | rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, |
507 | RGMII_CONFIG2_RX_PROG_SWAP, |
508 | RGMII_IO_MACRO_CONFIG2); |
509 | else |
510 | rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, |
511 | val: 0, RGMII_IO_MACRO_CONFIG2); |
512 | /* Write 0x5 to PRG_RCLK_DLY_CODE */ |
513 | rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, |
514 | val: (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG); |
515 | rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, |
516 | SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, |
517 | SDCC_HC_REG_DDR_CONFIG); |
518 | rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, |
519 | SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, |
520 | SDCC_HC_REG_DDR_CONFIG); |
521 | rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, |
522 | val: loopback, RGMII_IO_MACRO_CONFIG); |
523 | break; |
524 | default: |
525 | dev_err(dev, "Invalid speed %d\n" , ethqos->speed); |
526 | return -EINVAL; |
527 | } |
528 | |
529 | return 0; |
530 | } |
531 | |
532 | static int ethqos_configure_rgmii(struct qcom_ethqos *ethqos) |
533 | { |
534 | struct device *dev = ðqos->pdev->dev; |
535 | volatile unsigned int dll_lock; |
536 | unsigned int i, retry = 1000; |
537 | |
538 | /* Reset to POR values and enable clk */ |
539 | for (i = 0; i < ethqos->num_por; i++) |
540 | rgmii_writel(ethqos, value: ethqos->por[i].value, |
541 | offset: ethqos->por[i].offset); |
542 | ethqos_set_func_clk_en(ethqos); |
543 | |
544 | /* Initialize the DLL first */ |
545 | |
546 | /* Set DLL_RST */ |
547 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, |
548 | SDCC_DLL_CONFIG_DLL_RST, SDCC_HC_REG_DLL_CONFIG); |
549 | |
550 | /* Set PDN */ |
551 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, |
552 | SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG); |
553 | |
554 | if (ethqos->has_emac_ge_3) { |
555 | if (ethqos->speed == SPEED_1000) { |
556 | rgmii_writel(ethqos, value: 0x1800000, SDCC_TEST_CTL); |
557 | rgmii_writel(ethqos, value: 0x2C010800, SDCC_USR_CTL); |
558 | rgmii_writel(ethqos, value: 0xA001, SDCC_HC_REG_DLL_CONFIG2); |
559 | } else { |
560 | rgmii_writel(ethqos, value: 0x40010800, SDCC_USR_CTL); |
561 | rgmii_writel(ethqos, value: 0xA001, SDCC_HC_REG_DLL_CONFIG2); |
562 | } |
563 | } |
564 | |
565 | /* Clear DLL_RST */ |
566 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, val: 0, |
567 | SDCC_HC_REG_DLL_CONFIG); |
568 | |
569 | /* Clear PDN */ |
570 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, val: 0, |
571 | SDCC_HC_REG_DLL_CONFIG); |
572 | |
573 | if (ethqos->speed != SPEED_100 && ethqos->speed != SPEED_10) { |
574 | /* Set DLL_EN */ |
575 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN, |
576 | SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG); |
577 | |
578 | /* Set CK_OUT_EN */ |
579 | rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN, |
580 | SDCC_DLL_CONFIG_CK_OUT_EN, |
581 | SDCC_HC_REG_DLL_CONFIG); |
582 | |
583 | /* Set USR_CTL bit 26 with mask of 3 bits */ |
584 | if (!ethqos->has_emac_ge_3) |
585 | rgmii_updatel(ethqos, GENMASK(26, 24), BIT(26), |
586 | SDCC_USR_CTL); |
587 | |
588 | /* wait for DLL LOCK */ |
589 | do { |
590 | mdelay(1); |
591 | dll_lock = rgmii_readl(ethqos, SDC4_STATUS); |
592 | if (dll_lock & SDC4_STATUS_DLL_LOCK) |
593 | break; |
594 | retry--; |
595 | } while (retry > 0); |
596 | if (!retry) |
597 | dev_err(dev, "Timeout while waiting for DLL lock\n" ); |
598 | } |
599 | |
600 | if (ethqos->speed == SPEED_1000) |
601 | ethqos_dll_configure(ethqos); |
602 | |
603 | ethqos_rgmii_macro_init(ethqos); |
604 | |
605 | return 0; |
606 | } |
607 | |
608 | /* On interface toggle MAC registers gets reset. |
609 | * Configure MAC block for SGMII on ethernet phy link up |
610 | */ |
611 | static int ethqos_configure_sgmii(struct qcom_ethqos *ethqos) |
612 | { |
613 | struct net_device *dev = platform_get_drvdata(pdev: ethqos->pdev); |
614 | struct stmmac_priv *priv = netdev_priv(dev); |
615 | int val; |
616 | |
617 | val = readl(addr: ethqos->mac_base + MAC_CTRL_REG); |
618 | |
619 | switch (ethqos->speed) { |
620 | case SPEED_2500: |
621 | val &= ~ETHQOS_MAC_CTRL_PORT_SEL; |
622 | rgmii_updatel(ethqos, RGMII_CONFIG2_RGMII_CLK_SEL_CFG, |
623 | RGMII_CONFIG2_RGMII_CLK_SEL_CFG, |
624 | RGMII_IO_MACRO_CONFIG2); |
625 | if (ethqos->serdes_speed != SPEED_2500) |
626 | phy_set_speed(phy: ethqos->serdes_phy, SPEED_2500); |
627 | ethqos->serdes_speed = SPEED_2500; |
628 | stmmac_pcs_ctrl_ane(priv, priv->ioaddr, 0, 0, 0); |
629 | break; |
630 | case SPEED_1000: |
631 | val &= ~ETHQOS_MAC_CTRL_PORT_SEL; |
632 | rgmii_updatel(ethqos, RGMII_CONFIG2_RGMII_CLK_SEL_CFG, |
633 | RGMII_CONFIG2_RGMII_CLK_SEL_CFG, |
634 | RGMII_IO_MACRO_CONFIG2); |
635 | if (ethqos->serdes_speed != SPEED_1000) |
636 | phy_set_speed(phy: ethqos->serdes_phy, SPEED_1000); |
637 | ethqos->serdes_speed = SPEED_1000; |
638 | stmmac_pcs_ctrl_ane(priv, priv->ioaddr, 1, 0, 0); |
639 | break; |
640 | case SPEED_100: |
641 | val |= ETHQOS_MAC_CTRL_PORT_SEL | ETHQOS_MAC_CTRL_SPEED_MODE; |
642 | if (ethqos->serdes_speed != SPEED_1000) |
643 | phy_set_speed(phy: ethqos->serdes_phy, SPEED_1000); |
644 | ethqos->serdes_speed = SPEED_1000; |
645 | stmmac_pcs_ctrl_ane(priv, priv->ioaddr, 1, 0, 0); |
646 | break; |
647 | case SPEED_10: |
648 | val |= ETHQOS_MAC_CTRL_PORT_SEL; |
649 | val &= ~ETHQOS_MAC_CTRL_SPEED_MODE; |
650 | rgmii_updatel(ethqos, RGMII_CONFIG_SGMII_CLK_DVDR, |
651 | FIELD_PREP(RGMII_CONFIG_SGMII_CLK_DVDR, |
652 | SGMII_10M_RX_CLK_DVDR), |
653 | RGMII_IO_MACRO_CONFIG); |
654 | if (ethqos->serdes_speed != SPEED_1000) |
655 | phy_set_speed(phy: ethqos->serdes_phy, speed: ethqos->speed); |
656 | ethqos->serdes_speed = SPEED_1000; |
657 | stmmac_pcs_ctrl_ane(priv, priv->ioaddr, 1, 0, 0); |
658 | break; |
659 | } |
660 | |
661 | writel(val, addr: ethqos->mac_base + MAC_CTRL_REG); |
662 | |
663 | return val; |
664 | } |
665 | |
666 | static int ethqos_configure(struct qcom_ethqos *ethqos) |
667 | { |
668 | return ethqos->configure_func(ethqos); |
669 | } |
670 | |
671 | static void ethqos_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode) |
672 | { |
673 | struct qcom_ethqos *ethqos = priv; |
674 | |
675 | ethqos->speed = speed; |
676 | ethqos_update_link_clk(ethqos, speed); |
677 | ethqos_configure(ethqos); |
678 | } |
679 | |
680 | static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv) |
681 | { |
682 | struct qcom_ethqos *ethqos = priv; |
683 | int ret; |
684 | |
685 | ret = phy_init(phy: ethqos->serdes_phy); |
686 | if (ret) |
687 | return ret; |
688 | |
689 | ret = phy_power_on(phy: ethqos->serdes_phy); |
690 | if (ret) |
691 | return ret; |
692 | |
693 | return phy_set_speed(phy: ethqos->serdes_phy, speed: ethqos->speed); |
694 | } |
695 | |
696 | static void qcom_ethqos_serdes_powerdown(struct net_device *ndev, void *priv) |
697 | { |
698 | struct qcom_ethqos *ethqos = priv; |
699 | |
700 | phy_power_off(phy: ethqos->serdes_phy); |
701 | phy_exit(phy: ethqos->serdes_phy); |
702 | } |
703 | |
704 | static int ethqos_clks_config(void *priv, bool enabled) |
705 | { |
706 | struct qcom_ethqos *ethqos = priv; |
707 | int ret = 0; |
708 | |
709 | if (enabled) { |
710 | ret = clk_prepare_enable(clk: ethqos->link_clk); |
711 | if (ret) { |
712 | dev_err(ðqos->pdev->dev, "link_clk enable failed\n" ); |
713 | return ret; |
714 | } |
715 | |
716 | /* Enable functional clock to prevent DMA reset to timeout due |
717 | * to lacking PHY clock after the hardware block has been power |
718 | * cycled. The actual configuration will be adjusted once |
719 | * ethqos_fix_mac_speed() is invoked. |
720 | */ |
721 | ethqos_set_func_clk_en(ethqos); |
722 | } else { |
723 | clk_disable_unprepare(clk: ethqos->link_clk); |
724 | } |
725 | |
726 | return ret; |
727 | } |
728 | |
729 | static void ethqos_clks_disable(void *data) |
730 | { |
731 | ethqos_clks_config(priv: data, enabled: false); |
732 | } |
733 | |
734 | static void ethqos_ptp_clk_freq_config(struct stmmac_priv *priv) |
735 | { |
736 | struct plat_stmmacenet_data *plat_dat = priv->plat; |
737 | int err; |
738 | |
739 | if (!plat_dat->clk_ptp_ref) |
740 | return; |
741 | |
742 | /* Max the PTP ref clock out to get the best resolution possible */ |
743 | err = clk_set_rate(clk: plat_dat->clk_ptp_ref, ULONG_MAX); |
744 | if (err) |
745 | netdev_err(dev: priv->dev, format: "Failed to max out clk_ptp_ref: %d\n" , err); |
746 | plat_dat->clk_ptp_rate = clk_get_rate(clk: plat_dat->clk_ptp_ref); |
747 | |
748 | netdev_dbg(priv->dev, "PTP rate %d\n" , plat_dat->clk_ptp_rate); |
749 | } |
750 | |
751 | static int qcom_ethqos_probe(struct platform_device *pdev) |
752 | { |
753 | struct device_node *np = pdev->dev.of_node; |
754 | const struct ethqos_emac_driver_data *data; |
755 | struct plat_stmmacenet_data *plat_dat; |
756 | struct stmmac_resources stmmac_res; |
757 | struct device *dev = &pdev->dev; |
758 | struct qcom_ethqos *ethqos; |
759 | int ret, i; |
760 | |
761 | ret = stmmac_get_platform_resources(pdev, stmmac_res: &stmmac_res); |
762 | if (ret) |
763 | return dev_err_probe(dev, err: ret, |
764 | fmt: "Failed to get platform resources\n" ); |
765 | |
766 | plat_dat = devm_stmmac_probe_config_dt(pdev, mac: stmmac_res.mac); |
767 | if (IS_ERR(ptr: plat_dat)) { |
768 | return dev_err_probe(dev, err: PTR_ERR(ptr: plat_dat), |
769 | fmt: "dt configuration failed\n" ); |
770 | } |
771 | |
772 | plat_dat->clks_config = ethqos_clks_config; |
773 | |
774 | ethqos = devm_kzalloc(dev, size: sizeof(*ethqos), GFP_KERNEL); |
775 | if (!ethqos) |
776 | return -ENOMEM; |
777 | |
778 | ret = of_get_phy_mode(np, interface: ðqos->phy_mode); |
779 | if (ret) |
780 | return dev_err_probe(dev, err: ret, fmt: "Failed to get phy mode\n" ); |
781 | switch (ethqos->phy_mode) { |
782 | case PHY_INTERFACE_MODE_RGMII: |
783 | case PHY_INTERFACE_MODE_RGMII_ID: |
784 | case PHY_INTERFACE_MODE_RGMII_RXID: |
785 | case PHY_INTERFACE_MODE_RGMII_TXID: |
786 | ethqos->configure_func = ethqos_configure_rgmii; |
787 | break; |
788 | case PHY_INTERFACE_MODE_SGMII: |
789 | ethqos->configure_func = ethqos_configure_sgmii; |
790 | break; |
791 | default: |
792 | dev_err(dev, "Unsupported phy mode %s\n" , |
793 | phy_modes(ethqos->phy_mode)); |
794 | return -EINVAL; |
795 | } |
796 | |
797 | ethqos->pdev = pdev; |
798 | ethqos->rgmii_base = devm_platform_ioremap_resource_byname(pdev, name: "rgmii" ); |
799 | if (IS_ERR(ptr: ethqos->rgmii_base)) |
800 | return dev_err_probe(dev, err: PTR_ERR(ptr: ethqos->rgmii_base), |
801 | fmt: "Failed to map rgmii resource\n" ); |
802 | |
803 | ethqos->mac_base = stmmac_res.addr; |
804 | |
805 | data = of_device_get_match_data(dev); |
806 | ethqos->por = data->por; |
807 | ethqos->num_por = data->num_por; |
808 | ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en; |
809 | ethqos->has_emac_ge_3 = data->has_emac_ge_3; |
810 | |
811 | ethqos->link_clk = devm_clk_get(dev, id: data->link_clk_name ?: "rgmii" ); |
812 | if (IS_ERR(ptr: ethqos->link_clk)) |
813 | return dev_err_probe(dev, err: PTR_ERR(ptr: ethqos->link_clk), |
814 | fmt: "Failed to get link_clk\n" ); |
815 | |
816 | ret = ethqos_clks_config(priv: ethqos, enabled: true); |
817 | if (ret) |
818 | return ret; |
819 | |
820 | ret = devm_add_action_or_reset(dev, ethqos_clks_disable, ethqos); |
821 | if (ret) |
822 | return ret; |
823 | |
824 | ethqos->serdes_phy = devm_phy_optional_get(dev, string: "serdes" ); |
825 | if (IS_ERR(ptr: ethqos->serdes_phy)) |
826 | return dev_err_probe(dev, err: PTR_ERR(ptr: ethqos->serdes_phy), |
827 | fmt: "Failed to get serdes phy\n" ); |
828 | |
829 | ethqos->speed = SPEED_1000; |
830 | ethqos->serdes_speed = SPEED_1000; |
831 | ethqos_update_link_clk(ethqos, SPEED_1000); |
832 | ethqos_set_func_clk_en(ethqos); |
833 | |
834 | plat_dat->bsp_priv = ethqos; |
835 | plat_dat->fix_mac_speed = ethqos_fix_mac_speed; |
836 | plat_dat->dump_debug_regs = rgmii_dump; |
837 | plat_dat->ptp_clk_freq_config = ethqos_ptp_clk_freq_config; |
838 | plat_dat->has_gmac4 = 1; |
839 | if (ethqos->has_emac_ge_3) |
840 | plat_dat->dwmac4_addrs = &data->dwmac4_addrs; |
841 | plat_dat->pmt = 1; |
842 | if (of_property_read_bool(np, propname: "snps,tso" )) |
843 | plat_dat->flags |= STMMAC_FLAG_TSO_EN; |
844 | if (of_device_is_compatible(device: np, "qcom,qcs404-ethqos" )) |
845 | plat_dat->flags |= STMMAC_FLAG_RX_CLK_RUNS_IN_LPI; |
846 | if (data->has_integrated_pcs) |
847 | plat_dat->flags |= STMMAC_FLAG_HAS_INTEGRATED_PCS; |
848 | |
849 | if (ethqos->serdes_phy) { |
850 | plat_dat->serdes_powerup = qcom_ethqos_serdes_powerup; |
851 | plat_dat->serdes_powerdown = qcom_ethqos_serdes_powerdown; |
852 | } |
853 | |
854 | /* Enable TSO on queue0 and enable TBS on rest of the queues */ |
855 | for (i = 1; i < plat_dat->tx_queues_to_use; i++) |
856 | plat_dat->tx_queues_cfg[i].tbs_en = 1; |
857 | |
858 | return devm_stmmac_pltfr_probe(pdev, plat: plat_dat, res: &stmmac_res); |
859 | } |
860 | |
861 | static const struct of_device_id qcom_ethqos_match[] = { |
862 | { .compatible = "qcom,qcs404-ethqos" , .data = &emac_v2_3_0_data}, |
863 | { .compatible = "qcom,sa8775p-ethqos" , .data = &emac_v4_0_0_data}, |
864 | { .compatible = "qcom,sc8280xp-ethqos" , .data = &emac_v3_0_0_data}, |
865 | { .compatible = "qcom,sm8150-ethqos" , .data = &emac_v2_1_0_data}, |
866 | { } |
867 | }; |
868 | MODULE_DEVICE_TABLE(of, qcom_ethqos_match); |
869 | |
870 | static struct platform_driver qcom_ethqos_driver = { |
871 | .probe = qcom_ethqos_probe, |
872 | .driver = { |
873 | .name = "qcom-ethqos" , |
874 | .pm = &stmmac_pltfr_pm_ops, |
875 | .of_match_table = qcom_ethqos_match, |
876 | }, |
877 | }; |
878 | module_platform_driver(qcom_ethqos_driver); |
879 | |
880 | MODULE_DESCRIPTION("Qualcomm ETHQOS driver" ); |
881 | MODULE_LICENSE("GPL v2" ); |
882 | |