net: Adds Fast Ethernet Controller driver for Armada100
Subsystems (2)
PATCH v4 1/3 net: Adds Fast Ethernet Controller driver for Armada100
This patch adds support for Fast Ethernet Controller driver for Armada100 series.
---
Changes for v2:
- removed random MAC generation
- driver init function changed to register as per new naming convention
- code cleanup (Thanks to Wolfgang, Marek & Mike for tips)
Changes for v3:
- code cleanup
Changes for v4:
- Debug and Error messages updated
- base_addr param for armada100_fec_register changed to unsigned long
arch/arm/include/asm/arch-armada100/armada100.h | 1 + drivers/net/Makefile | 1 + drivers/net/armada100_fec.c | 762 +++++++++++++++++++++++ drivers/net/armada100_fec.h | 232 +++++++ include/netdev.h | 1 + 5 files changed, 997 insertions(+), 0 deletions(-) create mode 100644 drivers/net/armada100_fec.c create mode 100644 drivers/net/armada100_fec.h
arch/arm/include/asm/arch-armada100/armada100.h +1 -0
@@ -59,6 +59,7 @@#define ARMD1_MPMU_BASE 0xD4050000#define ARMD1_APMU_BASE 0xD4282800#define ARMD1_CPU_BASE 0xD4282C00 +#define ARMD1_FEC_BASE 0xC0800000/* * Main Power Management (MPMU) Registers
drivers/net/Makefile +1 -0
@@ -28,6 +28,7 @@ LIB := $(obj)libnet.o COBJS-$(CONFIG_DRIVER_3C589) += 3c589.o COBJS-$(CONFIG_PPC4xx_EMAC) += 4xx_enet.o COBJS-$(CONFIG_ALTERA_TSE) += altera_tse.o +COBJS-$(CONFIG_ARMADA100_FEC) += armada100_fec.o COBJS-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o COBJS-$(CONFIG_DRIVER_AX88180) += ax88180.o COBJS-$(CONFIG_BCM570x) += bcm570x.o
drivers/net/armada100_fec.c new file +762 -0
762 lines not on this page · raw message
drivers/net/armada100_fec.h new file +232 -0
232 lines not on this page · raw message
include/netdev.h +1 -0
@@ -94,6 +94,7 @@ int xilinx_emaclite_initialize (bd_t *bis, int base_addr);int sh_eth_initialize (bd_t *bis);int dm9000_initialize (bd_t *bis);int fecmxc_initialize (bd_t *bis); +int armada100_fec_register (unsigned long base_addr);/* Boards with PCI network controllers can call this from their board_eth_init() * function to initialize whatever's on board.
Signature · 1 line
1.7.0.4
PATCH v4 1/3 net: Adds Fast Ethernet Controller driver for Armada100
Quoted 4 lines · Ajay Bhargav
This patch adds support for Fast Ethernet Controller driver for Armada100 series.
Signed-off-by Ajay Bhargav <[email protected]>
[...]
drivers/net/armada100_fec.c line 85
Quoted 10 lines
drivers/net/armada100_fec.c new file +10
-0+static int smi_reg_read (const char *devname,u8 phy_addr,u8 phy_reg, +u16 *value) +{ +struct eth_device *dev =eth_get_dev_by_name (devname); +struct armdfec_device *darmdfec =to_darmdfec (dev); +struct armdfec_reg *regs = darmdfec->regs; +u32 val, reg_data; + +if (phy_addr ==PHY_ADR_REQ && phy_reg ==PHY_ADR_REQ ) { + reg_data =readl (®s->phyadr);
You use "reg_data" here and "val" below ... can't you use just one variable?
Quoted 36 lines
drivers/net/armada100_fec.c new file +36
-0+ *value = reg_data &0x1f ; +return 0 ; + } + +/* check parameters */ +if (phy_addr >PHY_MASK ) { +printf ("ARMD100 FEC: (%s) Invalid phy address: 0x%X\n" , + __func__, phy_addr); +return -EINVAL ; + } +if (phy_reg >PHY_MASK ) { +printf ("ARMD100 FEC: (%s) Invalid register offset: 0x%X\n" , + __func__, phy_reg); +return -EINVAL ; + } + +/* wait for the SMI register to become available */ +if (armdfec_phy_timeout (®s->smi,SMI_BUSY , FALSE)) { +printf ("ARMD100 FEC: (%s) PHY busy timeout\n" , __func__); +return -1 ; + } + +writel ((phy_addr <<16 ) | (phy_reg <<21 ) |SMI_OP_R , ®s->smi); + +/* now wait for the data to be valid */ +if (armdfec_phy_timeout (®s->smi,SMI_R_VALID , TRUE)) { + val =readl (®s->smi); +printf ("ARMD100 FEC: (%s) PHY Read timeout, val=0x%x\n" , + __func__, val); +return -1 ; + } + val =readl (®s->smi); + *value = val &0xffff ; + +return 0 ; +}
[...]
Quoted 30 lines
drivers/net/armada100_fec.c new file +30
-0+static int add_del_hash_entry (struct armdfec_device *darmdfec,u32 mach, +u32 macl,u32 rd,u32 skip,int del) +{ +struct addr_table_entry_t *entry, *start; +u32 newhi; +u32 newlo; +u32 i; + + newlo = (((mach >>4 ) &0xf ) <<15 ) + | (((mach >>0 ) &0xf ) <<11 ) + | (((mach >>12 ) &0xf ) <<7 ) + | (((mach >>8 ) &0xf ) <<3 ) + | (((macl >>20 ) &0x1 ) <<31 ) + | (((macl >>16 ) &0xf ) <<27 ) + | (((macl >>28 ) &0xf ) <<23 ) + | (((macl >>24 ) &0xf ) <<19 ) + | (skip <<HTESKIP ) | (rd <<HTERDBIT ) + |HTEVALID ; + + newhi = (((macl >>4 ) &0xf ) <<15 ) + | (((macl >>0 ) &0xf ) <<11 ) + | (((macl >>12 ) &0xf ) <<7 ) + | (((macl >>8 ) &0xf ) <<3 ) + | (((macl >>21 ) &0x7 ) <<0 ); + +/* +* Pick the appropriate table, start scanning for free/reusable +* entries at the index obtained by hashing the specified MAC address +*/ + start = (struct addr_table_entry_t *) (darmdfec->htpr);
drivers/net/armada100_fec.c line 307
Quoted 10 lines
drivers/net/armada100_fec.c new file +10
-0+ entry = start +hash_function (mach, macl); +for (i =0 ; i <HOP_NUMBER ; i++) { +if (!(entry->lo &HTEVALID )) { +break ; + }else { +/* if same address put in same position */ +if (((entry->lo &0xfffffff8 ) == (newlo &0xfffffff8 )) + && (entry->hi == newhi)) +break ; + }
What about
if (!(entry->lo & HTEVALID))
break;
if (((entry->lo & 0xfffffff8) == (newlo & 0xfffffff8))
&& (entry->hi == newhi)) {
break;
}? :-)
drivers/net/armada100_fec.c line 316
Quoted 9 lines
drivers/net/armada100_fec.c new file +9
-0+if (entry == start +0x7ff ) + entry = start; +else + entry++; + } + +if (((entry->lo &0xfffffff8 ) != (newlo &0xfffffff8 )) && + (entry->hi != newhi) && del) +return 0 ;
Now thinking of it, are you sure about this condition ? Shouldn't the first && be || instead ? And there should be parenthesis around that ?
Quoted 10 lines
drivers/net/armada100_fec.c new file +10
-0+ +if (i ==HOP_NUMBER ) { +if (!del) { +printf ("ARMD100 FEC: (%s) table section is full\n" , + __func__); +return -ENOSPC ; + }else { +return 0 ; + } + }
[...]
drivers/net/armada100_fec.c line 384
Quoted 2 lines
drivers/net/armada100_fec.c new file +2
-0+ +/* 64 should work but does not -- dhcp packets NEVER get transmitted. */
What's this about ?
Quoted 2 lines
drivers/net/armada100_fec.c new file +2
-0+if ((mtu >MAX_PKT_SIZE ) || (mtu <64 )) +return -EINVAL ;
[...]
drivers/net/armada100_fec.c line 589
Quoted 7 lines
drivers/net/armada100_fec.c new file +7
-0+static int armdfec_send (struct eth_device *dev,volatile void *dataptr, +int datasize) +{ +struct armdfec_device *darmdfec =to_darmdfec (dev); +struct armdfec_reg *regs = darmdfec->regs; +struct tx_desc *p_txdesc = darmdfec->p_txdesc; +void *p = (void *) dataptr;
Is this needed?
drivers/net/armada100_fec.c line 594
Quoted 5 lines
drivers/net/armada100_fec.c new file +5
-0+int retry =PHY_WAIT_ITERATIONS *PHY_WAIT_MICRO_SECONDS ; +u32 cmd_sts; + +/* Copy buffer if it's misaligned */ +if ((u32 ) dataptr &0x07 ) {
Space after typecast. Please fix globally.
drivers/net/armada100_fec.c line 602
Quoted 8 lines
drivers/net/armada100_fec.c new file +8
-0+if (datasize >PKTSIZE_ALIGN ) { +printf ("ARMD100 FEC: Non-aligned data too large (%d)\n" , + datasize); +return -1 ; + } +memcpy (darmdfec->p_aligned_txbuf, p, datasize); + p = darmdfec->p_aligned_txbuf; + }
The rest is really good !
Thanks!
Cheers
PATCH v4 1/3 net: Adds Fast Ethernet Controller driver for Armada100
In reply to Ajay BhargavQuoted 14 lines · On Tuesday, August 30, 2011 01:44:40 Ajay Bhargav wrote:
drivers/net/armada100_fec.c new file +14
-0+static void update_hash_table_mac_address (struct armdfec_device *darmdfec, +u8 *oaddr,u8 *addr) +{ +u32 mach; +u32 macl; + +/* Delete old entry */ +if (oaddr) { + mach = (oaddr[0 ] <<8 ) | oaddr[1 ]; + macl = (oaddr[2 ] <<24 ) | (oaddr[3 ] <<16 ) | + (oaddr[4 ] <<8 ) | oaddr[5 ]; +add_del_hash_entry (darmdfec, mach, macl,1 ,0 ,HASH_DELETE ); + } +
drivers/net/armada100_fec.c
Quoted 10 lines
drivers/net/armada100_fec.c new file +8
-0+/* Add new entry */ + mach = (addr[0 ] <<8 ) | addr[1 ]; + macl = (addr[2 ] <<24 ) | (addr[3 ] <<16 ) | (addr[4 ] <<8 ) | addr[5 ]; +add_del_hash_entry (darmdfec, mach, macl,1 ,0 ,HASH_ADD ); +} +static int armdfec_init (struct eth_device *dev,bd_t *bd) +{ +update_hash_table_mac_address (darmdfec, dev->enetaddr, dev->enetaddr);
i think something got lost along the way here :)
you'll probably want to have oaddr[] be a static local in update_hash_table_mac_address and use that to delete the old one when it differs from the new one, and then copy the new one into the static local. -mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110830/c5636d6f/attachment.pgp
PATCH v4 1/3 net: Adds Fast Ethernet Controller driver for Armada100
Quoted 29 lines · ----- "Mike Frysinger
Quoted 1 line · On Tuesday, August 30, 2011 01:44:40 Ajay Bhargav wrote:
+static void update_hash_table_mac_address(struct
armdfec_device*darmdfec,
Quoted 6 lines
drivers/net/armada100_fec.c new file +6
-0+ u8 *oaddr, u8 *addr) +{ +u32 mach; +u32 macl; + +/* Delete old entry */ drivers/net/armada100_fec.c
Quoted 10 lines
drivers/net/armada100_fec.c new file +10
-0+if (oaddr) { + mach = (oaddr[0 ] <<8 ) | oaddr[1 ]; + macl = (oaddr[2 ] <<24 ) | (oaddr[3 ] <<16 ) | + (oaddr[4 ] <<8 ) | oaddr[5 ]; +add_del_hash_entry (darmdfec, mach, macl,1 ,0 ,HASH_DELETE ); + } + +/* Add new entry */ + mach = (addr[0 ] <<8 ) | addr[1 ]; + macl = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) |addr[5];
drivers/net/armada100_fec.c
Quoted 7 lines
drivers/net/armada100_fec.c new file +5
-0+add_del_hash_entry (darmdfec, mach, macl,1 ,0 ,HASH_ADD ); +} +static int armdfec_init (struct eth_device *dev,bd_t *bd) +{ + update_hash_table_mac_address(darmdfec, dev->enetaddr,
dev->enetaddr);
Quoted 8 lines
i think something got lost along the way here :)
you'll probably want to have oaddr[] be a static local in
update_hash_table_mac_addressand use that to delete the old one when it
differs from the new one, and then copy the new one into the static local.
-mike
You can have multiple entries in Hash table for different MAC addresses. The reason old entry is deleted because it may be possible that hash entry in the list is skipped but not invalidated so the same entry is made valid in the list after removing the old one and updating list with new entry. The calculated has for a particular MAC address is going to be same.
Thanks,
Ajay Bhargav
PATCH v4 1/3 net: Adds Fast Ethernet Controller driver for Armada100
Quoted 51 lines · ----- "Ajay Bhargav
Quoted 29 lines · ----- "Mike Frysinger
Quoted 1 line · On Tuesday, August 30, 2011 01:44:40 Ajay Bhargav wrote:
+static void update_hash_table_mac_address(struct
armdfec_device*darmdfec,
Quoted 6 lines
drivers/net/armada100_fec.c new file +6
-0+ u8 *oaddr, u8 *addr) +{ +u32 mach; +u32 macl; + +/* Delete old entry */ drivers/net/armada100_fec.c
Quoted 10 lines
drivers/net/armada100_fec.c new file +10
-0+if (oaddr) { + mach = (oaddr[0 ] <<8 ) | oaddr[1 ]; + macl = (oaddr[2 ] <<24 ) | (oaddr[3 ] <<16 ) | + (oaddr[4 ] <<8 ) | oaddr[5 ]; +add_del_hash_entry (darmdfec, mach, macl,1 ,0 ,HASH_DELETE ); + } + +/* Add new entry */ + mach = (addr[0 ] <<8 ) | addr[1 ]; + macl = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) |addr[5];
drivers/net/armada100_fec.c
Quoted 7 lines
drivers/net/armada100_fec.c new file +5
-0+add_del_hash_entry (darmdfec, mach, macl,1 ,0 ,HASH_ADD ); +} +static int armdfec_init (struct eth_device *dev,bd_t *bd) +{ + update_hash_table_mac_address(darmdfec, dev->enetaddr,
dev->enetaddr);Quoted 4 lines
i think something got lost along the way here :)
you'll probably want to have oaddr[] be a static local in
update_hash_table_mac_addressand use that to delete the old onewhen
Quoted 4 lines
it
differs from the new one, and then copy the new one into the static local.
-mikeYou can have multiple entries in Hash table for different MAC addresses.
The reason old entry is deleted because it may be possible that hash entry
in the list is skipped but not invalidated so the same entry is made valid
in the list after removing the old one and updating list with new entry.
The calculated has for a particular MAC address is going to be same.
Quoted 2 lines
Thanks,
Ajay Bhargav
Adding to this.. In my case, its the first entry in hash table so I do not need to delete it, I can simply pass NULL in place of oaddr. That change I will make in the updated patch I am going to submit.
Thanks,
Ajay Bhargav