Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[cascardo/linux.git] / drivers / net / ethernet / mediatek / mtk_eth_soc.c
index 481f360..4cc50c0 100644 (file)
@@ -52,7 +52,7 @@ static const struct mtk_ethtool_stats {
 };
 
 static const char * const mtk_clks_source_name[] = {
-       "ethif", "esw", "gp1", "gp2"
+       "ethif", "esw", "gp1", "gp2", "trgpll"
 };
 
 void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
@@ -135,6 +135,33 @@ static int mtk_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
        return _mtk_mdio_read(eth, phy_addr, phy_reg);
 }
 
+static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth, int speed)
+{
+       u32 val;
+       int ret;
+
+       val = (speed == SPEED_1000) ?
+               INTF_MODE_RGMII_1000 : INTF_MODE_RGMII_10_100;
+       mtk_w32(eth, val, INTF_MODE);
+
+       regmap_update_bits(eth->ethsys, ETHSYS_CLKCFG0,
+                          ETHSYS_TRGMII_CLK_SEL362_5,
+                          ETHSYS_TRGMII_CLK_SEL362_5);
+
+       val = (speed == SPEED_1000) ? 250000000 : 500000000;
+       ret = clk_set_rate(eth->clks[MTK_CLK_TRGPLL], val);
+       if (ret)
+               dev_err(eth->dev, "Failed to set trgmii pll: %d\n", ret);
+
+       val = (speed == SPEED_1000) ?
+               RCK_CTRL_RGMII_1000 : RCK_CTRL_RGMII_10_100;
+       mtk_w32(eth, val, TRGMII_RCK_CTRL);
+
+       val = (speed == SPEED_1000) ?
+               TCK_CTRL_RGMII_1000 : TCK_CTRL_RGMII_10_100;
+       mtk_w32(eth, val, TRGMII_TCK_CTRL);
+}
+
 static void mtk_phy_link_adjust(struct net_device *dev)
 {
        struct mtk_mac *mac = netdev_priv(dev);
@@ -148,7 +175,7 @@ static void mtk_phy_link_adjust(struct net_device *dev)
        if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
                return;
 
-       switch (mac->phy_dev->speed) {
+       switch (dev->phydev->speed) {
        case SPEED_1000:
                mcr |= MAC_MCR_SPEED_1000;
                break;
@@ -157,20 +184,23 @@ static void mtk_phy_link_adjust(struct net_device *dev)
                break;
        };
 
-       if (mac->phy_dev->link)
+       if (mac->id == 0 && !mac->trgmii)
+               mtk_gmac0_rgmii_adjust(mac->hw, dev->phydev->speed);
+
+       if (dev->phydev->link)
                mcr |= MAC_MCR_FORCE_LINK;
 
-       if (mac->phy_dev->duplex) {
+       if (dev->phydev->duplex) {
                mcr |= MAC_MCR_FORCE_DPX;
 
-               if (mac->phy_dev->pause)
+               if (dev->phydev->pause)
                        rmt_adv = LPA_PAUSE_CAP;
-               if (mac->phy_dev->asym_pause)
+               if (dev->phydev->asym_pause)
                        rmt_adv |= LPA_PAUSE_ASYM;
 
-               if (mac->phy_dev->advertising & ADVERTISED_Pause)
+               if (dev->phydev->advertising & ADVERTISED_Pause)
                        lcl_adv |= ADVERTISE_PAUSE_CAP;
-               if (mac->phy_dev->advertising & ADVERTISED_Asym_Pause)
+               if (dev->phydev->advertising & ADVERTISED_Asym_Pause)
                        lcl_adv |= ADVERTISE_PAUSE_ASYM;
 
                flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
@@ -187,7 +217,7 @@ static void mtk_phy_link_adjust(struct net_device *dev)
 
        mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
 
-       if (mac->phy_dev->link)
+       if (dev->phydev->link)
                netif_carrier_on(dev);
        else
                netif_carrier_off(dev);
@@ -196,17 +226,9 @@ static void mtk_phy_link_adjust(struct net_device *dev)
 static int mtk_phy_connect_node(struct mtk_eth *eth, struct mtk_mac *mac,
                                struct device_node *phy_node)
 {
-       const __be32 *_addr = NULL;
        struct phy_device *phydev;
-       int phy_mode, addr;
+       int phy_mode;
 
-       _addr = of_get_property(phy_node, "reg", NULL);
-
-       if (!_addr || (be32_to_cpu(*_addr) >= 0x20)) {
-               pr_err("%s: invalid phy address\n", phy_node->name);
-               return -EINVAL;
-       }
-       addr = be32_to_cpu(*_addr);
        phy_mode = of_get_phy_mode(phy_node);
        if (phy_mode < 0) {
                dev_err(eth->dev, "incorrect phy-mode %d\n", phy_mode);
@@ -225,17 +247,17 @@ static int mtk_phy_connect_node(struct mtk_eth *eth, struct mtk_mac *mac,
                 mac->id, phydev_name(phydev), phydev->phy_id,
                 phydev->drv->name);
 
-       mac->phy_dev = phydev;
-
        return 0;
 }
 
-static int mtk_phy_connect(struct mtk_mac *mac)
+static int mtk_phy_connect(struct net_device *dev)
 {
-       struct mtk_eth *eth = mac->hw;
+       struct mtk_mac *mac = netdev_priv(dev);
+       struct mtk_eth *eth;
        struct device_node *np;
        u32 val;
 
+       eth = mac->hw;
        np = of_parse_phandle(mac->of_node, "phy-handle", 0);
        if (!np && of_phy_is_fixed_link(mac->of_node))
                if (!of_phy_register_fixed_link(mac->of_node))
@@ -244,6 +266,8 @@ static int mtk_phy_connect(struct mtk_mac *mac)
                return -ENODEV;
 
        switch (of_get_phy_mode(np)) {
+       case PHY_INTERFACE_MODE_TRGMII:
+               mac->trgmii = true;
        case PHY_INTERFACE_MODE_RGMII_TXID:
        case PHY_INTERFACE_MODE_RGMII_RXID:
        case PHY_INTERFACE_MODE_RGMII_ID:
@@ -271,20 +295,23 @@ static int mtk_phy_connect(struct mtk_mac *mac)
        val |= SYSCFG0_GE_MODE(mac->ge_mode, mac->id);
        regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
 
-       mtk_phy_connect_node(eth, mac, np);
-       mac->phy_dev->autoneg = AUTONEG_ENABLE;
-       mac->phy_dev->speed = 0;
-       mac->phy_dev->duplex = 0;
+       /* couple phydev to net_device */
+       if (mtk_phy_connect_node(eth, mac, np))
+               goto err_phy;
+
+       dev->phydev->autoneg = AUTONEG_ENABLE;
+       dev->phydev->speed = 0;
+       dev->phydev->duplex = 0;
 
        if (of_phy_is_fixed_link(mac->of_node))
-               mac->phy_dev->supported |=
+               dev->phydev->supported |=
                SUPPORTED_Pause | SUPPORTED_Asym_Pause;
 
-       mac->phy_dev->supported &= PHY_GBIT_FEATURES | SUPPORTED_Pause |
+       dev->phydev->supported &= PHY_GBIT_FEATURES | SUPPORTED_Pause |
                                   SUPPORTED_Asym_Pause;
-       mac->phy_dev->advertising = mac->phy_dev->supported |
+       dev->phydev->advertising = dev->phydev->supported |
                                    ADVERTISED_Autoneg;
-       phy_start_aneg(mac->phy_dev);
+       phy_start_aneg(dev->phydev);
 
        of_node_put(np);
 
@@ -292,7 +319,7 @@ static int mtk_phy_connect(struct mtk_mac *mac)
 
 err_phy:
        of_node_put(np);
-       dev_err(eth->dev, "invalid phy_mode\n");
+       dev_err(eth->dev, "%s: invalid phy\n", __func__);
        return -EINVAL;
 }
 
@@ -1710,7 +1737,7 @@ static int mtk_open(struct net_device *dev)
        }
        atomic_inc(&eth->dma_refcnt);
 
-       phy_start(mac->phy_dev);
+       phy_start(dev->phydev);
        netif_start_queue(dev);
 
        return 0;
@@ -1745,7 +1772,7 @@ static int mtk_stop(struct net_device *dev)
        struct mtk_eth *eth = mac->hw;
 
        netif_tx_disable(dev);
-       phy_stop(mac->phy_dev);
+       phy_stop(dev->phydev);
 
        /* only shutdown DMA if this is the last user */
        if (!atomic_dec_and_test(&eth->dma_refcnt))
@@ -1885,7 +1912,7 @@ static int __init mtk_init(struct net_device *dev)
                dev->addr_assign_type = NET_ADDR_RANDOM;
        }
 
-       return mtk_phy_connect(mac);
+       return mtk_phy_connect(dev);
 }
 
 static void mtk_uninit(struct net_device *dev)
@@ -1893,23 +1920,18 @@ static void mtk_uninit(struct net_device *dev)
        struct mtk_mac *mac = netdev_priv(dev);
        struct mtk_eth *eth = mac->hw;
 
-       phy_disconnect(mac->phy_dev);
-       mtk_mdio_cleanup(eth);
+       phy_disconnect(dev->phydev);
        mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0);
        mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0);
-       free_irq(eth->irq[1], dev);
-       free_irq(eth->irq[2], dev);
 }
 
 static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-       struct mtk_mac *mac = netdev_priv(dev);
-
        switch (cmd) {
        case SIOCGMIIPHY:
        case SIOCGMIIREG:
        case SIOCSMIIREG:
-               return phy_mii_ioctl(mac->phy_dev, ifr, cmd);
+               return phy_mii_ioctl(dev->phydev, ifr, cmd);
        default:
                break;
        }
@@ -1954,7 +1976,7 @@ static void mtk_pending_work(struct work_struct *work)
                if (!eth->mac[i] ||
                    of_phy_is_fixed_link(eth->mac[i]->of_node))
                        continue;
-               err = phy_init_hw(eth->mac[i]->phy_dev);
+               err = phy_init_hw(eth->netdev[i]->phydev);
                if (err)
                        dev_err(eth->dev, "%s: PHY init failed.\n",
                                eth->netdev[i]->name);
@@ -2014,35 +2036,26 @@ static int mtk_cleanup(struct mtk_eth *eth)
        return 0;
 }
 
-static int mtk_get_settings(struct net_device *dev,
-                           struct ethtool_cmd *cmd)
+int mtk_get_link_ksettings(struct net_device *ndev,
+                          struct ethtool_link_ksettings *cmd)
 {
-       struct mtk_mac *mac = netdev_priv(dev);
-       int err;
+       struct mtk_mac *mac = netdev_priv(ndev);
 
        if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
                return -EBUSY;
 
-       err = phy_read_status(mac->phy_dev);
-       if (err)
-               return -ENODEV;
-
-       return phy_ethtool_gset(mac->phy_dev, cmd);
+       return phy_ethtool_ksettings_get(ndev->phydev, cmd);
 }
 
-static int mtk_set_settings(struct net_device *dev,
-                           struct ethtool_cmd *cmd)
+int mtk_set_link_ksettings(struct net_device *ndev,
+                          const struct ethtool_link_ksettings *cmd)
 {
-       struct mtk_mac *mac = netdev_priv(dev);
+       struct mtk_mac *mac = netdev_priv(ndev);
 
-       if (cmd->phy_address != mac->phy_dev->mdio.addr) {
-               mac->phy_dev = mdiobus_get_phy(mac->hw->mii_bus,
-                                              cmd->phy_address);
-               if (!mac->phy_dev)
-                       return -ENODEV;
-       }
+       if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
+               return -EBUSY;
 
-       return phy_ethtool_sset(mac->phy_dev, cmd);
+       return phy_ethtool_ksettings_set(ndev->phydev, cmd);
 }
 
 static void mtk_get_drvinfo(struct net_device *dev,
@@ -2076,7 +2089,7 @@ static int mtk_nway_reset(struct net_device *dev)
        if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
                return -EBUSY;
 
-       return genphy_restart_aneg(mac->phy_dev);
+       return genphy_restart_aneg(dev->phydev);
 }
 
 static u32 mtk_get_link(struct net_device *dev)
@@ -2087,11 +2100,11 @@ static u32 mtk_get_link(struct net_device *dev)
        if (unlikely(test_bit(MTK_RESETTING, &mac->hw->state)))
                return -EBUSY;
 
-       err = genphy_update_link(mac->phy_dev);
+       err = genphy_update_link(dev->phydev);
        if (err)
                return ethtool_op_get_link(dev);
 
-       return mac->phy_dev->link;
+       return dev->phydev->link;
 }
 
 static void mtk_get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@ -2137,8 +2150,9 @@ static void mtk_get_ethtool_stats(struct net_device *dev,
                }
        }
 
+       data_src = (u64 *)hwstats;
+
        do {
-               data_src = (u64 *)hwstats;
                data_dst = data;
                start = u64_stats_fetch_begin_irq(&hwstats->syncp);
 
@@ -2204,8 +2218,8 @@ static int mtk_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
 }
 
 static const struct ethtool_ops mtk_ethtool_ops = {
-       .get_settings           = mtk_get_settings,
-       .set_settings           = mtk_set_settings,
+       .get_link_ksettings     = mtk_get_link_ksettings,
+       .set_link_ksettings     = mtk_set_link_ksettings,
        .get_drvinfo            = mtk_get_drvinfo,
        .get_msglevel           = mtk_get_msglevel,
        .set_msglevel           = mtk_set_msglevel,
@@ -2453,6 +2467,7 @@ static int mtk_remove(struct platform_device *pdev)
        netif_napi_del(&eth->tx_napi);
        netif_napi_del(&eth->rx_napi);
        mtk_cleanup(eth);
+       mtk_mdio_cleanup(eth);
 
        return 0;
 }
@@ -2461,6 +2476,7 @@ const struct of_device_id of_mtk_match[] = {
        { .compatible = "mediatek,mt7623-eth" },
        {},
 };
+MODULE_DEVICE_TABLE(of, of_mtk_match);
 
 static struct platform_driver mtk_driver = {
        .probe = mtk_probe,