summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2019-02-13 20:31:47 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2019-02-13 20:31:47 +0100
commit2a17e75a976d11c1712972d29813094b8020ac35 (patch)
treeea0e991c927752937803d72a5411f7159365aa83 /drivers/net
parenta5f75fe8175aefec5b7cefaadc5359096c8eb22c (diff)
parent7185b353c96e1e831533eeaaada06ad9bebf84a2 (diff)
downloadbarebox-2a17e75a976d11c1712972d29813094b8020ac35.tar.gz
barebox-2a17e75a976d11c1712972d29813094b8020ac35.tar.xz
Merge branch 'for-next/misc'
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/designware.c42
-rw-r--r--drivers/net/phy/micrel.c32
2 files changed, 65 insertions, 9 deletions
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 3c9bca981c..0ee6d3d78a 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -328,24 +328,48 @@ static int dwc_ether_rx(struct eth_device *dev)
u32 status = desc_p->txrx_status;
int length = 0;
+ int ret = 0;
/* Check if the owner is the CPU */
if (status & DESC_RXSTS_OWNBYDMA)
return 0;
- length = (status & DESC_RXSTS_FRMLENMSK) >>
- DESC_RXSTS_FRMLENSHFT;
+ if ((status & (DESC_RXSTS_ERROR | DESC_RXSTS_DAFILTERFAIL |
+ DESC_RXSTS_SAFILTERFAIL)) ||
+ (status & (DESC_RXSTS_RXIPC_GIANTFRAME |
+ DESC_RXSTS_RXFRAMEETHER)) ==
+ DESC_RXSTS_RXIPC_GIANTFRAME) {
+ /* Error in packet - discard it */
+ dev_warn(&dev->dev, "Rx error status (%x)\n",
+ status & (DESC_RXSTS_DAFILTERFAIL |
+ DESC_RXSTS_ERROR |
+ DESC_RXSTS_RXTRUNCATED |
+ DESC_RXSTS_SAFILTERFAIL |
+ DESC_RXSTS_RXIPC_GIANTFRAME |
+ DESC_RXSTS_RXDAMAGED |
+ DESC_RXSTS_RXIPC_GIANT |
+ DESC_RXSTS_RXCOLLISION |
+ DESC_RXSTS_RXFRAMEETHER |
+ DESC_RXSTS_RXWATCHDOG |
+ DESC_RXSTS_RXMIIERROR |
+ DESC_RXSTS_RXCRC));
+ ret = -EIO;
+ } else {
+ length = (status & DESC_RXSTS_FRMLENMSK) >>
+ DESC_RXSTS_FRMLENSHFT;
+
+ dma_sync_single_for_cpu((unsigned long)desc_p->dmamac_addr,
+ length, DMA_FROM_DEVICE);
+ net_receive(dev, desc_p->dmamac_addr, length);
+ dma_sync_single_for_device((unsigned long)desc_p->dmamac_addr,
+ length, DMA_FROM_DEVICE);
+ ret = length;
+ }
/*
* Make the current descriptor valid again and go to
* the next one
*/
- dma_sync_single_for_cpu((unsigned long)desc_p->dmamac_addr, length,
- DMA_FROM_DEVICE);
- net_receive(dev, desc_p->dmamac_addr, length);
- dma_sync_single_for_device((unsigned long)desc_p->dmamac_addr, length,
- DMA_FROM_DEVICE);
-
desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA;
/* Test the wrap-around condition. */
@@ -354,7 +378,7 @@ static int dwc_ether_rx(struct eth_device *dev)
priv->rx_currdescnum = desc_num;
- return length;
+ return ret;
}
static void dwc_ether_halt (struct eth_device *dev)
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 67c2ca9d54..8f0b81d8fa 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -220,6 +220,7 @@ static int ksz9031_config_init(struct phy_device *phydev)
"txd2-skew-ps", "txd3-skew-ps"
};
static const char *control_skews[2] = {"txen-skew-ps", "rxdv-skew-ps"};
+ int ret;
if (!of_node && dev->parent->device_node)
of_node = dev->parent->device_node;
@@ -240,9 +241,40 @@ static int ksz9031_config_init(struct phy_device *phydev)
ksz9031_of_load_skew_values(phydev, of_node,
MII_KSZ9031RN_TX_DATA_PAD_SKEW, 4,
tx_data_skews, 4);
+
+ /* Silicon Errata Sheet (DS80000691D or DS80000692D):
+ * When the device links in the 1000BASE-T slave mode only,
+ * the optional 125MHz reference output clock (CLK125_NDO)
+ * has wide duty cycle variation.
+ *
+ * The optional CLK125_NDO clock does not meet the RGMII
+ * 45/55 percent (min/max) duty cycle requirement and therefore
+ * cannot be used directly by the MAC side for clocking
+ * applications that have setup/hold time requirements on
+ * rising and falling clock edges.
+ *
+ * Workaround:
+ * Force the phy to be the master to receive a stable clock
+ * which meets the duty cycle requirement.
+ */
+ if (of_property_read_bool(of_node, "micrel,force-master")) {
+ ret = phy_read(phydev, MII_CTRL1000);
+ if (ret < 0)
+ goto err_force_master;
+
+ /* enable master mode, config & prefer master */
+ ret |= CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER;
+ ret = phy_write(phydev, MII_CTRL1000, ret);
+ if (ret < 0)
+ goto err_force_master;
+ }
}
return ksz9031_center_flp_timing(phydev);
+
+err_force_master:
+ dev_err(dev, "failed to force the phy to master mode\n");
+ return ret;
}
#define KSZ8873MLL_GLOBAL_CONTROL_4 0x06