2 * Atheros AR71xx built-in ethernet mac driver
4 * Copyright (C) 2010 Michael Kurz <michi.kurz@googlemail.com>
5 * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
6 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
8 * Based on Atheros' AG7100 driver
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published
12 * by the Free Software Foundation.
20 #include <asm/ar71xx.h>
25 #define DBG(fmt,args...) printf(fmt ,##args)
27 #define DBG(fmt,args...)
31 static struct ag71xx agtable
[] = {
33 .mac_base
= KSEG1ADDR(AR71XX_GE0_BASE
),
34 .mii_ctrl
= KSEG1ADDR(AR71XX_MII_BASE
+ MII_REG_MII0_CTRL
),
35 .mii_if
= CONFIG_AG71XX_MII0_IIF
,
37 .mac_base
= KSEG1ADDR(AR71XX_GE1_BASE
),
38 .mii_ctrl
= KSEG1ADDR(AR71XX_MII_BASE
+ MII_REG_MII1_CTRL
),
39 .mii_if
= CONFIG_AG71XX_MII1_IIF
,
43 static int ag71xx_ring_alloc(struct ag71xx_ring
*ring
, unsigned int size
)
49 ring
->desc_size
= sizeof(struct ag71xx_desc
);
50 if (ring
->desc_size
% (CONFIG_SYS_CACHELINE_SIZE
)) {
51 rsize
= roundup(ring
->desc_size
, CONFIG_SYS_CACHELINE_SIZE
);
52 DBG("ag71xx: ring %p, desc size %u rounded to %u\n",
53 ring
, ring
->desc_size
,
55 ring
->desc_size
= rsize
;
58 ring
->descs_cpu
= (u8
*) malloc((size
* ring
->desc_size
)
59 + CONFIG_SYS_CACHELINE_SIZE
- 1);
60 if (!ring
->descs_cpu
) {
64 ring
->descs_cpu
= (u8
*) UNCACHED_SDRAM((((u32
) ring
->descs_cpu
+
65 CONFIG_SYS_CACHELINE_SIZE
- 1) & ~(CONFIG_SYS_CACHELINE_SIZE
- 1)));
66 ring
->descs_dma
= (u8
*) virt_to_phys(ring
->descs_cpu
);
70 ring
->buf
= malloc(size
* sizeof(*ring
->buf
));
75 memset(ring
->buf
, 0, size
* sizeof(*ring
->buf
));
77 for (i
= 0; i
< size
; i
++) {
79 (struct ag71xx_desc
*)&ring
->descs_cpu
[i
* ring
->desc_size
];
80 DBG("ag71xx: ring %p, desc %d at %p\n",
81 ring
, i
, ring
->buf
[i
].desc
);
84 flush_cache( (u32
) ring
->buf
, size
* sizeof(*ring
->buf
));
92 static void ag71xx_ring_tx_init(struct ag71xx
*ag
)
94 struct ag71xx_ring
*ring
= &ag
->tx_ring
;
97 for (i
= 0; i
< AG71XX_TX_RING_SIZE
; i
++) {
98 ring
->buf
[i
].desc
->next
= (u32
) virt_to_phys((ring
->descs_dma
+
99 ring
->desc_size
* ((i
+ 1) % AG71XX_TX_RING_SIZE
)));
101 ring
->buf
[i
].desc
->ctrl
= DESC_EMPTY
;
102 ring
->buf
[i
].skb
= NULL
;
108 static void ag71xx_ring_rx_clean(struct ag71xx
*ag
)
110 struct ag71xx_ring
*ring
= &ag
->rx_ring
;
116 for (i
= 0; i
< AG71XX_RX_RING_SIZE
; i
++) {
117 ring
->buf
[i
].desc
->data
= (u32
) virt_to_phys(NetRxPackets
[i
]);
118 flush_cache((u32
) NetRxPackets
[i
], PKTSIZE_ALIGN
);
119 ring
->buf
[i
].desc
->ctrl
= DESC_EMPTY
;
125 static int ag71xx_ring_rx_init(struct ag71xx
*ag
)
127 struct ag71xx_ring
*ring
= &ag
->rx_ring
;
130 for (i
= 0; i
< AG71XX_RX_RING_SIZE
; i
++) {
131 ring
->buf
[i
].desc
->next
= (u32
) virt_to_phys((ring
->descs_dma
+
132 ring
->desc_size
* ((i
+ 1) % AG71XX_RX_RING_SIZE
)));
134 DBG("ag71xx: RX desc at %p, next is %08x\n",
136 ring
->buf
[i
].desc
->next
);
139 for (i
= 0; i
< AG71XX_RX_RING_SIZE
; i
++) {
140 ring
->buf
[i
].desc
->data
= (u32
) virt_to_phys(NetRxPackets
[i
]);
141 ring
->buf
[i
].desc
->ctrl
= DESC_EMPTY
;
149 static int ag71xx_rings_init(struct ag71xx
*ag
)
153 ret
= ag71xx_ring_alloc(&ag
->tx_ring
, AG71XX_TX_RING_SIZE
);
157 ag71xx_ring_tx_init(ag
);
159 ret
= ag71xx_ring_alloc(&ag
->rx_ring
, AG71XX_RX_RING_SIZE
);
163 ret
= ag71xx_ring_rx_init(ag
);
167 static void ar71xx_set_pll(u32 cfg_reg
, u32 pll_reg
, u32 pll_val
, u32 shift
)
169 uint32_t base
= KSEG1ADDR(AR71XX_PLL_BASE
);
172 t
= readl(base
+ cfg_reg
);
175 writel(t
, base
+ cfg_reg
);
178 writel(pll_val
, base
+ pll_reg
);
181 writel(t
, base
+ cfg_reg
);
185 writel(t
, base
+ cfg_reg
);
188 debug("ar71xx: pll_reg %#x: %#x\n", (unsigned int)(base
+ pll_reg
),
189 readl(base
+ pll_reg
));
192 static void ar91xx_set_pll_ge0(int speed
)
194 //u32 val = ar71xx_get_eth_pll(0, speed);
199 pll_val
= 0x00441099;
202 pll_val
= 0x13000a44;
205 pll_val
= 0x1a000000;
211 ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG
, AR91XX_PLL_REG_ETH0_INT_CLOCK
,
212 pll_val
, AR91XX_ETH0_PLL_SHIFT
);
215 static void ar91xx_set_pll_ge1(int speed
)
217 //u32 val = ar71xx_get_eth_pll(1, speed);
222 pll_val
= 0x00441099;
225 pll_val
= 0x13000a44;
228 pll_val
= 0x1a000000;
234 ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG
, AR91XX_PLL_REG_ETH1_INT_CLOCK
,
235 pll_val
, AR91XX_ETH1_PLL_SHIFT
);
238 static void ag71xx_hw_set_macaddr(struct ag71xx
*ag
, unsigned char *mac
)
242 t
= (((u32
) mac
[5]) << 24) | (((u32
) mac
[4]) << 16)
243 | (((u32
) mac
[3]) << 8) | ((u32
) mac
[2]);
245 ag71xx_wr(ag
, AG71XX_REG_MAC_ADDR1
, t
);
247 t
= (((u32
) mac
[1]) << 24) | (((u32
) mac
[0]) << 16);
248 ag71xx_wr(ag
, AG71XX_REG_MAC_ADDR2
, t
);
251 static void ag71xx_dma_reset(struct ag71xx
*ag
)
256 DBG("%s: txdesc reg: 0x%08x rxdesc reg: 0x%08x\n",
258 ag71xx_rr(ag
, AG71XX_REG_TX_DESC
),
259 ag71xx_rr(ag
, AG71XX_REG_RX_DESC
));
262 ag71xx_wr(ag
, AG71XX_REG_RX_CTRL
, 0);
263 ag71xx_wr(ag
, AG71XX_REG_TX_CTRL
, 0);
265 /* clear descriptor addresses */
266 ag71xx_wr(ag
, AG71XX_REG_TX_DESC
, 0);
267 ag71xx_wr(ag
, AG71XX_REG_RX_DESC
, 0);
269 /* clear pending RX/TX interrupts */
270 for (i
= 0; i
< 256; i
++) {
271 ag71xx_wr(ag
, AG71XX_REG_RX_STATUS
, RX_STATUS_PR
);
272 ag71xx_wr(ag
, AG71XX_REG_TX_STATUS
, TX_STATUS_PS
);
275 /* clear pending errors */
276 ag71xx_wr(ag
, AG71XX_REG_RX_STATUS
, RX_STATUS_BE
| RX_STATUS_OF
);
277 ag71xx_wr(ag
, AG71XX_REG_TX_STATUS
, TX_STATUS_BE
| TX_STATUS_UR
);
279 val
= ag71xx_rr(ag
, AG71XX_REG_RX_STATUS
);
281 printf("%s: unable to clear DMA Rx status: %08x\n",
284 val
= ag71xx_rr(ag
, AG71XX_REG_TX_STATUS
);
286 /* mask out reserved bits */
290 printf("%s: unable to clear DMA Tx status: %08x\n",
294 static void ag71xx_halt(struct eth_device
*dev
)
296 struct ag71xx
*ag
= (struct ag71xx
*) dev
->priv
;
299 ag71xx_wr(ag
, AG71XX_REG_RX_CTRL
, 0);
301 ag71xx_dma_reset(ag
);
304 #define MAX_WAIT 1000
306 static int ag71xx_send(struct eth_device
*dev
, volatile void *packet
,
309 struct ag71xx
*ag
= (struct ag71xx
*) dev
->priv
;
310 struct ag71xx_ring
*ring
= &ag
->tx_ring
;
311 struct ag71xx_desc
*desc
;
314 i
= ring
->curr
% AG71XX_TX_RING_SIZE
;
315 desc
= ring
->buf
[i
].desc
;
317 if (!ag71xx_desc_empty(desc
)) {
318 printf("%s: tx buffer full\n", ag
->dev
->name
);
322 flush_cache((u32
) packet
, length
);
323 desc
->data
= (u32
) virt_to_phys(packet
);
324 desc
->ctrl
= (length
& DESC_PKTLEN_M
);
326 DBG("%s: sending %#08x length %#08x\n",
327 ag
->dev
->name
, desc
->data
, desc
->ctrl
);
330 if (ring
->curr
>= AG71XX_TX_RING_SIZE
){
334 /* enable TX engine */
335 ag71xx_wr(ag
, AG71XX_REG_TX_CTRL
, TX_CTRL_TXE
);
337 for (i
= 0; i
< MAX_WAIT
; i
++)
339 if (ag71xx_desc_empty(desc
))
344 printf("%s: tx timed out!\n", ag
->dev
->name
);
348 /* disable TX engine */
349 ag71xx_wr(ag
, AG71XX_REG_TX_CTRL
, 0);
351 desc
->ctrl
= DESC_EMPTY
;
356 static int ag71xx_recv(struct eth_device
*dev
)
358 struct ag71xx
*ag
= (struct ag71xx
*) dev
->priv
;
359 struct ag71xx_ring
*ring
= &ag
->rx_ring
;
362 unsigned int i
= ring
->curr
% AG71XX_RX_RING_SIZE
;
363 struct ag71xx_desc
*desc
= ring
->buf
[i
].desc
;
366 if (ag71xx_desc_empty(desc
))
369 DBG("%s: rx packets, curr=%u\n", dev
->name
, ring
->curr
);
371 pktlen
= ag71xx_desc_pktlen(desc
);
372 pktlen
-= ETH_FCS_LEN
;
375 NetReceive(NetRxPackets
[i
] , pktlen
);
376 flush_cache( (u32
) NetRxPackets
[i
], PKTSIZE_ALIGN
);
378 ring
->buf
[i
].desc
->ctrl
= DESC_EMPTY
;
380 if (ring
->curr
>= AG71XX_RX_RING_SIZE
){
386 if ((ag71xx_rr(ag
, AG71XX_REG_RX_CTRL
) & RX_CTRL_RXE
) == 0) {
387 /* start RX engine */
388 ag71xx_wr(ag
, AG71XX_REG_RX_CTRL
, RX_CTRL_RXE
);
395 static char *ag71xx_speed_str(struct ag71xx
*ag
)
410 void ag71xx_link_adjust(struct ag71xx
*ag
)
418 DBG("%s: link down\n", ag
->dev
->name
);
422 cfg2
= ag71xx_rr(ag
, AG71XX_REG_MAC_CFG2
);
423 cfg2
&= ~(MAC_CFG2_IF_1000
| MAC_CFG2_IF_10_100
| MAC_CFG2_FDX
);
424 cfg2
|= (ag
->duplex
) ? MAC_CFG2_FDX
: 0;
426 ifctl
= ag71xx_rr(ag
, AG71XX_REG_MAC_IFCTL
);
427 ifctl
&= ~(MAC_IFCTL_SPEED
);
429 fifo5
= ag71xx_rr(ag
, AG71XX_REG_FIFO_CFG5
);
430 fifo5
&= ~FIFO_CFG5_BM
;
434 mii_speed
= MII_CTRL_SPEED_1000
;
435 cfg2
|= MAC_CFG2_IF_1000
;
436 fifo5
|= FIFO_CFG5_BM
;
439 mii_speed
= MII_CTRL_SPEED_100
;
440 cfg2
|= MAC_CFG2_IF_10_100
;
441 ifctl
|= MAC_IFCTL_SPEED
;
444 mii_speed
= MII_CTRL_SPEED_10
;
445 cfg2
|= MAC_CFG2_IF_10_100
;
452 ag71xx_wr(ag
, AG71XX_REG_FIFO_CFG3
, 0x00780fff);
455 ar91xx_set_pll_ge0(ag
->speed
);
457 ar91xx_set_pll_ge1(ag
->speed
);
459 ag71xx_mii_ctrl_set_speed(ag
, mii_speed
);
461 ag71xx_wr(ag
, AG71XX_REG_MAC_CFG2
, cfg2
);
462 ag71xx_wr(ag
, AG71XX_REG_FIFO_CFG5
, fifo5
);
463 ag71xx_wr(ag
, AG71XX_REG_MAC_IFCTL
, ifctl
);
465 DBG("%s: link up (%sMbps/%s duplex)\n",
467 ag71xx_speed_str(ag
),
468 (1 == ag
->duplex
) ? "Full" : "Half");
470 DBG("%s: fifo_cfg0=%#x, fifo_cfg1=%#x, fifo_cfg2=%#x\n",
472 ag71xx_rr(ag
, AG71XX_REG_FIFO_CFG0
),
473 ag71xx_rr(ag
, AG71XX_REG_FIFO_CFG1
),
474 ag71xx_rr(ag
, AG71XX_REG_FIFO_CFG2
));
476 DBG("%s: fifo_cfg3=%#x, fifo_cfg4=%#x, fifo_cfg5=%#x\n",
478 ag71xx_rr(ag
, AG71XX_REG_FIFO_CFG3
),
479 ag71xx_rr(ag
, AG71XX_REG_FIFO_CFG4
),
480 ag71xx_rr(ag
, AG71XX_REG_FIFO_CFG5
));
482 DBG("%s: mac_cfg2=%#x, mac_ifctl=%#x, mii_ctrl=%#x\n",
484 ag71xx_rr(ag
, AG71XX_REG_MAC_CFG2
),
485 ag71xx_rr(ag
, AG71XX_REG_MAC_IFCTL
),
486 ag71xx_mii_ctrl_rr(ag
));
489 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
490 static int ag71xx_getMiiSpeed(struct ag71xx
*ag
)
492 uint16_t phyreg
, cap
;
494 if (miiphy_read(ag
->phyname
, ag
->phyid
,
495 PHY_BMSR
, &phyreg
)) {
496 puts("PHY_BMSR read failed, assuming no link\n");
500 if ((phyreg
& PHY_BMSR_LS
) == 0) {
504 if (miiphy_read(ag
->phyname
, ag
->phyid
,
505 PHY_1000BTSR
, &phyreg
))
508 if (phyreg
& PHY_1000BTSR_1000FD
) {
509 ag
->speed
= SPEED_1000
;
511 } else if (phyreg
& PHY_1000BTSR_1000HD
) {
512 ag
->speed
= SPEED_1000
;
515 if (miiphy_read(ag
->phyname
, ag
->phyid
,
519 if (miiphy_read(ag
->phyname
, ag
->phyid
,
520 PHY_ANLPAR
, &phyreg
))
524 if (cap
& PHY_ANLPAR_TXFD
) {
525 ag
->speed
= SPEED_100
;
527 } else if (cap
& PHY_ANLPAR_TX
) {
528 ag
->speed
= SPEED_100
;
530 } else if (cap
& PHY_ANLPAR_10FD
) {
531 ag
->speed
= SPEED_10
;
534 ag
->speed
= SPEED_10
;
545 static int ag71xx_hw_start(struct eth_device
*dev
, bd_t
* bd
)
547 struct ag71xx
*ag
= (struct ag71xx
*) dev
->priv
;
549 ag71xx_dma_reset(ag
);
551 ag71xx_ring_rx_clean(ag
);
552 ag71xx_ring_tx_init(ag
);
554 ag71xx_wr(ag
, AG71XX_REG_TX_DESC
,
555 (u32
) virt_to_phys(ag
->tx_ring
.descs_dma
));
556 ag71xx_wr(ag
, AG71XX_REG_RX_DESC
,
557 (u32
) virt_to_phys(ag
->rx_ring
.descs_dma
));
559 ag71xx_hw_set_macaddr(ag
, ag
->dev
->enetaddr
);
564 ag
->speed
= SPEED_1000
;
567 #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
568 if (ag71xx_getMiiSpeed(ag
))
571 /* only fixed, without mii */
576 ag71xx_link_adjust(ag
);
578 DBG("%s: txdesc reg: %#08x rxdesc reg: %#08x\n",
580 ag71xx_rr(ag
, AG71XX_REG_TX_DESC
),
581 ag71xx_rr(ag
, AG71XX_REG_RX_DESC
));
583 /* start RX engine */
584 ag71xx_wr(ag
, AG71XX_REG_RX_CTRL
, RX_CTRL_RXE
);
589 #define FIFO_CFG0_INIT (FIFO_CFG0_ALL << FIFO_CFG0_ENABLE_SHIFT)
591 #define FIFO_CFG4_INIT (FIFO_CFG4_DE | FIFO_CFG4_DV | FIFO_CFG4_FC | \
592 FIFO_CFG4_CE | FIFO_CFG4_CR | FIFO_CFG4_LM | \
593 FIFO_CFG4_LO | FIFO_CFG4_OK | FIFO_CFG4_MC | \
594 FIFO_CFG4_BC | FIFO_CFG4_DR | FIFO_CFG4_LE | \
595 FIFO_CFG4_CF | FIFO_CFG4_PF | FIFO_CFG4_UO | \
598 #define FIFO_CFG5_INIT (FIFO_CFG5_DE | FIFO_CFG5_DV | FIFO_CFG5_FC | \
599 FIFO_CFG5_CE | FIFO_CFG5_LO | FIFO_CFG5_OK | \
600 FIFO_CFG5_MC | FIFO_CFG5_BC | FIFO_CFG5_DR | \
601 FIFO_CFG5_CF | FIFO_CFG5_PF | FIFO_CFG5_VT | \
602 FIFO_CFG5_LE | FIFO_CFG5_FT | FIFO_CFG5_16 | \
603 FIFO_CFG5_17 | FIFO_CFG5_SF)
605 static int ag71xx_hw_init(struct ag71xx
*ag
)
609 uint32_t mask
, mii_type
;
611 if (ag
->macNum
== 0) {
612 mask
= (RESET_MODULE_GE0_MAC
| RESET_MODULE_GE0_PHY
);
615 mask
= (RESET_MODULE_GE1_MAC
| RESET_MODULE_GE1_PHY
);
620 ag71xx_sb(ag
, AG71XX_REG_MAC_CFG1
, MAC_CFG1_SR
);
624 reg
= ar71xx_reset_rr(AR91XX_RESET_REG_RESET_MODULE
);
625 ar71xx_reset_wr(AR91XX_RESET_REG_RESET_MODULE
, reg
| mask
);
629 reg
= ar71xx_reset_rr(AR91XX_RESET_REG_RESET_MODULE
);
630 ar71xx_reset_wr(AR91XX_RESET_REG_RESET_MODULE
, reg
& ~mask
);
633 /* setup MAC configuration registers */
634 ag71xx_wr(ag
, AG71XX_REG_MAC_CFG1
, (MAC_CFG1_RXE
| MAC_CFG1_TXE
));
636 ag71xx_sb(ag
, AG71XX_REG_MAC_CFG2
,
637 MAC_CFG2_PAD_CRC_EN
| MAC_CFG2_LEN_CHECK
);
639 /* setup FIFO configuration register 0 */
640 ag71xx_wr(ag
, AG71XX_REG_FIFO_CFG0
, FIFO_CFG0_INIT
);
642 /* setup MII interface type */
643 ag71xx_mii_ctrl_set_if(ag
, ag
->mii_if
);
645 /* setup mdio clock divisor */
646 ag71xx_wr(ag
, AG71XX_REG_MII_CFG
, MII_CFG_CLK_DIV_20
);
648 /* setup FIFO configuration registers */
649 ag71xx_sb(ag
, AG71XX_REG_FIFO_CFG4
, FIFO_CFG4_INIT
);
650 ag71xx_wr(ag
, AG71XX_REG_FIFO_CFG1
, 0x0fff0000);
651 ag71xx_wr(ag
, AG71XX_REG_FIFO_CFG2
, 0x00001fff);
652 ag71xx_wr(ag
, AG71XX_REG_FIFO_CFG5
, FIFO_CFG5_INIT
);
654 ag71xx_dma_reset(ag
);
656 ret
= ag71xx_rings_init(ag
);
660 ag71xx_wr(ag
, AG71XX_REG_TX_DESC
,
661 (u32
) virt_to_phys(ag
->tx_ring
.descs_dma
));
662 ag71xx_wr(ag
, AG71XX_REG_RX_DESC
,
663 (u32
) virt_to_phys(ag
->rx_ring
.descs_dma
));
665 ag71xx_hw_set_macaddr(ag
, ag
->dev
->enetaddr
);
670 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
671 #define AG71XX_MDIO_RETRY 1000
672 #define AG71XX_MDIO_DELAY 5
674 static inline struct ag71xx
*ag71xx_name2mac(char *devname
)
676 if (strcmp(devname
, agtable
[0].dev
->name
) == 0)
678 else if (strcmp(devname
, agtable
[1].dev
->name
) == 0)
684 static inline void ag71xx_mdio_wr(struct ag71xx
*ag
, unsigned reg
,
689 r
= ag
->mac_base
+ reg
;
696 static inline u32
ag71xx_mdio_rr(struct ag71xx
*ag
, unsigned reg
)
698 return readl(ag
->mac_base
+ reg
);
701 static int ag71xx_mdio_read(char *devname
, unsigned char addr
,
702 unsigned char reg
, unsigned short *val
)
704 struct ag71xx
*ag
= ag71xx_name2mac(devname
);
708 ag71xx_mdio_wr(ag
, AG71XX_REG_MII_CMD
, MII_CMD_WRITE
);
709 ag71xx_mdio_wr(ag
, AG71XX_REG_MII_ADDR
,
710 ((addr
& 0xff) << MII_ADDR_SHIFT
) | (reg
& 0xff));
711 ag71xx_mdio_wr(ag
, AG71XX_REG_MII_CMD
, MII_CMD_READ
);
713 i
= AG71XX_MDIO_RETRY
;
714 while (ag71xx_mdio_rr(ag
, AG71XX_REG_MII_IND
) & MII_IND_BUSY
) {
716 printf("%s: mii_read timed out\n",
720 udelay(AG71XX_MDIO_DELAY
);
723 regData
= (uint16_t) ag71xx_mdio_rr(ag
, AG71XX_REG_MII_STATUS
) & 0xffff;
724 ag71xx_mdio_wr(ag
, AG71XX_REG_MII_CMD
, MII_CMD_WRITE
);
726 DBG("mii_read: addr=%04x, reg=%04x, value=%04x\n", addr
, reg
, regData
);
734 static int ag71xx_mdio_write(char *devname
, unsigned char addr
,
735 unsigned char reg
, unsigned short val
)
737 struct ag71xx
*ag
= ag71xx_name2mac(devname
);
743 DBG("mii_write: addr=%04x, reg=%04x, value=%04x\n", addr
, reg
, val
);
745 ag71xx_mdio_wr(ag
, AG71XX_REG_MII_ADDR
,
746 ((addr
& 0xff) << MII_ADDR_SHIFT
) | (reg
& 0xff));
747 ag71xx_mdio_wr(ag
, AG71XX_REG_MII_CTRL
, val
);
749 i
= AG71XX_MDIO_RETRY
;
750 while (ag71xx_mdio_rr(ag
, AG71XX_REG_MII_IND
) & MII_IND_BUSY
) {
752 printf("%s: mii_write timed out\n",
756 udelay(AG71XX_MDIO_DELAY
);
763 int ag71xx_register(bd_t
* bis
, char *phyname
[], uint16_t phyid
[], uint16_t phyfixed
[])
766 u8 used_ports
[MAX_AG71XX_DEVS
] = CONFIG_AG71XX_PORTS
;
768 for (i
= 0; i
< MAX_AG71XX_DEVS
; i
++) {
769 /*skip if port is configured not to use */
770 if (used_ports
[i
] == 0)
773 agtable
[i
].dev
= malloc(sizeof(struct eth_device
));
774 if (agtable
[i
].dev
== NULL
) {
775 puts("malloc failed\n");
778 memset(agtable
[i
].dev
, 0, sizeof(struct eth_device
));
779 sprintf(agtable
[i
].dev
->name
, "eth%d", i
);
781 agtable
[i
].dev
->iobase
= 0;
782 agtable
[i
].dev
->init
= ag71xx_hw_start
;
783 agtable
[i
].dev
->halt
= ag71xx_halt
;
784 agtable
[i
].dev
->send
= ag71xx_send
;
785 agtable
[i
].dev
->recv
= ag71xx_recv
;
786 agtable
[i
].dev
->priv
= (void *) (&agtable
[i
]);
787 agtable
[i
].macNum
= i
;
788 eth_register(agtable
[i
].dev
);
789 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
791 if ((phyname
== NULL
) || (phyid
== NULL
) || (phyfixed
== NULL
))
794 agtable
[i
].phyname
= strdup(phyname
[i
]);
795 agtable
[i
].phyid
= phyid
[i
];
796 agtable
[i
].phyfixed
= phyfixed
[i
];
798 miiphy_register(agtable
[i
].dev
->name
, ag71xx_mdio_read
,
802 if (ag71xx_hw_init(&agtable
[i
]))