1
2
3
4
5
6
7
8
9#include <common.h>
10#include <dm.h>
11#include <errno.h>
12#include <miiphy.h>
13#include <malloc.h>
14#include <linux/compiler.h>
15#include <linux/err.h>
16#include <linux/mii.h>
17#include <wait_bit.h>
18#include <asm/io.h>
19
20#include <mach/ath79.h>
21
22DECLARE_GLOBAL_DATA_PTR;
23
24enum ag7xxx_model {
25 AG7XXX_MODEL_AG933X,
26 AG7XXX_MODEL_AG934X,
27};
28
29#define AG7XXX_ETH_CFG1 0x00
30#define AG7XXX_ETH_CFG1_SOFT_RST BIT(31)
31#define AG7XXX_ETH_CFG1_RX_RST BIT(19)
32#define AG7XXX_ETH_CFG1_TX_RST BIT(18)
33#define AG7XXX_ETH_CFG1_LOOPBACK BIT(8)
34#define AG7XXX_ETH_CFG1_RX_EN BIT(2)
35#define AG7XXX_ETH_CFG1_TX_EN BIT(0)
36
37#define AG7XXX_ETH_CFG2 0x04
38#define AG7XXX_ETH_CFG2_IF_1000 BIT(9)
39#define AG7XXX_ETH_CFG2_IF_10_100 BIT(8)
40#define AG7XXX_ETH_CFG2_IF_SPEED_MASK (3 << 8)
41#define AG7XXX_ETH_CFG2_HUGE_FRAME_EN BIT(5)
42#define AG7XXX_ETH_CFG2_LEN_CHECK BIT(4)
43#define AG7XXX_ETH_CFG2_PAD_CRC_EN BIT(2)
44#define AG7XXX_ETH_CFG2_FDX BIT(0)
45
46#define AG7XXX_ETH_MII_MGMT_CFG 0x20
47#define AG7XXX_ETH_MII_MGMT_CFG_RESET BIT(31)
48
49#define AG7XXX_ETH_MII_MGMT_CMD 0x24
50#define AG7XXX_ETH_MII_MGMT_CMD_READ 0x1
51
52#define AG7XXX_ETH_MII_MGMT_ADDRESS 0x28
53#define AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT 8
54
55#define AG7XXX_ETH_MII_MGMT_CTRL 0x2c
56
57#define AG7XXX_ETH_MII_MGMT_STATUS 0x30
58
59#define AG7XXX_ETH_MII_MGMT_IND 0x34
60#define AG7XXX_ETH_MII_MGMT_IND_INVALID BIT(2)
61#define AG7XXX_ETH_MII_MGMT_IND_BUSY BIT(0)
62
63#define AG7XXX_ETH_ADDR1 0x40
64#define AG7XXX_ETH_ADDR2 0x44
65
66#define AG7XXX_ETH_FIFO_CFG_0 0x48
67#define AG7XXX_ETH_FIFO_CFG_1 0x4c
68#define AG7XXX_ETH_FIFO_CFG_2 0x50
69#define AG7XXX_ETH_FIFO_CFG_3 0x54
70#define AG7XXX_ETH_FIFO_CFG_4 0x58
71#define AG7XXX_ETH_FIFO_CFG_5 0x5c
72
73#define AG7XXX_ETH_DMA_TX_CTRL 0x180
74#define AG7XXX_ETH_DMA_TX_CTRL_TXE BIT(0)
75
76#define AG7XXX_ETH_DMA_TX_DESC 0x184
77
78#define AG7XXX_ETH_DMA_TX_STATUS 0x188
79
80#define AG7XXX_ETH_DMA_RX_CTRL 0x18c
81#define AG7XXX_ETH_DMA_RX_CTRL_RXE BIT(0)
82
83#define AG7XXX_ETH_DMA_RX_DESC 0x190
84
85#define AG7XXX_ETH_DMA_RX_STATUS 0x194
86
87
88#define AG7XXX_GMAC_ETH_CFG 0x00
89#define AG7XXX_ETH_CFG_SW_PHY_ADDR_SWAP BIT(8)
90#define AG7XXX_ETH_CFG_SW_PHY_SWAP BIT(7)
91#define AG7XXX_ETH_CFG_SW_ONLY_MODE BIT(6)
92#define AG7XXX_ETH_CFG_GE0_ERR_EN BIT(5)
93#define AG7XXX_ETH_CFG_MII_GE0_SLAVE BIT(4)
94#define AG7XXX_ETH_CFG_MII_GE0_MASTER BIT(3)
95#define AG7XXX_ETH_CFG_GMII_GE0 BIT(2)
96#define AG7XXX_ETH_CFG_MII_GE0 BIT(1)
97#define AG7XXX_ETH_CFG_RGMII_GE0 BIT(0)
98
99#define CONFIG_TX_DESCR_NUM 8
100#define CONFIG_RX_DESCR_NUM 8
101#define CONFIG_ETH_BUFSIZE 2048
102#define TX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM)
103#define RX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM)
104
105
106struct ag7xxx_dma_desc {
107 u32 data_addr;
108#define AG7XXX_DMADESC_IS_EMPTY BIT(31)
109#define AG7XXX_DMADESC_FTPP_OVERRIDE_OFFSET 16
110#define AG7XXX_DMADESC_PKT_SIZE_OFFSET 0
111#define AG7XXX_DMADESC_PKT_SIZE_MASK 0xfff
112 u32 config;
113 u32 next_desc;
114 u32 _pad[5];
115};
116
117struct ar7xxx_eth_priv {
118 struct ag7xxx_dma_desc tx_mac_descrtable[CONFIG_TX_DESCR_NUM];
119 struct ag7xxx_dma_desc rx_mac_descrtable[CONFIG_RX_DESCR_NUM];
120 char txbuffs[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
121 char rxbuffs[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
122
123 void __iomem *regs;
124 void __iomem *phyregs;
125
126 struct eth_device *dev;
127 struct phy_device *phydev;
128 struct mii_dev *bus;
129
130 u32 interface;
131 u32 tx_currdescnum;
132 u32 rx_currdescnum;
133 enum ag7xxx_model model;
134};
135
136
137
138
139static int ag7xxx_switch_read(struct mii_dev *bus, int addr, int reg, u16 *val)
140{
141 struct ar7xxx_eth_priv *priv = bus->priv;
142 void __iomem *regs = priv->phyregs;
143 int ret;
144
145 writel(0x0, regs + AG7XXX_ETH_MII_MGMT_CMD);
146 writel((addr << AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT) | reg,
147 regs + AG7XXX_ETH_MII_MGMT_ADDRESS);
148 writel(AG7XXX_ETH_MII_MGMT_CMD_READ,
149 regs + AG7XXX_ETH_MII_MGMT_CMD);
150
151 ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND,
152 AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
153 if (ret)
154 return ret;
155
156 *val = readl(regs + AG7XXX_ETH_MII_MGMT_STATUS) & 0xffff;
157 writel(0x0, regs + AG7XXX_ETH_MII_MGMT_CMD);
158
159 return 0;
160}
161
162static int ag7xxx_switch_write(struct mii_dev *bus, int addr, int reg, u16 val)
163{
164 struct ar7xxx_eth_priv *priv = bus->priv;
165 void __iomem *regs = priv->phyregs;
166 int ret;
167
168 writel((addr << AG7XXX_ETH_MII_MGMT_ADDRESS_SHIFT) | reg,
169 regs + AG7XXX_ETH_MII_MGMT_ADDRESS);
170 writel(val, regs + AG7XXX_ETH_MII_MGMT_CTRL);
171
172 ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND,
173 AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0);
174
175 return ret;
176}
177
178static int ag7xxx_switch_reg_read(struct mii_dev *bus, int reg, u32 *val)
179{
180 struct ar7xxx_eth_priv *priv = bus->priv;
181 u32 phy_addr;
182 u32 reg_addr;
183 u32 phy_temp;
184 u32 reg_temp;
185 u16 rv = 0;
186 int ret;
187
188 if (priv->model == AG7XXX_MODEL_AG933X) {
189 phy_addr = 0x1f;
190 reg_addr = 0x10;
191 } else if (priv->model == AG7XXX_MODEL_AG934X) {
192 phy_addr = 0x18;
193 reg_addr = 0x00;
194 } else
195 return -EINVAL;
196
197 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
198 if (ret)
199 return ret;
200
201 phy_temp = ((reg >> 6) & 0x7) | 0x10;
202 reg_temp = (reg >> 1) & 0x1e;
203 *val = 0;
204
205 ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 0, &rv);
206 if (ret < 0)
207 return ret;
208 *val |= rv;
209
210 ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 1, &rv);
211 if (ret < 0)
212 return ret;
213 *val |= (rv << 16);
214
215 return 0;
216}
217
218static int ag7xxx_switch_reg_write(struct mii_dev *bus, int reg, u32 val)
219{
220 struct ar7xxx_eth_priv *priv = bus->priv;
221 u32 phy_addr;
222 u32 reg_addr;
223 u32 phy_temp;
224 u32 reg_temp;
225 int ret;
226
227 if (priv->model == AG7XXX_MODEL_AG933X) {
228 phy_addr = 0x1f;
229 reg_addr = 0x10;
230 } else if (priv->model == AG7XXX_MODEL_AG934X) {
231 phy_addr = 0x18;
232 reg_addr = 0x00;
233 } else
234 return -EINVAL;
235
236 ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
237 if (ret)
238 return ret;
239
240 phy_temp = ((reg >> 6) & 0x7) | 0x10;
241 reg_temp = (reg >> 1) & 0x1e;
242
243
244
245
246
247
248
249
250
251 if ((priv->model == AG7XXX_MODEL_AG933X) && (reg == 0x98)) {
252 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 0, val & 0xffff);
253 if (ret < 0)
254 return ret;
255
256 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16);
257 if (ret < 0)
258 return ret;
259 } else {
260 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16);
261 if (ret < 0)
262 return ret;
263
264 ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 0, val & 0xffff);
265 if (ret < 0)
266 return ret;
267 }
268
269 return 0;
270}
271
272static u16 ag7xxx_mdio_rw(struct mii_dev *bus, int addr, int reg, u32 val)
273{
274 u32 data;
275
276
277 ag7xxx_switch_reg_read(bus, 0x98, &data);
278 data = val | (reg << 16) | (addr << 21) | BIT(30) | BIT(31);
279 ag7xxx_switch_reg_write(bus, 0x98, data);
280
281
282 do {
283 ag7xxx_switch_reg_read(bus, 0x98, &data);
284 } while (data & BIT(31));
285
286 return data & 0xffff;
287}
288
289static int ag7xxx_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
290{
291 return ag7xxx_mdio_rw(bus, addr, reg, BIT(27));
292}
293
294static int ag7xxx_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
295 u16 val)
296{
297 ag7xxx_mdio_rw(bus, addr, reg, val);
298 return 0;
299}
300
301
302
303
304static void ag7xxx_dma_clean_tx(struct udevice *dev)
305{
306 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
307 struct ag7xxx_dma_desc *curr, *next;
308 u32 start, end;
309 int i;
310
311 for (i = 0; i < CONFIG_TX_DESCR_NUM; i++) {
312 curr = &priv->tx_mac_descrtable[i];
313 next = &priv->tx_mac_descrtable[(i + 1) % CONFIG_TX_DESCR_NUM];
314
315 curr->data_addr = virt_to_phys(&priv->txbuffs[i * CONFIG_ETH_BUFSIZE]);
316 curr->config = AG7XXX_DMADESC_IS_EMPTY;
317 curr->next_desc = virt_to_phys(next);
318 }
319
320 priv->tx_currdescnum = 0;
321
322
323 start = (u32)(&priv->tx_mac_descrtable[0]);
324 end = start + sizeof(priv->tx_mac_descrtable);
325 flush_dcache_range(start, end);
326}
327
328static void ag7xxx_dma_clean_rx(struct udevice *dev)
329{
330 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
331 struct ag7xxx_dma_desc *curr, *next;
332 u32 start, end;
333 int i;
334
335 for (i = 0; i < CONFIG_RX_DESCR_NUM; i++) {
336 curr = &priv->rx_mac_descrtable[i];
337 next = &priv->rx_mac_descrtable[(i + 1) % CONFIG_RX_DESCR_NUM];
338
339 curr->data_addr = virt_to_phys(&priv->rxbuffs[i * CONFIG_ETH_BUFSIZE]);
340 curr->config = AG7XXX_DMADESC_IS_EMPTY;
341 curr->next_desc = virt_to_phys(next);
342 }
343
344 priv->rx_currdescnum = 0;
345
346
347 start = (u32)(&priv->rx_mac_descrtable[0]);
348 end = start + sizeof(priv->rx_mac_descrtable);
349 flush_dcache_range(start, end);
350 invalidate_dcache_range(start, end);
351
352 start = (u32)&priv->rxbuffs;
353 end = start + sizeof(priv->rxbuffs);
354 invalidate_dcache_range(start, end);
355}
356
357
358
359
360static int ag7xxx_eth_send(struct udevice *dev, void *packet, int length)
361{
362 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
363 struct ag7xxx_dma_desc *curr;
364 u32 start, end;
365
366 curr = &priv->tx_mac_descrtable[priv->tx_currdescnum];
367
368
369 start = (u32)curr;
370 end = start + sizeof(*curr);
371 invalidate_dcache_range(start, end);
372
373 if (!(curr->config & AG7XXX_DMADESC_IS_EMPTY)) {
374 printf("ag7xxx: Out of TX DMA descriptors!\n");
375 return -EPERM;
376 }
377
378
379 memcpy(phys_to_virt(curr->data_addr), packet, length);
380 curr->config = length & AG7XXX_DMADESC_PKT_SIZE_MASK;
381
382
383 start = (u32)curr;
384 end = start + sizeof(*curr);
385 flush_dcache_range(start, end);
386 start = (u32)phys_to_virt(curr->data_addr);
387 end = start + length;
388 flush_dcache_range(start, end);
389
390
391 writel(AG7XXX_ETH_DMA_TX_CTRL_TXE,
392 priv->regs + AG7XXX_ETH_DMA_TX_CTRL);
393
394
395 priv->tx_currdescnum = (priv->tx_currdescnum + 1) % CONFIG_TX_DESCR_NUM;
396
397 return 0;
398}
399
400static int ag7xxx_eth_recv(struct udevice *dev, int flags, uchar **packetp)
401{
402 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
403 struct ag7xxx_dma_desc *curr;
404 u32 start, end, length;
405
406 curr = &priv->rx_mac_descrtable[priv->rx_currdescnum];
407
408
409 start = (u32)curr;
410 end = start + sizeof(*curr);
411 invalidate_dcache_range(start, end);
412
413
414 if (curr->config & AG7XXX_DMADESC_IS_EMPTY)
415 return -EAGAIN;
416
417 length = curr->config & AG7XXX_DMADESC_PKT_SIZE_MASK;
418
419
420 start = (u32)phys_to_virt(curr->data_addr);
421 end = start + length;
422 invalidate_dcache_range(start, end);
423
424
425 *packetp = phys_to_virt(curr->data_addr);
426 return length;
427}
428
429static int ag7xxx_eth_free_pkt(struct udevice *dev, uchar *packet,
430 int length)
431{
432 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
433 struct ag7xxx_dma_desc *curr;
434 u32 start, end;
435
436 curr = &priv->rx_mac_descrtable[priv->rx_currdescnum];
437
438 curr->config = AG7XXX_DMADESC_IS_EMPTY;
439
440
441 start = (u32)curr;
442 end = start + sizeof(*curr);
443 flush_dcache_range(start, end);
444
445
446 priv->rx_currdescnum = (priv->rx_currdescnum + 1) % CONFIG_RX_DESCR_NUM;
447
448 return 0;
449}
450
451static int ag7xxx_eth_start(struct udevice *dev)
452{
453 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
454
455
456
457
458 ag7xxx_dma_clean_tx(dev);
459 ag7xxx_dma_clean_rx(dev);
460
461
462 writel(virt_to_phys(&priv->tx_mac_descrtable[priv->tx_currdescnum]),
463 priv->regs + AG7XXX_ETH_DMA_TX_DESC);
464 writel(virt_to_phys(&priv->rx_mac_descrtable[priv->rx_currdescnum]),
465 priv->regs + AG7XXX_ETH_DMA_RX_DESC);
466 writel(AG7XXX_ETH_DMA_RX_CTRL_RXE,
467 priv->regs + AG7XXX_ETH_DMA_RX_CTRL);
468
469 return 0;
470}
471
472static void ag7xxx_eth_stop(struct udevice *dev)
473{
474 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
475
476
477 writel(0, priv->regs + AG7XXX_ETH_DMA_TX_CTRL);
478 wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0,
479 1000, 0);
480
481
482 writel(0, priv->regs + AG7XXX_ETH_DMA_RX_CTRL);
483 wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0,
484 1000, 0);
485}
486
487
488
489
490static int ag7xxx_eth_write_hwaddr(struct udevice *dev)
491{
492 struct eth_pdata *pdata = dev_get_platdata(dev);
493 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
494 unsigned char *mac = pdata->enetaddr;
495 u32 macid_lo, macid_hi;
496
497 macid_hi = mac[3] | (mac[2] << 8) | (mac[1] << 16) | (mac[0] << 24);
498 macid_lo = (mac[5] << 16) | (mac[4] << 24);
499
500 writel(macid_lo, priv->regs + AG7XXX_ETH_ADDR1);
501 writel(macid_hi, priv->regs + AG7XXX_ETH_ADDR2);
502
503 return 0;
504}
505
506static void ag7xxx_hw_setup(struct udevice *dev)
507{
508 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
509 u32 speed;
510
511 setbits_be32(priv->regs + AG7XXX_ETH_CFG1,
512 AG7XXX_ETH_CFG1_RX_RST | AG7XXX_ETH_CFG1_TX_RST |
513 AG7XXX_ETH_CFG1_SOFT_RST);
514
515 mdelay(10);
516
517 writel(AG7XXX_ETH_CFG1_RX_EN | AG7XXX_ETH_CFG1_TX_EN,
518 priv->regs + AG7XXX_ETH_CFG1);
519
520 if (priv->interface == PHY_INTERFACE_MODE_RMII)
521 speed = AG7XXX_ETH_CFG2_IF_10_100;
522 else
523 speed = AG7XXX_ETH_CFG2_IF_1000;
524
525 clrsetbits_be32(priv->regs + AG7XXX_ETH_CFG2,
526 AG7XXX_ETH_CFG2_IF_SPEED_MASK,
527 speed | AG7XXX_ETH_CFG2_PAD_CRC_EN |
528 AG7XXX_ETH_CFG2_LEN_CHECK);
529
530 writel(0xfff0000, priv->regs + AG7XXX_ETH_FIFO_CFG_1);
531 writel(0x1fff, priv->regs + AG7XXX_ETH_FIFO_CFG_2);
532
533 writel(0x1f00, priv->regs + AG7XXX_ETH_FIFO_CFG_0);
534 setbits_be32(priv->regs + AG7XXX_ETH_FIFO_CFG_4, 0x3ffff);
535 writel(0x10ffff, priv->regs + AG7XXX_ETH_FIFO_CFG_1);
536 writel(0xaaa0555, priv->regs + AG7XXX_ETH_FIFO_CFG_2);
537 writel(0x7eccf, priv->regs + AG7XXX_ETH_FIFO_CFG_5);
538 writel(0x1f00140, priv->regs + AG7XXX_ETH_FIFO_CFG_3);
539}
540
541static int ag7xxx_mii_get_div(void)
542{
543 ulong freq = get_bus_freq(0);
544
545 switch (freq / 1000000) {
546 case 150: return 0x7;
547 case 175: return 0x5;
548 case 200: return 0x4;
549 case 210: return 0x9;
550 case 220: return 0x9;
551 default: return 0x7;
552 }
553}
554
555static int ag7xxx_mii_setup(struct udevice *dev)
556{
557 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
558 int i, ret, div = ag7xxx_mii_get_div();
559 u32 reg;
560
561 if (priv->model == AG7XXX_MODEL_AG933X) {
562
563 if (priv->interface == PHY_INTERFACE_MODE_RMII)
564 return 0;
565 }
566
567 if (priv->model == AG7XXX_MODEL_AG934X) {
568 writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | 0x4,
569 priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
570 writel(0x4, priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
571 return 0;
572 }
573
574 for (i = 0; i < 10; i++) {
575 writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | div,
576 priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
577 writel(div, priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
578
579
580 ret = ag7xxx_switch_reg_read(priv->bus, 0x10c, ®);
581 if (ret)
582 continue;
583
584 if (reg != 0x18007fff)
585 continue;
586
587 return 0;
588 }
589
590 return -EINVAL;
591}
592
593static int ag933x_phy_setup_wan(struct udevice *dev)
594{
595 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
596
597
598 return ag7xxx_mdio_write(priv->bus, 4, 0, MII_BMCR, 0x9000);
599}
600
601static int ag933x_phy_setup_lan(struct udevice *dev)
602{
603 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
604 int i, ret;
605 u32 reg;
606
607
608 ret = ag7xxx_switch_reg_read(priv->bus, 0, ®);
609 if (ret)
610 return ret;
611 reg |= BIT(31);
612 ret = ag7xxx_switch_reg_write(priv->bus, 0, reg);
613 if (ret)
614 return ret;
615
616 do {
617 ret = ag7xxx_switch_reg_read(priv->bus, 0, ®);
618 if (ret)
619 return ret;
620 } while (reg & BIT(31));
621
622
623 for (i = 0; i < 4; i++) {
624 ret = ag7xxx_mdio_write(priv->bus, 0x4, 0, MII_BMCR, 0x9000);
625 if (ret)
626 return ret;
627 }
628
629
630 ret = ag7xxx_switch_reg_write(priv->bus, 0x78, BIT(8));
631 if (ret)
632 return ret;
633
634 for (i = 0; i < 4; i++) {
635 ret = ag7xxx_switch_reg_write(priv->bus, i * 0x100, BIT(9));
636 if (ret)
637 return ret;
638 }
639
640
641 ret = ag7xxx_switch_reg_write(priv->bus, 0x38, 0xc000050e);
642 if (ret)
643 return ret;
644
645
646 ret = ag7xxx_switch_reg_write(priv->bus, 0x104, 0x4004);
647 if (ret)
648 return ret;
649
650
651 ret = ag7xxx_switch_reg_write(priv->bus, 0x70, 0xfa50);
652 if (ret)
653 return ret;
654
655
656 ret = ag7xxx_switch_reg_read(priv->bus, 0x5c, ®);
657 if (ret)
658 return ret;
659 reg |= 0x100000;
660 ret = ag7xxx_switch_reg_write(priv->bus, 0x5c, reg);
661 if (ret)
662 return ret;
663
664 return 0;
665}
666
667static int ag933x_phy_setup_reset_set(struct udevice *dev, int port)
668{
669 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
670 int ret;
671
672 ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_ADVERTISE,
673 ADVERTISE_ALL | ADVERTISE_PAUSE_CAP |
674 ADVERTISE_PAUSE_ASYM);
675 if (ret)
676 return ret;
677
678 if (priv->model == AG7XXX_MODEL_AG934X) {
679 ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_CTRL1000,
680 ADVERTISE_1000FULL);
681 if (ret)
682 return ret;
683 }
684
685 return ag7xxx_mdio_write(priv->bus, port, 0, MII_BMCR,
686 BMCR_ANENABLE | BMCR_RESET);
687}
688
689static int ag933x_phy_setup_reset_fin(struct udevice *dev, int port)
690{
691 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
692 int ret;
693
694 do {
695 ret = ag7xxx_mdio_read(priv->bus, port, 0, MII_BMCR);
696 if (ret < 0)
697 return ret;
698 mdelay(10);
699 } while (ret & BMCR_RESET);
700
701 return 0;
702}
703
704static int ag933x_phy_setup_common(struct udevice *dev)
705{
706 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
707 int i, ret, phymax;
708
709 if (priv->model == AG7XXX_MODEL_AG933X)
710 phymax = 4;
711 else if (priv->model == AG7XXX_MODEL_AG934X)
712 phymax = 5;
713 else
714 return -EINVAL;
715
716 if (priv->interface == PHY_INTERFACE_MODE_RMII) {
717 ret = ag933x_phy_setup_reset_set(dev, phymax);
718 if (ret)
719 return ret;
720
721 ret = ag933x_phy_setup_reset_fin(dev, phymax);
722 if (ret)
723 return ret;
724
725
726 ret = ag7xxx_mdio_read(priv->bus, phymax, 0, MII_MIPSCR);
727 if (ret < 0)
728 return ret;
729
730 return 0;
731 }
732
733
734 for (i = 0; i < phymax; i++) {
735 ret = ag933x_phy_setup_reset_set(dev, i);
736 if (ret)
737 return ret;
738 }
739
740 for (i = 0; i < phymax; i++) {
741 ret = ag933x_phy_setup_reset_fin(dev, i);
742 if (ret)
743 return ret;
744 }
745
746 for (i = 0; i < phymax; i++) {
747
748 ret = ag7xxx_mdio_read(priv->bus, i, 0, MII_MIPSCR);
749 if (ret < 0)
750 return ret;
751 }
752
753 return 0;
754}
755
756static int ag934x_phy_setup(struct udevice *dev)
757{
758 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
759 int i, ret;
760 u32 reg;
761
762 ret = ag7xxx_switch_reg_write(priv->bus, 0x624, 0x7f7f7f7f);
763 if (ret)
764 return ret;
765 ret = ag7xxx_switch_reg_write(priv->bus, 0x10, 0x40000000);
766 if (ret)
767 return ret;
768 ret = ag7xxx_switch_reg_write(priv->bus, 0x4, 0x07600000);
769 if (ret)
770 return ret;
771 ret = ag7xxx_switch_reg_write(priv->bus, 0xc, 0x01000000);
772 if (ret)
773 return ret;
774 ret = ag7xxx_switch_reg_write(priv->bus, 0x7c, 0x0000007e);
775 if (ret)
776 return ret;
777
778
779 ret = ag7xxx_switch_reg_read(priv->bus, 0, ®);
780 if (ret)
781 return ret;
782 if ((reg & 0xffff) == 0x1201) {
783 for (i = 0; i < 5; i++) {
784 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1d, 0x0);
785 if (ret)
786 return ret;
787 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1e, 0x02ea);
788 if (ret)
789 return ret;
790 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1d, 0x3d);
791 if (ret)
792 return ret;
793 ret = ag7xxx_mdio_write(priv->bus, i, 0, 0x1e, 0x68a0);
794 if (ret)
795 return ret;
796 }
797 }
798
799 ret = ag7xxx_switch_reg_read(priv->bus, 0x66c, ®);
800 if (ret)
801 return ret;
802 reg &= ~0x70000;
803 ret = ag7xxx_switch_reg_write(priv->bus, 0x66c, reg);
804 if (ret)
805 return ret;
806
807 return 0;
808}
809
810static int ag7xxx_mac_probe(struct udevice *dev)
811{
812 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
813 int ret;
814
815 ag7xxx_hw_setup(dev);
816 ret = ag7xxx_mii_setup(dev);
817 if (ret)
818 return ret;
819
820 ag7xxx_eth_write_hwaddr(dev);
821
822 if (priv->model == AG7XXX_MODEL_AG933X) {
823 if (priv->interface == PHY_INTERFACE_MODE_RMII)
824 ret = ag933x_phy_setup_wan(dev);
825 else
826 ret = ag933x_phy_setup_lan(dev);
827 } else if (priv->model == AG7XXX_MODEL_AG934X) {
828 ret = ag934x_phy_setup(dev);
829 } else {
830 return -EINVAL;
831 }
832
833 if (ret)
834 return ret;
835
836 return ag933x_phy_setup_common(dev);
837}
838
839static int ag7xxx_mdio_probe(struct udevice *dev)
840{
841 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
842 struct mii_dev *bus = mdio_alloc();
843
844 if (!bus)
845 return -ENOMEM;
846
847 bus->read = ag7xxx_mdio_read;
848 bus->write = ag7xxx_mdio_write;
849 snprintf(bus->name, sizeof(bus->name), dev->name);
850
851 bus->priv = (void *)priv;
852
853 return mdio_register(bus);
854}
855
856static int ag7xxx_get_phy_iface_offset(struct udevice *dev)
857{
858 int offset;
859
860 offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset, "phy");
861 if (offset <= 0) {
862 debug("%s: PHY OF node not found (ret=%i)\n", __func__, offset);
863 return -EINVAL;
864 }
865
866 offset = fdt_parent_offset(gd->fdt_blob, offset);
867 if (offset <= 0) {
868 debug("%s: PHY OF node parent MDIO bus not found (ret=%i)\n",
869 __func__, offset);
870 return -EINVAL;
871 }
872
873 offset = fdt_parent_offset(gd->fdt_blob, offset);
874 if (offset <= 0) {
875 debug("%s: PHY MDIO OF node parent MAC not found (ret=%i)\n",
876 __func__, offset);
877 return -EINVAL;
878 }
879
880 return offset;
881}
882
883static int ag7xxx_eth_probe(struct udevice *dev)
884{
885 struct eth_pdata *pdata = dev_get_platdata(dev);
886 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
887 void __iomem *iobase, *phyiobase;
888 int ret, phyreg;
889
890
891 ret = ag7xxx_get_phy_iface_offset(dev);
892 if (ret <= 0)
893 return ret;
894 phyreg = fdtdec_get_int(gd->fdt_blob, ret, "reg", -1);
895
896 iobase = map_physmem(pdata->iobase, 0x200, MAP_NOCACHE);
897 phyiobase = map_physmem(phyreg, 0x200, MAP_NOCACHE);
898
899 debug("%s, iobase=%p, phyiobase=%p, priv=%p\n",
900 __func__, iobase, phyiobase, priv);
901 priv->regs = iobase;
902 priv->phyregs = phyiobase;
903 priv->interface = pdata->phy_interface;
904 priv->model = dev_get_driver_data(dev);
905
906 ret = ag7xxx_mdio_probe(dev);
907 if (ret)
908 return ret;
909
910 priv->bus = miiphy_get_dev_by_name(dev->name);
911
912 ret = ag7xxx_mac_probe(dev);
913 debug("%s, ret=%d\n", __func__, ret);
914
915 return ret;
916}
917
918static int ag7xxx_eth_remove(struct udevice *dev)
919{
920 struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
921
922 free(priv->phydev);
923 mdio_unregister(priv->bus);
924 mdio_free(priv->bus);
925
926 return 0;
927}
928
929static const struct eth_ops ag7xxx_eth_ops = {
930 .start = ag7xxx_eth_start,
931 .send = ag7xxx_eth_send,
932 .recv = ag7xxx_eth_recv,
933 .free_pkt = ag7xxx_eth_free_pkt,
934 .stop = ag7xxx_eth_stop,
935 .write_hwaddr = ag7xxx_eth_write_hwaddr,
936};
937
938static int ag7xxx_eth_ofdata_to_platdata(struct udevice *dev)
939{
940 struct eth_pdata *pdata = dev_get_platdata(dev);
941 const char *phy_mode;
942 int ret;
943
944 pdata->iobase = dev_get_addr(dev);
945 pdata->phy_interface = -1;
946
947
948 ret = ag7xxx_get_phy_iface_offset(dev);
949 if (ret <= 0)
950 return ret;
951
952 phy_mode = fdt_getprop(gd->fdt_blob, ret, "phy-mode", NULL);
953 if (phy_mode)
954 pdata->phy_interface = phy_get_interface_by_name(phy_mode);
955 if (pdata->phy_interface == -1) {
956 debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
957 return -EINVAL;
958 }
959
960 return 0;
961}
962
963static const struct udevice_id ag7xxx_eth_ids[] = {
964 { .compatible = "qca,ag933x-mac", .data = AG7XXX_MODEL_AG933X },
965 { .compatible = "qca,ag934x-mac", .data = AG7XXX_MODEL_AG934X },
966 { }
967};
968
969U_BOOT_DRIVER(eth_ag7xxx) = {
970 .name = "eth_ag7xxx",
971 .id = UCLASS_ETH,
972 .of_match = ag7xxx_eth_ids,
973 .ofdata_to_platdata = ag7xxx_eth_ofdata_to_platdata,
974 .probe = ag7xxx_eth_probe,
975 .remove = ag7xxx_eth_remove,
976 .ops = &ag7xxx_eth_ops,
977 .priv_auto_alloc_size = sizeof(struct ar7xxx_eth_priv),
978 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
979 .flags = DM_FLAG_ALLOC_PRIV_DMA,
980};
981