layerscape: add patches-5.4
[openwrt/staging/wigyori.git] / target / linux / layerscape / patches-5.4 / 701-net-0368-Revert-net-dsa-felix-Add-PCS-operations-for-PHYLINK.patch
diff --git a/target/linux/layerscape/patches-5.4/701-net-0368-Revert-net-dsa-felix-Add-PCS-operations-for-PHYLINK.patch b/target/linux/layerscape/patches-5.4/701-net-0368-Revert-net-dsa-felix-Add-PCS-operations-for-PHYLINK.patch
new file mode 100644 (file)
index 0000000..ea01a8b
--- /dev/null
@@ -0,0 +1,440 @@
+From 9ee918eb911853c7b46cd84779d857988366e845 Mon Sep 17 00:00:00 2001
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+Date: Mon, 6 Jan 2020 14:30:24 +0200
+Subject: [PATCH] Revert "net: dsa: felix: Add PCS operations for PHYLINK"
+
+This reverts commit 1082a3ef9e832cc52c4b0053c7c52453376f4830.
+
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+---
+ drivers/net/dsa/ocelot/felix.c         |  23 +--
+ drivers/net/dsa/ocelot/felix.h         |   7 +-
+ drivers/net/dsa/ocelot/felix_vsc9959.c | 292 +--------------------------------
+ 3 files changed, 8 insertions(+), 314 deletions(-)
+
+--- a/drivers/net/dsa/ocelot/felix.c
++++ b/drivers/net/dsa/ocelot/felix.c
+@@ -265,7 +265,7 @@ static int felix_get_ts_info(struct dsa_
+ static int felix_init_structs(struct felix *felix, int num_phys_ports)
+ {
+       struct ocelot *ocelot = &felix->ocelot;
+-      resource_size_t switch_base;
++      resource_size_t base;
+       int port, i, err;
+       ocelot->num_phys_ports = num_phys_ports;
+@@ -281,8 +281,7 @@ static int felix_init_structs(struct fel
+       ocelot->ops             = felix->info->ops;
+       ocelot->quirks          = felix->info->quirks;
+-      switch_base = pci_resource_start(felix->pdev,
+-                                       felix->info->switch_pci_bar);
++      base = pci_resource_start(felix->pdev, felix->info->pci_bar);
+       for (i = 0; i < TARGET_MAX; i++) {
+               struct regmap *target;
+@@ -293,8 +292,8 @@ static int felix_init_structs(struct fel
+               res = &felix->info->target_io_res[i];
+               res->flags = IORESOURCE_MEM;
+-              res->start += switch_base;
+-              res->end += switch_base;
++              res->start += base;
++              res->end += base;
+               target = ocelot_regmap_init(ocelot, res);
+               if (IS_ERR(target)) {
+@@ -328,8 +327,8 @@ static int felix_init_structs(struct fel
+               res = &felix->info->port_io_res[port];
+               res->flags = IORESOURCE_MEM;
+-              res->start += switch_base;
+-              res->end += switch_base;
++              res->start += base;
++              res->end += base;
+               port_regs = devm_ioremap_resource(ocelot->dev, res);
+               if (IS_ERR(port_regs)) {
+@@ -343,12 +342,6 @@ static int felix_init_structs(struct fel
+               ocelot->ports[port] = ocelot_port;
+       }
+-      if (felix->info->mdio_bus_alloc) {
+-              err = felix->info->mdio_bus_alloc(ocelot);
+-              if (err < 0)
+-                      return err;
+-      }
+-
+       return 0;
+ }
+@@ -384,10 +377,6 @@ static int felix_setup(struct dsa_switch
+ static void felix_teardown(struct dsa_switch *ds)
+ {
+       struct ocelot *ocelot = ds->priv;
+-      struct felix *felix = ocelot_to_felix(ocelot);
+-
+-      if (felix->imdio)
+-              mdiobus_unregister(felix->imdio);
+       /* stop workqueue thread */
+       ocelot_deinit(ocelot);
+--- a/drivers/net/dsa/ocelot/felix.h
++++ b/drivers/net/dsa/ocelot/felix.h
+@@ -10,7 +10,6 @@
+ struct felix_info {
+       struct resource                 *target_io_res;
+       struct resource                 *port_io_res;
+-      struct resource                 *imdio_res;
+       const struct reg_field          *regfields;
+       const u32 *const                *map;
+       const struct ocelot_ops         *ops;
+@@ -18,10 +17,8 @@ struct felix_info {
+       const struct ocelot_stat_layout *stats_layout;
+       unsigned int                    num_stats;
+       int                             num_ports;
+-      int                             switch_pci_bar;
+-      int                             imdio_pci_bar;
++      int                             pci_bar;
+       unsigned long                   quirks;
+-      int (*mdio_bus_alloc)(struct ocelot *ocelot);
+ };
+ extern struct felix_info              felix_info_vsc9959;
+@@ -36,8 +33,6 @@ struct felix {
+       struct pci_dev                  *pdev;
+       struct felix_info               *info;
+       struct ocelot                   ocelot;
+-      struct mii_bus                  *imdio;
+-      struct phy_device               **pcs;
+ };
+ #endif
+--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
++++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
+@@ -2,7 +2,6 @@
+ /* Copyright 2017 Microsemi Corporation
+  * Copyright 2018-2019 NXP Semiconductors
+  */
+-#include <linux/fsl/enetc_mdio.h>
+ #include <soc/mscc/ocelot_sys.h>
+ #include <soc/mscc/ocelot.h>
+ #include <linux/iopoll.h>
+@@ -391,15 +390,6 @@ static struct resource vsc9959_port_io_r
+       },
+ };
+-/* Port MAC 0 Internal MDIO bus through which the SerDes acting as an
+- * SGMII/QSGMII MAC PCS can be found.
+- */
+-static struct resource vsc9959_imdio_res = {
+-      .start          = 0x8030,
+-      .end            = 0x8040,
+-      .name           = "imdio",
+-};
+-
+ static const struct reg_field vsc9959_regfields[] = {
+       [ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 6, 6),
+       [ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 5),
+@@ -579,291 +569,13 @@ static int vsc9959_reset(struct ocelot *
+       return 0;
+ }
+-void vsc9959_pcs_validate(struct ocelot *ocelot, int port,
+-                        unsigned long *supported,
+-                        struct phylink_link_state *state)
+-{
+-      __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+-
+-      if (state->interface != PHY_INTERFACE_MODE_NA &&
+-          state->interface != PHY_INTERFACE_MODE_GMII &&
+-          state->interface != PHY_INTERFACE_MODE_SGMII &&
+-          state->interface != PHY_INTERFACE_MODE_QSGMII &&
+-          state->interface != PHY_INTERFACE_MODE_USXGMII) {
+-              bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
+-              return;
+-      }
+-
+-      /* No half-duplex. */
+-      phylink_set_port_modes(mask);
+-      phylink_set(mask, Autoneg);
+-      phylink_set(mask, Pause);
+-      phylink_set(mask, Asym_Pause);
+-      phylink_set(mask, 10baseT_Full);
+-      phylink_set(mask, 100baseT_Full);
+-      phylink_set(mask, 1000baseT_Full);
+-      phylink_set(mask, 1000baseX_Full);
+-      phylink_set(mask, 2500baseT_Full);
+-      phylink_set(mask, 2500baseX_Full);
+-      phylink_set(mask, 1000baseKX_Full);
+-
+-      bitmap_and(supported, supported, mask,
+-                 __ETHTOOL_LINK_MODE_MASK_NBITS);
+-      bitmap_and(state->advertising, state->advertising, mask,
+-                 __ETHTOOL_LINK_MODE_MASK_NBITS);
+-}
+-
+-static void vsc9959_pcs_an_restart(struct ocelot *ocelot, int port)
+-{
+-      struct felix *felix = ocelot_to_felix(ocelot);
+-      struct phy_device *pcs = felix->pcs[port];
+-
+-      if (!pcs)
+-              return;
+-
+-      phy_set_bits(pcs, MII_BMCR, BMCR_ANRESTART);
+-}
+-
+-static void vsc9959_pcs_init_sgmii(struct phy_device *pcs,
+-                                 unsigned int link_an_mode,
+-                                 const struct phylink_link_state *state)
+-{
+-      /* SGMII spec requires tx_config_Reg[15:0] to be exactly 0x4001
+-       * for the MAC PCS in order to acknowledge the AN.
+-       */
+-      phy_write(pcs, MII_ADVERTISE, ADVERTISE_SGMII | ADVERTISE_LPACK);
+-
+-      /* Set to SGMII mode, use AN */
+-      phy_write(pcs, ENETC_PCS_IF_MODE, ENETC_PCS_IF_MODE_SGMII_AN);
+-
+-      /* Adjust link timer for SGMII */
+-      phy_write(pcs, ENETC_PCS_LINK_TIMER1, ENETC_PCS_LINK_TIMER1_VAL);
+-      phy_write(pcs, ENETC_PCS_LINK_TIMER2, ENETC_PCS_LINK_TIMER2_VAL);
+-
+-      phy_write(pcs, MII_BMCR, BMCR_SPEED1000 |
+-                               BMCR_FULLDPLX |
+-                               BMCR_ANENABLE);
+-}
+-
+-#define ADVERTISE_USXGMII_FDX         BIT(12)
+-
+-static void vsc9959_pcs_init_sxgmii(struct phy_device *pcs,
+-                                  unsigned int link_an_mode,
+-                                  const struct phylink_link_state *state)
+-{
+-      /* Configure device ability for the USXGMII Replicator */
+-      phy_write_mmd(pcs, MDIO_MMD_VEND2, MII_ADVERTISE,
+-                    ADVERTISE_SGMII |
+-                    ADVERTISE_LPACK |
+-                    ADVERTISE_USXGMII_FDX);
+-}
+-
+-static void vsc9959_pcs_init(struct ocelot *ocelot, int port,
+-                           unsigned int link_an_mode,
+-                           const struct phylink_link_state *state)
+-{
+-      struct felix *felix = ocelot_to_felix(ocelot);
+-      struct phy_device *pcs = felix->pcs[port];
+-
+-      if (!pcs)
+-              return;
+-
+-      if (link_an_mode == MLO_AN_FIXED) {
+-              phydev_err(pcs, "Fixed modes are not yet supported.\n");
+-              return;
+-      }
+-
+-      pcs->interface = state->interface;
+-      if (pcs->interface == PHY_INTERFACE_MODE_USXGMII)
+-              pcs->is_c45 = true;
+-      else
+-              pcs->is_c45 = false;
+-
+-      /* The PCS does not implement the BMSR register fully, so capability
+-       * detection via genphy_read_abilities does not work. Since we can get
+-       * the PHY config word from the LPA register though, there is still
+-       * value in using the generic phy_resolve_aneg_linkmode function. So
+-       * populate the supported and advertising link modes manually here.
+-       */
+-      linkmode_set_bit_array(phy_basic_ports_array,
+-                             ARRAY_SIZE(phy_basic_ports_array),
+-                             pcs->supported);
+-      linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, pcs->supported);
+-      linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, pcs->supported);
+-      linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, pcs->supported);
+-      linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, pcs->supported);
+-      phy_advertise_supported(pcs);
+-
+-      switch (pcs->interface) {
+-      case PHY_INTERFACE_MODE_SGMII:
+-      case PHY_INTERFACE_MODE_QSGMII:
+-              vsc9959_pcs_init_sgmii(pcs, link_an_mode, state);
+-              break;
+-      case PHY_INTERFACE_MODE_USXGMII:
+-              vsc9959_pcs_init_sxgmii(pcs, link_an_mode, state);
+-              break;
+-      default:
+-              dev_err(ocelot->dev, "Unsupported link mode %s\n",
+-                      phy_modes(pcs->interface));
+-      }
+-}
+-
+-static void vsc9959_pcs_link_state(struct ocelot *ocelot, int port,
+-                                 struct phylink_link_state *state)
+-{
+-      struct felix *felix = ocelot_to_felix(ocelot);
+-      struct phy_device *pcs = felix->pcs[port];
+-      int err;
+-
+-      if (!pcs)
+-              return;
+-
+-      /* Reading PCS status not yet supported for USXGMII */
+-      if (pcs->is_c45) {
+-              state->link = 1;
+-              return;
+-      }
+-
+-      pcs->speed = SPEED_UNKNOWN;
+-      pcs->duplex = DUPLEX_UNKNOWN;
+-      pcs->pause = 0;
+-      pcs->asym_pause = 0;
+-
+-      err = genphy_update_link(pcs);
+-      if (err < 0)
+-              return;
+-
+-      if (pcs->autoneg_complete) {
+-              u16 lpa = phy_read(pcs, MII_LPA);
+-
+-              switch (state->interface) {
+-              case PHY_INTERFACE_MODE_SGMII:
+-              case PHY_INTERFACE_MODE_QSGMII:
+-                      mii_lpa_to_linkmode_lpa_sgmii(pcs->lp_advertising, lpa);
+-                      break;
+-              default:
+-                      return;
+-              }
+-
+-              phy_resolve_aneg_linkmode(pcs);
+-      }
+-
+-      state->an_complete = pcs->autoneg_complete;
+-      state->an_enabled = pcs->autoneg;
+-      state->link = pcs->link;
+-      state->duplex = pcs->duplex;
+-      state->speed = pcs->speed;
+-      /* SGMII AN does not negotiate flow control, but that's ok,
+-       * since phylink already knows that, and does:
+-       *      link_state.pause |= pl->phy_state.pause;
+-       */
+-      state->pause = pcs->pause;
+-
+-      dev_dbg(ocelot->dev,
+-              "%s: mode=%s/%s/%s adv=%*pb lpa=%*pb link=%u an_enabled=%u an_complete=%u\n",
+-              __func__,
+-              phy_modes(state->interface),
+-              phy_speed_to_str(state->speed),
+-              phy_duplex_to_str(state->duplex),
+-              __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising,
+-              __ETHTOOL_LINK_MODE_MASK_NBITS, state->lp_advertising,
+-              state->link, state->an_enabled, state->an_complete);
+-}
+-
+ static const struct ocelot_ops vsc9959_ops = {
+       .reset                  = vsc9959_reset,
+-      .pcs_init               = vsc9959_pcs_init,
+-      .pcs_an_restart         = vsc9959_pcs_an_restart,
+-      .pcs_link_state         = vsc9959_pcs_link_state,
+-      .pcs_validate           = vsc9959_pcs_validate,
+ };
+-static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
+-{
+-      struct felix *felix = ocelot_to_felix(ocelot);
+-      struct enetc_mdio_priv *mdio_priv;
+-      struct device *dev = ocelot->dev;
+-      resource_size_t imdio_base;
+-      void __iomem *imdio_regs;
+-      struct resource *res;
+-      struct enetc_hw *hw;
+-      struct mii_bus *bus;
+-      int port;
+-      int rc;
+-
+-      felix->pcs = devm_kcalloc(dev, felix->info->num_ports,
+-                                sizeof(struct phy_device),
+-                                GFP_KERNEL);
+-      if (!felix->pcs) {
+-              dev_err(dev, "failed to allocate array for PCS PHYs\n");
+-              return -ENOMEM;
+-      }
+-
+-      imdio_base = pci_resource_start(felix->pdev,
+-                                      felix->info->imdio_pci_bar);
+-
+-      res = felix->info->imdio_res;
+-      res->flags = IORESOURCE_MEM;
+-      res->start += imdio_base;
+-      res->end += imdio_base;
+-
+-      imdio_regs = devm_ioremap_resource(dev, res);
+-      if (IS_ERR(imdio_regs)) {
+-              dev_err(dev, "failed to map internal MDIO registers\n");
+-              return PTR_ERR(imdio_regs);
+-      }
+-
+-      hw = enetc_hw_alloc(dev, imdio_regs);
+-      if (IS_ERR(hw)) {
+-              dev_err(dev, "failed to allocate ENETC HW structure\n");
+-              return PTR_ERR(hw);
+-      }
+-
+-      bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
+-      if (!bus)
+-              return -ENOMEM;
+-
+-      bus->name = "VSC9959 internal MDIO bus";
+-      bus->read = enetc_mdio_read;
+-      bus->write = enetc_mdio_write;
+-      bus->parent = dev;
+-      mdio_priv = bus->priv;
+-      mdio_priv->hw = hw;
+-      /* This gets added to imdio_regs, which already maps addresses
+-       * starting with the proper offset.
+-       */
+-      mdio_priv->mdio_base = 0;
+-      snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));
+-
+-      /* Needed in order to initialize the bus mutex lock */
+-      rc = mdiobus_register(bus);
+-      if (rc < 0) {
+-              dev_err(dev, "failed to register MDIO bus\n");
+-              return rc;
+-      }
+-
+-      felix->imdio = bus;
+-
+-      for (port = 0; port < felix->info->num_ports; port++) {
+-              struct phy_device *pcs;
+-              bool is_c45 = false;
+-
+-              pcs = get_phy_device(felix->imdio, port, is_c45);
+-              if (IS_ERR(pcs))
+-                      continue;
+-
+-              felix->pcs[port] = pcs;
+-
+-              dev_info(dev, "Found PCS at internal MDIO address %d\n", port);
+-      }
+-
+-      return 0;
+-}
+-
+ struct felix_info felix_info_vsc9959 = {
+       .target_io_res          = vsc9959_target_io_res,
+       .port_io_res            = vsc9959_port_io_res,
+-      .imdio_res              = &vsc9959_imdio_res,
+       .regfields              = vsc9959_regfields,
+       .map                    = vsc9959_regmap,
+       .ops                    = &vsc9959_ops,
+@@ -871,8 +583,6 @@ struct felix_info felix_info_vsc9959 = {
+       .num_stats              = ARRAY_SIZE(vsc9959_stats_layout),
+       .shared_queue_sz        = 128 * 1024,
+       .num_ports              = 6,
+-      .switch_pci_bar         = 4,
+-      .imdio_pci_bar          = 0,
++      .pci_bar                = 4,
+       .quirks                 = OCELOT_PCS_PERFORMS_RATE_ADAPTATION,
+-      .mdio_bus_alloc         = vsc9959_mdio_bus_alloc,
+ };