]>
Commit | Line | Data |
---|---|---|
c895ef46 SR |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * MediaTek ethernet IP driver for U-Boot | |
4 | * | |
5 | * Copyright (C) 2018 Stefan Roese <[email protected]> | |
6 | * | |
7 | * This code is mostly based on the code extracted from this MediaTek | |
8 | * github repository: | |
9 | * | |
10 | * https://github.com/MediaTek-Labs/linkit-smart-uboot.git | |
11 | * | |
12 | * I was not able to find a specific license or other developers | |
13 | * copyrights here, so I can't add them here. | |
14 | */ | |
15 | ||
16 | #include <common.h> | |
17 | #include <dm.h> | |
18 | #include <malloc.h> | |
19 | #include <miiphy.h> | |
20 | #include <net.h> | |
21 | #include <regmap.h> | |
22 | #include <syscon.h> | |
23 | #include <wait_bit.h> | |
24 | #include <asm/io.h> | |
25 | #include <linux/bitfield.h> | |
26 | #include <linux/err.h> | |
27 | ||
28 | /* System controller register */ | |
29 | #define MT7628_RSTCTRL_REG 0x34 | |
30 | #define RSTCTRL_EPHY_RST BIT(24) | |
31 | ||
32 | #define MT7628_AGPIO_CFG_REG 0x3c | |
33 | #define MT7628_EPHY_GPIO_AIO_EN GENMASK(20, 17) | |
34 | #define MT7628_EPHY_P0_DIS BIT(16) | |
35 | ||
36 | #define MT7628_GPIO2_MODE_REG 0x64 | |
37 | ||
38 | /* Ethernet frame engine register */ | |
39 | #define PDMA_RELATED 0x0800 | |
40 | ||
41 | #define TX_BASE_PTR0 (PDMA_RELATED + 0x000) | |
42 | #define TX_MAX_CNT0 (PDMA_RELATED + 0x004) | |
43 | #define TX_CTX_IDX0 (PDMA_RELATED + 0x008) | |
44 | #define TX_DTX_IDX0 (PDMA_RELATED + 0x00c) | |
45 | ||
46 | #define RX_BASE_PTR0 (PDMA_RELATED + 0x100) | |
47 | #define RX_MAX_CNT0 (PDMA_RELATED + 0x104) | |
48 | #define RX_CALC_IDX0 (PDMA_RELATED + 0x108) | |
49 | ||
50 | #define PDMA_GLO_CFG (PDMA_RELATED + 0x204) | |
51 | #define PDMA_RST_IDX (PDMA_RELATED + 0x208) | |
52 | #define DLY_INT_CFG (PDMA_RELATED + 0x20c) | |
53 | ||
54 | #define SDM_RELATED 0x0c00 | |
55 | ||
56 | #define SDM_MAC_ADRL (SDM_RELATED + 0x0c) /* MAC address LSB */ | |
57 | #define SDM_MAC_ADRH (SDM_RELATED + 0x10) /* MAC Address MSB */ | |
58 | ||
59 | #define RST_DTX_IDX0 BIT(0) | |
60 | #define RST_DRX_IDX0 BIT(16) | |
61 | ||
62 | #define TX_DMA_EN BIT(0) | |
63 | #define TX_DMA_BUSY BIT(1) | |
64 | #define RX_DMA_EN BIT(2) | |
65 | #define RX_DMA_BUSY BIT(3) | |
66 | #define TX_WB_DDONE BIT(6) | |
67 | ||
68 | /* Ethernet switch register */ | |
69 | #define MT7628_SWITCH_FCT0 0x0008 | |
70 | #define MT7628_SWITCH_PFC1 0x0014 | |
71 | #define MT7628_SWITCH_FPA 0x0084 | |
72 | #define MT7628_SWITCH_SOCPC 0x008c | |
73 | #define MT7628_SWITCH_POC0 0x0090 | |
74 | #define MT7628_SWITCH_POC2 0x0098 | |
75 | #define MT7628_SWITCH_SGC 0x009c | |
76 | #define MT7628_SWITCH_PCR0 0x00c0 | |
77 | #define PCR0_PHY_ADDR GENMASK(4, 0) | |
78 | #define PCR0_PHY_REG GENMASK(12, 8) | |
79 | #define PCR0_WT_PHY_CMD BIT(13) | |
80 | #define PCR0_RD_PHY_CMD BIT(14) | |
81 | #define PCR0_WT_DATA GENMASK(31, 16) | |
82 | ||
83 | #define MT7628_SWITCH_PCR1 0x00c4 | |
84 | #define PCR1_WT_DONE BIT(0) | |
85 | #define PCR1_RD_RDY BIT(1) | |
86 | #define PCR1_RD_DATA GENMASK(31, 16) | |
87 | ||
88 | #define MT7628_SWITCH_FPA1 0x00c8 | |
89 | #define MT7628_SWITCH_FCT2 0x00cc | |
90 | #define MT7628_SWITCH_SGC2 0x00e4 | |
91 | #define MT7628_SWITCH_BMU_CTRL 0x0110 | |
92 | ||
93 | /* rxd2 */ | |
94 | #define RX_DMA_DONE BIT(31) | |
95 | #define RX_DMA_LSO BIT(30) | |
96 | #define RX_DMA_PLEN0 GENMASK(29, 16) | |
97 | #define RX_DMA_TAG BIT(15) | |
98 | ||
99 | struct fe_rx_dma { | |
100 | unsigned int rxd1; | |
101 | unsigned int rxd2; | |
102 | unsigned int rxd3; | |
103 | unsigned int rxd4; | |
104 | } __packed __aligned(4); | |
105 | ||
106 | #define TX_DMA_PLEN0 GENMASK(29, 16) | |
107 | #define TX_DMA_LS1 BIT(14) | |
108 | #define TX_DMA_LS0 BIT(30) | |
109 | #define TX_DMA_DONE BIT(31) | |
110 | ||
111 | #define TX_DMA_INS_VLAN_MT7621 BIT(16) | |
112 | #define TX_DMA_INS_VLAN BIT(7) | |
113 | #define TX_DMA_INS_PPPOE BIT(12) | |
114 | #define TX_DMA_PN GENMASK(26, 24) | |
115 | ||
116 | struct fe_tx_dma { | |
117 | unsigned int txd1; | |
118 | unsigned int txd2; | |
119 | unsigned int txd3; | |
120 | unsigned int txd4; | |
121 | } __packed __aligned(4); | |
122 | ||
123 | #define NUM_RX_DESC 256 | |
124 | #define NUM_TX_DESC 4 | |
125 | ||
126 | #define PADDING_LENGTH 60 | |
127 | ||
128 | #define MTK_QDMA_PAGE_SIZE 2048 | |
129 | ||
130 | #define CONFIG_MDIO_TIMEOUT 100 | |
131 | #define CONFIG_DMA_STOP_TIMEOUT 100 | |
132 | #define CONFIG_TX_DMA_TIMEOUT 100 | |
133 | ||
134 | #define LINK_DELAY_TIME 500 /* 500 ms */ | |
135 | #define LINK_TIMEOUT 10000 /* 10 seconds */ | |
136 | ||
137 | struct mt7628_eth_dev { | |
138 | void __iomem *base; /* frame engine base address */ | |
139 | void __iomem *eth_sw_base; /* switch base address */ | |
140 | struct regmap *sysctrl_regmap; /* system-controller reg-map */ | |
141 | ||
142 | struct mii_dev *bus; | |
143 | ||
144 | struct fe_tx_dma *tx_ring; | |
145 | struct fe_rx_dma *rx_ring; | |
146 | ||
147 | u8 *rx_buf[NUM_RX_DESC]; | |
148 | ||
149 | /* Point to the next RXD DMA wants to use in RXD Ring0 */ | |
150 | int rx_dma_idx; | |
151 | /* Point to the next TXD in TXD Ring0 CPU wants to use */ | |
152 | int tx_dma_idx; | |
153 | }; | |
154 | ||
155 | static int mdio_wait_read(struct mt7628_eth_dev *priv, u32 mask, bool mask_set) | |
156 | { | |
157 | void __iomem *base = priv->eth_sw_base; | |
158 | int ret; | |
159 | ||
160 | ret = wait_for_bit_le32(base + MT7628_SWITCH_PCR1, mask, mask_set, | |
161 | CONFIG_MDIO_TIMEOUT, false); | |
162 | if (ret) { | |
163 | printf("MDIO operation timeout!\n"); | |
164 | return -ETIMEDOUT; | |
165 | } | |
166 | ||
167 | return 0; | |
168 | } | |
169 | ||
170 | static int mii_mgr_read(struct mt7628_eth_dev *priv, | |
171 | u32 phy_addr, u32 phy_register, u32 *read_data) | |
172 | { | |
173 | void __iomem *base = priv->eth_sw_base; | |
174 | u32 status = 0; | |
175 | u32 ret; | |
176 | ||
177 | *read_data = 0xffff; | |
178 | /* Make sure previous read operation is complete */ | |
179 | ret = mdio_wait_read(priv, PCR1_RD_RDY, false); | |
180 | if (ret) | |
181 | return ret; | |
182 | ||
183 | writel(PCR0_RD_PHY_CMD | | |
184 | FIELD_PREP(PCR0_PHY_REG, phy_register) | | |
185 | FIELD_PREP(PCR0_PHY_ADDR, phy_addr), | |
186 | base + MT7628_SWITCH_PCR0); | |
187 | ||
188 | /* Make sure previous read operation is complete */ | |
189 | ret = mdio_wait_read(priv, PCR1_RD_RDY, true); | |
190 | if (ret) | |
191 | return ret; | |
192 | ||
193 | status = readl(base + MT7628_SWITCH_PCR1); | |
194 | *read_data = FIELD_GET(PCR1_RD_DATA, status); | |
195 | ||
196 | return 0; | |
197 | } | |
198 | ||
199 | static int mii_mgr_write(struct mt7628_eth_dev *priv, | |
200 | u32 phy_addr, u32 phy_register, u32 write_data) | |
201 | { | |
202 | void __iomem *base = priv->eth_sw_base; | |
203 | u32 data; | |
204 | int ret; | |
205 | ||
206 | /* Make sure previous write operation is complete */ | |
207 | ret = mdio_wait_read(priv, PCR1_WT_DONE, false); | |
208 | if (ret) | |
209 | return ret; | |
210 | ||
211 | data = FIELD_PREP(PCR0_WT_DATA, write_data) | | |
212 | FIELD_PREP(PCR0_PHY_REG, phy_register) | | |
213 | FIELD_PREP(PCR0_PHY_ADDR, phy_addr) | | |
214 | PCR0_WT_PHY_CMD; | |
215 | writel(data, base + MT7628_SWITCH_PCR0); | |
216 | ||
217 | return mdio_wait_read(priv, PCR1_WT_DONE, true); | |
218 | } | |
219 | ||
220 | static int mt7628_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) | |
221 | { | |
222 | u32 val; | |
223 | int ret; | |
224 | ||
225 | ret = mii_mgr_read(bus->priv, addr, reg, &val); | |
226 | if (ret) | |
227 | return ret; | |
228 | ||
229 | return val; | |
230 | } | |
231 | ||
232 | static int mt7628_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, | |
233 | u16 value) | |
234 | { | |
235 | return mii_mgr_write(bus->priv, addr, reg, value); | |
236 | } | |
237 | ||
238 | static void mt7628_ephy_init(struct mt7628_eth_dev *priv) | |
239 | { | |
240 | int i; | |
241 | ||
242 | mii_mgr_write(priv, 0, 31, 0x2000); /* change G2 page */ | |
243 | mii_mgr_write(priv, 0, 26, 0x0000); | |
244 | ||
245 | for (i = 0; i < 5; i++) { | |
246 | mii_mgr_write(priv, i, 31, 0x8000); /* change L0 page */ | |
247 | mii_mgr_write(priv, i, 0, 0x3100); | |
248 | ||
249 | /* EEE disable */ | |
250 | mii_mgr_write(priv, i, 30, 0xa000); | |
251 | mii_mgr_write(priv, i, 31, 0xa000); /* change L2 page */ | |
252 | mii_mgr_write(priv, i, 16, 0x0606); | |
253 | mii_mgr_write(priv, i, 23, 0x0f0e); | |
254 | mii_mgr_write(priv, i, 24, 0x1610); | |
255 | mii_mgr_write(priv, i, 30, 0x1f15); | |
256 | mii_mgr_write(priv, i, 28, 0x6111); | |
257 | } | |
258 | ||
259 | /* 100Base AOI setting */ | |
260 | mii_mgr_write(priv, 0, 31, 0x5000); /* change G5 page */ | |
261 | mii_mgr_write(priv, 0, 19, 0x004a); | |
262 | mii_mgr_write(priv, 0, 20, 0x015a); | |
263 | mii_mgr_write(priv, 0, 21, 0x00ee); | |
264 | mii_mgr_write(priv, 0, 22, 0x0033); | |
265 | mii_mgr_write(priv, 0, 23, 0x020a); | |
266 | mii_mgr_write(priv, 0, 24, 0x0000); | |
267 | mii_mgr_write(priv, 0, 25, 0x024a); | |
268 | mii_mgr_write(priv, 0, 26, 0x035a); | |
269 | mii_mgr_write(priv, 0, 27, 0x02ee); | |
270 | mii_mgr_write(priv, 0, 28, 0x0233); | |
271 | mii_mgr_write(priv, 0, 29, 0x000a); | |
272 | mii_mgr_write(priv, 0, 30, 0x0000); | |
273 | ||
274 | /* Fix EPHY idle state abnormal behavior */ | |
275 | mii_mgr_write(priv, 0, 31, 0x4000); /* change G4 page */ | |
276 | mii_mgr_write(priv, 0, 29, 0x000d); | |
277 | mii_mgr_write(priv, 0, 30, 0x0500); | |
278 | } | |
279 | ||
280 | static void rt305x_esw_init(struct mt7628_eth_dev *priv) | |
281 | { | |
282 | void __iomem *base = priv->eth_sw_base; | |
283 | ||
284 | /* | |
285 | * FC_RLS_TH=200, FC_SET_TH=160 | |
286 | * DROP_RLS=120, DROP_SET_TH=80 | |
287 | */ | |
288 | writel(0xc8a07850, base + MT7628_SWITCH_FCT0); | |
289 | writel(0x00000000, base + MT7628_SWITCH_SGC2); | |
290 | writel(0x00405555, base + MT7628_SWITCH_PFC1); | |
291 | writel(0x00007f7f, base + MT7628_SWITCH_POC0); | |
292 | writel(0x00007f7f, base + MT7628_SWITCH_POC2); /* disable VLAN */ | |
293 | writel(0x0002500c, base + MT7628_SWITCH_FCT2); | |
294 | /* hashing algorithm=XOR48, aging interval=300sec */ | |
295 | writel(0x0008a301, base + MT7628_SWITCH_SGC); | |
296 | writel(0x02404040, base + MT7628_SWITCH_SOCPC); | |
297 | ||
298 | /* Ext PHY Addr=0x1f */ | |
299 | writel(0x3f502b28, base + MT7628_SWITCH_FPA1); | |
300 | writel(0x00000000, base + MT7628_SWITCH_FPA); | |
301 | /* 1us cycle number=125 (FE's clock=125Mhz) */ | |
302 | writel(0x7d000000, base + MT7628_SWITCH_BMU_CTRL); | |
303 | ||
304 | /* Configure analog GPIO setup */ | |
305 | regmap_update_bits(priv->sysctrl_regmap, MT7628_AGPIO_CFG_REG, | |
306 | MT7628_EPHY_P0_DIS, MT7628_EPHY_GPIO_AIO_EN); | |
307 | ||
308 | /* Reset PHY */ | |
309 | regmap_update_bits(priv->sysctrl_regmap, MT7628_RSTCTRL_REG, | |
310 | 0, RSTCTRL_EPHY_RST); | |
311 | regmap_update_bits(priv->sysctrl_regmap, MT7628_RSTCTRL_REG, | |
312 | RSTCTRL_EPHY_RST, 0); | |
313 | mdelay(10); | |
314 | ||
315 | /* Set P0 EPHY LED mode */ | |
316 | regmap_update_bits(priv->sysctrl_regmap, MT7628_GPIO2_MODE_REG, | |
317 | 0x0ffc0ffc, 0x05540554); | |
318 | mdelay(10); | |
319 | ||
320 | mt7628_ephy_init(priv); | |
321 | } | |
322 | ||
323 | static void eth_dma_start(struct mt7628_eth_dev *priv) | |
324 | { | |
325 | void __iomem *base = priv->base; | |
326 | ||
327 | setbits_le32(base + PDMA_GLO_CFG, TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN); | |
328 | } | |
329 | ||
330 | static void eth_dma_stop(struct mt7628_eth_dev *priv) | |
331 | { | |
332 | void __iomem *base = priv->base; | |
333 | int ret; | |
334 | ||
335 | clrbits_le32(base + PDMA_GLO_CFG, TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN); | |
336 | ||
337 | /* Wait for DMA to stop */ | |
338 | ret = wait_for_bit_le32(base + PDMA_GLO_CFG, | |
339 | RX_DMA_BUSY | TX_DMA_BUSY, false, | |
340 | CONFIG_DMA_STOP_TIMEOUT, false); | |
341 | if (ret) | |
342 | printf("DMA stop timeout error!\n"); | |
343 | } | |
344 | ||
345 | static int mt7628_eth_write_hwaddr(struct udevice *dev) | |
346 | { | |
347 | struct mt7628_eth_dev *priv = dev_get_priv(dev); | |
348 | void __iomem *base = priv->base; | |
349 | u8 *addr = ((struct eth_pdata *)dev_get_platdata(dev))->enetaddr; | |
350 | u32 val; | |
351 | ||
352 | /* Set MAC address. */ | |
353 | val = addr[0]; | |
354 | val = (val << 8) | addr[1]; | |
355 | writel(val, base + SDM_MAC_ADRH); | |
356 | ||
357 | val = addr[2]; | |
358 | val = (val << 8) | addr[3]; | |
359 | val = (val << 8) | addr[4]; | |
360 | val = (val << 8) | addr[5]; | |
361 | writel(val, base + SDM_MAC_ADRL); | |
362 | ||
363 | return 0; | |
364 | } | |
365 | ||
366 | static int mt7628_eth_send(struct udevice *dev, void *packet, int length) | |
367 | { | |
368 | struct mt7628_eth_dev *priv = dev_get_priv(dev); | |
369 | void __iomem *base = priv->base; | |
370 | int ret; | |
371 | int idx; | |
372 | int i; | |
373 | ||
374 | idx = priv->tx_dma_idx; | |
375 | ||
376 | /* Pad message to a minimum length */ | |
377 | if (length < PADDING_LENGTH) { | |
378 | char *p = (char *)packet; | |
379 | ||
380 | for (i = 0; i < PADDING_LENGTH - length; i++) | |
381 | p[length + i] = 0; | |
382 | length = PADDING_LENGTH; | |
383 | } | |
384 | ||
385 | /* Check if buffer is ready for next TX DMA */ | |
386 | ret = wait_for_bit_le32(&priv->tx_ring[idx].txd2, TX_DMA_DONE, true, | |
387 | CONFIG_TX_DMA_TIMEOUT, false); | |
388 | if (ret) { | |
389 | printf("TX: DMA still busy on buffer %d\n", idx); | |
390 | return ret; | |
391 | } | |
392 | ||
393 | flush_dcache_range((u32)packet, (u32)packet + length); | |
394 | ||
395 | priv->tx_ring[idx].txd1 = CPHYSADDR(packet); | |
396 | priv->tx_ring[idx].txd2 &= ~TX_DMA_PLEN0; | |
397 | priv->tx_ring[idx].txd2 |= FIELD_PREP(TX_DMA_PLEN0, length); | |
398 | priv->tx_ring[idx].txd2 &= ~TX_DMA_DONE; | |
399 | ||
400 | idx = (idx + 1) % NUM_TX_DESC; | |
401 | ||
402 | /* Make sure the writes executed at this place */ | |
403 | wmb(); | |
404 | writel(idx, base + TX_CTX_IDX0); | |
405 | ||
406 | priv->tx_dma_idx = idx; | |
407 | ||
408 | return 0; | |
409 | } | |
410 | ||
411 | static int mt7628_eth_recv(struct udevice *dev, int flags, uchar **packetp) | |
412 | { | |
413 | struct mt7628_eth_dev *priv = dev_get_priv(dev); | |
414 | u32 rxd_info; | |
415 | int length; | |
416 | int idx; | |
417 | ||
418 | idx = priv->rx_dma_idx; | |
419 | ||
420 | rxd_info = priv->rx_ring[idx].rxd2; | |
421 | if ((rxd_info & RX_DMA_DONE) == 0) | |
422 | return -EAGAIN; | |
423 | ||
424 | length = FIELD_GET(RX_DMA_PLEN0, priv->rx_ring[idx].rxd2); | |
425 | if (length == 0 || length > MTK_QDMA_PAGE_SIZE) { | |
426 | printf("%s: invalid length (%d bytes)\n", __func__, length); | |
427 | return -EIO; | |
428 | } | |
429 | ||
430 | *packetp = priv->rx_buf[idx]; | |
431 | invalidate_dcache_range((u32)*packetp, (u32)*packetp + length); | |
432 | ||
433 | priv->rx_ring[idx].rxd4 = 0; | |
434 | priv->rx_ring[idx].rxd2 = RX_DMA_LSO; | |
435 | ||
436 | /* Make sure the writes executed at this place */ | |
437 | wmb(); | |
438 | ||
439 | return length; | |
440 | } | |
441 | ||
442 | static int mt7628_eth_free_pkt(struct udevice *dev, uchar *packet, int length) | |
443 | { | |
444 | struct mt7628_eth_dev *priv = dev_get_priv(dev); | |
445 | void __iomem *base = priv->base; | |
446 | int idx; | |
447 | ||
448 | idx = priv->rx_dma_idx; | |
449 | ||
450 | /* Move point to next RXD which wants to alloc */ | |
451 | writel(idx, base + RX_CALC_IDX0); | |
452 | ||
453 | /* Update to Next packet point that was received */ | |
454 | idx = (idx + 1) % NUM_RX_DESC; | |
455 | ||
456 | priv->rx_dma_idx = idx; | |
457 | ||
458 | return 0; | |
459 | } | |
460 | ||
461 | static int phy_link_up(struct mt7628_eth_dev *priv) | |
462 | { | |
463 | u32 val; | |
464 | ||
465 | mii_mgr_read(priv, 0x00, MII_BMSR, &val); | |
466 | return !!(val & BMSR_LSTATUS); | |
467 | } | |
468 | ||
469 | static int mt7628_eth_start(struct udevice *dev) | |
470 | { | |
471 | struct mt7628_eth_dev *priv = dev_get_priv(dev); | |
472 | void __iomem *base = priv->base; | |
473 | uchar packet[MTK_QDMA_PAGE_SIZE]; | |
474 | uchar *packetp; | |
475 | int i; | |
476 | ||
477 | for (i = 0; i < NUM_RX_DESC; i++) { | |
478 | memset((void *)&priv->rx_ring[i], 0, sizeof(priv->rx_ring[0])); | |
479 | priv->rx_ring[i].rxd2 |= RX_DMA_LSO; | |
480 | priv->rx_ring[i].rxd1 = CPHYSADDR(priv->rx_buf[i]); | |
481 | } | |
482 | ||
483 | for (i = 0; i < NUM_TX_DESC; i++) { | |
484 | memset((void *)&priv->tx_ring[i], 0, sizeof(priv->tx_ring[0])); | |
485 | priv->tx_ring[i].txd2 = TX_DMA_LS0 | TX_DMA_DONE; | |
486 | priv->tx_ring[i].txd4 = FIELD_PREP(TX_DMA_PN, 1); | |
487 | } | |
488 | ||
489 | priv->rx_dma_idx = 0; | |
490 | priv->tx_dma_idx = 0; | |
491 | ||
492 | /* Make sure the writes executed at this place */ | |
493 | wmb(); | |
494 | ||
495 | /* disable delay interrupt */ | |
496 | writel(0, base + DLY_INT_CFG); | |
497 | ||
498 | clrbits_le32(base + PDMA_GLO_CFG, 0xffff0000); | |
499 | ||
500 | /* Tell the adapter where the TX/RX rings are located. */ | |
501 | writel(CPHYSADDR(&priv->rx_ring[0]), base + RX_BASE_PTR0); | |
502 | writel(CPHYSADDR((u32)&priv->tx_ring[0]), base + TX_BASE_PTR0); | |
503 | ||
504 | writel(NUM_RX_DESC, base + RX_MAX_CNT0); | |
505 | writel(NUM_TX_DESC, base + TX_MAX_CNT0); | |
506 | ||
507 | writel(priv->tx_dma_idx, base + TX_CTX_IDX0); | |
508 | writel(RST_DTX_IDX0, base + PDMA_RST_IDX); | |
509 | ||
510 | writel(NUM_RX_DESC - 1, base + RX_CALC_IDX0); | |
511 | writel(RST_DRX_IDX0, base + PDMA_RST_IDX); | |
512 | ||
513 | /* Make sure the writes executed at this place */ | |
514 | wmb(); | |
515 | eth_dma_start(priv); | |
516 | ||
517 | /* Check if link is not up yet */ | |
518 | if (!phy_link_up(priv)) { | |
519 | /* Wait for link to come up */ | |
520 | ||
521 | printf("Waiting for link to come up ."); | |
522 | for (i = 0; i < (LINK_TIMEOUT / LINK_DELAY_TIME); i++) { | |
523 | mdelay(LINK_DELAY_TIME); | |
524 | if (phy_link_up(priv)) { | |
525 | mdelay(100); /* Ensure all is ready */ | |
526 | break; | |
527 | } | |
528 | ||
529 | printf("."); | |
530 | } | |
531 | ||
532 | if (phy_link_up(priv)) | |
533 | printf(" done\n"); | |
534 | else | |
535 | printf(" timeout! Trying anyways\n"); | |
536 | } | |
537 | ||
538 | /* | |
539 | * The integrated switch seems to queue some received ethernet | |
540 | * packets in some FIFO. Lets read the already queued packets | |
541 | * out by using the receive routine, so that these old messages | |
542 | * are dropped before the new xfer starts. | |
543 | */ | |
544 | packetp = &packet[0]; | |
545 | while (mt7628_eth_recv(dev, 0, &packetp) != -EAGAIN) | |
546 | mt7628_eth_free_pkt(dev, packetp, 0); | |
547 | ||
548 | return 0; | |
549 | } | |
550 | ||
551 | static void mt7628_eth_stop(struct udevice *dev) | |
552 | { | |
553 | struct mt7628_eth_dev *priv = dev_get_priv(dev); | |
554 | ||
555 | eth_dma_stop(priv); | |
556 | } | |
557 | ||
558 | static int mt7628_eth_probe(struct udevice *dev) | |
559 | { | |
560 | struct mt7628_eth_dev *priv = dev_get_priv(dev); | |
561 | struct udevice *syscon; | |
562 | struct mii_dev *bus; | |
563 | int ret; | |
564 | int i; | |
565 | ||
566 | /* Save frame-engine base address for later use */ | |
567 | priv->base = dev_remap_addr_index(dev, 0); | |
568 | if (IS_ERR(priv->base)) | |
569 | return PTR_ERR(priv->base); | |
570 | ||
571 | /* Save switch base address for later use */ | |
572 | priv->eth_sw_base = dev_remap_addr_index(dev, 1); | |
573 | if (IS_ERR(priv->eth_sw_base)) | |
574 | return PTR_ERR(priv->eth_sw_base); | |
575 | ||
576 | /* Get system controller regmap */ | |
577 | ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, | |
578 | "syscon", &syscon); | |
579 | if (ret) { | |
580 | pr_err("unable to find syscon device\n"); | |
581 | return ret; | |
582 | } | |
583 | ||
584 | priv->sysctrl_regmap = syscon_get_regmap(syscon); | |
585 | if (!priv->sysctrl_regmap) { | |
586 | pr_err("unable to find regmap\n"); | |
587 | return -ENODEV; | |
588 | } | |
589 | ||
590 | /* Put rx and tx rings into KSEG1 area (uncached) */ | |
591 | priv->tx_ring = (struct fe_tx_dma *) | |
592 | KSEG1ADDR(memalign(ARCH_DMA_MINALIGN, | |
593 | sizeof(*priv->tx_ring) * NUM_TX_DESC)); | |
594 | priv->rx_ring = (struct fe_rx_dma *) | |
595 | KSEG1ADDR(memalign(ARCH_DMA_MINALIGN, | |
596 | sizeof(*priv->rx_ring) * NUM_RX_DESC)); | |
597 | ||
598 | for (i = 0; i < NUM_RX_DESC; i++) | |
599 | priv->rx_buf[i] = memalign(PKTALIGN, MTK_QDMA_PAGE_SIZE); | |
600 | ||
601 | bus = mdio_alloc(); | |
602 | if (!bus) { | |
603 | printf("Failed to allocate MDIO bus\n"); | |
604 | return -ENOMEM; | |
605 | } | |
606 | ||
607 | bus->read = mt7628_mdio_read; | |
608 | bus->write = mt7628_mdio_write; | |
609 | snprintf(bus->name, sizeof(bus->name), dev->name); | |
610 | bus->priv = (void *)priv; | |
611 | ||
612 | ret = mdio_register(bus); | |
613 | if (ret) | |
614 | return ret; | |
615 | ||
616 | /* Switch configuration */ | |
617 | rt305x_esw_init(priv); | |
618 | ||
619 | return 0; | |
620 | } | |
621 | ||
622 | static const struct eth_ops mt7628_eth_ops = { | |
623 | .start = mt7628_eth_start, | |
624 | .send = mt7628_eth_send, | |
625 | .recv = mt7628_eth_recv, | |
626 | .free_pkt = mt7628_eth_free_pkt, | |
627 | .stop = mt7628_eth_stop, | |
628 | .write_hwaddr = mt7628_eth_write_hwaddr, | |
629 | }; | |
630 | ||
631 | static const struct udevice_id mt7628_eth_ids[] = { | |
632 | { .compatible = "mediatek,mt7628-eth" }, | |
633 | { } | |
634 | }; | |
635 | ||
636 | U_BOOT_DRIVER(mt7628_eth) = { | |
637 | .name = "mt7628_eth", | |
638 | .id = UCLASS_ETH, | |
639 | .of_match = mt7628_eth_ids, | |
640 | .probe = mt7628_eth_probe, | |
641 | .ops = &mt7628_eth_ops, | |
642 | .priv_auto_alloc_size = sizeof(struct mt7628_eth_dev), | |
643 | .platdata_auto_alloc_size = sizeof(struct eth_pdata), | |
644 | }; |