summaryrefslogtreecommitdiff
path: root/drivers/net/fec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/fec.c')
-rwxr-xr-xdrivers/net/fec.c73
1 files changed, 60 insertions, 13 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 1ae6cb0f0210..b1fa4647f911 100755
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -156,6 +156,13 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
#define PKT_MINBUF_SIZE 64
#define PKT_MAXBLR_SIZE 1520
+/* Pause frame feild and FIFO threshold */
+#define FEC_ENET_FCE (1 << 5)
+#define FEC_ENET_RSEM_V 0x84
+#define FEC_ENET_RSFL_V 16
+#define FEC_ENET_RAEM_V 0x8
+#define FEC_ENET_RAFL_V 0x8
+#define FEC_ENET_OPD_V 0xFFF0
/*
* The 5270/5271/5280/5282/532x RX control register also contains maximum frame
@@ -1449,6 +1456,28 @@ static const struct net_device_ops fec_netdev_ops = {
#endif
};
+/* Init TX buffer descriptors
+ */
+static void fec_enet_txbd_init(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ struct bufdesc *bdp;
+ int i;
+
+ /* ...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++;
+ }
+
+ /* Set the last buffer to wrap */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+}
+
/*
* XXX: We need to clean up on failure exits here.
*
@@ -1505,19 +1534,8 @@ static int fec_enet_init(struct net_device *ndev)
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;
+ /* Init transmit descriptors */
+ fec_enet_txbd_init(ndev);
fec_restart(ndev, 0);
@@ -1568,6 +1586,8 @@ fec_restart(struct net_device *dev, int duplex)
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);
+ /* Reinit transmit descriptors */
+ fec_enet_txbd_init(dev);
fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
fep->cur_rx = fep->rx_bd_base;
@@ -1617,6 +1637,16 @@ fec_restart(struct net_device *dev, int duplex)
else
val |= (1 << 9);
+ /* Enable pause frame
+ * ENET pause frame has two issues as ticket TKT116501
+ * The issues have been fixed on Rigel TO1.1 and Arik TO1.2
+ */
+ if ((cpu_is_mx6q() &&
+ (mx6q_revision() >= IMX_CHIP_REVISION_1_2)) ||
+ (cpu_is_mx6dl() &&
+ (mx6dl_revision() >= IMX_CHIP_REVISION_1_1)))
+ val |= FEC_ENET_FCE;
+
writel(val, fep->hwp + FEC_R_CNTRL);
}
@@ -1670,6 +1700,23 @@ fec_restart(struct net_device *dev, int duplex)
fep->phy_dev->speed == SPEED_1000)
val |= (0x1 << 5);
+ /* RX FIFO threshold setting for ENET pause frame feature
+ * Only set the parameters after ticket TKT116501 fixed.
+ * The issue has been fixed on Rigel TO1.1 and Arik TO1.2
+ */
+ if ((cpu_is_mx6q() &&
+ (mx6q_revision() >= IMX_CHIP_REVISION_1_2)) ||
+ (cpu_is_mx6dl() &&
+ (mx6dl_revision() >= IMX_CHIP_REVISION_1_1))) {
+ writel(FEC_ENET_RSEM_V, fep->hwp + FEC_R_FIFO_RSEM);
+ writel(FEC_ENET_RSFL_V, fep->hwp + FEC_R_FIFO_RSFL);
+ writel(FEC_ENET_RAEM_V, fep->hwp + FEC_R_FIFO_RAEM);
+ writel(FEC_ENET_RAFL_V, fep->hwp + FEC_R_FIFO_RAFL);
+
+ /* OPD */
+ writel(FEC_ENET_OPD_V, fep->hwp + FEC_OPD);
+ }
+
if (cpu_is_mx6q() || cpu_is_mx6dl()) {
/* enable endian swap */
val |= (0x1 << 8);