These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / ethernet / apm / xgene / xgene_enet_hw.c
index b927021..c31e691 100644 (file)
@@ -87,10 +87,11 @@ static void xgene_enet_ring_rd32(struct xgene_enet_desc_ring *ring,
 
 static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring)
 {
+       struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev);
        int i;
 
        xgene_enet_ring_wr32(ring, CSR_RING_CONFIG, ring->num);
-       for (i = 0; i < NUM_RING_CONFIG; i++) {
+       for (i = 0; i < pdata->ring_ops->num_ring_config; i++) {
                xgene_enet_ring_wr32(ring, CSR_RING_WR_BASE + (i * 4),
                                     ring->state[i]);
        }
@@ -98,7 +99,7 @@ static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring)
 
 static void xgene_enet_clr_ring_state(struct xgene_enet_desc_ring *ring)
 {
-       memset(ring->state, 0, sizeof(u32) * NUM_RING_CONFIG);
+       memset(ring->state, 0, sizeof(ring->state));
        xgene_enet_write_ring_state(ring);
 }
 
@@ -106,7 +107,8 @@ static void xgene_enet_set_ring_state(struct xgene_enet_desc_ring *ring)
 {
        xgene_enet_ring_set_type(ring);
 
-       if (xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH0)
+       if (xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH0 ||
+           xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH1)
                xgene_enet_ring_set_recombbuf(ring);
 
        xgene_enet_ring_init(ring);
@@ -141,8 +143,8 @@ static void xgene_enet_clr_desc_ring_id(struct xgene_enet_desc_ring *ring)
        xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, 0);
 }
 
-struct xgene_enet_desc_ring *xgene_enet_setup_ring(
-                                       struct xgene_enet_desc_ring *ring)
+static struct xgene_enet_desc_ring *xgene_enet_setup_ring(
+                                   struct xgene_enet_desc_ring *ring)
 {
        u32 size = ring->size;
        u32 i, data;
@@ -168,7 +170,7 @@ struct xgene_enet_desc_ring *xgene_enet_setup_ring(
        return ring;
 }
 
-void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring)
+static void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring)
 {
        u32 data;
        bool is_bufpool;
@@ -186,6 +188,22 @@ out:
        xgene_enet_clr_ring_state(ring);
 }
 
+static void xgene_enet_wr_cmd(struct xgene_enet_desc_ring *ring, int count)
+{
+       iowrite32(count, ring->cmd);
+}
+
+static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring)
+{
+       u32 __iomem *cmd_base = ring->cmd_base;
+       u32 ring_state, num_msgs;
+
+       ring_state = ioread32(&cmd_base[1]);
+       num_msgs = GET_VAL(NUMMSGSINQ, ring_state);
+
+       return num_msgs;
+}
+
 void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
                            struct xgene_enet_pdata *pdata,
                            enum xgene_enet_err_code status)
@@ -441,8 +459,48 @@ 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;
        u32 value, mc2;
        u32 intf_ctl, rgmii;
        u32 icm0, icm2;
@@ -458,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);
@@ -471,15 +531,23 @@ 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_TXCLK_MUXSEL0_SET(&rgmii, 4);
+               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;
                xgene_enet_wr_csr(pdata, DEBUG_REG_ADDR, value);
                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);
 
@@ -498,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);
@@ -593,7 +662,7 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
        if (!xgene_ring_mgr_init(pdata))
                return -ENODEV;
 
-       if (pdata->clk) {
+       if (!IS_ERR(pdata->clk)) {
                clk_prepare_enable(pdata->clk);
                clk_disable_unprepare(pdata->clk);
                clk_prepare_enable(pdata->clk);
@@ -612,7 +681,8 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
 
 static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
 {
-       clk_disable_unprepare(pdata->clk);
+       if (!IS_ERR(pdata->clk))
+               clk_disable_unprepare(pdata->clk);
 }
 
 static int xgene_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
@@ -671,16 +741,24 @@ static int xgene_enet_phy_connect(struct net_device *ndev)
                        netdev_dbg(ndev, "No phy-handle found in DT\n");
                        return -ENODEV;
                }
-               pdata->phy_dev = of_phy_find_device(phy_np);
-       }
 
-       phy_dev = pdata->phy_dev;
+               phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link,
+                                        0, pdata->phy_mode);
+               if (!phy_dev) {
+                       netdev_err(ndev, "Could not connect to PHY\n");
+                       return -ENODEV;
+               }
+
+               pdata->phy_dev = phy_dev;
+       } else {
+               phy_dev = pdata->phy_dev;
 
-       if (!phy_dev ||
-           phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
-                              pdata->phy_mode)) {
-               netdev_err(ndev, "Could not connect to PHY\n");
-               return  -ENODEV;
+               if (!phy_dev ||
+                   phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
+                                      pdata->phy_mode)) {
+                       netdev_err(ndev, "Could not connect to PHY\n");
+                       return  -ENODEV;
+               }
        }
 
        pdata->phy_speed = SPEED_UNKNOWN;
@@ -734,7 +812,7 @@ static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
        if (ret)
                return -EINVAL;
 
-       phy = get_phy_device(mdio, phy_id, true);
+       phy = get_phy_device(mdio, phy_id, false);
        if (!phy || IS_ERR(phy))
                return -EIO;
 
@@ -783,6 +861,9 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
 
 void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
 {
+       if (pdata->phy_dev)
+               phy_disconnect(pdata->phy_dev);
+
        mdiobus_unregister(pdata->mdio_bus);
        mdiobus_free(pdata->mdio_bus);
        pdata->mdio_bus = NULL;
@@ -803,3 +884,12 @@ struct xgene_port_ops xgene_gport_ops = {
        .cle_bypass = xgene_enet_cle_bypass,
        .shutdown = xgene_gport_shutdown,
 };
+
+struct xgene_ring_ops xgene_ring1_ops = {
+       .num_ring_config = NUM_RING_CONFIG,
+       .num_ring_id_shift = 6,
+       .setup = xgene_enet_setup_ring,
+       .clear = xgene_enet_clear_ring,
+       .wr_cmd = xgene_enet_wr_cmd,
+       .len = xgene_enet_ring_len,
+};