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 * SPDX-License-Identifier: GPL-2.0+
18 #include <asm/types.h>
19 #include <asm/byteorder.h>
20 #include <linux/err.h>
21 #include <linux/mii.h>
23 #include <asm/arch/armada100.h>
24 #include "armada100_fec.h"
26 #define PHY_ADR_REQ 0xFF /* Magic number to read/write PHY address */
29 static int eth_dump_regs(struct eth_device
*dev
)
31 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
32 struct armdfec_reg
*regs
= darmdfec
->regs
;
35 printf("\noffset: phy_adr, value: 0x%x\n", readl(®s
->phyadr
));
36 printf("offset: smi, value: 0x%x\n", readl(®s
->smi
));
37 for (i
= 0x400; i
<= 0x4e4; i
+= 4)
38 printf("offset: 0x%x, value: 0x%x\n",
39 i
, readl(ARMD1_FEC_BASE
+ i
));
44 static int armdfec_phy_timeout(u32
*reg
, u32 flag
, int cond
)
46 u32 timeout
= PHY_WAIT_ITERATIONS
;
51 if (cond
&& (reg_val
& flag
))
53 else if (!cond
&& !(reg_val
& flag
))
55 udelay(PHY_WAIT_MICRO_SECONDS
);
60 static int smi_reg_read(const char *devname
, u8 phy_addr
, u8 phy_reg
,
63 struct eth_device
*dev
= eth_get_dev_by_name(devname
);
64 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
65 struct armdfec_reg
*regs
= darmdfec
->regs
;
68 if (phy_addr
== PHY_ADR_REQ
&& phy_reg
== PHY_ADR_REQ
) {
69 val
= readl(®s
->phyadr
);
74 /* check parameters */
75 if (phy_addr
> PHY_MASK
) {
76 printf("ARMD100 FEC: (%s) Invalid phy address: 0x%X\n",
80 if (phy_reg
> PHY_MASK
) {
81 printf("ARMD100 FEC: (%s) Invalid register offset: 0x%X\n",
86 /* wait for the SMI register to become available */
87 if (armdfec_phy_timeout(®s
->smi
, SMI_BUSY
, false)) {
88 printf("ARMD100 FEC: (%s) PHY busy timeout\n", __func__
);
92 writel((phy_addr
<< 16) | (phy_reg
<< 21) | SMI_OP_R
, ®s
->smi
);
94 /* now wait for the data to be valid */
95 if (armdfec_phy_timeout(®s
->smi
, SMI_R_VALID
, true)) {
96 val
= readl(®s
->smi
);
97 printf("ARMD100 FEC: (%s) PHY Read timeout, val=0x%x\n",
101 val
= readl(®s
->smi
);
102 *value
= val
& 0xffff;
107 static int smi_reg_write(const char *devname
,
108 u8 phy_addr
, u8 phy_reg
, u16 value
)
110 struct eth_device
*dev
= eth_get_dev_by_name(devname
);
111 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
112 struct armdfec_reg
*regs
= darmdfec
->regs
;
114 if (phy_addr
== PHY_ADR_REQ
&& phy_reg
== PHY_ADR_REQ
) {
115 clrsetbits_le32(®s
->phyadr
, 0x1f, value
& 0x1f);
119 /* check parameters */
120 if (phy_addr
> PHY_MASK
) {
121 printf("ARMD100 FEC: (%s) Invalid phy address\n", __func__
);
124 if (phy_reg
> PHY_MASK
) {
125 printf("ARMD100 FEC: (%s) Invalid register offset\n", __func__
);
129 /* wait for the SMI register to become available */
130 if (armdfec_phy_timeout(®s
->smi
, SMI_BUSY
, false)) {
131 printf("ARMD100 FEC: (%s) PHY busy timeout\n", __func__
);
135 writel((phy_addr
<< 16) | (phy_reg
<< 21) | SMI_OP_W
| (value
& 0xffff),
141 * Abort any transmit and receive operations and put DMA
142 * in idle state. AT and AR bits are cleared upon entering
143 * in IDLE state. So poll those bits to verify operation.
145 static void abortdma(struct eth_device
*dev
)
147 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
148 struct armdfec_reg
*regs
= darmdfec
->regs
;
153 while (--maxretries
) {
154 writel(SDMA_CMD_AR
| SDMA_CMD_AT
, ®s
->sdma_cmd
);
159 tmp
= readl(®s
->sdma_cmd
);
160 if (!(tmp
& (SDMA_CMD_AR
| SDMA_CMD_AT
)))
169 printf("ARMD100 FEC: (%s) DMA Stuck\n", __func__
);
172 static inline u32
nibble_swapping_32_bit(u32 x
)
174 return ((x
& 0xf0f0f0f0) >> 4) | ((x
& 0x0f0f0f0f) << 4);
177 static inline u32
nibble_swapping_16_bit(u32 x
)
179 return ((x
& 0x0000f0f0) >> 4) | ((x
& 0x00000f0f) << 4);
182 static inline u32
flip_4_bits(u32 x
)
184 return ((x
& 0x01) << 3) | ((x
& 0x002) << 1)
185 | ((x
& 0x04) >> 1) | ((x
& 0x008) >> 3);
189 * This function will calculate the hash function of the address.
190 * depends on the hash mode and hash size.
192 * mach - the 2 most significant bytes of the MAC address.
193 * macl - the 4 least significant bytes of the MAC address.
195 * return the calculated entry.
197 static u32
hash_function(u32 mach
, u32 macl
)
209 addrh
= nibble_swapping_16_bit(mach
);
210 addrl
= nibble_swapping_32_bit(macl
);
212 addrhswapped
= flip_4_bits(addrh
& 0xf)
213 + ((flip_4_bits((addrh
>> 4) & 0xf)) << 4)
214 + ((flip_4_bits((addrh
>> 8) & 0xf)) << 8)
215 + ((flip_4_bits((addrh
>> 12) & 0xf)) << 12);
217 addrlswapped
= flip_4_bits(addrl
& 0xf)
218 + ((flip_4_bits((addrl
>> 4) & 0xf)) << 4)
219 + ((flip_4_bits((addrl
>> 8) & 0xf)) << 8)
220 + ((flip_4_bits((addrl
>> 12) & 0xf)) << 12)
221 + ((flip_4_bits((addrl
>> 16) & 0xf)) << 16)
222 + ((flip_4_bits((addrl
>> 20) & 0xf)) << 20)
223 + ((flip_4_bits((addrl
>> 24) & 0xf)) << 24)
224 + ((flip_4_bits((addrl
>> 28) & 0xf)) << 28);
226 addrh
= addrhswapped
;
227 addrl
= addrlswapped
;
229 addr0
= (addrl
>> 2) & 0x03f;
230 addr1
= (addrl
& 0x003) | (((addrl
>> 8) & 0x7f) << 2);
231 addr2
= (addrl
>> 15) & 0x1ff;
232 addr3
= ((addrl
>> 24) & 0x0ff) | ((addrh
& 1) << 8);
234 hashresult
= (addr0
<< 9) | (addr1
^ addr2
^ addr3
);
235 hashresult
= hashresult
& 0x07ff;
240 * This function will add an entry to the address table.
241 * depends on the hash mode and hash size that was initialized.
243 * mach - the 2 most significant bytes of the MAC address.
244 * macl - the 4 least significant bytes of the MAC address.
245 * skip - if 1, skip this address.
246 * rd - the RD field in the address table.
248 * address table entry is added.
250 * -ENOSPC if table full
252 static int add_del_hash_entry(struct armdfec_device
*darmdfec
, u32 mach
,
253 u32 macl
, u32 rd
, u32 skip
, int del
)
255 struct addr_table_entry_t
*entry
, *start
;
260 newlo
= (((mach
>> 4) & 0xf) << 15)
261 | (((mach
>> 0) & 0xf) << 11)
262 | (((mach
>> 12) & 0xf) << 7)
263 | (((mach
>> 8) & 0xf) << 3)
264 | (((macl
>> 20) & 0x1) << 31)
265 | (((macl
>> 16) & 0xf) << 27)
266 | (((macl
>> 28) & 0xf) << 23)
267 | (((macl
>> 24) & 0xf) << 19)
268 | (skip
<< HTESKIP
) | (rd
<< HTERDBIT
)
271 newhi
= (((macl
>> 4) & 0xf) << 15)
272 | (((macl
>> 0) & 0xf) << 11)
273 | (((macl
>> 12) & 0xf) << 7)
274 | (((macl
>> 8) & 0xf) << 3)
275 | (((macl
>> 21) & 0x7) << 0);
278 * Pick the appropriate table, start scanning for free/reusable
279 * entries at the index obtained by hashing the specified MAC address
281 start
= (struct addr_table_entry_t
*)(darmdfec
->htpr
);
282 entry
= start
+ hash_function(mach
, macl
);
283 for (i
= 0; i
< HOP_NUMBER
; i
++) {
284 if (!(entry
->lo
& HTEVALID
)) {
287 /* if same address put in same position */
288 if (((entry
->lo
& 0xfffffff8) == (newlo
& 0xfffffff8))
289 && (entry
->hi
== newhi
))
292 if (entry
== start
+ 0x7ff)
298 if (((entry
->lo
& 0xfffffff8) != (newlo
& 0xfffffff8)) &&
299 (entry
->hi
!= newhi
) && del
)
302 if (i
== HOP_NUMBER
) {
304 printf("ARMD100 FEC: (%s) table section is full\n",
313 * Update the selected entry
327 * Create an addressTable entry from MAC address info
328 * found in the specifed net_device struct
330 * Input : pointer to ethernet interface network device structure
333 static void update_hash_table_mac_address(struct armdfec_device
*darmdfec
,
339 /* Delete old entry */
341 mach
= (oaddr
[0] << 8) | oaddr
[1];
342 macl
= (oaddr
[2] << 24) | (oaddr
[3] << 16) |
343 (oaddr
[4] << 8) | oaddr
[5];
344 add_del_hash_entry(darmdfec
, mach
, macl
, 1, 0, HASH_DELETE
);
348 mach
= (addr
[0] << 8) | addr
[1];
349 macl
= (addr
[2] << 24) | (addr
[3] << 16) | (addr
[4] << 8) | addr
[5];
350 add_del_hash_entry(darmdfec
, mach
, macl
, 1, 0, HASH_ADD
);
353 /* Address Table Initialization */
354 static void init_hashtable(struct eth_device
*dev
)
356 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
357 struct armdfec_reg
*regs
= darmdfec
->regs
;
358 memset(darmdfec
->htpr
, 0, HASH_ADDR_TABLE_SIZE
);
359 writel((u32
)darmdfec
->htpr
, ®s
->htpr
);
363 * This detects PHY chip from address 0-31 by reading PHY status
364 * registers. PHY chip can be connected at any of this address.
366 static int ethernet_phy_detect(struct eth_device
*dev
)
372 for (addr
= 0; addr
< 32; addr
++) {
373 if (miiphy_read(dev
->name
, addr
, MII_BMSR
, &mii_status
) != 0)
377 /* invalid MII status. More validation required here... */
378 if (mii_status
== 0 || mii_status
== 0xffff)
382 if (miiphy_read(dev
->name
, addr
, MII_PHYSID1
, &tmp
) != 0)
387 if (miiphy_read(dev
->name
, addr
, MII_PHYSID2
, &tmp
) != 0)
393 if ((val
& 0xfffffff0) != 0)
399 static void armdfec_init_rx_desc_ring(struct armdfec_device
*darmdfec
)
401 struct rx_desc
*p_rx_desc
;
404 /* initialize the Rx descriptors ring */
405 p_rx_desc
= darmdfec
->p_rxdesc
;
406 for (i
= 0; i
< RINGSZ
; i
++) {
407 p_rx_desc
->cmd_sts
= BUF_OWNED_BY_DMA
| RX_EN_INT
;
408 p_rx_desc
->buf_size
= PKTSIZE_ALIGN
;
409 p_rx_desc
->byte_cnt
= 0;
410 p_rx_desc
->buf_ptr
= darmdfec
->p_rxbuf
+ i
* PKTSIZE_ALIGN
;
411 if (i
== (RINGSZ
- 1)) {
412 p_rx_desc
->nxtdesc_p
= darmdfec
->p_rxdesc
;
414 p_rx_desc
->nxtdesc_p
= (struct rx_desc
*)
415 ((u32
)p_rx_desc
+ ARMDFEC_RXQ_DESC_ALIGNED_SIZE
);
416 p_rx_desc
= p_rx_desc
->nxtdesc_p
;
419 darmdfec
->p_rxdesc_curr
= darmdfec
->p_rxdesc
;
422 static int armdfec_init(struct eth_device
*dev
, bd_t
*bd
)
424 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
425 struct armdfec_reg
*regs
= darmdfec
->regs
;
429 armdfec_init_rx_desc_ring(darmdfec
);
431 /* Disable interrupts */
432 writel(0, ®s
->im
);
433 writel(0, ®s
->ic
);
434 /* Write to ICR to clear interrupts. */
435 writel(0, ®s
->iwc
);
438 * Abort any transmit and receive operations and put DMA
443 /* Initialize address hash table */
446 /* SDMA configuration */
447 writel(SDCR_BSZ8
| /* Burst size = 32 bytes */
448 SDCR_RIFB
| /* Rx interrupt on frame */
449 SDCR_BLMT
| /* Little endian transmit */
450 SDCR_BLMR
| /* Little endian receive */
451 SDCR_RC_MAX_RETRANS
, /* Max retransmit count */
453 /* Port Configuration */
454 writel(PCR_HS
, ®s
->pconf
); /* Hash size is 1/2kb */
456 /* Set extended port configuration */
457 writel(PCXR_2BSM
| /* Two byte suffix aligns IP hdr */
458 PCXR_DSCP_EN
| /* Enable DSCP in IP */
459 PCXR_MFL_1536
| /* Set MTU = 1536 */
460 PCXR_FLP
| /* do not force link pass */
461 PCXR_TX_HIGH_PRI
, /* Transmit - high priority queue */
464 update_hash_table_mac_address(darmdfec
, NULL
, dev
->enetaddr
);
466 /* Update TX and RX queue descriptor register */
467 temp
= (u32
)®s
->txcdp
[TXQ
];
468 writel((u32
)darmdfec
->p_txdesc
, temp
);
469 temp
= (u32
)®s
->rxfdp
[RXQ
];
470 writel((u32
)darmdfec
->p_rxdesc
, temp
);
471 temp
= (u32
)®s
->rxcdp
[RXQ
];
472 writel((u32
)darmdfec
->p_rxdesc_curr
, temp
);
474 /* Enable Interrupts */
475 writel(ALL_INTS
, ®s
->im
);
477 /* Enable Ethernet Port */
478 setbits_le32(®s
->pconf
, PCR_EN
);
480 /* Enable RX DMA engine */
481 setbits_le32(®s
->sdma_cmd
, SDMA_CMD_ERD
);
487 #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
489 #if defined(CONFIG_PHY_BASE_ADR)
490 miiphy_write(dev
->name
, PHY_ADR_REQ
, PHY_ADR_REQ
, CONFIG_PHY_BASE_ADR
);
492 /* Search phy address from range 0-31 */
493 phy_adr
= ethernet_phy_detect(dev
);
495 printf("ARMD100 FEC: PHY not detected at address range 0-31\n");
498 debug("ARMD100 FEC: PHY detected at addr %d\n", phy_adr
);
499 miiphy_write(dev
->name
, PHY_ADR_REQ
, PHY_ADR_REQ
, phy_adr
);
503 #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
504 /* Wait up to 5s for the link status */
505 for (i
= 0; i
< 5; i
++) {
508 miiphy_read(dev
->name
, 0xFF, 0xFF, &phy_adr
);
509 /* Return if we get link up */
510 if (miiphy_link(dev
->name
, phy_adr
))
515 printf("ARMD100 FEC: No link on %s\n", dev
->name
);
522 static void armdfec_halt(struct eth_device
*dev
)
524 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
525 struct armdfec_reg
*regs
= darmdfec
->regs
;
528 clrbits_le32(®s
->sdma_cmd
, SDMA_CMD_ERD
);
531 * Abort any transmit and receive operations and put DMA
536 /* Disable interrupts */
537 writel(0, ®s
->im
);
538 writel(0, ®s
->ic
);
539 writel(0, ®s
->iwc
);
542 clrbits_le32(®s
->pconf
, PCR_EN
);
545 static int armdfec_send(struct eth_device
*dev
, void *dataptr
, int datasize
)
547 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
548 struct armdfec_reg
*regs
= darmdfec
->regs
;
549 struct tx_desc
*p_txdesc
= darmdfec
->p_txdesc
;
550 void *p
= (void *)dataptr
;
551 int retry
= PHY_WAIT_ITERATIONS
* PHY_WAIT_MICRO_SECONDS
;
554 /* Copy buffer if it's misaligned */
555 if ((u32
)dataptr
& 0x07) {
556 if (datasize
> PKTSIZE_ALIGN
) {
557 printf("ARMD100 FEC: Non-aligned data too large (%d)\n",
561 memcpy(darmdfec
->p_aligned_txbuf
, p
, datasize
);
562 p
= darmdfec
->p_aligned_txbuf
;
565 p_txdesc
->cmd_sts
= TX_ZERO_PADDING
| TX_GEN_CRC
;
566 p_txdesc
->cmd_sts
|= TX_FIRST_DESC
| TX_LAST_DESC
;
567 p_txdesc
->cmd_sts
|= BUF_OWNED_BY_DMA
;
568 p_txdesc
->cmd_sts
|= TX_EN_INT
;
569 p_txdesc
->buf_ptr
= p
;
570 p_txdesc
->byte_cnt
= datasize
;
572 /* Apply send command using high priority TX queue */
573 temp
= (u32
)®s
->txcdp
[TXQ
];
574 writel((u32
)p_txdesc
, temp
);
575 writel(SDMA_CMD_TXDL
| SDMA_CMD_TXDH
| SDMA_CMD_ERD
, ®s
->sdma_cmd
);
578 * wait for packet xmit completion
580 cmd_sts
= readl(&p_txdesc
->cmd_sts
);
581 while (cmd_sts
& BUF_OWNED_BY_DMA
) {
582 /* return fail if error is detected */
583 if ((cmd_sts
& (TX_ERROR
| TX_LAST_DESC
)) ==
584 (TX_ERROR
| TX_LAST_DESC
)) {
585 printf("ARMD100 FEC: (%s) in xmit packet\n", __func__
);
588 cmd_sts
= readl(&p_txdesc
->cmd_sts
);
590 printf("ARMD100 FEC: (%s) xmit packet timeout!\n",
599 static int armdfec_recv(struct eth_device
*dev
)
601 struct armdfec_device
*darmdfec
= to_darmdfec(dev
);
602 struct rx_desc
*p_rxdesc_curr
= darmdfec
->p_rxdesc_curr
;
607 /* wait untill rx packet available or timeout */
609 if (timeout
< PHY_WAIT_ITERATIONS
* PHY_WAIT_MICRO_SECONDS
) {
612 debug("ARMD100 FEC: %s time out...\n", __func__
);
615 } while (readl(&p_rxdesc_curr
->cmd_sts
) & BUF_OWNED_BY_DMA
);
617 if (p_rxdesc_curr
->byte_cnt
!= 0) {
618 debug("ARMD100 FEC: %s: Received %d byte Packet @ 0x%x"
619 "(cmd_sts= %08x)\n", __func__
,
620 (u32
)p_rxdesc_curr
->byte_cnt
,
621 (u32
)p_rxdesc_curr
->buf_ptr
,
622 (u32
)p_rxdesc_curr
->cmd_sts
);
626 * In case received a packet without first/last bits on
627 * OR the error summary bit is on,
628 * the packets needs to be dropeed.
630 cmd_sts
= readl(&p_rxdesc_curr
->cmd_sts
);
632 if ((cmd_sts
& (RX_FIRST_DESC
| RX_LAST_DESC
)) !=
633 (RX_FIRST_DESC
| RX_LAST_DESC
)) {
634 printf("ARMD100 FEC: (%s) Dropping packet spread on"
635 " multiple descriptors\n", __func__
);
636 } else if (cmd_sts
& RX_ERROR
) {
637 printf("ARMD100 FEC: (%s) Dropping packet with errors\n",
640 /* !!! call higher layer processing */
641 debug("ARMD100 FEC: (%s) Sending Received packet to"
642 " upper layer (NetReceive)\n", __func__
);
645 * let the upper layer handle the packet, subtract offset
646 * as two dummy bytes are added in received buffer see
647 * PORT_CONFIG_EXT register bit TWO_Byte_Stuff_Mode bit.
649 NetReceive((p_rxdesc_curr
->buf_ptr
+ RX_BUF_OFFSET
),
650 (int)(p_rxdesc_curr
->byte_cnt
- RX_BUF_OFFSET
));
653 * free these descriptors and point next in the ring
655 p_rxdesc_curr
->cmd_sts
= BUF_OWNED_BY_DMA
| RX_EN_INT
;
656 p_rxdesc_curr
->buf_size
= PKTSIZE_ALIGN
;
657 p_rxdesc_curr
->byte_cnt
= 0;
659 temp
= (u32
)&darmdfec
->p_rxdesc_curr
;
660 writel((u32
)p_rxdesc_curr
->nxtdesc_p
, temp
);
665 int armada100_fec_register(unsigned long base_addr
)
667 struct armdfec_device
*darmdfec
;
668 struct eth_device
*dev
;
670 darmdfec
= malloc(sizeof(struct armdfec_device
));
674 memset(darmdfec
, 0, sizeof(struct armdfec_device
));
676 darmdfec
->htpr
= memalign(8, HASH_ADDR_TABLE_SIZE
);
680 darmdfec
->p_rxdesc
= memalign(PKTALIGN
,
681 ARMDFEC_RXQ_DESC_ALIGNED_SIZE
* RINGSZ
+ 1);
683 if (!darmdfec
->p_rxdesc
)
686 darmdfec
->p_rxbuf
= memalign(PKTALIGN
, RINGSZ
* PKTSIZE_ALIGN
+ 1);
687 if (!darmdfec
->p_rxbuf
)
690 darmdfec
->p_aligned_txbuf
= memalign(8, PKTSIZE_ALIGN
);
691 if (!darmdfec
->p_aligned_txbuf
)
694 darmdfec
->p_txdesc
= memalign(PKTALIGN
, sizeof(struct tx_desc
) + 1);
695 if (!darmdfec
->p_txdesc
)
698 dev
= &darmdfec
->dev
;
699 /* Assign ARMADA100 Fast Ethernet Controller Base Address */
700 darmdfec
->regs
= (void *)base_addr
;
702 /* must be less than sizeof(dev->name) */
703 strcpy(dev
->name
, "armd-fec0");
705 dev
->init
= armdfec_init
;
706 dev
->halt
= armdfec_halt
;
707 dev
->send
= armdfec_send
;
708 dev
->recv
= armdfec_recv
;
712 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
713 miiphy_register(dev
->name
, smi_reg_read
, smi_reg_write
);
718 free(darmdfec
->p_aligned_txbuf
);
719 free(darmdfec
->p_rxbuf
);
720 free(darmdfec
->p_rxdesc
);
721 free(darmdfec
->htpr
);
724 printf("AMD100 FEC: (%s) Failed to allocate memory\n", __func__
);