mirror of
https://github.com/genesi/linux-legacy.git
synced 2026-02-03 23:54:40 +00:00
ENGR00124252 MX28: Support Switch port0 as ethernet port
The L2 Switch have 4 ports, and the port0 can be used as ethernet port when Switch is configured to operate as a 3-Port Switch (Switch Mode). Signed-off-by: Niu Xule <b23300@freescale.com>
This commit is contained in:
@@ -103,7 +103,6 @@ static int switch_enet_close(struct net_device *dev);
|
||||
static void set_multicast_list(struct net_device *dev);
|
||||
static void switch_restart(struct net_device *dev, int duplex);
|
||||
static void switch_stop(struct net_device *dev);
|
||||
static int switch_set_mac_address(struct net_device *dev, void *addr);
|
||||
|
||||
#define NMII 20
|
||||
|
||||
@@ -124,7 +123,8 @@ static void *swap_buffer(void *bufaddr, int len)
|
||||
|
||||
for (i = 0; i < (len + 3) / 4; i++, buf++)
|
||||
*buf = __swab32(*buf);
|
||||
return bufaddr;
|
||||
|
||||
return bufaddr;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -132,7 +132,7 @@ static void *swap_buffer(void *bufaddr, int len)
|
||||
struct eswPortInfo g_info;
|
||||
|
||||
static unsigned char switch_mac_default[] = {
|
||||
0x00, 0x04, 0x9F, 0x00, 0xB3, 0x49,
|
||||
0x00, 0x08, 0x02, 0x6B, 0xA3, 0x1A,
|
||||
};
|
||||
|
||||
static void switch_request_intrs(struct net_device *dev,
|
||||
@@ -159,17 +159,17 @@ static void switch_set_mii(struct net_device *dev)
|
||||
fecp = (struct switch_t *)fep->hwp;
|
||||
|
||||
writel(MCF_FEC_RCR_PROM | MCF_FEC_RCR_RMII_MODE |
|
||||
MCF_FEC_RCR_MAX_FL(1522) | MCF_FEC_RCR_CRC_FWD,
|
||||
MCF_FEC_RCR_MAX_FL(1522),
|
||||
fep->enet_addr + MCF_FEC_RCR0);
|
||||
writel(MCF_FEC_RCR_PROM | MCF_FEC_RCR_RMII_MODE |
|
||||
MCF_FEC_RCR_MAX_FL(1522) | MCF_FEC_RCR_CRC_FWD,
|
||||
MCF_FEC_RCR_MAX_FL(1522),
|
||||
fep->enet_addr + MCF_FEC_RCR1);
|
||||
/* TCR */
|
||||
writel(MCF_FEC_TCR_FDEN, fep->enet_addr + MCF_FEC_TCR0);
|
||||
writel(MCF_FEC_TCR_FDEN, fep->enet_addr + MCF_FEC_TCR1);
|
||||
|
||||
/* ECR */
|
||||
#ifdef MODELO_ENHANCE_BUFFER
|
||||
#ifdef L2SWITCH_ENHANCED_BUFFER
|
||||
writel(MCF_FEC_ECR_ETHER_EN | MCF_FEC_ECR_ENA_1588,
|
||||
fep->enet_addr + MCF_FEC_ECR0);
|
||||
writel(MCF_FEC_ECR_ETHER_EN | MCF_FEC_ECR_ENA_1588,
|
||||
@@ -191,10 +191,9 @@ static void switch_set_mii(struct net_device *dev)
|
||||
|
||||
#ifdef CONFIG_ARCH_MXS
|
||||
/* Can't get phy(8720) ID when set to 2.5M on MX28, lower it*/
|
||||
writel((readl(fep->enet_addr + MCF_FEC_MSCR0) << 2),
|
||||
fep->enet_addr + MCF_FEC_MSCR0);
|
||||
writel((readl(fep->enet_addr + MCF_FEC_MSCR0) << 2),
|
||||
fep->enet_addr + MCF_FEC_MSCR1);
|
||||
fep->phy_speed = readl(fep->enet_addr + MCF_FEC_MSCR0) << 2;
|
||||
writel(fep->phy_speed, fep->enet_addr + MCF_FEC_MSCR0);
|
||||
writel(fep->phy_speed, fep->enet_addr + MCF_FEC_MSCR1);
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -204,7 +203,6 @@ static void switch_get_mac(struct net_device *dev)
|
||||
struct switch_enet_private *fep = netdev_priv(dev);
|
||||
unsigned char *iap, tmpaddr[ETH_ALEN];
|
||||
static int index;
|
||||
|
||||
#ifdef CONFIG_M5272
|
||||
if (FEC_FLASHMAC) {
|
||||
/*
|
||||
@@ -609,7 +607,7 @@ static int esw_get_forced_forward(
|
||||
fecp = fep->hwp;
|
||||
*ulForceForward = fecp->ESW_P0FFEN;
|
||||
#ifdef DEBUG_FORCED_FORWARD
|
||||
printk(KERN_INFO "%s ESW_P0FFEN %x\n",
|
||||
printk(KERN_INFO "%s ESW_P0FFEN %#lx\n",
|
||||
__func__, fecp->ESW_P0FFEN);
|
||||
#endif
|
||||
return 0;
|
||||
@@ -624,7 +622,7 @@ static void esw_get_port_enable(
|
||||
fecp = fep->hwp;
|
||||
*ulPortEnable = fecp->ESW_PER;
|
||||
#ifdef DEBUG_PORT_ENABLE
|
||||
printk(KERN_INFO "%s fecp->ESW_PER %x\n",
|
||||
printk(KERN_INFO "%s fecp->ESW_PER %#lx\n",
|
||||
__func__, fecp->ESW_PER);
|
||||
#endif
|
||||
}
|
||||
@@ -723,7 +721,7 @@ static void esw_get_port_broadcast(
|
||||
fecp = fep->hwp;
|
||||
*ulPortBroadcast = fecp->ESW_DBCR;
|
||||
#ifdef DEBUG_PORT_BROADCAST
|
||||
printk(KERN_INFO "%s fecp->ESW_DBCR %x\n",
|
||||
printk(KERN_INFO "%s fecp->ESW_DBCR %#lx\n",
|
||||
__func__, fecp->ESW_DBCR);
|
||||
#endif
|
||||
}
|
||||
@@ -775,7 +773,7 @@ static void esw_get_port_multicast(
|
||||
fecp = fep->hwp;
|
||||
*ulPortMulticast = fecp->ESW_DMCR;
|
||||
#ifdef DEBUG_PORT_MULTICAST
|
||||
printk(KERN_INFO "%s fecp->ESW_DMCR %x\n",
|
||||
printk(KERN_INFO "%s fecp->ESW_DMCR %#lx\n",
|
||||
__func__, fecp->ESW_DMCR);
|
||||
#endif
|
||||
}
|
||||
@@ -827,7 +825,7 @@ static void esw_get_port_blocking(
|
||||
fecp = fep->hwp;
|
||||
*ulPortBlocking = (fecp->ESW_BKLR & 0x00ff);
|
||||
#ifdef DEBUG_PORT_BLOCKING
|
||||
printk(KERN_INFO "%s fecp->ESW_BKLR %x\n",
|
||||
printk(KERN_INFO "%s fecp->ESW_BKLR %#lx\n",
|
||||
__func__, fecp->ESW_BKLR);
|
||||
#endif
|
||||
}
|
||||
@@ -879,7 +877,7 @@ static void esw_get_port_learning(
|
||||
fecp = fep->hwp;
|
||||
*ulPortLearning = (fecp->ESW_BKLR & 0xff00) >> 16;
|
||||
#ifdef DEBUG_PORT_LEARNING
|
||||
printk(KERN_INFO "%s fecp->ESW_BKLR %x\n",
|
||||
printk(KERN_INFO "%s fecp->ESW_BKLR %#lx\n",
|
||||
__func__, fecp->ESW_BKLR);
|
||||
#endif
|
||||
}
|
||||
@@ -922,7 +920,7 @@ static int esw_port_learning_config(
|
||||
|
||||
fecp->ESW_BKLR = tmp;
|
||||
#ifdef DEBUG_PORT_LEARNING
|
||||
printk(KERN_INFO "%s ESW_BKLR %x, switch_imask %x\n",
|
||||
printk(KERN_INFO "%s ESW_BKLR %#lx, switch_imask %#lx\n",
|
||||
__func__, fecp->ESW_BKLR, fecp->switch_imask);
|
||||
#endif
|
||||
return 0;
|
||||
@@ -989,7 +987,7 @@ static void esw_get_ip_snoop_config(
|
||||
#ifdef DEBUG_IP_SNOOP
|
||||
printk(KERN_INFO "%s ", __func__);
|
||||
for (i = 0; i < 8; i++)
|
||||
printk(KERN_INFO " reg(%d) %x", fecp->ESW_IPSNP[i]);
|
||||
printk(KERN_INFO " reg(%d) %#lx", fecp->ESW_IPSNP[i]);
|
||||
printk(KERN_INFO "\n");
|
||||
#endif
|
||||
|
||||
@@ -1062,7 +1060,7 @@ static void esw_get_tcpudp_port_snoop_config(
|
||||
#ifdef DEBUG_TCPUDP_PORT_SNOOP
|
||||
printk(KERN_INFO "%s ", __func__);
|
||||
for (i = 0; i < 8; i++)
|
||||
printk(KERN_INFO " reg(%d) %x", fecp->ESW_PSNP[i]);
|
||||
printk(KERN_INFO " reg(%d) %#lx", fecp->ESW_PSNP[i]);
|
||||
printk(KERN_INFO "\n");
|
||||
#endif
|
||||
|
||||
@@ -1088,11 +1086,11 @@ static void esw_get_port_mirroring(
|
||||
pPortMirrorStatus->ESW_ENGDAH = fecp->ESW_ENGDAH;
|
||||
pPortMirrorStatus->ESW_MCVAL = fecp->ESW_MCVAL;
|
||||
#ifdef DEBUG_PORT_MIRROR
|
||||
printk(KERN_INFO "%s : ESW_MCR %x, ESW_EGMAP %x\n"
|
||||
"ESW_INGMAP %x, ESW_INGSAL %x, "
|
||||
"ESW_INGSAH %x ESW_INGDAL %x, ESW_INGDAH %x\n"
|
||||
"ESW_ENGSAL %x, ESW_ENGSAH%x, ESW_ENGDAL %x,"
|
||||
"ESW_ENGDAH %x, ESW_MCVAL %x\n",
|
||||
printk(KERN_INFO "%s : ESW_MCR %#lx, ESW_EGMAP %#lx\n"
|
||||
"ESW_INGMAP %#lx, ESW_INGSAL %#lx, "
|
||||
"ESW_INGSAH %#lx ESW_INGDAL %#lx, ESW_INGDAH %#lx\n"
|
||||
"ESW_ENGSAL %#lx, ESW_ENGSAH%#lx, ESW_ENGDAL %#lx,"
|
||||
"ESW_ENGDAH %#lx, ESW_MCVAL %#lx\n",
|
||||
__func__, fecp->ESW_MCR, fecp->ESW_EGMAP, fecp->ESW_INGMAP,
|
||||
fecp->ESW_INGSAL, fecp->ESW_INGSAH, fecp->ESW_INGDAL,
|
||||
fecp->ESW_INGDAH, fecp->ESW_ENGSAL, fecp->ESW_ENGSAH,
|
||||
@@ -1247,7 +1245,7 @@ static void esw_get_vlan_verification(
|
||||
*ulValue = fecp->ESW_VLANV;
|
||||
|
||||
#ifdef DEBUG_VLAN_VERIFICATION_CONFIG
|
||||
printk(KERN_INFO "%s: ESW_VLANV %x\n",
|
||||
printk(KERN_INFO "%s: ESW_VLANV %#lx\n",
|
||||
__func__, fecp->ESW_VLANV);
|
||||
#endif
|
||||
}
|
||||
@@ -1309,7 +1307,7 @@ static int esw_set_vlan_verification(
|
||||
}
|
||||
|
||||
#ifdef DEBUG_VLAN_VERIFICATION_CONFIG
|
||||
printk(KERN_INFO "%s: ESW_VLANV %x\n",
|
||||
printk(KERN_INFO "%s: ESW_VLANV %#lx\n",
|
||||
__func__, fecp->ESW_VLANV);
|
||||
#endif
|
||||
return 0;
|
||||
@@ -1326,7 +1324,7 @@ static void esw_get_vlan_resolution_table(
|
||||
*ulValue = fecp->ESW_VRES[vlan_domain_num];
|
||||
|
||||
#ifdef DEBUG_VLAN_DOMAIN_TABLE
|
||||
printk(KERN_INFO "%s: ESW_VRES[%d] = %x\n",
|
||||
printk(KERN_INFO "%s: ESW_VRES[%d] = %#lx\n",
|
||||
__func__, vlan_domain_num,
|
||||
fecp->ESW_VRES[vlan_domain_num]);
|
||||
#endif
|
||||
@@ -1362,7 +1360,7 @@ int esw_set_vlan_resolution_table(
|
||||
| vlan_domain_port;
|
||||
|
||||
#ifdef DEBUG_VLAN_DOMAIN_TABLE
|
||||
printk(KERN_INFO "%s: ESW_VRES[%d] = %x\n",
|
||||
printk(KERN_INFO "%s: ESW_VRES[%d] = %#lx\n",
|
||||
__func__, vlan_domain_num,
|
||||
fecp->ESW_VRES[vlan_domain_num]);
|
||||
#endif
|
||||
@@ -1387,9 +1385,9 @@ static void esw_get_vlan_input_config(
|
||||
for (i = 0; i < 32; i++)
|
||||
pVlanInputConfig->ESW_VRES[i] = fecp->ESW_VRES[i];
|
||||
#ifdef DEBUG_VLAN_INTPUT_CONFIG
|
||||
printk(KERN_INFO "%s: ESW_VLANV %x, ESW_VIMSEL %x, "
|
||||
"ESW_VIMEN %x, ESW_PID[0], ESW_PID[1] %x, "
|
||||
"ESW_PID[2] %x", __func__,
|
||||
printk(KERN_INFO "%s: ESW_VLANV %#lx, ESW_VIMSEL %#lx, "
|
||||
"ESW_VIMEN %#lx, ESW_PID[0], ESW_PID[1] %#lx, "
|
||||
"ESW_PID[2] %#lx", __func__,
|
||||
fecp->ESW_VLANV, fecp->ESW_VIMSEL, fecp->ESW_VIMEN,
|
||||
fecp->ESW_PID[0], fecp->ESW_PID[1], fecp->ESW_PID[2]);
|
||||
#endif
|
||||
@@ -1469,7 +1467,7 @@ static void esw_get_vlan_output_config(struct switch_enet_private *fep,
|
||||
|
||||
*ulVlanOutputConfig = fecp->ESW_VOMSEL;
|
||||
#ifdef DEBUG_VLAN_OUTPUT_CONFIG
|
||||
printk(KERN_INFO "%s: ESW_VOMSEL %x", __func__,
|
||||
printk(KERN_INFO "%s: ESW_VOMSEL %#lx", __func__,
|
||||
fecp->ESW_VOMSEL);
|
||||
#endif
|
||||
}
|
||||
@@ -1661,8 +1659,8 @@ static int esw_get_statistics_status(
|
||||
pStatistics->ESW_NDISCN = fecp->ESW_NDISCN;
|
||||
pStatistics->ESW_NDISCB = fecp->ESW_NDISCB;
|
||||
#ifdef DEBUG_STATISTICS
|
||||
printk(KERN_ERR "%s:ESW_DISCN %x, ESW_DISCB %x,"
|
||||
"ESW_NDISCN %x, ESW_NDISCB %x\n",
|
||||
printk(KERN_ERR "%s:ESW_DISCN %#lx, ESW_DISCB %#lx,"
|
||||
"ESW_NDISCN %#lx, ESW_NDISCB %#lx\n",
|
||||
__func__, fecp->ESW_DISCN, fecp->ESW_DISCB,
|
||||
fecp->ESW_NDISCN, fecp->ESW_NDISCB);
|
||||
#endif
|
||||
@@ -1693,8 +1691,8 @@ static int esw_get_port_statistics_status(
|
||||
pPortStatistics->MCF_ESW_PBL =
|
||||
fecp->port_statistics_status[port].MCF_ESW_PBL;
|
||||
#ifdef DEBUG_PORT_STATISTICS
|
||||
printk(KERN_ERR "%s : port[%d].MCF_ESW_POQC %x, MCF_ESW_PMVID %x,"
|
||||
" MCF_ESW_PMVTAG %x, MCF_ESW_PBL %x\n",
|
||||
printk(KERN_ERR "%s : port[%d].MCF_ESW_POQC %#lx, MCF_ESW_PMVID %#lx,"
|
||||
" MCF_ESW_PMVTAG %#lx, MCF_ESW_PBL %#lx\n",
|
||||
__func__, port,
|
||||
fecp->port_statistics_status[port].MCF_ESW_POQC,
|
||||
fecp->port_statistics_status[port].MCF_ESW_PMVID,
|
||||
@@ -1719,8 +1717,8 @@ static int esw_get_output_queue_status(
|
||||
pOutputQueue->ESW_QWT = fecp->ESW_QWT;
|
||||
pOutputQueue->ESW_P0BCT = fecp->ESW_P0BCT;
|
||||
#ifdef DEBUG_OUTPUT_QUEUE
|
||||
printk(KERN_ERR "%s:ESW_MMSR %x, ESW_LMT %x, ESW_LFC %x, "
|
||||
"ESW_IOSR %x, ESW_PCSR %x, ESW_QWT %x, ESW_P0BCT %x\n",
|
||||
printk(KERN_ERR "%s:ESW_MMSR %#lx, ESW_LMT %#lx, ESW_LFC %#lx, "
|
||||
"ESW_IOSR %#lx, ESW_PCSR %#lx, ESW_QWT %#lx, ESW_P0BCT %#lx\n",
|
||||
__func__, fecp->ESW_MMSR,
|
||||
fecp->ESW_LMT, fecp->ESW_LFC,
|
||||
fecp->ESW_IOSR, fecp->ESW_PCSR,
|
||||
@@ -1760,8 +1758,8 @@ static int esw_set_output_queue_memory(
|
||||
return -1;
|
||||
}
|
||||
#ifdef DEBUG_OUTPUT_QUEUE
|
||||
printk(KERN_ERR "%s:ESW_MMSR %x, ESW_LMT %x, ESW_LFC %x, "
|
||||
"ESW_IOSR %x, ESW_PCSR %x, ESW_QWT %x, ESW_P0BCT %x\n",
|
||||
printk(KERN_ERR "%s:ESW_MMSR %#lx, ESW_LMT %#lx, ESW_LFC %#lx, "
|
||||
"ESW_IOSR %#lx, ESW_PCSR %#lx, ESW_QWT %#lx, ESW_P0BCT %#lx\n",
|
||||
__func__, fecp->ESW_MMSR,
|
||||
fecp->ESW_LMT, fecp->ESW_LFC,
|
||||
fecp->ESW_IOSR, fecp->ESW_PCSR,
|
||||
@@ -1778,7 +1776,7 @@ int esw_set_irq_mask(
|
||||
|
||||
fecp = fep->hwp;
|
||||
#ifdef DEBUG_IRQ
|
||||
printk(KERN_INFO "%s: irq event %x, irq mask %x "
|
||||
printk(KERN_INFO "%s: irq event %#lx, irq mask %#lx "
|
||||
" mask %x, enable %x\n",
|
||||
__func__, fecp->switch_ievent,
|
||||
fecp->switch_imask, mask, enable);
|
||||
@@ -1793,10 +1791,10 @@ int esw_set_irq_mask(
|
||||
return -1;
|
||||
}
|
||||
#ifdef DEBUG_IRQ
|
||||
printk(KERN_INFO "%s: irq event %x, irq mask %x, "
|
||||
"rx_des_start %x, tx_des_start %x, "
|
||||
"rx_buff_size %x, rx_des_active %x, "
|
||||
"tx_des_active %x\n",
|
||||
printk(KERN_INFO "%s: irq event %#lx, irq mask %#lx, "
|
||||
"rx_des_start %#lx, tx_des_start %#lx, "
|
||||
"rx_buff_size %#lx, rx_des_active %#lx, "
|
||||
"tx_des_active %#lx\n",
|
||||
__func__, fecp->switch_ievent, fecp->switch_imask,
|
||||
fecp->fec_r_des_start, fecp->fec_x_des_start,
|
||||
fecp->fec_r_buff_size, fecp->fec_r_des_active,
|
||||
@@ -1814,7 +1812,7 @@ static void esw_get_switch_mode(
|
||||
fecp = fep->hwp;
|
||||
*ulModeConfig = fecp->ESW_MODE;
|
||||
#ifdef DEBUG_SWITCH_MODE
|
||||
printk(KERN_INFO "%s: mode %x \n"
|
||||
printk(KERN_INFO "%s: mode %#lx \n",
|
||||
__func__, fecp->ESW_MODE);
|
||||
#endif
|
||||
}
|
||||
@@ -1828,7 +1826,7 @@ static void esw_switch_mode_configure(
|
||||
fecp = fep->hwp;
|
||||
fecp->ESW_MODE |= configure;
|
||||
#ifdef DEBUG_SWITCH_MODE
|
||||
printk(KERN_INFO "%s: mode %x \n"
|
||||
printk(KERN_INFO "%s: mode %#lx \n",
|
||||
__func__, fecp->ESW_MODE);
|
||||
#endif
|
||||
}
|
||||
@@ -1843,7 +1841,7 @@ static void esw_get_bridge_port(
|
||||
fecp = fep->hwp;
|
||||
*ulBMPConfig = fecp->ESW_BMPC;
|
||||
#ifdef DEBUG_BRIDGE_PORT
|
||||
printk(KERN_INFO "%s: bridge management port %x \n"
|
||||
printk(KERN_INFO "%s: bridge management port %#lx \n",
|
||||
__func__, fecp->ESW_BMPC);
|
||||
#endif
|
||||
}
|
||||
@@ -1857,7 +1855,7 @@ static void esw_bridge_port_configure(
|
||||
fecp = fep->hwp;
|
||||
fecp->ESW_BMPC |= configure;
|
||||
#ifdef DEBUG_BRIDGE_PORT
|
||||
printk(KERN_INFO "%s: bridge management port %x \n"
|
||||
printk(KERN_INFO "%s: bridge management port %#lx \n",
|
||||
__func__, fecp->ESW_BMPC);
|
||||
#endif
|
||||
}
|
||||
@@ -1895,16 +1893,22 @@ void esw_check_rxb_txb_interrupt(struct switch_enet_private *fep)
|
||||
fecp->ESW_P0FFEN, fecp->ESW_BKLR);
|
||||
}
|
||||
|
||||
static void esw_mac_addr_static(struct switch_enet_private *fep)
|
||||
static int esw_mac_addr_static(struct switch_enet_private *fep)
|
||||
{
|
||||
unsigned char mac_addr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
unsigned char mac_addr0[6] = {0x00, 0x04, 0x9F, 0x00, 0xB3, 0x49};
|
||||
struct switch_t *fecp;
|
||||
|
||||
fecp = fep->hwp;
|
||||
fecp->ESW_DBCR = MCF_ESW_DBCR_P1;
|
||||
esw_update_atable_static(mac_addr, 7, 7, fep);
|
||||
esw_update_atable_static(mac_addr0, 7, 7, fep);
|
||||
|
||||
if (is_valid_ether_addr(fep->netdev->dev_addr))
|
||||
esw_update_atable_static(fep->netdev->dev_addr, 7, 7, fep);
|
||||
else{
|
||||
printk(KERN_ERR "Can not add available mac address"
|
||||
" for switch!!\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void esw_main(struct switch_enet_private *fep)
|
||||
@@ -2599,6 +2603,7 @@ switch_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
struct switch_enet_private *fep;
|
||||
struct switch_t *fecp;
|
||||
struct cbd_t *bdp;
|
||||
void *bufaddr;
|
||||
unsigned short status;
|
||||
unsigned long flags;
|
||||
|
||||
@@ -2625,30 +2630,26 @@ switch_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
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;
|
||||
printk(KERN_ERR "%s: skb->len %u, dev->stats.tx_bytes %lx,"
|
||||
" bdp->cbd_bufaddr %lx skb->data %lx\n",
|
||||
__func__, skb->len, dev->stats.tx_bytes,
|
||||
bdp->cbd_bufaddr, (unsigned long)skb->data);
|
||||
|
||||
/*
|
||||
* On some FEC implementations data must be aligned on
|
||||
* 4-byte boundaries. Use bounce buffers to copy data
|
||||
* and get it aligned. Ugh.
|
||||
*/
|
||||
if (bdp->cbd_bufaddr & FEC_ALIGNMENT) {
|
||||
unsigned int index1;
|
||||
index1 = bdp - fep->tx_bd_base;
|
||||
printk(KERN_ERR "%s: bdp->cbd_bufaddr %lx\n",
|
||||
__func__, bdp->cbd_bufaddr);
|
||||
memcpy(fep->tx_bounce[index1],
|
||||
(void *)skb->data, bdp->cbd_datlen);
|
||||
bdp->cbd_bufaddr = __pa(fep->tx_bounce[index1]);
|
||||
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);
|
||||
bufaddr = fep->tx_bounce[index];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_MXS
|
||||
swap_buffer((void *)bdp->cbd_bufaddr, skb->len);
|
||||
swap_buffer(bufaddr, skb->len);
|
||||
#endif
|
||||
|
||||
/* Save skb pointer. */
|
||||
fep->tx_skbuff[fep->skb_cur] = skb;
|
||||
|
||||
@@ -2659,7 +2660,7 @@ switch_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
* Push the data cache so the CPM does not get stale memory
|
||||
* data.
|
||||
*/
|
||||
bdp->cbd_bufaddr = dma_map_single(&dev->dev, (void *)bdp->cbd_bufaddr,
|
||||
bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr,
|
||||
FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
|
||||
|
||||
/*
|
||||
@@ -2670,7 +2671,7 @@ switch_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
|
||||
| BD_ENET_TX_LAST | BD_ENET_TX_TC);
|
||||
bdp->cbd_sc = status;
|
||||
#ifdef MODELO_BUFFER
|
||||
#ifdef L2SWITCH_ENHANCED_BUFFER
|
||||
bdp->bdu = 0x00000000;
|
||||
bdp->ebd_status = TX_BD_INT | TX_BD_TS;
|
||||
#endif
|
||||
@@ -2693,7 +2694,7 @@ switch_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
printk(KERN_ERR "%s: net stop\n", __func__);
|
||||
}
|
||||
|
||||
fep->cur_tx = (struct cbd_t *)bdp;
|
||||
fep->cur_tx = bdp;
|
||||
|
||||
spin_unlock_irqrestore(&fep->hw_lock, flags);
|
||||
|
||||
@@ -2823,6 +2824,9 @@ switch_enet_tx(struct net_device *dev)
|
||||
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 */
|
||||
if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
|
||||
@@ -2875,7 +2879,7 @@ switch_enet_tx(struct net_device *dev)
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
}
|
||||
fep->dirty_tx = (struct cbd_t *)bdp;
|
||||
fep->dirty_tx = bdp;
|
||||
spin_unlock(&fep->hw_lock);
|
||||
}
|
||||
|
||||
@@ -2910,8 +2914,8 @@ switch_enet_rx(struct net_device *dev)
|
||||
* These get messed up if we get called due to a busy condition.
|
||||
*/
|
||||
bdp = fep->cur_rx;
|
||||
#ifdef MODELO_BUFFER
|
||||
printk(KERN_ERR "%s: cbd_sc %x cbd_datlen %x cbd_bufaddr %x "
|
||||
#ifdef L2SWITCH_ENHANCED_BUFFER
|
||||
printk(KERN_INFO "%s: cbd_sc %x cbd_datlen %x cbd_bufaddr %x "
|
||||
"ebd_status %x bdu %x length_proto_type %x "
|
||||
"payload_checksum %x\n",
|
||||
__func__, bdp->cbd_sc, bdp->cbd_datlen,
|
||||
@@ -2963,29 +2967,33 @@ while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
|
||||
dev->stats.rx_bytes += pkt_len;
|
||||
data = (__u8 *)__va(bdp->cbd_bufaddr);
|
||||
|
||||
dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
|
||||
DMA_FROM_DEVICE);
|
||||
#ifdef CONFIG_ARCH_MXS
|
||||
swap_buffer(data, pkt_len);
|
||||
#endif
|
||||
/*
|
||||
* 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);
|
||||
|
||||
if (skb == NULL) {
|
||||
printk(KERN_ERR "%s: Memory squeeze, "
|
||||
"dropping packet.\n", dev->name);
|
||||
skb = dev_alloc_skb(pkt_len - 4 + NET_IP_ALIGN);
|
||||
if (unlikely(!skb)) {
|
||||
printk("%s: Memory squeeze, dropping packet.\n",
|
||||
dev->name);
|
||||
dev->stats.rx_dropped++;
|
||||
} else {
|
||||
/*
|
||||
* skb_put(skb, pkt_len -4);
|
||||
* skb_copy_to_linear_data(skb, data, pkt_len - 4);
|
||||
*/
|
||||
skb_put(skb, pkt_len); /* Make room */
|
||||
skb_copy_to_linear_data(skb, data, pkt_len);
|
||||
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 */
|
||||
@@ -3008,18 +3016,7 @@ rx_processing_done:
|
||||
*/
|
||||
fecp->fec_r_des_active = MCF_ESW_RDAR_R_DES_ACTIVE;
|
||||
} /* while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) */
|
||||
fep->cur_rx = (struct cbd_t *)bdp;
|
||||
|
||||
#if 0
|
||||
/* Doing this here will allow us to process all frames in the
|
||||
* ring before the FEC is allowed to put more there. On a heavily
|
||||
* loaded network, some frames may be lost. Unfortunately, this
|
||||
* increases the interrupt overhead since we can potentially work
|
||||
* our way back to the interrupt return only to come right back
|
||||
* here.
|
||||
*/
|
||||
fecp->fec_r_des_active = 0;
|
||||
#endif
|
||||
fep->cur_rx = bdp;
|
||||
|
||||
spin_unlock(&fep->hw_lock);
|
||||
}
|
||||
@@ -3337,14 +3334,94 @@ static int fec_switch_init_phy(struct net_device *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void fec_enet_free_buffers(struct net_device *dev)
|
||||
{
|
||||
struct switch_enet_private *fep = netdev_priv(dev);
|
||||
int i;
|
||||
struct sk_buff *skb;
|
||||
struct cbd_t *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 switch_enet_private *fep = netdev_priv(dev);
|
||||
int i;
|
||||
struct sk_buff *skb;
|
||||
struct cbd_t *bdp;
|
||||
|
||||
bdp = fep->rx_bd_base;
|
||||
for (i = 0; i < RX_RING_SIZE; i++) {
|
||||
skb = dev_alloc_skb(SWITCH_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,
|
||||
SWITCH_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
|
||||
bdp->cbd_sc = BD_ENET_RX_EMPTY;
|
||||
#ifdef L2SWITCH_ENHANCED_BUFFER
|
||||
bdp->bdu = 0x00000000;
|
||||
bdp->ebd_status = RX_BD_INT;
|
||||
#endif
|
||||
#ifdef CONFIG_FEC_1588
|
||||
bdp->cbd_esc = BD_ENET_RX_INT;
|
||||
#endif
|
||||
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(SWITCH_ENET_TX_FRSIZE, GFP_KERNEL);
|
||||
|
||||
bdp->cbd_sc = 0;
|
||||
bdp->cbd_bufaddr = 0;
|
||||
#ifdef CONFIG_FEC_1588
|
||||
bdp->cbd_esc = BD_ENET_TX_INT;
|
||||
#endif
|
||||
bdp++;
|
||||
}
|
||||
|
||||
/* Set the last buffer to wrap. */
|
||||
bdp--;
|
||||
bdp->cbd_sc |= BD_SC_WRAP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
switch_enet_open(struct net_device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct switch_enet_private *fep = netdev_priv(dev);
|
||||
/* I should reset the ring buffers here, but I don't yet know
|
||||
* a simple way to do that.
|
||||
*/
|
||||
switch_set_mac_address(dev, NULL);
|
||||
clk_enable(fep->clk);
|
||||
ret = fec_enet_alloc_buffers(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
fep->link = 0;
|
||||
#ifdef FEC_PHY
|
||||
@@ -3377,8 +3454,6 @@ switch_enet_open(struct net_device *dev)
|
||||
|
||||
fep->currTime = 0;
|
||||
fep->learning_irqhandle_enable = 0;
|
||||
/* enable timer for Learning Aging Function */
|
||||
/* add_timer(&fep->timer_aging); */
|
||||
|
||||
esw_main(fep);
|
||||
|
||||
@@ -3401,6 +3476,9 @@ switch_enet_close(struct net_device *dev)
|
||||
phy_stop(fep->phydev);
|
||||
phy_write(fep->phydev, MII_BMCR, BMCR_PDOWN);
|
||||
#endif
|
||||
fec_enet_free_buffers(dev);
|
||||
clk_disable(fep->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3480,8 +3558,37 @@ static void set_multicast_list(struct net_device *dev)
|
||||
|
||||
/* Set a MAC change in hardware */
|
||||
static int
|
||||
switch_set_mac_address(struct net_device *dev, void *addr)
|
||||
switch_set_mac_address(struct net_device *dev, void *p)
|
||||
{
|
||||
struct switch_enet_private *fep = netdev_priv(dev);
|
||||
struct sockaddr *addr = p;
|
||||
struct switch_t *fecp;
|
||||
|
||||
if (!is_valid_ether_addr(addr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
fecp = fep->hwp;
|
||||
fecp->ESW_DBCR = MCF_ESW_DBCR_P1;
|
||||
|
||||
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
|
||||
|
||||
writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
|
||||
(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24),
|
||||
fep->enet_addr + MCF_FEC_PAUR0);
|
||||
writel((dev->dev_addr[5] << 16)
|
||||
| ((dev->dev_addr[4]+(unsigned char)(0)) << 24),
|
||||
fep->enet_addr + MCF_FEC_PAUR0);
|
||||
|
||||
writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
|
||||
(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24),
|
||||
fep->enet_addr + MCF_FEC_PAUR1);
|
||||
writel((dev->dev_addr[5] << 16)
|
||||
| ((dev->dev_addr[4]+(unsigned char)(1)) << 24),
|
||||
fep->enet_addr + MCF_FEC_PAUR1);
|
||||
|
||||
esw_update_atable_static(dev->dev_addr, 7, 7, fep);
|
||||
fecp->ESW_DBCR = MCF_ESW_DBCR_P1 | MCF_ESW_DBCR_P2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3501,17 +3608,40 @@ static const struct net_device_ops fec_netdev_ops = {
|
||||
.ndo_set_mac_address = switch_set_mac_address,
|
||||
};
|
||||
|
||||
static int switch_mac_addr_setup(char *mac_addr)
|
||||
{
|
||||
char *ptr, *p = mac_addr;
|
||||
unsigned long tmp;
|
||||
int i = 0, ret = 0;
|
||||
|
||||
while (p && (*p) && i < 6) {
|
||||
ptr = strchr(p, ':');
|
||||
if (ptr)
|
||||
*ptr++ = '\0';
|
||||
if (strlen(p)) {
|
||||
ret = strict_strtoul(p, 16, &tmp);
|
||||
if (ret < 0 || tmp > 0xff)
|
||||
break;
|
||||
switch_mac_default[i++] = tmp;
|
||||
}
|
||||
p = ptr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__setup("fec_mac=", switch_mac_addr_setup);
|
||||
|
||||
/* Initialize the FEC Ethernet */
|
||||
static int __init switch_enet_init(struct net_device *dev,
|
||||
int slot, struct platform_device *pdev)
|
||||
{
|
||||
struct switch_enet_private *fep = netdev_priv(dev);
|
||||
struct resource *r;
|
||||
unsigned long mem_addr;
|
||||
struct cbd_t *bdp;
|
||||
struct cbd_t *cbd_base;
|
||||
struct switch_t *fecp;
|
||||
int i, j;
|
||||
int i;
|
||||
struct switch_platform_data *plat = pdev->dev.platform_data;
|
||||
|
||||
/* Only allow us to be probed once. */
|
||||
@@ -3519,9 +3649,10 @@ static int __init switch_enet_init(struct net_device *dev,
|
||||
return -ENXIO;
|
||||
|
||||
/* Allocate memory for buffer descriptors */
|
||||
mem_addr = __get_free_page(GFP_DMA);
|
||||
if (mem_addr == 0) {
|
||||
printk(KERN_ERR "Switch: allocate descriptor memory failed?\n");
|
||||
cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma,
|
||||
GFP_KERNEL);
|
||||
if (!cbd_base) {
|
||||
printk(KERN_ERR "FEC: allocate descriptor memory failed?\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -3614,48 +3745,20 @@ static int __init switch_enet_init(struct net_device *dev,
|
||||
if (plat && plat->get_mac)
|
||||
plat->get_mac(dev);
|
||||
|
||||
cbd_base = (struct cbd_t *)mem_addr;
|
||||
if (cbd_base == 0) {
|
||||
printk(KERN_ERR "Switch: allocate memory failed?\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (plat && plat->uncache)
|
||||
plat->uncache(mem_addr);
|
||||
|
||||
/* Set receive and transmit descriptor base */
|
||||
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;
|
||||
|
||||
fep->skb_cur = fep->skb_dirty = 0;
|
||||
|
||||
/* Initialize the receive buffer descriptors */
|
||||
bdp = fep->rx_bd_base;
|
||||
for (i = 0; i < SWITCH_ENET_RX_PAGES; i++) {
|
||||
for (i = 0; i < RX_RING_SIZE; i++) {
|
||||
bdp->cbd_sc = 0;
|
||||
|
||||
/* Allocate a page */
|
||||
mem_addr = __get_free_page(GFP_DMA);
|
||||
if (mem_addr == 0) {
|
||||
printk(KERN_ERR "Switch: allocate memory failed?\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (plat && plat->uncache)
|
||||
plat->uncache(mem_addr);
|
||||
|
||||
/* Initialize the BD for every fragment in the page */
|
||||
for (j = 0; j < SWITCH_ENET_RX_FRPPG; j++) {
|
||||
bdp->cbd_sc = BD_ENET_RX_EMPTY;
|
||||
bdp->cbd_bufaddr = __pa(mem_addr);
|
||||
#ifdef MODELO_BUFFER
|
||||
bdp->bdu = 0x00000000;
|
||||
bdp->ebd_status = RX_BD_INT;
|
||||
#ifdef L2SWITCH_ENHANCED_BUFFER
|
||||
bdp->bdu = 0x00000000;
|
||||
bdp->ebd_status = RX_BD_INT;
|
||||
#endif
|
||||
mem_addr += SWITCH_ENET_RX_FRSIZE;
|
||||
bdp++;
|
||||
}
|
||||
bdp++;
|
||||
}
|
||||
|
||||
/* Set the last buffer to wrap */
|
||||
@@ -3664,16 +3767,7 @@ static int __init switch_enet_init(struct net_device *dev,
|
||||
|
||||
/* ...and the same for transmmit */
|
||||
bdp = fep->tx_bd_base;
|
||||
for (i = 0, j = SWITCH_ENET_TX_FRPPG; i < TX_RING_SIZE; i++) {
|
||||
if (j >= SWITCH_ENET_TX_FRPPG) {
|
||||
mem_addr = __get_free_page(GFP_DMA);
|
||||
j = 1;
|
||||
} else {
|
||||
mem_addr += SWITCH_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 */
|
||||
bdp->cbd_sc = 0;
|
||||
bdp->cbd_bufaddr = 0;
|
||||
@@ -3684,10 +3778,6 @@ static int __init switch_enet_init(struct net_device *dev,
|
||||
bdp--;
|
||||
bdp->cbd_sc |= BD_SC_WRAP;
|
||||
|
||||
/* Set receive and transmit descriptor base */
|
||||
fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base));
|
||||
fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base));
|
||||
|
||||
/*
|
||||
* Install our interrupt handlers. This varies depending on
|
||||
* the architecture.
|
||||
@@ -3695,20 +3785,6 @@ static int __init switch_enet_init(struct net_device *dev,
|
||||
if (plat && plat->request_intrs)
|
||||
plat->request_intrs(dev, switch_enet_interrupt, dev);
|
||||
|
||||
/*
|
||||
* fecp->fec_grp_hash_table_high = 0;
|
||||
* fecp->fec_grp_hash_table_low = 0;
|
||||
*/
|
||||
fecp->fec_r_buff_size = RX_BUFFER_SIZE;
|
||||
/* fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; */
|
||||
fecp->fec_r_des_active = MCF_ESW_RDAR_R_DES_ACTIVE;
|
||||
/*
|
||||
* if (plat->hash_table == 0) {
|
||||
* fecp->fec_hash_table_high = 0;
|
||||
* fecp->fec_hash_table_low = 0;
|
||||
* }
|
||||
*/
|
||||
|
||||
dev->base_addr = (unsigned long)fecp;
|
||||
|
||||
/* The FEC Ethernet specific entries in the device structure. */
|
||||
@@ -3719,11 +3795,6 @@ static int __init switch_enet_init(struct net_device *dev,
|
||||
if (plat && plat->set_mii)
|
||||
plat->set_mii(dev);
|
||||
|
||||
/* Clear and enable interrupts */
|
||||
fecp->switch_ievent = 0xffffffff;
|
||||
fecp->switch_imask = MCF_ESW_IMR_RXB | MCF_ESW_IMR_TXB |
|
||||
MCF_ESW_IMR_RXF | MCF_ESW_IMR_TXF;
|
||||
esw_clear_atable(fep);
|
||||
|
||||
#ifndef CONFIG_FEC_SHARED_PHY
|
||||
fep->phy_addr = 0;
|
||||
@@ -3735,6 +3806,112 @@ static int __init switch_enet_init(struct net_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void enet_reset(struct net_device *dev, int duplex)
|
||||
{
|
||||
struct switch_enet_private *fep = netdev_priv(dev);
|
||||
|
||||
/* ECR */
|
||||
#ifdef L2SWITCH_ENHANCED_BUFFER
|
||||
writel(MCF_FEC_ECR_ENA_1588
|
||||
| MCF_FEC_ECR_MAGIC_ENA,
|
||||
fep->enet_addr + MCF_FEC_ECR0);
|
||||
writel(MCF_FEC_ECR_ENA_1588,
|
||||
| MCF_FEC_ECR_MAGIC_ENA,
|
||||
fep->enet_addr + MCF_FEC_ECR1);
|
||||
#else /*legac buffer*/
|
||||
writel(MCF_FEC_ECR_MAGIC_ENA,
|
||||
fep->enet_addr + MCF_FEC_ECR0);
|
||||
writel(MCF_FEC_ECR_MAGIC_ENA,
|
||||
fep->enet_addr + MCF_FEC_ECR1);
|
||||
#endif
|
||||
/* EMRBR */
|
||||
writel(PKT_MAXBLR_SIZE, fep->enet_addr + MCF_FEC_EMRBR0);
|
||||
writel(PKT_MAXBLR_SIZE, fep->enet_addr + MCF_FEC_EMRBR1);
|
||||
|
||||
/*
|
||||
* set the receive and transmit BDs ring base to
|
||||
* hardware registers(ERDSR & ETDSR)
|
||||
*/
|
||||
writel(fep->bd_dma, fep->enet_addr + MCF_FEC_ERDSR0);
|
||||
writel(fep->bd_dma, fep->enet_addr + MCF_FEC_ERDSR1);
|
||||
writel((unsigned long)fep->bd_dma + sizeof(struct cbd_t) * RX_RING_SIZE,
|
||||
fep->enet_addr + MCF_FEC_ETDSR0);
|
||||
writel((unsigned long)fep->bd_dma + sizeof(struct cbd_t) * RX_RING_SIZE,
|
||||
fep->enet_addr + MCF_FEC_ETDSR1);
|
||||
#ifdef CONFIG_ARCH_MXS
|
||||
/* Can't get phy(8720) ID when set to 2.5M on MX28, lower it */
|
||||
writel(fep->phy_speed,
|
||||
fep->enet_addr + MCF_FEC_MSCR0);
|
||||
writel(fep->phy_speed,
|
||||
fep->enet_addr + MCF_FEC_MSCR1);
|
||||
#endif
|
||||
fep->full_duplex = duplex;
|
||||
|
||||
/* EIR */
|
||||
writel(0, fep->enet_addr + MCF_FEC_EIR0);
|
||||
writel(0, fep->enet_addr + MCF_FEC_EIR1);
|
||||
|
||||
/* IAUR */
|
||||
writel(0, fep->enet_addr + MCF_FEC_IAUR0);
|
||||
writel(0, fep->enet_addr + MCF_FEC_IAUR1);
|
||||
|
||||
/* IALR */
|
||||
writel(0, fep->enet_addr + MCF_FEC_IALR0);
|
||||
writel(0, fep->enet_addr + MCF_FEC_IALR1);
|
||||
|
||||
/* GAUR */
|
||||
writel(0, fep->enet_addr + MCF_FEC_GAUR0);
|
||||
writel(0, fep->enet_addr + MCF_FEC_GAUR1);
|
||||
|
||||
/* GALR */
|
||||
writel(0, fep->enet_addr + MCF_FEC_GALR0);
|
||||
writel(0, fep->enet_addr + MCF_FEC_GALR1);
|
||||
|
||||
/* EMRBR */
|
||||
writel(PKT_MAXBLR_SIZE, fep->enet_addr + MCF_FEC_EMRBR0);
|
||||
writel(PKT_MAXBLR_SIZE, fep->enet_addr + MCF_FEC_EMRBR1);
|
||||
msleep(10);
|
||||
|
||||
/* EIMR */
|
||||
writel(FEC_ENET_TXF | FEC_ENET_RXF, fep->enet_addr + MCF_FEC_EIMR0);
|
||||
writel(FEC_ENET_TXF | FEC_ENET_RXF, fep->enet_addr + MCF_FEC_EIMR1);
|
||||
|
||||
/* PALR PAUR */
|
||||
/* Set the station address for the ENET Adapter */
|
||||
writel(dev->dev_addr[3] |
|
||||
dev->dev_addr[2]<<8 |
|
||||
dev->dev_addr[1]<<16 |
|
||||
dev->dev_addr[0]<<24, fep->enet_addr + MCF_FEC_PALR0);
|
||||
writel(dev->dev_addr[5]<<16 |
|
||||
(dev->dev_addr[4]+(unsigned char)(0))<<24,
|
||||
fep->enet_addr + MCF_FEC_PAUR0);
|
||||
writel(dev->dev_addr[3] |
|
||||
dev->dev_addr[2]<<8 |
|
||||
dev->dev_addr[1]<<16 |
|
||||
dev->dev_addr[0]<<24, fep->enet_addr + MCF_FEC_PALR1);
|
||||
writel(dev->dev_addr[5]<<16 |
|
||||
(dev->dev_addr[4]+(unsigned char)(1))<<24,
|
||||
fep->enet_addr + MCF_FEC_PAUR1);
|
||||
|
||||
/* RCR */
|
||||
writel(readl(fep->enet_addr + MCF_FEC_RCR0)
|
||||
| MCF_FEC_RCR_FCE | MCF_FEC_RCR_PROM,
|
||||
fep->enet_addr + MCF_FEC_RCR0);
|
||||
writel(readl(fep->enet_addr + MCF_FEC_RCR1)
|
||||
| MCF_FEC_RCR_FCE | MCF_FEC_RCR_PROM,
|
||||
fep->enet_addr + MCF_FEC_RCR1);
|
||||
|
||||
/* TCR */
|
||||
writel(0x1c, fep->enet_addr + MCF_FEC_TCR0);
|
||||
writel(0x1c, fep->enet_addr + MCF_FEC_TCR1);
|
||||
|
||||
/* ECR */
|
||||
writel(readl(fep->enet_addr + MCF_FEC_ECR0) | MCF_FEC_ECR_ETHER_EN,
|
||||
fep->enet_addr + MCF_FEC_ECR0);
|
||||
writel(readl(fep->enet_addr + MCF_FEC_ECR1) | MCF_FEC_ECR_ETHER_EN,
|
||||
fep->enet_addr + MCF_FEC_ECR1);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called to start or restart the FEC during a link
|
||||
* change. This only happens when switching between half and full
|
||||
@@ -3744,7 +3921,6 @@ static void
|
||||
switch_restart(struct net_device *dev, int duplex)
|
||||
{
|
||||
struct switch_enet_private *fep;
|
||||
struct cbd_t *bdp;
|
||||
struct switch_t *fecp;
|
||||
int i;
|
||||
struct switch_platform_data *plat;
|
||||
@@ -3775,13 +3951,10 @@ switch_restart(struct net_device *dev, int duplex)
|
||||
* plat->enable_phy_intr();
|
||||
*/
|
||||
|
||||
/* Set station address */
|
||||
switch_set_mac_address(dev, NULL);
|
||||
|
||||
/* Reset all multicast */
|
||||
/*
|
||||
* fecp->fec_grp_hash_table_high = 0;
|
||||
*fecp->fec_grp_hash_table_low = 0;
|
||||
* fecp->fec_grp_hash_table_low = 0;
|
||||
*/
|
||||
|
||||
/* Set maximum receive buffer size */
|
||||
@@ -3789,9 +3962,11 @@ switch_restart(struct net_device *dev, int duplex)
|
||||
|
||||
if (plat && plat->localhw_setup)
|
||||
plat->localhw_setup();
|
||||
|
||||
/* Set receive and transmit descriptor base */
|
||||
fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base));
|
||||
fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base));
|
||||
fecp->fec_r_des_start = fep->bd_dma;
|
||||
fecp->fec_x_des_start = (unsigned long)fep->bd_dma
|
||||
+ sizeof(struct cbd_t) * RX_RING_SIZE;
|
||||
|
||||
fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
|
||||
fep->cur_rx = fep->rx_bd_base;
|
||||
@@ -3805,42 +3980,10 @@ switch_restart(struct net_device *dev, int duplex)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
#ifdef MODELO_BUFFER
|
||||
bdp->bdu = 0x00000000;
|
||||
bdp->ebd_status = RX_BD_INT;
|
||||
#endif
|
||||
bdp++;
|
||||
}
|
||||
|
||||
/* Set the last buffer to wrap */
|
||||
bdp--;
|
||||
bdp->cbd_sc |= BD_SC_WRAP;
|
||||
|
||||
/* ...and the same for transmmit */
|
||||
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;
|
||||
|
||||
fep->full_duplex = duplex;
|
||||
enet_reset(dev, duplex);
|
||||
esw_clear_atable(fep);
|
||||
|
||||
/* And last, enable the transmit and receive processing */
|
||||
fecp->fec_r_buff_size = RX_BUFFER_SIZE;
|
||||
/* fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; */
|
||||
fecp->fec_r_des_active = MCF_ESW_RDAR_R_DES_ACTIVE;
|
||||
|
||||
/* Enable interrupts we wish to service */
|
||||
|
||||
@@ -224,15 +224,44 @@ struct eswAddrTable_t {
|
||||
#define MCF_FEC_ECR0 (0x24 / sizeof(unsigned long))
|
||||
#define MCF_FEC_ECR1 (0x4024 / sizeof(unsigned long))
|
||||
|
||||
#define MCF_FEC_RCR_PROM (0x00000008)
|
||||
#define MCF_FEC_RCR_RMII_MODE (0x00000100)
|
||||
#define MCF_FEC_RCR_MAX_FL(x) (((x)&0x00003FFF)<<16)
|
||||
#define MCF_FEC_RCR_CRC_FWD (0x00004000)
|
||||
#define MCF_FEC_PALR0 (0xE4 / sizeof(unsigned long))
|
||||
#define MCF_FEC_PALR1 (0x40E4 / sizeof(unsigned long))
|
||||
#define MCF_FEC_PAUR0 (0xE8 / sizeof(unsigned long))
|
||||
#define MCF_FEC_PAUR1 (0x40E8 / sizeof(unsigned long))
|
||||
|
||||
#define MCF_FEC_TCR_FDEN (0x00000004)
|
||||
#define MCF_FEC_ERDSR0 (0x180 / sizeof(unsigned long))
|
||||
#define MCF_FEC_ERDSR1 (0x4180 / sizeof(unsigned long))
|
||||
#define MCF_FEC_ETDSR0 (0x184 / sizeof(unsigned long))
|
||||
#define MCF_FEC_ETDSR1 (0x4184 / sizeof(unsigned long))
|
||||
|
||||
#define MCF_FEC_ECR_ETHER_EN (0x00000002)
|
||||
#define MCF_FEC_ECR_ENA_1588 (0x00000010)
|
||||
#define MCF_FEC_IAUR0 (0x118 / sizeof(unsigned long))
|
||||
#define MCF_FEC_IAUR1 (0x4118 / sizeof(unsigned long))
|
||||
#define MCF_FEC_IALR0 (0x11C / sizeof(unsigned long))
|
||||
#define MCF_FEC_IALR1 (0x411C / sizeof(unsigned long))
|
||||
|
||||
#define MCF_FEC_GAUR0 (0x120 / sizeof(unsigned long))
|
||||
#define MCF_FEC_GAUR1 (0x4120 / sizeof(unsigned long))
|
||||
#define MCF_FEC_GALR0 (0x124 / sizeof(unsigned long))
|
||||
#define MCF_FEC_GALR1 (0x4124 / sizeof(unsigned long))
|
||||
|
||||
#define MCF_FEC_EMRBR0 (0x188 / sizeof(unsigned long))
|
||||
#define MCF_FEC_EMRBR1 (0x4188 / sizeof(unsigned long))
|
||||
|
||||
#define MCF_FEC_RCR_DRT (0x00000002)
|
||||
#define MCF_FEC_RCR_PROM (0x00000008)
|
||||
#define MCF_FEC_RCR_FCE (0x00000020)
|
||||
#define MCF_FEC_RCR_RMII_MODE (0x00000100)
|
||||
#define MCF_FEC_RCR_MAX_FL(x) (((x)&0x00003FFF)<<16)
|
||||
#define MCF_FEC_RCR_CRC_FWD (0x00004000)
|
||||
#define MCF_FEC_RCR_NO_LGTH_CHECK (0x40000000)
|
||||
#define MCF_FEC_TCR_FDEN (0x00000004)
|
||||
|
||||
#define MCF_FEC_ECR_RESET (0x00000001)
|
||||
#define MCF_FEC_ECR_ETHER_EN (0x00000002)
|
||||
#define MCF_FEC_ECR_MAGIC_ENA (0x00000004)
|
||||
#define MCF_FEC_ECR_ENA_1588 (0x00000010)
|
||||
|
||||
#define MCF_FEC_ERDSR(x) ((x) << 2)
|
||||
|
||||
/*-------------ioctl command ---------------------------------------*/
|
||||
#define ESW_SET_LEARNING_CONF 0x9101
|
||||
@@ -484,7 +513,7 @@ struct cbd_t {
|
||||
unsigned short cbd_datlen; /* Data length */
|
||||
#endif
|
||||
unsigned long cbd_bufaddr; /* Buffer address */
|
||||
#ifdef MODELO_BUFFER
|
||||
#ifdef L2SWITCH_ENHANCED_BUFFER
|
||||
unsigned long ebd_status;
|
||||
unsigned short length_proto_type;
|
||||
unsigned short payload_checksum;
|
||||
@@ -532,11 +561,12 @@ struct switch_enet_private {
|
||||
/* 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;
|
||||
|
||||
/* CPM dual port RAM relative addresses.
|
||||
*/
|
||||
/* CPM dual port RAM relative addresses */
|
||||
dma_addr_t bd_dma;
|
||||
struct cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */
|
||||
struct cbd_t *tx_bd_base;
|
||||
struct cbd_t *cur_rx, *cur_tx; /* The next free ring entry */
|
||||
|
||||
@@ -4346,6 +4346,12 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
|
||||
default:
|
||||
if ((cmd >= SIOCDEVPRIVATE &&
|
||||
cmd <= SIOCDEVPRIVATE + 15) ||
|
||||
|
||||
#if defined(CONFIG_FEC_L2SWITCH)
|
||||
(cmd >= 0x9101 &&
|
||||
cmd <= 0x92ff) ||
|
||||
#endif
|
||||
|
||||
cmd == SIOCBONDENSLAVE ||
|
||||
cmd == SIOCBONDRELEASE ||
|
||||
cmd == SIOCBONDSETHWADDR ||
|
||||
@@ -4538,6 +4544,10 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
||||
*/
|
||||
default:
|
||||
if (cmd == SIOCWANDEV ||
|
||||
#if defined(CONFIG_FEC_L2SWITCH)
|
||||
(cmd >= 0x9101 &&
|
||||
cmd <= 0x92ff) ||
|
||||
#endif
|
||||
(cmd >= SIOCDEVPRIVATE &&
|
||||
cmd <= SIOCDEVPRIVATE + 15)) {
|
||||
dev_load(net, ifr.ifr_name);
|
||||
|
||||
Reference in New Issue
Block a user