drivers: net: xgene: Add support RGMII TX/RX delay configuration
authorIyappan Subramanian <isubramanian@apm.com>
Mon, 26 Oct 2015 22:25:15 +0000 (15:25 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 30 Oct 2015 03:21:51 +0000 (12:21 +0900)
Add RGMII TX/RX delay configuration support. RGMII standard requires 2ns
delay to help the RGMII bridge receiver to sample data correctly. If the
default value does not provide proper centering of the data sample, the
TX/RX delay parameters can be used to adjust accordingly.

Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
drivers/net/ethernet/apm/xgene/xgene_enet_main.c
drivers/net/ethernet/apm/xgene/xgene_enet_main.h

index 652f21889a485321ef0c9895e1c063529697a9fc..33850a0f7e823b08a322cd53107904da7d1f78da 100644 (file)
@@ -461,6 +461,7 @@ static void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
 
 static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
 {
+       struct device *dev = &pdata->pdev->dev;
        u32 value, mc2;
        u32 intf_ctl, rgmii;
        u32 icm0, icm2;
@@ -490,7 +491,12 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
        default:
                ENET_INTERFACE_MODE2_SET(&mc2, 2);
                intf_ctl |= ENET_GHD_MODE;
-               CFG_TXCLK_MUXSEL0_SET(&rgmii, 4);
+
+               if (dev->of_node) {
+                       CFG_TXCLK_MUXSEL0_SET(&rgmii, pdata->tx_delay);
+                       CFG_RXCLK_MUXSEL0_SET(&rgmii, pdata->rx_delay);
+               }
+
                xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, &value);
                value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
                xgene_enet_wr_csr(pdata, DEBUG_REG_ADDR, value);
index ff05bbcff26dc94feccd898faca2a381cbeef7c4..6dee73c3c1e132a7be7387e6e72be7c9b5239afe 100644 (file)
@@ -144,6 +144,7 @@ enum xgene_enet_rm {
 #define CFG_BYPASS_UNISEC_RX           BIT(1)
 #define CFG_CLE_BYPASS_EN0             BIT(31)
 #define CFG_TXCLK_MUXSEL0_SET(dst, val)        xgene_set_bits(dst, val, 29, 3)
+#define CFG_RXCLK_MUXSEL0_SET(dst, val)        xgene_set_bits(dst, val, 26, 3)
 
 #define CFG_CLE_IP_PROTOCOL0_SET(dst, val)     xgene_set_bits(dst, val, 16, 2)
 #define CFG_CLE_DSTQID0_SET(dst, val)          xgene_set_bits(dst, val, 0, 12)
index 6b1846df7b0c68f7874f7e69863caf57f6fa46bf..ce1068771b327e711fd1723065f9f3ad3c5dadc3 100644 (file)
@@ -1118,6 +1118,47 @@ static int xgene_get_port_id_dt(struct device *dev, struct xgene_enet_pdata *pda
        return ret;
 }
 
+static int xgene_get_tx_delay(struct xgene_enet_pdata *pdata)
+{
+       struct device *dev = &pdata->pdev->dev;
+       int delay, ret;
+
+       ret = of_property_read_u32(dev->of_node, "tx-delay", &delay);
+       if (ret) {
+               pdata->tx_delay = 4;
+               return 0;
+       }
+
+       if (delay < 0 || delay > 7) {
+               dev_err(dev, "Invalid tx-delay specified\n");
+               return -EINVAL;
+       }
+
+       pdata->tx_delay = delay;
+
+       return 0;
+}
+
+static int xgene_get_rx_delay(struct xgene_enet_pdata *pdata)
+{
+       struct device *dev = &pdata->pdev->dev;
+       int delay, ret;
+
+       ret = of_property_read_u32(dev->of_node, "rx-delay", &delay);
+       if (ret) {
+               pdata->rx_delay = 2;
+               return 0;
+       }
+
+       if (delay < 0 || delay > 7) {
+               dev_err(dev, "Invalid rx-delay specified\n");
+               return -EINVAL;
+       }
+
+       pdata->rx_delay = delay;
+
+       return 0;
+}
 
 static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
 {
@@ -1194,6 +1235,14 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
                return -ENODEV;
        }
 
+       ret = xgene_get_tx_delay(pdata);
+       if (ret)
+               return ret;
+
+       ret = xgene_get_rx_delay(pdata);
+       if (ret)
+               return ret;
+
        ret = platform_get_irq(pdev, 0);
        if (ret <= 0) {
                dev_err(dev, "Unable to get ENET Rx IRQ\n");
index ff89a5d98d01c639ed063312261dbf39f8dc6fbd..a6e56b88c0a07a6bee7a1f0e6a050db802e5e989 100644 (file)
@@ -184,6 +184,8 @@ struct xgene_enet_pdata {
        u8 bp_bufnum;
        u16 ring_num;
        u32 mss;
+       u8 tx_delay;
+       u8 rx_delay;
 };
 
 struct xgene_indirect_ctl {