drivers: net: xgene: fix RGMII 10/100Mb mode
authorIyappan Subramanian <isubramanian@apm.com>
Sat, 7 Nov 2015 19:50:40 +0000 (11:50 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 9 Nov 2015 02:00:20 +0000 (21:00 -0500)
This patch fixes the RGMII 10/100M mode by reprogramming the clock.

Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Tested-by: Fushen Chen <fchen@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

index 33850a0f7e823b08a322cd53107904da7d1f78da..c31e691d11fc2eb5b786fc3769f700563f63a0da 100644 (file)
@@ -459,6 +459,45 @@ static void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
        xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0);
 }
 
+static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata)
+{
+       struct device *dev = &pdata->pdev->dev;
+
+       if (dev->of_node) {
+               struct clk *parent = clk_get_parent(pdata->clk);
+
+               switch (pdata->phy_speed) {
+               case SPEED_10:
+                       clk_set_rate(parent, 2500000);
+                       break;
+               case SPEED_100:
+                       clk_set_rate(parent, 25000000);
+                       break;
+               default:
+                       clk_set_rate(parent, 125000000);
+                       break;
+               }
+       }
+#ifdef CONFIG_ACPI
+       else {
+               switch (pdata->phy_speed) {
+               case SPEED_10:
+                       acpi_evaluate_object(ACPI_HANDLE(dev),
+                                            "S10", NULL, NULL);
+                       break;
+               case SPEED_100:
+                       acpi_evaluate_object(ACPI_HANDLE(dev),
+                                            "S100", NULL, NULL);
+                       break;
+               default:
+                       acpi_evaluate_object(ACPI_HANDLE(dev),
+                                            "S1G", NULL, NULL);
+                       break;
+               }
+       }
+#endif
+}
+
 static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
 {
        struct device *dev = &pdata->pdev->dev;
@@ -477,12 +516,14 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
        switch (pdata->phy_speed) {
        case SPEED_10:
                ENET_INTERFACE_MODE2_SET(&mc2, 1);
+               intf_ctl &= ~(ENET_LHD_MODE | ENET_GHD_MODE);
                CFG_MACMODE_SET(&icm0, 0);
                CFG_WAITASYNCRD_SET(&icm2, 500);
                rgmii &= ~CFG_SPEED_1250;
                break;
        case SPEED_100:
                ENET_INTERFACE_MODE2_SET(&mc2, 1);
+               intf_ctl &= ~ENET_GHD_MODE;
                intf_ctl |= ENET_LHD_MODE;
                CFG_MACMODE_SET(&icm0, 1);
                CFG_WAITASYNCRD_SET(&icm2, 80);
@@ -490,12 +531,15 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
                break;
        default:
                ENET_INTERFACE_MODE2_SET(&mc2, 2);
+               intf_ctl &= ~ENET_LHD_MODE;
                intf_ctl |= ENET_GHD_MODE;
-
+               CFG_MACMODE_SET(&icm0, 2);
+               CFG_WAITASYNCRD_SET(&icm2, 0);
                if (dev->of_node) {
                        CFG_TXCLK_MUXSEL0_SET(&rgmii, pdata->tx_delay);
                        CFG_RXCLK_MUXSEL0_SET(&rgmii, pdata->rx_delay);
                }
+               rgmii |= CFG_SPEED_1250;
 
                xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, &value);
                value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
@@ -503,7 +547,7 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
                break;
        }
 
-       mc2 |= FULL_DUPLEX2;
+       mc2 |= FULL_DUPLEX2 | PAD_CRC;
        xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
        xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
 
@@ -522,6 +566,7 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
        /* Rtype should be copied from FP */
        xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0);
        xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
+       xgene_enet_configure_clock(pdata);
 
        /* Rx-Tx traffic resume */
        xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
index 6dee73c3c1e132a7be7387e6e72be7c9b5239afe..c153a1dc5ff78136c4fc99d1ec60970d99e095a0 100644 (file)
@@ -181,6 +181,7 @@ enum xgene_enet_rm {
 #define ENET_LHD_MODE                  BIT(25)
 #define ENET_GHD_MODE                  BIT(26)
 #define FULL_DUPLEX2                   BIT(0)
+#define PAD_CRC                                BIT(2)
 #define SCAN_AUTO_INCR                 BIT(5)
 #define TBYT_ADDR                      0x38
 #define TPKT_ADDR                      0x39
index ce1068771b327e711fd1723065f9f3ad3c5dadc3..991412ce6f48fbbf6fdfd6255003a0aa90e67e01 100644 (file)
@@ -698,7 +698,6 @@ static int xgene_enet_open(struct net_device *ndev)
        else
                schedule_delayed_work(&pdata->link_work, PHY_POLL_LINK_OFF);
 
-       netif_carrier_off(ndev);
        netif_start_queue(ndev);
 
        return ret;