/* The saved address of a sent-in-place packet/buffer, for skfree(). */
unsigned char *tx_bounce[TX_RING_SIZE];
struct sk_buff* tx_skbuff[TX_RING_SIZE];
+ struct sk_buff* rx_skbuff[RX_RING_SIZE];
ushort skb_cur;
ushort skb_dirty;
int full_duplex;
};
-static int fec_enet_open(struct net_device *dev);
-static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void fec_enet_mii(struct net_device *dev);
static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
static void fec_enet_tx(struct net_device *dev);
static void fec_enet_rx(struct net_device *dev);
static int fec_enet_close(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
static void fec_restart(struct net_device *dev, int duplex);
static void fec_stop(struct net_device *dev);
-static void fec_set_mac_address(struct net_device *dev);
/* MII processing. We keep this as simple as possible. Requests are
{
struct fec_enet_private *fep = netdev_priv(dev);
struct bufdesc *bdp;
+ void *bufaddr;
unsigned short status;
unsigned long flags;
if (!fep->link) {
/* Link is down or autonegotiation is in progress. */
- return 1;
+ return NETDEV_TX_BUSY;
}
spin_lock_irqsave(&fep->hw_lock, flags);
*/
printk("%s: tx queue full!.\n", dev->name);
spin_unlock_irqrestore(&fep->hw_lock, flags);
- return 1;
+ return NETDEV_TX_BUSY;
}
/* Clear all of the status flags */
status &= ~BD_ENET_TX_STATS;
/* Set buffer length and buffer pointer */
- bdp->cbd_bufaddr = __pa(skb->data);
+ bufaddr = skb->data;
bdp->cbd_datlen = skb->len;
/*
* 4-byte boundaries. Use bounce buffers to copy data
* and get it aligned. Ugh.
*/
- if (bdp->cbd_bufaddr & FEC_ALIGNMENT) {
+ if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
unsigned int index;
index = bdp - fep->tx_bd_base;
memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len);
- bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]);
+ bufaddr = fep->tx_bounce[index];
}
/* Save skb pointer */
/* Push the data cache so the CPM does not get stale memory
* data.
*/
- dma_sync_single(NULL, bdp->cbd_bufaddr,
- bdp->cbd_datlen, DMA_TO_DEVICE);
+ bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr,
+ FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
/* Send it on its way. Tell FEC it's ready, interrupt when done,
* it's the last BD of the frame, and to put the CRC on the end.
spin_unlock_irqrestore(&fep->hw_lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
static void
{
struct fec_enet_private *fep = netdev_priv(dev);
- printk("%s: transmit timed out.\n", dev->name);
dev->stats.tx_errors++;
-#ifndef final_version
- {
- int i;
- struct bufdesc *bdp;
-
- printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n",
- (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "",
- (unsigned long)fep->dirty_tx,
- (unsigned long)fep->cur_rx);
-
- bdp = fep->tx_bd_base;
- printk(" tx: %u buffers\n", TX_RING_SIZE);
- for (i = 0 ; i < TX_RING_SIZE; i++) {
- printk(" %08x: %04x %04x %08x\n",
- (uint) bdp,
- bdp->cbd_sc,
- bdp->cbd_datlen,
- (int) bdp->cbd_bufaddr);
- bdp++;
- }
- bdp = fep->rx_bd_base;
- printk(" rx: %lu buffers\n", (unsigned long) RX_RING_SIZE);
- for (i = 0 ; i < RX_RING_SIZE; i++) {
- printk(" %08x: %04x %04x %08x\n",
- (uint) bdp,
- bdp->cbd_sc,
- bdp->cbd_datlen,
- (int) bdp->cbd_bufaddr);
- bdp++;
- }
- }
-#endif
fec_restart(dev, fep->full_duplex);
netif_wake_queue(dev);
}
struct sk_buff *skb;
fep = netdev_priv(dev);
- spin_lock_irq(&fep->hw_lock);
+ spin_lock(&fep->hw_lock);
bdp = fep->dirty_tx;
while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
- if (bdp == fep->cur_tx && fep->tx_full == 0) break;
+ if (bdp == fep->cur_tx && fep->tx_full == 0)
+ break;
+
+ dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
+ bdp->cbd_bufaddr = 0;
skb = fep->tx_skbuff[fep->skb_dirty];
/* Check for errors. */
}
}
fep->dirty_tx = bdp;
- spin_unlock_irq(&fep->hw_lock);
+ spin_unlock(&fep->hw_lock);
}
flush_cache_all();
#endif
- spin_lock_irq(&fep->hw_lock);
+ spin_lock(&fep->hw_lock);
/* First, grab all of the stats for the incoming packet.
* These get messed up if we get called due to a busy condition.
dev->stats.rx_bytes += pkt_len;
data = (__u8*)__va(bdp->cbd_bufaddr);
- dma_sync_single(NULL, (unsigned long)__pa(data),
- pkt_len - 4, DMA_FROM_DEVICE);
+ dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
+ DMA_FROM_DEVICE);
/* This does 16 byte alignment, exactly what we need.
* The packet length includes FCS, but we don't want to
* include that when passing upstream as it messes up
* bridging applications.
*/
- skb = dev_alloc_skb(pkt_len - 4);
+ skb = dev_alloc_skb(pkt_len - 4 + NET_IP_ALIGN);
- if (skb == NULL) {
+ if (unlikely(!skb)) {
printk("%s: Memory squeeze, dropping packet.\n",
dev->name);
dev->stats.rx_dropped++;
} else {
+ skb_reserve(skb, NET_IP_ALIGN);
skb_put(skb, pkt_len - 4); /* Make room */
skb_copy_to_linear_data(skb, data, pkt_len - 4);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
}
+
+ bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen,
+ DMA_FROM_DEVICE);
rx_processing_done:
/* Clear the status flags for this buffer */
status &= ~BD_ENET_RX_STATS;
}
fep->cur_rx = bdp;
- spin_unlock_irq(&fep->hw_lock);
+ spin_unlock(&fep->hw_lock);
}
/* called from interrupt context */
mii_list_t *mip;
fep = netdev_priv(dev);
- spin_lock_irq(&fep->mii_lock);
+ spin_lock(&fep->mii_lock);
if ((mip = mii_head) == NULL) {
printk("MII and no head!\n");
writel(mip->mii_regval, fep->hwp + FEC_MII_DATA);
unlock:
- spin_unlock_irq(&fep->mii_lock);
+ spin_unlock(&fep->mii_lock);
}
static int
-mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *))
+mii_queue_unlocked(struct net_device *dev, int regval,
+ void (*func)(uint, struct net_device *))
{
struct fec_enet_private *fep;
- unsigned long flags;
mii_list_t *mip;
int retval;
/* Add PHY address to register command */
fep = netdev_priv(dev);
- spin_lock_irqsave(&fep->mii_lock, flags);
regval |= fep->phy_addr << 23;
retval = 0;
retval = 1;
}
+ return retval;
+}
+
+static int
+mii_queue(struct net_device *dev, int regval,
+ void (*func)(uint, struct net_device *))
+{
+ struct fec_enet_private *fep;
+ unsigned long flags;
+ int retval;
+ fep = netdev_priv(dev);
+ spin_lock_irqsave(&fep->mii_lock, flags);
+ retval = mii_queue_unlocked(dev, regval, func);
spin_unlock_irqrestore(&fep->mii_lock, flags);
return retval;
}
},
};
+static phy_info_t phy_info_lan8700 = {
+ 0x0007C0C,
+ "LAN8700",
+ (const phy_cmd_t []) { /* config */
+ { mk_mii_read(MII_REG_CR), mii_parse_cr },
+ { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* startup */
+ { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+ { mk_mii_read(MII_REG_SR), mii_parse_sr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* act_int */
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* shutdown */
+ { mk_mii_end, }
+ },
+};
/* ------------------------------------------------------------------------- */
static phy_info_t const * const phy_info[] = {
&phy_info_am79c874,
&phy_info_ks8721bl,
&phy_info_dp83848,
+ &phy_info_lan8700,
NULL
};
printk("FEC: Could not allocate fec(MII) IRQ(66)!\n");
}
-static void __inline__ fec_disable_phy_intr(void)
+static void __inline__ fec_disable_phy_intr(struct net_device *dev)
{
- volatile unsigned long *icrp;
- icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
- *icrp = 0x08000000;
-}
-
-static void __inline__ fec_phy_ack_intr(void)
-{
- volatile unsigned long *icrp;
- /* Acknowledge the interrupt */
- icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
- *icrp = 0x0d000000;
+ free_irq(66, dev);
}
+#endif
#ifdef CONFIG_M5272
static void __inline__ fec_get_mac(struct net_device *dev)
/* Got first part of ID, now get remainder */
fep->phy_id = phytype << 16;
- mii_queue(dev, mk_mii_read(MII_REG_PHYIR2),
+ mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR2),
mii_discover_phy3);
} else {
fep->phy_addr++;
- mii_queue(dev, mk_mii_read(MII_REG_PHYIR1),
+ mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR1),
mii_discover_phy);
}
} else {
writel(0, fep->hwp + FEC_MII_SPEED);
fep->phy_speed = 0;
#ifdef HAVE_mii_link_interrupt
- fec_disable_phy_intr();
+ fec_disable_phy_intr(dev);
#endif
}
}
struct net_device *dev = dev_id;
struct fec_enet_private *fep = netdev_priv(dev);
- fec_phy_ack_intr();
-
mii_do_cmd(dev, fep->phy->ack_int);
mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */
}
#endif
+static void fec_enet_free_buffers(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ int i;
+ struct sk_buff *skb;
+ struct bufdesc *bdp;
+
+ bdp = fep->rx_bd_base;
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ skb = fep->rx_skbuff[i];
+
+ if (bdp->cbd_bufaddr)
+ dma_unmap_single(&dev->dev, bdp->cbd_bufaddr,
+ FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+ if (skb)
+ dev_kfree_skb(skb);
+ bdp++;
+ }
+
+ bdp = fep->tx_bd_base;
+ for (i = 0; i < TX_RING_SIZE; i++)
+ kfree(fep->tx_bounce[i]);
+}
+
+static int fec_enet_alloc_buffers(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ int i;
+ struct sk_buff *skb;
+ struct bufdesc *bdp;
+
+ bdp = fep->rx_bd_base;
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE);
+ if (!skb) {
+ fec_enet_free_buffers(dev);
+ return -ENOMEM;
+ }
+ fep->rx_skbuff[i] = skb;
+
+ bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
+ FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+ bdp->cbd_sc = BD_ENET_RX_EMPTY;
+ bdp++;
+ }
+
+ /* Set the last buffer to wrap. */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ bdp = fep->tx_bd_base;
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
+
+ bdp->cbd_sc = 0;
+ bdp->cbd_bufaddr = 0;
+ bdp++;
+ }
+
+ /* Set the last buffer to wrap. */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ return 0;
+}
+
static int
fec_enet_open(struct net_device *dev)
{
struct fec_enet_private *fep = netdev_priv(dev);
+ int ret;
/* I should reset the ring buffers here, but I don't yet know
* a simple way to do that.
*/
- fec_set_mac_address(dev);
+
+ ret = fec_enet_alloc_buffers(dev);
+ if (ret)
+ return ret;
fep->sequence_done = 0;
fep->link = 0;
+ fec_restart(dev, 1);
+
if (fep->phy) {
mii_do_cmd(dev, fep->phy->ack_int);
mii_do_cmd(dev, fep->phy->config);
schedule();
mii_do_cmd(dev, fep->phy->startup);
-
- /* Set the initial link state to true. A lot of hardware
- * based on this device does not implement a PHY interrupt,
- * so we are never notified of link change.
- */
- fep->link = 1;
- } else {
- fep->link = 1; /* lets just try it and see */
- /* no phy, go full duplex, it's most likely a hub chip */
- fec_restart(dev, 1);
}
+ /* Set the initial link state to true. A lot of hardware
+ * based on this device does not implement a PHY interrupt,
+ * so we are never notified of link change.
+ */
+ fep->link = 1;
+
netif_start_queue(dev);
fep->opened = 1;
return 0;
netif_stop_queue(dev);
fec_stop(dev);
+ fec_enet_free_buffers(dev);
+
return 0;
}
tmp = readl(fep->hwp + FEC_R_CNTRL);
tmp |= 0x8;
writel(tmp, fep->hwp + FEC_R_CNTRL);
- } else {
- tmp = readl(fep->hwp + FEC_R_CNTRL);
- tmp &= ~0x8;
- writel(tmp, fep->hwp + FEC_R_CNTRL);
+ return;
+ }
- if (dev->flags & IFF_ALLMULTI) {
- /* Catch all multicast addresses, so set the
- * filter to all 1's
- */
- writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
- writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
- } else {
- /* Clear filter and add the addresses in hash register
- */
- writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
- writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-
- dmi = dev->mc_list;
-
- for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) {
- /* Only support group multicast for now */
- if (!(dmi->dmi_addr[0] & 1))
- continue;
-
- /* calculate crc32 value of mac address */
- crc = 0xffffffff;
-
- for (i = 0; i < dmi->dmi_addrlen; i++) {
- data = dmi->dmi_addr[i];
- for (bit = 0; bit < 8; bit++, data >>= 1) {
- crc = (crc >> 1) ^
- (((crc ^ data) & 1) ? CRC32_POLY : 0);
- }
- }
-
- /* only upper 6 bits (HASH_BITS) are used
- * which point to specific bit in he hash registers
- */
- hash = (crc >> (32 - HASH_BITS)) & 0x3f;
-
- if (hash > 31) {
- tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
- tmp |= 1 << (hash - 32);
- writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
- } else {
- tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW);
- tmp |= 1 << hash;
- writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
- }
+ tmp = readl(fep->hwp + FEC_R_CNTRL);
+ tmp &= ~0x8;
+ writel(tmp, fep->hwp + FEC_R_CNTRL);
+
+ if (dev->flags & IFF_ALLMULTI) {
+ /* Catch all multicast addresses, so set the
+ * filter to all 1's
+ */
+ writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+ writel(0xffffffff, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+
+ return;
+ }
+
+ /* Clear filter and add the addresses in hash register
+ */
+ writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+ writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+
+ dmi = dev->mc_list;
+
+ for (j = 0; j < netdev_mc_count(dev); j++, dmi = dmi->next) {
+ /* Only support group multicast for now */
+ if (!(dmi->dmi_addr[0] & 1))
+ continue;
+
+ /* calculate crc32 value of mac address */
+ crc = 0xffffffff;
+
+ for (i = 0; i < dmi->dmi_addrlen; i++) {
+ data = dmi->dmi_addr[i];
+ for (bit = 0; bit < 8; bit++, data >>= 1) {
+ crc = (crc >> 1) ^
+ (((crc ^ data) & 1) ? CRC32_POLY : 0);
}
}
+
+ /* only upper 6 bits (HASH_BITS) are used
+ * which point to specific bit in he hash registers
+ */
+ hash = (crc >> (32 - HASH_BITS)) & 0x3f;
+
+ if (hash > 31) {
+ tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+ tmp |= 1 << (hash - 32);
+ writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+ } else {
+ tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+ tmp |= 1 << hash;
+ writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+ }
}
}
/* Set a MAC change in hardware. */
-static void
-fec_set_mac_address(struct net_device *dev)
+static int
+fec_set_mac_address(struct net_device *dev, void *p)
{
struct fec_enet_private *fep = netdev_priv(dev);
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
- /* Set station address. */
writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24),
fep->hwp + FEC_ADDR_LOW);
writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24),
fep + FEC_ADDR_HIGH);
+ return 0;
}
+static const struct net_device_ops fec_netdev_ops = {
+ .ndo_open = fec_enet_open,
+ .ndo_stop = fec_enet_close,
+ .ndo_start_xmit = fec_enet_start_xmit,
+ .ndo_set_multicast_list = set_multicast_list,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_tx_timeout = fec_timeout,
+ .ndo_set_mac_address = fec_set_mac_address,
+};
+
/*
* XXX: We need to clean up on failure exits here.
*
* index is only used in legacy code
*/
-int __init fec_enet_init(struct net_device *dev, int index)
+static int fec_enet_init(struct net_device *dev, int index)
{
struct fec_enet_private *fep = netdev_priv(dev);
- unsigned long mem_addr;
- struct bufdesc *bdp, *cbd_base;
- int i, j;
+ struct bufdesc *cbd_base;
+ struct bufdesc *bdp;
+ int i;
/* Allocate memory for buffer descriptors. */
cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma,
fep->hwp = (void __iomem *)dev->base_addr;
fep->netdev = dev;
- /* Whack a reset. We should wait for this. */
- writel(1, fep->hwp + FEC_ECNTRL);
- udelay(10);
-
/* Set the Ethernet address */
#ifdef CONFIG_M5272
fec_get_mac(dev);
fep->rx_bd_base = cbd_base;
fep->tx_bd_base = cbd_base + RX_RING_SIZE;
- fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
- fep->cur_rx = fep->rx_bd_base;
+#ifdef HAVE_mii_link_interrupt
+ fec_request_mii_intr(dev);
+#endif
+ /* The FEC Ethernet specific entries in the device structure */
+ dev->watchdog_timeo = TX_TIMEOUT;
+ dev->netdev_ops = &fec_netdev_ops;
- fep->skb_cur = fep->skb_dirty = 0;
+ for (i=0; i<NMII-1; i++)
+ mii_cmds[i].mii_next = &mii_cmds[i+1];
+ mii_free = mii_cmds;
+
+ /* Set MII speed to 2.5 MHz */
+ fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999)
+ / 2500000) / 2) & 0x3F) << 1;
/* Initialize the receive buffer descriptors. */
bdp = fep->rx_bd_base;
- for (i=0; i<FEC_ENET_RX_PAGES; i++) {
-
- /* Allocate a page */
- mem_addr = __get_free_page(GFP_KERNEL);
- /* XXX: missing check for allocation failure */
+ for (i = 0; i < RX_RING_SIZE; i++) {
- /* Initialize the BD for every fragment in the page */
- for (j=0; j<FEC_ENET_RX_FRPPG; j++) {
- bdp->cbd_sc = BD_ENET_RX_EMPTY;
- bdp->cbd_bufaddr = __pa(mem_addr);
- mem_addr += FEC_ENET_RX_FRSIZE;
- bdp++;
- }
+ /* Initialize the BD for every fragment in the page. */
+ bdp->cbd_sc = 0;
+ bdp++;
}
/* Set the last buffer to wrap */
/* ...and the same for transmit */
bdp = fep->tx_bd_base;
- for (i=0, j=FEC_ENET_TX_FRPPG; i<TX_RING_SIZE; i++) {
- if (j >= FEC_ENET_TX_FRPPG) {
- mem_addr = __get_free_page(GFP_KERNEL);
- j = 1;
- } else {
- mem_addr += FEC_ENET_TX_FRSIZE;
- j++;
- }
- fep->tx_bounce[i] = (unsigned char *) mem_addr;
+ for (i = 0; i < TX_RING_SIZE; i++) {
- /* Initialize the BD for every fragment in the page */
+ /* Initialize the BD for every fragment in the page. */
bdp->cbd_sc = 0;
bdp->cbd_bufaddr = 0;
bdp++;
bdp--;
bdp->cbd_sc |= BD_SC_WRAP;
- /* Set receive and transmit descriptor base */
- writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
- writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE,
- fep->hwp + FEC_X_DES_START);
-
-#ifdef HAVE_mii_link_interrupt
- fec_request_mii_intr(dev);
-#endif
-
- writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
- writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
- writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
- writel(2, fep->hwp + FEC_ECNTRL);
- writel(0, fep->hwp + FEC_R_DES_ACTIVE);
-#ifndef CONFIG_M5272
- writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
- writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
-#endif
-
- /* The FEC Ethernet specific entries in the device structure */
- dev->open = fec_enet_open;
- dev->hard_start_xmit = fec_enet_start_xmit;
- dev->tx_timeout = fec_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
- dev->stop = fec_enet_close;
- dev->set_multicast_list = set_multicast_list;
-
- for (i=0; i<NMII-1; i++)
- mii_cmds[i].mii_next = &mii_cmds[i+1];
- mii_free = mii_cmds;
-
- /* setup MII interface */
- writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL);
- writel(0, fep->hwp + FEC_X_CNTRL);
-
- /* Set MII speed to 2.5 MHz */
- fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999)
- / 2500000) / 2) & 0x3F) << 1;
- writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
fec_restart(dev, 0);
- /* Clear and enable interrupts */
- writel(0xffc00000, fep->hwp + FEC_IEVENT);
- writel(FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII,
- fep->hwp + FEC_IMASK);
-
/* Queue up command to detect the PHY and initialize the
* remainder of the interface.
*/
fec_restart(struct net_device *dev, int duplex)
{
struct fec_enet_private *fep = netdev_priv(dev);
- struct bufdesc *bdp;
int i;
/* Whack a reset. We should wait for this. */
/* Clear any outstanding interrupt. */
writel(0xffc00000, fep->hwp + FEC_IEVENT);
- /* Set station address. */
- fec_set_mac_address(dev);
-
/* Reset all multicast. */
writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
+#ifndef CONFIG_M5272
+ writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
+ writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
+#endif
/* Set maximum receive buffer size. */
writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
}
}
- /* Initialize the receive buffer descriptors. */
- bdp = fep->rx_bd_base;
- for (i = 0; i < RX_RING_SIZE; i++) {
-
- /* Initialize the BD for every fragment in the page. */
- bdp->cbd_sc = BD_ENET_RX_EMPTY;
- bdp++;
- }
-
- /* Set the last buffer to wrap */
- bdp--;
- bdp->cbd_sc |= BD_SC_WRAP;
-
- /* ...and the same for transmit */
- bdp = fep->tx_bd_base;
- for (i = 0; i < TX_RING_SIZE; i++) {
-
- /* Initialize the BD for every fragment in the page. */
- bdp->cbd_sc = 0;
- bdp->cbd_bufaddr = 0;
- bdp++;
- }
-
- /* Set the last buffer to wrap */
- bdp--;
- bdp->cbd_sc |= BD_SC_WRAP;
-
/* Enable MII mode */
if (duplex) {
/* MII enable / FD enable */