3 * eInfochips Ltd. <www.einfochips.com>
4 * Written-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
7 * Marvell Semiconductor <www.marvell.com>
8 * Contributor: Mahavir Jain <mjain@marvell.com>
10 * See file CREDITS for list of people who contributed to this
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation; either version 2 of
16 * the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
34 #include <asm/types.h>
35 #include <asm/byteorder.h>
36 #include <linux/err.h>
37 #include <linux/mii.h>
39 #include <asm/arch/armada100.h>
40 #include "armada100_fec.h"
42 #define PHY_ADR_REQ 0xFF /* Magic number to read/write PHY address */
45 static int eth_dump_regs(struct eth_device
*dev
)
47 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
48 struct armdfec_reg
*regs
= darmdfec
->regs
;
51 printf("\noffset: phy_adr, value: 0x%x\n", readl(®s
->phyadr
));
52 printf("offset: smi, value: 0x%x\n", readl(®s
->smi
));
53 for (i
= 0x400; i
<= 0x4e4; i
+= 4)
54 printf("offset: 0x%x, value: 0x%x\n",
55 i
, readl(ARMD1_FEC_BASE
+ i
));
60 static int armdfec_phy_timeout(u32
*reg
, u32 flag
, int cond
)
62 u32 timeout
= PHY_WAIT_ITERATIONS
;
67 if (cond
&& (reg_val
& flag
))
69 else if (!cond
&& !(reg_val
& flag
))
71 udelay(PHY_WAIT_MICRO_SECONDS
);
76 static int smi_reg_read(const char *devname
, u8 phy_addr
, u8 phy_reg
,
79 struct eth_device
*dev
= eth_get_dev_by_name(devname
);
80 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
81 struct armdfec_reg
*regs
= darmdfec
->regs
;
84 if (phy_addr
== PHY_ADR_REQ
&& phy_reg
== PHY_ADR_REQ
) {
85 val
= readl(®s
->phyadr
);
90 /* check parameters */
91 if (phy_addr
> PHY_MASK
) {
92 printf("ARMD100 FEC: (%s) Invalid phy address: 0x%X\n",
96 if (phy_reg
> PHY_MASK
) {
97 printf("ARMD100 FEC: (%s) Invalid register offset: 0x%X\n",
102 /* wait for the SMI register to become available */
103 if (armdfec_phy_timeout(®s
->smi
, SMI_BUSY
, false)) {
104 printf("ARMD100 FEC: (%s) PHY busy timeout\n", __func__
);
108 writel((phy_addr
<< 16) | (phy_reg
<< 21) | SMI_OP_R
, ®s
->smi
);
110 /* now wait for the data to be valid */
111 if (armdfec_phy_timeout(®s
->smi
, SMI_R_VALID
, true)) {
112 val
= readl(®s
->smi
);
113 printf("ARMD100 FEC: (%s) PHY Read timeout, val=0x%x\n",
117 val
= readl(®s
->smi
);
118 *value
= val
& 0xffff;
123 static int smi_reg_write(const char *devname
,
124 u8 phy_addr
, u8 phy_reg
, u16 value
)
126 struct eth_device
*dev
= eth_get_dev_by_name(devname
);
127 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
128 struct armdfec_reg
*regs
= darmdfec
->regs
;
130 if (phy_addr
== PHY_ADR_REQ
&& phy_reg
== PHY_ADR_REQ
) {
131 clrsetbits_le32(®s
->phyadr
, 0x1f, value
& 0x1f);
135 /* check parameters */
136 if (phy_addr
> PHY_MASK
) {
137 printf("ARMD100 FEC: (%s) Invalid phy address\n", __func__
);
140 if (phy_reg
> PHY_MASK
) {
141 printf("ARMD100 FEC: (%s) Invalid register offset\n", __func__
);
145 /* wait for the SMI register to become available */
146 if (armdfec_phy_timeout(®s
->smi
, SMI_BUSY
, false)) {
147 printf("ARMD100 FEC: (%s) PHY busy timeout\n", __func__
);
151 writel((phy_addr
<< 16) | (phy_reg
<< 21) | SMI_OP_W
| (value
& 0xffff),
157 * Abort any transmit and receive operations and put DMA
158 * in idle state. AT and AR bits are cleared upon entering
159 * in IDLE state. So poll those bits to verify operation.
161 static void abortdma(struct eth_device
*dev
)
163 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
164 struct armdfec_reg
*regs
= darmdfec
->regs
;
169 while (--maxretries
) {
170 writel(SDMA_CMD_AR
| SDMA_CMD_AT
, ®s
->sdma_cmd
);
175 tmp
= readl(®s
->sdma_cmd
);
176 if (!(tmp
& (SDMA_CMD_AR
| SDMA_CMD_AT
)))
185 printf("ARMD100 FEC: (%s) DMA Stuck\n", __func__
);
188 static inline u32
nibble_swapping_32_bit(u32 x
)
190 return ((x
& 0xf0f0f0f0) >> 4) | ((x
& 0x0f0f0f0f) << 4);
193 static inline u32
nibble_swapping_16_bit(u32 x
)
195 return ((x
& 0x0000f0f0) >> 4) | ((x
& 0x00000f0f) << 4);
198 static inline u32
flip_4_bits(u32 x
)
200 return ((x
& 0x01) << 3) | ((x
& 0x002) << 1)
201 | ((x
& 0x04) >> 1) | ((x
& 0x008) >> 3);
205 * This function will calculate the hash function of the address.
206 * depends on the hash mode and hash size.
208 * mach - the 2 most significant bytes of the MAC address.
209 * macl - the 4 least significant bytes of the MAC address.
211 * return the calculated entry.
213 static u32
hash_function(u32 mach
, u32 macl
)
225 addrh
= nibble_swapping_16_bit(mach
);
226 addrl
= nibble_swapping_32_bit(macl
);
228 addrhswapped
= flip_4_bits(addrh
& 0xf)
229 + ((flip_4_bits((addrh
>> 4) & 0xf)) << 4)
230 + ((flip_4_bits((addrh
>> 8) & 0xf)) << 8)
231 + ((flip_4_bits((addrh
>> 12) & 0xf)) << 12);
233 addrlswapped
= flip_4_bits(addrl
& 0xf)
234 + ((flip_4_bits((addrl
>> 4) & 0xf)) << 4)
235 + ((flip_4_bits((addrl
>> 8) & 0xf)) << 8)
236 + ((flip_4_bits((addrl
>> 12) & 0xf)) << 12)
237 + ((flip_4_bits((addrl
>> 16) & 0xf)) << 16)
238 + ((flip_4_bits((addrl
>> 20) & 0xf)) << 20)
239 + ((flip_4_bits((addrl
>> 24) & 0xf)) << 24)
240 + ((flip_4_bits((addrl
>> 28) & 0xf)) << 28);
242 addrh
= addrhswapped
;
243 addrl
= addrlswapped
;
245 addr0
= (addrl
>> 2) & 0x03f;
246 addr1
= (addrl
& 0x003) | (((addrl
>> 8) & 0x7f) << 2);
247 addr2
= (addrl
>> 15) & 0x1ff;
248 addr3
= ((addrl
>> 24) & 0x0ff) | ((addrh
& 1) << 8);
250 hashresult
= (addr0
<< 9) | (addr1
^ addr2
^ addr3
);
251 hashresult
= hashresult
& 0x07ff;
256 * This function will add an entry to the address table.
257 * depends on the hash mode and hash size that was initialized.
259 * mach - the 2 most significant bytes of the MAC address.
260 * macl - the 4 least significant bytes of the MAC address.
261 * skip - if 1, skip this address.
262 * rd - the RD field in the address table.
264 * address table entry is added.
266 * -ENOSPC if table full
268 static int add_del_hash_entry(struct armdfec_device
*darmdfec
, u32 mach
,
269 u32 macl
, u32 rd
, u32 skip
, int del
)
271 struct addr_table_entry_t
*entry
, *start
;
276 newlo
= (((mach
>> 4) & 0xf) << 15)
277 | (((mach
>> 0) & 0xf) << 11)
278 | (((mach
>> 12) & 0xf) << 7)
279 | (((mach
>> 8) & 0xf) << 3)
280 | (((macl
>> 20) & 0x1) << 31)
281 | (((macl
>> 16) & 0xf) << 27)
282 | (((macl
>> 28) & 0xf) << 23)
283 | (((macl
>> 24) & 0xf) << 19)
284 | (skip
<< HTESKIP
) | (rd
<< HTERDBIT
)
287 newhi
= (((macl
>> 4) & 0xf) << 15)
288 | (((macl
>> 0) & 0xf) << 11)
289 | (((macl
>> 12) & 0xf) << 7)
290 | (((macl
>> 8) & 0xf) << 3)
291 | (((macl
>> 21) & 0x7) << 0);
294 * Pick the appropriate table, start scanning for free/reusable
295 * entries at the index obtained by hashing the specified MAC address
297 start
= (struct addr_table_entry_t
*)(darmdfec
->htpr
);
298 entry
= start
+ hash_function(mach
, macl
);
299 for (i
= 0; i
< HOP_NUMBER
; i
++) {
300 if (!(entry
->lo
& HTEVALID
)) {
303 /* if same address put in same position */
304 if (((entry
->lo
& 0xfffffff8) == (newlo
& 0xfffffff8))
305 && (entry
->hi
== newhi
))
308 if (entry
== start
+ 0x7ff)
314 if (((entry
->lo
& 0xfffffff8) != (newlo
& 0xfffffff8)) &&
315 (entry
->hi
!= newhi
) && del
)
318 if (i
== HOP_NUMBER
) {
320 printf("ARMD100 FEC: (%s) table section is full\n",
329 * Update the selected entry
343 * Create an addressTable entry from MAC address info
344 * found in the specifed net_device struct
346 * Input : pointer to ethernet interface network device structure
349 static void update_hash_table_mac_address(struct armdfec_device
*darmdfec
,
355 /* Delete old entry */
357 mach
= (oaddr
[0] << 8) | oaddr
[1];
358 macl
= (oaddr
[2] << 24) | (oaddr
[3] << 16) |
359 (oaddr
[4] << 8) | oaddr
[5];
360 add_del_hash_entry(darmdfec
, mach
, macl
, 1, 0, HASH_DELETE
);
364 mach
= (addr
[0] << 8) | addr
[1];
365 macl
= (addr
[2] << 24) | (addr
[3] << 16) | (addr
[4] << 8) | addr
[5];
366 add_del_hash_entry(darmdfec
, mach
, macl
, 1, 0, HASH_ADD
);
369 /* Address Table Initialization */
370 static void init_hashtable(struct eth_device
*dev
)
372 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
373 struct armdfec_reg
*regs
= darmdfec
->regs
;
374 memset(darmdfec
->htpr
, 0, HASH_ADDR_TABLE_SIZE
);
375 writel((u32
)darmdfec
->htpr
, ®s
->htpr
);
379 * This detects PHY chip from address 0-31 by reading PHY status
380 * registers. PHY chip can be connected at any of this address.
382 static int ethernet_phy_detect(struct eth_device
*dev
)
388 for (addr
= 0; addr
< 32; addr
++) {
389 if (miiphy_read(dev
->name
, addr
, MII_BMSR
, &mii_status
) != 0)
393 /* invalid MII status. More validation required here... */
394 if (mii_status
== 0 || mii_status
== 0xffff)
398 if (miiphy_read(dev
->name
, addr
, MII_PHYSID1
, &tmp
) != 0)
403 if (miiphy_read(dev
->name
, addr
, MII_PHYSID2
, &tmp
) != 0)
409 if ((val
& 0xfffffff0) != 0)
415 static void armdfec_init_rx_desc_ring(struct armdfec_device
*darmdfec
)
417 struct rx_desc
*p_rx_desc
;
420 /* initialize the Rx descriptors ring */
421 p_rx_desc
= darmdfec
->p_rxdesc
;
422 for (i
= 0; i
< RINGSZ
; i
++) {
423 p_rx_desc
->cmd_sts
= BUF_OWNED_BY_DMA
| RX_EN_INT
;
424 p_rx_desc
->buf_size
= PKTSIZE_ALIGN
;
425 p_rx_desc
->byte_cnt
= 0;
426 p_rx_desc
->buf_ptr
= darmdfec
->p_rxbuf
+ i
* PKTSIZE_ALIGN
;
427 if (i
== (RINGSZ
- 1)) {
428 p_rx_desc
->nxtdesc_p
= darmdfec
->p_rxdesc
;
430 p_rx_desc
->nxtdesc_p
= (struct rx_desc
*)
431 ((u32
)p_rx_desc
+ ARMDFEC_RXQ_DESC_ALIGNED_SIZE
);
432 p_rx_desc
= p_rx_desc
->nxtdesc_p
;
435 darmdfec
->p_rxdesc_curr
= darmdfec
->p_rxdesc
;
438 static int armdfec_init(struct eth_device
*dev
, bd_t
*bd
)
440 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
441 struct armdfec_reg
*regs
= darmdfec
->regs
;
445 armdfec_init_rx_desc_ring(darmdfec
);
447 /* Disable interrupts */
448 writel(0, ®s
->im
);
449 writel(0, ®s
->ic
);
450 /* Write to ICR to clear interrupts. */
451 writel(0, ®s
->iwc
);
454 * Abort any transmit and receive operations and put DMA
459 /* Initialize address hash table */
462 /* SDMA configuration */
463 writel(SDCR_BSZ8
| /* Burst size = 32 bytes */
464 SDCR_RIFB
| /* Rx interrupt on frame */
465 SDCR_BLMT
| /* Little endian transmit */
466 SDCR_BLMR
| /* Little endian receive */
467 SDCR_RC_MAX_RETRANS
, /* Max retransmit count */
469 /* Port Configuration */
470 writel(PCR_HS
, ®s
->pconf
); /* Hash size is 1/2kb */
472 /* Set extended port configuration */
473 writel(PCXR_2BSM
| /* Two byte suffix aligns IP hdr */
474 PCXR_DSCP_EN
| /* Enable DSCP in IP */
475 PCXR_MFL_1536
| /* Set MTU = 1536 */
476 PCXR_FLP
| /* do not force link pass */
477 PCXR_TX_HIGH_PRI
, /* Transmit - high priority queue */
480 update_hash_table_mac_address(darmdfec
, NULL
, dev
->enetaddr
);
482 /* Update TX and RX queue descriptor register */
483 temp
= (u32
)®s
->txcdp
[TXQ
];
484 writel((u32
)darmdfec
->p_txdesc
, temp
);
485 temp
= (u32
)®s
->rxfdp
[RXQ
];
486 writel((u32
)darmdfec
->p_rxdesc
, temp
);
487 temp
= (u32
)®s
->rxcdp
[RXQ
];
488 writel((u32
)darmdfec
->p_rxdesc_curr
, temp
);
490 /* Enable Interrupts */
491 writel(ALL_INTS
, ®s
->im
);
493 /* Enable Ethernet Port */
494 setbits_le32(®s
->pconf
, PCR_EN
);
496 /* Enable RX DMA engine */
497 setbits_le32(®s
->sdma_cmd
, SDMA_CMD_ERD
);
503 #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
505 #if defined(CONFIG_PHY_BASE_ADR)
506 miiphy_write(dev
->name
, PHY_ADR_REQ
, PHY_ADR_REQ
, CONFIG_PHY_BASE_ADR
);
508 /* Search phy address from range 0-31 */
509 phy_adr
= ethernet_phy_detect(dev
);
511 printf("ARMD100 FEC: PHY not detected at address range 0-31\n");
514 debug("ARMD100 FEC: PHY detected at addr %d\n", phy_adr
);
515 miiphy_write(dev
->name
, PHY_ADR_REQ
, PHY_ADR_REQ
, phy_adr
);
519 #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
520 /* Wait up to 5s for the link status */
521 for (i
= 0; i
< 5; i
++) {
524 miiphy_read(dev
->name
, 0xFF, 0xFF, &phy_adr
);
525 /* Return if we get link up */
526 if (miiphy_link(dev
->name
, phy_adr
))
531 printf("ARMD100 FEC: No link on %s\n", dev
->name
);
538 static void armdfec_halt(struct eth_device
*dev
)
540 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
541 struct armdfec_reg
*regs
= darmdfec
->regs
;
544 clrbits_le32(®s
->sdma_cmd
, SDMA_CMD_ERD
);
547 * Abort any transmit and receive operations and put DMA
552 /* Disable interrupts */
553 writel(0, ®s
->im
);
554 writel(0, ®s
->ic
);
555 writel(0, ®s
->iwc
);
558 clrbits_le32(®s
->pconf
, PCR_EN
);
561 static int armdfec_send(struct eth_device
*dev
, void *dataptr
, int datasize
)
563 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
564 struct armdfec_reg
*regs
= darmdfec
->regs
;
565 struct tx_desc
*p_txdesc
= darmdfec
->p_txdesc
;
566 void *p
= (void *)dataptr
;
567 int retry
= PHY_WAIT_ITERATIONS
* PHY_WAIT_MICRO_SECONDS
;
570 /* Copy buffer if it's misaligned */
571 if ((u32
)dataptr
& 0x07) {
572 if (datasize
> PKTSIZE_ALIGN
) {
573 printf("ARMD100 FEC: Non-aligned data too large (%d)\n",
577 memcpy(darmdfec
->p_aligned_txbuf
, p
, datasize
);
578 p
= darmdfec
->p_aligned_txbuf
;
581 p_txdesc
->cmd_sts
= TX_ZERO_PADDING
| TX_GEN_CRC
;
582 p_txdesc
->cmd_sts
|= TX_FIRST_DESC
| TX_LAST_DESC
;
583 p_txdesc
->cmd_sts
|= BUF_OWNED_BY_DMA
;
584 p_txdesc
->cmd_sts
|= TX_EN_INT
;
585 p_txdesc
->buf_ptr
= p
;
586 p_txdesc
->byte_cnt
= datasize
;
588 /* Apply send command using high priority TX queue */
589 temp
= (u32
)®s
->txcdp
[TXQ
];
590 writel((u32
)p_txdesc
, temp
);
591 writel(SDMA_CMD_TXDL
| SDMA_CMD_TXDH
| SDMA_CMD_ERD
, ®s
->sdma_cmd
);
594 * wait for packet xmit completion
596 cmd_sts
= readl(&p_txdesc
->cmd_sts
);
597 while (cmd_sts
& BUF_OWNED_BY_DMA
) {
598 /* return fail if error is detected */
599 if ((cmd_sts
& (TX_ERROR
| TX_LAST_DESC
)) ==
600 (TX_ERROR
| TX_LAST_DESC
)) {
601 printf("ARMD100 FEC: (%s) in xmit packet\n", __func__
);
604 cmd_sts
= readl(&p_txdesc
->cmd_sts
);
606 printf("ARMD100 FEC: (%s) xmit packet timeout!\n",
615 static int armdfec_recv(struct eth_device
*dev
)
617 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
618 struct rx_desc
*p_rxdesc_curr
= darmdfec
->p_rxdesc_curr
;
623 /* wait untill rx packet available or timeout */
625 if (timeout
< PHY_WAIT_ITERATIONS
* PHY_WAIT_MICRO_SECONDS
) {
628 debug("ARMD100 FEC: %s time out...\n", __func__
);
631 } while (readl(&p_rxdesc_curr
->cmd_sts
) & BUF_OWNED_BY_DMA
);
633 if (p_rxdesc_curr
->byte_cnt
!= 0) {
634 debug("ARMD100 FEC: %s: Received %d byte Packet @ 0x%x"
635 "(cmd_sts= %08x)\n", __func__
,
636 (u32
)p_rxdesc_curr
->byte_cnt
,
637 (u32
)p_rxdesc_curr
->buf_ptr
,
638 (u32
)p_rxdesc_curr
->cmd_sts
);
642 * In case received a packet without first/last bits on
643 * OR the error summary bit is on,
644 * the packets needs to be dropeed.
646 cmd_sts
= readl(&p_rxdesc_curr
->cmd_sts
);
648 if ((cmd_sts
& (RX_FIRST_DESC
| RX_LAST_DESC
)) !=
649 (RX_FIRST_DESC
| RX_LAST_DESC
)) {
650 printf("ARMD100 FEC: (%s) Dropping packet spread on"
651 " multiple descriptors\n", __func__
);
652 } else if (cmd_sts
& RX_ERROR
) {
653 printf("ARMD100 FEC: (%s) Dropping packet with errors\n",
656 /* !!! call higher layer processing */
657 debug("ARMD100 FEC: (%s) Sending Received packet to"
658 " upper layer (NetReceive)\n", __func__
);
661 * let the upper layer handle the packet, subtract offset
662 * as two dummy bytes are added in received buffer see
663 * PORT_CONFIG_EXT register bit TWO_Byte_Stuff_Mode bit.
665 NetReceive((p_rxdesc_curr
->buf_ptr
+ RX_BUF_OFFSET
),
666 (int)(p_rxdesc_curr
->byte_cnt
- RX_BUF_OFFSET
));
669 * free these descriptors and point next in the ring
671 p_rxdesc_curr
->cmd_sts
= BUF_OWNED_BY_DMA
| RX_EN_INT
;
672 p_rxdesc_curr
->buf_size
= PKTSIZE_ALIGN
;
673 p_rxdesc_curr
->byte_cnt
= 0;
675 temp
= (u32
)&darmdfec
->p_rxdesc_curr
;
676 writel((u32
)p_rxdesc_curr
->nxtdesc_p
, temp
);
681 int armada100_fec_register(unsigned long base_addr
)
683 struct armdfec_device
*darmdfec
;
684 struct eth_device
*dev
;
686 darmdfec
= malloc(sizeof(struct armdfec_device
));
690 memset(darmdfec
, 0, sizeof(struct armdfec_device
));
692 darmdfec
->htpr
= memalign(8, HASH_ADDR_TABLE_SIZE
);
696 darmdfec
->p_rxdesc
= memalign(PKTALIGN
,
697 ARMDFEC_RXQ_DESC_ALIGNED_SIZE
* RINGSZ
+ 1);
699 if (!darmdfec
->p_rxdesc
)
702 darmdfec
->p_rxbuf
= memalign(PKTALIGN
, RINGSZ
* PKTSIZE_ALIGN
+ 1);
703 if (!darmdfec
->p_rxbuf
)
706 darmdfec
->p_aligned_txbuf
= memalign(8, PKTSIZE_ALIGN
);
707 if (!darmdfec
->p_aligned_txbuf
)
710 darmdfec
->p_txdesc
= memalign(PKTALIGN
, sizeof(struct tx_desc
) + 1);
711 if (!darmdfec
->p_txdesc
)
714 dev
= &darmdfec
->dev
;
715 /* Assign ARMADA100 Fast Ethernet Controller Base Address */
716 darmdfec
->regs
= (void *)base_addr
;
718 /* must be less than sizeof(dev->name) */
719 strcpy(dev
->name
, "armd-fec0");
721 dev
->init
= armdfec_init
;
722 dev
->halt
= armdfec_halt
;
723 dev
->send
= armdfec_send
;
724 dev
->recv
= armdfec_recv
;
728 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
729 miiphy_register(dev
->name
, smi_reg_read
, smi_reg_write
);
734 free(darmdfec
->p_aligned_txbuf
);
735 free(darmdfec
->p_rxbuf
);
736 free(darmdfec
->p_rxdesc
);
737 free(darmdfec
->htpr
);
740 printf("AMD100 FEC: (%s) Failed to allocate memory\n", __func__
);