source of highlighter
plain | download
    1 From 34a467c0a401adc514bb335ac0fc9f2197cc59a4 Mon Sep 17 00:00:00 2001
    2 From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
    3 Date: Mon, 10 Jan 2022 20:03:22 +0000
    4 Subject: [PATCH] net: dsa: mv88e6xxx: convert 88e639x to phylink_pcs
    5 
    6 Convert the 88E6390, 88E6390X, and 88E6393X family of switches to use
    7 the phylink_pcs infrastructure.
    8 
    9 Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
   10 ---
   11  drivers/net/dsa/mv88e6xxx/Makefile   |   1 +
   12  drivers/net/dsa/mv88e6xxx/chip.c     |  98 +--
   13  drivers/net/dsa/mv88e6xxx/pcs-639x.c | 902 +++++++++++++++++++++++++++
   14  drivers/net/dsa/mv88e6xxx/serdes.c   | 743 ----------------------
   15  drivers/net/dsa/mv88e6xxx/serdes.h   |  36 +-
   16  5 files changed, 941 insertions(+), 839 deletions(-)
   17  create mode 100644 drivers/net/dsa/mv88e6xxx/pcs-639x.c
   18 
   19 diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile
   20 index 03dd49d0c71f..e6062a2c1eaf 100644
   21 --- a/drivers/net/dsa/mv88e6xxx/Makefile
   22 +++ b/drivers/net/dsa/mv88e6xxx/Makefile
   23 @@ -11,6 +11,7 @@ mv88e6xxx-objs += global2_scratch.o
   24  mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o
   25  mv88e6xxx-objs += pcs-6185.o
   26  mv88e6xxx-objs += pcs-6352.o
   27 +mv88e6xxx-objs += pcs-639x.o
   28  mv88e6xxx-objs += phy.o
   29  mv88e6xxx-objs += port.o
   30  mv88e6xxx-objs += port_hidden.o
   31 diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
   32 index 4b4e27c4120c..0aa0519bab50 100644
   33 --- a/drivers/net/dsa/mv88e6xxx/chip.c
   34 +++ b/drivers/net/dsa/mv88e6xxx/chip.c
   35 @@ -4349,16 +4349,11 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
   36         .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
   37         .stu_getnext = mv88e6352_g1_stu_getnext,
   38         .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
   39 -       .serdes_power = mv88e6390_serdes_power,
   40 +       .pcs_init = mv88e6390_pcs_init,
   41 +       .pcs_teardown = mv88e639x_pcs_teardown,
   42 +       .pcs_select = mv88e639x_pcs_select,
   43         .serdes_get_lane = mv88e6341_serdes_get_lane,
   44 -       /* Check status register pause & lpa register */
   45 -       .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
   46 -       .serdes_pcs_config = mv88e6390_serdes_pcs_config,
   47 -       .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
   48 -       .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
   49         .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
   50 -       .serdes_irq_enable = mv88e6390_serdes_irq_enable,
   51 -       .serdes_irq_status = mv88e6390_serdes_irq_status,
   52         .gpio_ops = &mv88e6352_gpio_ops,
   53         .serdes_get_sset_count = mv88e6390_serdes_get_sset_count,
   54         .serdes_get_strings = mv88e6390_serdes_get_strings,
   55 @@ -4733,16 +4728,11 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
   56         .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
   57         .stu_getnext = mv88e6390_g1_stu_getnext,
   58         .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
   59 -       .serdes_power = mv88e6390_serdes_power,
   60 +       .pcs_init = mv88e6390_pcs_init,
   61 +       .pcs_teardown = mv88e639x_pcs_teardown,
   62 +       .pcs_select = mv88e639x_pcs_select,
   63         .serdes_get_lane = mv88e6390_serdes_get_lane,
   64 -       /* Check status register pause & lpa register */
   65 -       .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
   66 -       .serdes_pcs_config = mv88e6390_serdes_pcs_config,
   67 -       .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
   68 -       .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
   69         .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
   70 -       .serdes_irq_enable = mv88e6390_serdes_irq_enable,
   71 -       .serdes_irq_status = mv88e6390_serdes_irq_status,
   72         .serdes_get_strings = mv88e6390_serdes_get_strings,
   73         .serdes_get_stats = mv88e6390_serdes_get_stats,
   74         .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
   75 @@ -4796,16 +4786,11 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
   76         .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
   77         .stu_getnext = mv88e6390_g1_stu_getnext,
   78         .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
   79 -       .serdes_power = mv88e6390_serdes_power,
   80 +       .pcs_init = mv88e6390_pcs_init,
   81 +       .pcs_teardown = mv88e639x_pcs_teardown,
   82 +       .pcs_select = mv88e639x_pcs_select,
   83         .serdes_get_lane = mv88e6390x_serdes_get_lane,
   84 -       /* Check status register pause & lpa register */
   85 -       .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
   86 -       .serdes_pcs_config = mv88e6390_serdes_pcs_config,
   87 -       .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
   88 -       .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
   89         .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
   90 -       .serdes_irq_enable = mv88e6390_serdes_irq_enable,
   91 -       .serdes_irq_status = mv88e6390_serdes_irq_status,
   92         .serdes_get_strings = mv88e6390_serdes_get_strings,
   93         .serdes_get_stats = mv88e6390_serdes_get_stats,
   94         .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
   95 @@ -4857,16 +4842,11 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
   96         .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
   97         .stu_getnext = mv88e6390_g1_stu_getnext,
   98         .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
   99 -       .serdes_power = mv88e6390_serdes_power,
  100 +       .pcs_init = mv88e6390_pcs_init,
  101 +       .pcs_teardown = mv88e639x_pcs_teardown,
  102 +       .pcs_select = mv88e639x_pcs_select,
  103         .serdes_get_lane = mv88e6390_serdes_get_lane,
  104 -       /* Check status register pause & lpa register */
  105 -       .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
  106 -       .serdes_pcs_config = mv88e6390_serdes_pcs_config,
  107 -       .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
  108 -       .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
  109         .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
  110 -       .serdes_irq_enable = mv88e6390_serdes_irq_enable,
  111 -       .serdes_irq_status = mv88e6390_serdes_irq_status,
  112         .serdes_get_strings = mv88e6390_serdes_get_strings,
  113         .serdes_get_stats = mv88e6390_serdes_get_stats,
  114         .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
  115 @@ -5018,16 +4998,11 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
  116         .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
  117         .stu_getnext = mv88e6390_g1_stu_getnext,
  118         .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
  119 -       .serdes_power = mv88e6390_serdes_power,
  120 +       .pcs_init = mv88e6390_pcs_init,
  121 +       .pcs_teardown = mv88e639x_pcs_teardown,
  122 +       .pcs_select = mv88e639x_pcs_select,
  123         .serdes_get_lane = mv88e6390_serdes_get_lane,
  124 -       /* Check status register pause & lpa register */
  125 -       .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
  126 -       .serdes_pcs_config = mv88e6390_serdes_pcs_config,
  127 -       .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
  128 -       .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
  129         .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
  130 -       .serdes_irq_enable = mv88e6390_serdes_irq_enable,
  131 -       .serdes_irq_status = mv88e6390_serdes_irq_status,
  132         .serdes_get_strings = mv88e6390_serdes_get_strings,
  133         .serdes_get_stats = mv88e6390_serdes_get_stats,
  134         .serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
  135 @@ -5171,16 +5146,11 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
  136         .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
  137         .stu_getnext = mv88e6352_g1_stu_getnext,
  138         .stu_loadpurge = mv88e6352_g1_stu_loadpurge,
  139 -       .serdes_power = mv88e6390_serdes_power,
  140 +       .pcs_init = mv88e6390_pcs_init,
  141 +       .pcs_teardown = mv88e639x_pcs_teardown,
  142 +       .pcs_select = mv88e639x_pcs_select,
  143         .serdes_get_lane = mv88e6341_serdes_get_lane,
  144 -       /* Check status register pause & lpa register */
  145 -       .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
  146 -       .serdes_pcs_config = mv88e6390_serdes_pcs_config,
  147 -       .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
  148 -       .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
  149         .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
  150 -       .serdes_irq_enable = mv88e6390_serdes_irq_enable,
  151 -       .serdes_irq_status = mv88e6390_serdes_irq_status,
  152         .gpio_ops = &mv88e6352_gpio_ops,
  153         .avb_ops = &mv88e6390_avb_ops,
  154         .ptp_ops = &mv88e6352_ptp_ops,
  155 @@ -5389,16 +5359,11 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
  156         .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
  157         .stu_getnext = mv88e6390_g1_stu_getnext,
  158         .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
  159 -       .serdes_power = mv88e6390_serdes_power,
  160 +       .pcs_init = mv88e6390_pcs_init,
  161 +       .pcs_teardown = mv88e639x_pcs_teardown,
  162 +       .pcs_select = mv88e639x_pcs_select,
  163         .serdes_get_lane = mv88e6390_serdes_get_lane,
  164 -       /* Check status register pause & lpa register */
  165 -       .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
  166 -       .serdes_pcs_config = mv88e6390_serdes_pcs_config,
  167 -       .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
  168 -       .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
  169         .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
  170 -       .serdes_irq_enable = mv88e6390_serdes_irq_enable,
  171 -       .serdes_irq_status = mv88e6390_serdes_irq_status,
  172         .gpio_ops = &mv88e6352_gpio_ops,
  173         .avb_ops = &mv88e6390_avb_ops,
  174         .ptp_ops = &mv88e6352_ptp_ops,
  175 @@ -5456,15 +5421,11 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
  176         .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
  177         .stu_getnext = mv88e6390_g1_stu_getnext,
  178         .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
  179 -       .serdes_power = mv88e6390_serdes_power,
  180 +       .pcs_init = mv88e6390_pcs_init,
  181 +       .pcs_teardown = mv88e639x_pcs_teardown,
  182 +       .pcs_select = mv88e639x_pcs_select,
  183         .serdes_get_lane = mv88e6390x_serdes_get_lane,
  184 -       .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state,
  185 -       .serdes_pcs_config = mv88e6390_serdes_pcs_config,
  186 -       .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
  187 -       .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
  188         .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
  189 -       .serdes_irq_enable = mv88e6390_serdes_irq_enable,
  190 -       .serdes_irq_status = mv88e6390_serdes_irq_status,
  191         .serdes_get_sset_count = mv88e6390_serdes_get_sset_count,
  192         .serdes_get_strings = mv88e6390_serdes_get_strings,
  193         .serdes_get_stats = mv88e6390_serdes_get_stats,
  194 @@ -5478,7 +5439,6 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
  195  
  196  static const struct mv88e6xxx_ops mv88e6393x_ops = {
  197         /* MV88E6XXX_FAMILY_6393 */
  198 -       .setup_errata = mv88e6393x_serdes_setup_errata,
  199         .irl_init_all = mv88e6390_g2_irl_init_all,
  200         .get_eeprom = mv88e6xxx_g2_get_eeprom8,
  201         .set_eeprom = mv88e6xxx_g2_set_eeprom8,
  202 @@ -5526,15 +5486,11 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
  203         .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
  204         .stu_getnext = mv88e6390_g1_stu_getnext,
  205         .stu_loadpurge = mv88e6390_g1_stu_loadpurge,
  206 -       .serdes_power = mv88e6393x_serdes_power,
  207 +       .pcs_init = mv88e6393x_pcs_init,
  208 +       .pcs_teardown = mv88e639x_pcs_teardown,
  209 +       .pcs_select = mv88e639x_pcs_select,
  210         .serdes_get_lane = mv88e6393x_serdes_get_lane,
  211 -       .serdes_pcs_get_state = mv88e6393x_serdes_pcs_get_state,
  212 -       .serdes_pcs_config = mv88e6390_serdes_pcs_config,
  213 -       .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart,
  214 -       .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up,
  215         .serdes_irq_mapping = mv88e6390_serdes_irq_mapping,
  216 -       .serdes_irq_enable = mv88e6393x_serdes_irq_enable,
  217 -       .serdes_irq_status = mv88e6393x_serdes_irq_status,
  218         /* TODO: serdes stats */
  219         .gpio_ops = &mv88e6352_gpio_ops,
  220         .avb_ops = &mv88e6390_avb_ops,
  221 diff --git a/drivers/net/dsa/mv88e6xxx/pcs-639x.c b/drivers/net/dsa/mv88e6xxx/pcs-639x.c
  222 new file mode 100644
  223 index 000000000000..eaa01359e94e
  224 --- /dev/null
  225 +++ b/drivers/net/dsa/mv88e6xxx/pcs-639x.c
  226 @@ -0,0 +1,902 @@
  227 +// SPDX-License-Identifier: GPL-2.0-or-later
  228 +/*
  229 + * Marvell 88E6352 family SERDES PCS support
  230 + *
  231 + * Copyright (c) 2008 Marvell Semiconductor
  232 + *
  233 + * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
  234 + */
  235 +#include <linux/interrupt.h>
  236 +#include <linux/irqdomain.h>
  237 +#include <linux/mii.h>
  238 +
  239 +#include "chip.h"
  240 +#include "global2.h"
  241 +#include "phy.h"
  242 +#include "port.h"
  243 +#include "serdes.h"
  244 +
  245 +struct mv88e639x_pcs {
  246 +       struct mdio_device mdio;
  247 +       struct phylink_pcs sgmii_pcs;
  248 +       struct phylink_pcs xg_pcs;
  249 +       bool supports_5g;
  250 +       phy_interface_t interface;
  251 +       unsigned int irq;
  252 +       char name[64];
  253 +       irqreturn_t (*handle_irq)(struct mv88e639x_pcs *mpcs);
  254 +       struct mv88e6xxx_port *port;
  255 +};
  256 +
  257 +static int mv88e639x_read(struct mv88e639x_pcs *mpcs, u16 regnum, u16 *val)
  258 +{
  259 +       u32 reg_c45 = mdiobus_c45_addr(MDIO_MMD_PHYXS, regnum);
  260 +       int err;
  261 +
  262 +       err = mdiodev_read(&mpcs->mdio, reg_c45);
  263 +       if (err < 0)
  264 +               return err;
  265 +
  266 +       *val = err;
  267 +
  268 +       return 0;
  269 +}
  270 +
  271 +static int mv88e639x_write(struct mv88e639x_pcs *mpcs, u16 regnum, u16 val)
  272 +{
  273 +       u32 reg_c45 = mdiobus_c45_addr(MDIO_MMD_PHYXS, regnum);
  274 +
  275 +       return mdiodev_write(&mpcs->mdio, reg_c45, val);
  276 +}
  277 +
  278 +static int mv88e639x_modify(struct mv88e639x_pcs *mpcs, u16 regnum, u16 mask,
  279 +                           u16 val)
  280 +{
  281 +       u32 reg_c45 = mdiobus_c45_addr(MDIO_MMD_PHYXS, regnum);
  282 +
  283 +       return mdiodev_modify(&mpcs->mdio, reg_c45, mask, val);
  284 +}
  285 +
  286 +static int mv88e639x_modify_changed(struct mv88e639x_pcs *mpcs, u16 regnum,
  287 +                                   u16 mask, u16 set)
  288 +{
  289 +       u32 reg_c45 = mdiobus_c45_addr(MDIO_MMD_PHYXS, regnum);
  290 +
  291 +       return mdiodev_modify_changed(&mpcs->mdio, reg_c45, mask, set);
  292 +}
  293 +
  294 +static struct mv88e639x_pcs *
  295 +mv88e639x_pcs_alloc(struct device *dev, struct mii_bus *bus, unsigned int addr,
  296 +                   int port)
  297 +{
  298 +       struct mv88e639x_pcs *mpcs;
  299 +
  300 +       mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL);
  301 +       if (!mpcs)
  302 +               return NULL;
  303 +
  304 +       mpcs->mdio.dev.parent = dev;
  305 +       mpcs->mdio.bus = bus;
  306 +       mpcs->mdio.addr = addr;
  307 +
  308 +       snprintf(mpcs->name, sizeof(mpcs->name),
  309 +                "mv88e6xxx-%s-serdes-%d", dev_name(dev), port);
  310 +
  311 +       return mpcs;
  312 +}
  313 +
  314 +static void mv88e639x_pcs_link_change(struct mv88e639x_pcs *mpcs,
  315 +                                     bool link_down)
  316 +{
  317 +       struct mv88e6xxx_port *port = mpcs->port;
  318 +
  319 +       dsa_port_phylink_mac_change(port->chip->ds, port->port, !link_down);
  320 +}
  321 +
  322 +static irqreturn_t mv88e639x_pcs_handle_irq(int irq, void *dev_id)
  323 +{
  324 +       struct mv88e639x_pcs *mpcs = dev_id;
  325 +       irqreturn_t (*handler)(struct mv88e639x_pcs *);
  326 +
  327 +       handler = READ_ONCE(mpcs->handle_irq);
  328 +       if (!handler)
  329 +               return IRQ_NONE;
  330 +
  331 +       return handler(mpcs);
  332 +}
  333 +
  334 +static int mv88e639x_pcs_setup_irq(struct mv88e639x_pcs *mpcs,
  335 +                                  struct mv88e6xxx_chip *chip, int port)
  336 +{
  337 +       unsigned int irq;
  338 +
  339 +       irq = mv88e6xxx_serdes_irq_mapping(chip, port);
  340 +       if (!irq) {
  341 +               /* Use polling mode */
  342 +               mpcs->sgmii_pcs.poll = true;
  343 +               mpcs->xg_pcs.poll = true;
  344 +               return 0;
  345 +       }
  346 +
  347 +       mpcs->irq = irq;
  348 +
  349 +       return request_threaded_irq(irq, NULL, mv88e639x_pcs_handle_irq,
  350 +                                   IRQF_ONESHOT, mpcs->name, mpcs);
  351 +}
  352 +
  353 +void mv88e639x_pcs_teardown(struct mv88e6xxx_chip *chip, int port)
  354 +{
  355 +       struct mv88e639x_pcs *mpcs = chip->ports[port].pcs_private;
  356 +
  357 +       if (!mpcs)
  358 +               return;
  359 +
  360 +       if (mpcs->irq)
  361 +               free_irq(mpcs->irq, mpcs);
  362 +
  363 +       kfree(mpcs);
  364 +
  365 +       chip->ports[port].pcs_private = NULL;
  366 +}
  367 +
  368 +static struct mv88e639x_pcs *sgmii_pcs_to_mv88e639x_pcs(struct phylink_pcs *pcs)
  369 +{
  370 +       return container_of(pcs, struct mv88e639x_pcs, sgmii_pcs);
  371 +}
  372 +
  373 +static irqreturn_t mv88e639x_sgmii_handle_irq(struct mv88e639x_pcs *mpcs)
  374 +{
  375 +       u16 int_status;
  376 +       bool link_down;
  377 +       int err;
  378 +
  379 +       err = mv88e639x_read(mpcs, MV88E6390_SGMII_INT_STATUS, &int_status);
  380 +       if (err)
  381 +               return IRQ_NONE;
  382 +
  383 +       if (int_status & (MV88E6390_SGMII_INT_LINK_DOWN |
  384 +                         MV88E6390_SGMII_INT_LINK_UP)) {
  385 +               link_down = !!(int_status & MV88E6390_SGMII_INT_LINK_DOWN);
  386 +
  387 +               mv88e639x_pcs_link_change(mpcs, link_down);
  388 +
  389 +               return IRQ_HANDLED;
  390 +       }
  391 +
  392 +       return IRQ_NONE;
  393 +}
  394 +
  395 +static int mv88e639x_sgmii_pcs_control_irq(struct mv88e639x_pcs *mpcs,
  396 +                                          bool enable)
  397 +{
  398 +       u16 val = 0;
  399 +
  400 +       if (enable)
  401 +               val |= MV88E6390_SGMII_INT_LINK_DOWN |
  402 +                      MV88E6390_SGMII_INT_LINK_UP;
  403 +
  404 +       return mv88e639x_modify(mpcs, MV88E6390_SGMII_INT_ENABLE,
  405 +                               MV88E6390_SGMII_INT_LINK_DOWN |
  406 +                               MV88E6390_SGMII_INT_LINK_UP, val);
  407 +}
  408 +
  409 +static int mv88e639x_sgmii_pcs_control_pwr(struct mv88e639x_pcs *mpcs,
  410 +                                          bool enable)
  411 +{
  412 +       u16 mask, val;
  413 +
  414 +       if (enable) {
  415 +               mask = BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN;
  416 +               val = 0;
  417 +       } else {
  418 +               mask = val = BMCR_PDOWN;
  419 +       }
  420 +
  421 +       return mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, mask, val);
  422 +}
  423 +
  424 +static int mv88e639x_sgmii_pcs_enable(struct phylink_pcs *pcs)
  425 +{
  426 +       struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
  427 +
  428 +       /* power enable done in post_config */
  429 +       mpcs->handle_irq = mv88e639x_sgmii_handle_irq;
  430 +
  431 +       return mv88e639x_sgmii_pcs_control_irq(mpcs, !!mpcs->irq);
  432 +}
  433 +
  434 +static void mv88e639x_sgmii_pcs_disable(struct phylink_pcs *pcs)
  435 +{
  436 +       struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
  437 +
  438 +       mv88e639x_sgmii_pcs_control_irq(mpcs, false);
  439 +       mv88e639x_sgmii_pcs_control_pwr(mpcs, false);
  440 +}
  441 +
  442 +static void mv88e639x_sgmii_pcs_pre_config(struct phylink_pcs *pcs,
  443 +                                          phy_interface_t interface)
  444 +{
  445 +       struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
  446 +
  447 +       mv88e639x_sgmii_pcs_control_pwr(mpcs, false);
  448 +}
  449 +
  450 +static int mv88e639x_sgmii_pcs_post_config(struct phylink_pcs *pcs,
  451 +                                          phy_interface_t interface)
  452 +{
  453 +       struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
  454 +
  455 +       mv88e639x_sgmii_pcs_control_pwr(mpcs, true);
  456 +
  457 +       return 0;
  458 +}
  459 +
  460 +static void mv88e639x_sgmii_pcs_get_state(struct phylink_pcs *pcs,
  461 +                                         struct phylink_link_state *state)
  462 +{
  463 +       struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
  464 +       u16 bmsr, lpa, status;
  465 +       int err;
  466 +
  467 +       err = mv88e639x_read(mpcs, MV88E6390_SGMII_BMSR, &bmsr);
  468 +       if (err) {
  469 +               dev_err(mpcs->mdio.dev.parent,
  470 +                       "can't read Serdes PHY %s: %pe\n",
  471 +                       "BMSR", ERR_PTR(err));
  472 +               state->link = false;
  473 +               return;
  474 +       }
  475 +
  476 +       err = mv88e639x_read(mpcs, MV88E6390_SGMII_LPA, &lpa);
  477 +       if (err) {
  478 +               dev_err(mpcs->mdio.dev.parent,
  479 +                       "can't read Serdes PHY %s: %pe\n",
  480 +                       "LPA", ERR_PTR(err));
  481 +               state->link = false;
  482 +               return;
  483 +       }
  484 +
  485 +       err = mv88e639x_read(mpcs, MV88E6390_SGMII_PHY_STATUS, &status);
  486 +       if (err) {
  487 +               dev_err(mpcs->mdio.dev.parent,
  488 +                       "can't read Serdes PHY %s: %pe\n",
  489 +                       "status", ERR_PTR(err));
  490 +               state->link = false;
  491 +               return;
  492 +       }
  493 +
  494 +       mv88e6xxx_pcs_decode_state(mpcs->mdio.dev.parent, bmsr, lpa, status,
  495 +                                  state);
  496 +}
  497 +
  498 +static int mv88e639x_sgmii_pcs_config(struct phylink_pcs *pcs,
  499 +                                     unsigned int mode,
  500 +                                     phy_interface_t interface,
  501 +                                     const unsigned long *advertising,
  502 +                                     bool permit_pause_to_mac)
  503 +{
  504 +       struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
  505 +       u16 val, bmcr;
  506 +       bool changed;
  507 +       int adv, err;
  508 +
  509 +       adv = phylink_mii_c22_pcs_encode_advertisement(interface, advertising);
  510 +       if (adv < 0)
  511 +               return 0;
  512 +
  513 +       mpcs->interface = interface;
  514 +
  515 +       err = mv88e639x_modify_changed(mpcs, MV88E6390_SGMII_ADVERTISE,
  516 +                                      0xffff, adv);
  517 +       if (err < 0)
  518 +               return err;
  519 +
  520 +       changed = err > 0;
  521 +
  522 +       err = mv88e639x_read(mpcs, MV88E6390_SGMII_BMCR, &val);
  523 +       if (err)
  524 +               return err;
  525 +
  526 +       if (phylink_autoneg_inband(mode))
  527 +               bmcr = val | BMCR_ANENABLE;
  528 +       else
  529 +               bmcr = val & ~BMCR_ANENABLE;
  530 +
  531 +       /* setting ANENABLE triggers a restart of negotiation */
  532 +       if (bmcr == val)
  533 +               return changed;
  534 +
  535 +       return mv88e639x_write(mpcs, MV88E6390_SGMII_BMCR, bmcr);
  536 +}
  537 +
  538 +static void mv88e639x_sgmii_pcs_an_restart(struct phylink_pcs *pcs)
  539 +{
  540 +       struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
  541 +
  542 +       mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR,
  543 +                        BMCR_ANRESTART, BMCR_ANRESTART);
  544 +}
  545 +
  546 +static void mv88e639x_sgmii_pcs_link_up(struct phylink_pcs *pcs,
  547 +                                       unsigned int mode,
  548 +                                       phy_interface_t interface,
  549 +                                       int speed, int duplex)
  550 +{
  551 +       struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
  552 +       u16 bmcr;
  553 +       int err;
  554 +
  555 +       if (phylink_autoneg_inband(mode))
  556 +               return;
  557 +
  558 +       bmcr = mii_bmcr_encode_fixed(speed, duplex);
  559 +
  560 +       err = mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR,
  561 +                              BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX,
  562 +                              bmcr);
  563 +       if (err)
  564 +               dev_err(mpcs->mdio.dev.parent,
  565 +                       "can't access Serdes PHY %s: %pe\n",
  566 +                       "BMCR", ERR_PTR(err));
  567 +}
  568 +
  569 +static const struct phylink_pcs_ops mv88e639x_sgmii_pcs_ops = {
  570 +       .pcs_enable = mv88e639x_sgmii_pcs_enable,
  571 +       .pcs_disable = mv88e639x_sgmii_pcs_disable,
  572 +       .pcs_pre_config = mv88e639x_sgmii_pcs_pre_config,
  573 +       .pcs_post_config = mv88e639x_sgmii_pcs_post_config,
  574 +       .pcs_get_state = mv88e639x_sgmii_pcs_get_state,
  575 +       .pcs_an_restart = mv88e639x_sgmii_pcs_an_restart,
  576 +       .pcs_config = mv88e639x_sgmii_pcs_config,
  577 +       .pcs_link_up = mv88e639x_sgmii_pcs_link_up,
  578 +};
  579 +
  580 +static struct mv88e639x_pcs *xg_pcs_to_mv88e639x_pcs(struct phylink_pcs *pcs)
  581 +{
  582 +       return container_of(pcs, struct mv88e639x_pcs, xg_pcs);
  583 +}
  584 +
  585 +static int mv88e639x_xg_pcs_enable(struct mv88e639x_pcs *mpcs)
  586 +{
  587 +       return mv88e639x_modify(mpcs, MV88E6390_10G_CTRL1,
  588 +                               MDIO_CTRL1_RESET | MDIO_PCS_CTRL1_LOOPBACK |
  589 +                               MDIO_CTRL1_LPOWER, 0);
  590 +}
  591 +
  592 +static void mv88e639x_xg_pcs_disable(struct mv88e639x_pcs *mpcs)
  593 +{
  594 +       mv88e639x_modify(mpcs, MV88E6390_10G_CTRL1, MDIO_CTRL1_LPOWER,
  595 +                        MDIO_CTRL1_LPOWER);
  596 +}
  597 +
  598 +static void mv88e639x_xg_pcs_get_state(struct phylink_pcs *pcs,
  599 +                                      struct phylink_link_state *state)
  600 +{
  601 +       struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
  602 +       u16 status;
  603 +       int err;
  604 +
  605 +       state->link = false;
  606 +
  607 +       err = mv88e639x_read(mpcs, MV88E6390_10G_STAT1, &status);
  608 +       if (err) {
  609 +               dev_err(mpcs->mdio.dev.parent,
  610 +                       "can't read Serdes PHY %s: %pe\n",
  611 +                       "STAT1", ERR_PTR(err));
  612 +               return;
  613 +       }
  614 +
  615 +       state->link = !!(status & MDIO_STAT1_LSTATUS);
  616 +       if (state->link) {
  617 +               switch (state->interface) {
  618 +               case PHY_INTERFACE_MODE_5GBASER:
  619 +                       state->speed = SPEED_5000;
  620 +                       break;
  621 +
  622 +               case PHY_INTERFACE_MODE_10GBASER:
  623 +               case PHY_INTERFACE_MODE_RXAUI:
  624 +               case PHY_INTERFACE_MODE_XAUI:
  625 +                       state->speed = SPEED_10000;
  626 +                       break;
  627 +
  628 +               default:
  629 +                       state->link = false;
  630 +                       return;
  631 +               }
  632 +
  633 +               state->duplex = DUPLEX_FULL;
  634 +       }
  635 +}
  636 +
  637 +static int mv88e639x_xg_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
  638 +                                  phy_interface_t interface,
  639 +                                  const unsigned long *advertising,
  640 +                                  bool permit_pause_to_mac)
  641 +{
  642 +       return 0;
  643 +}
  644 +
  645 +struct phylink_pcs *mv88e639x_pcs_select(struct mv88e6xxx_chip *chip, int port,
  646 +                                        phy_interface_t mode)
  647 +{
  648 +       struct mv88e639x_pcs *mpcs;
  649 +
  650 +       mpcs = chip->ports[port].pcs_private;
  651 +       if (!mpcs)
  652 +               return NULL;
  653 +
  654 +       switch (mode) {
  655 +       case PHY_INTERFACE_MODE_SGMII:
  656 +       case PHY_INTERFACE_MODE_1000BASEX:
  657 +       case PHY_INTERFACE_MODE_2500BASEX:
  658 +               return &mpcs->sgmii_pcs;
  659 +
  660 +       case PHY_INTERFACE_MODE_5GBASER:
  661 +               if (!mpcs->supports_5g)
  662 +                       return NULL;
  663 +               fallthrough;
  664 +       case PHY_INTERFACE_MODE_10GBASER:
  665 +       case PHY_INTERFACE_MODE_XAUI:
  666 +       case PHY_INTERFACE_MODE_RXAUI:
  667 +               return &mpcs->xg_pcs;
  668 +
  669 +       default:
  670 +               return NULL;
  671 +       }
  672 +}
  673 +
  674 +/* Marvell 88E6390 Specific support */
  675 +
  676 +static irqreturn_t mv88e6390_xg_handle_irq(struct mv88e639x_pcs *mpcs)
  677 +{
  678 +       u16 int_status;
  679 +       bool link_down;
  680 +       int err;
  681 +
  682 +       err = mv88e639x_read(mpcs, MV88E6390_10G_INT_STATUS, &int_status);
  683 +       if (err)
  684 +               return IRQ_NONE;
  685 +
  686 +       if (int_status & (MV88E6390_10G_INT_LINK_DOWN |
  687 +                         MV88E6390_10G_INT_LINK_UP)) {
  688 +               link_down = !!(int_status & MV88E6390_10G_INT_LINK_DOWN);
  689 +
  690 +               mv88e639x_pcs_link_change(mpcs, link_down);
  691 +
  692 +               return IRQ_HANDLED;
  693 +       }
  694 +
  695 +       return IRQ_NONE;
  696 +}
  697 +
  698 +static int mv88e6390_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable)
  699 +{
  700 +       u16 val = 0;
  701 +
  702 +       if (enable)
  703 +               val = MV88E6390_10G_INT_LINK_DOWN | MV88E6390_10G_INT_LINK_UP;
  704 +
  705 +       return mv88e639x_modify(mpcs, MV88E6390_10G_INT_ENABLE,
  706 +                               MV88E6390_10G_INT_LINK_DOWN |
  707 +                               MV88E6390_10G_INT_LINK_UP, val);
  708 +}
  709 +
  710 +static int mv88e6390_xg_pcs_enable(struct phylink_pcs *pcs)
  711 +{
  712 +       struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
  713 +       int err;
  714 +
  715 +       err = mv88e639x_xg_pcs_enable(mpcs);
  716 +       if (err)
  717 +               return err;
  718 +
  719 +       mpcs->handle_irq = mv88e6390_xg_handle_irq;
  720 +
  721 +       return mv88e6390_xg_control_irq(mpcs, !!mpcs->irq);
  722 +}
  723 +
  724 +static void mv88e6390_xg_pcs_disable(struct phylink_pcs *pcs)
  725 +{
  726 +       struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
  727 +
  728 +       mv88e6390_xg_control_irq(mpcs, false);
  729 +       mv88e639x_xg_pcs_disable(mpcs);
  730 +}
  731 +
  732 +static const struct phylink_pcs_ops mv88e6390_xg_pcs_ops = {
  733 +       .pcs_enable = mv88e6390_xg_pcs_enable,
  734 +       .pcs_disable = mv88e6390_xg_pcs_disable,
  735 +       .pcs_get_state = mv88e639x_xg_pcs_get_state,
  736 +       .pcs_config = mv88e639x_xg_pcs_config,
  737 +};
  738 +
  739 +static int mv88e6390_pcs_enable_checker(struct mv88e639x_pcs *mpcs)
  740 +{
  741 +       return mv88e639x_modify(mpcs, MV88E6390_PG_CONTROL,
  742 +                               MV88E6390_PG_CONTROL_ENABLE_PC,
  743 +                               MV88E6390_PG_CONTROL_ENABLE_PC);
  744 +}
  745 +
  746 +int mv88e6390_pcs_init(struct mv88e6xxx_chip *chip, int port)
  747 +{
  748 +       struct mv88e639x_pcs *mpcs;
  749 +       struct mii_bus *bus;
  750 +       struct device *dev;
  751 +       int lane, err;
  752 +
  753 +       lane = mv88e6xxx_serdes_get_lane(chip, port);
  754 +       if (lane < 0)
  755 +               return 0;
  756 +
  757 +       bus = mv88e6xxx_default_mdio_bus(chip);
  758 +       dev = chip->dev;
  759 +
  760 +       mpcs = mv88e639x_pcs_alloc(dev, bus, lane, port);
  761 +       if (!mpcs)
  762 +               return -ENOMEM;
  763 +
  764 +       mpcs->port = &chip->ports[port];
  765 +       mpcs->sgmii_pcs.ops = &mv88e639x_sgmii_pcs_ops;
  766 +       mpcs->xg_pcs.ops = &mv88e6390_xg_pcs_ops;
  767 +
  768 +       err = mv88e639x_pcs_setup_irq(mpcs, chip, port);
  769 +       if (err)
  770 +               goto err_free;
  771 +
  772 +       /* 6390 and 6390x has the checker, 6393x doesn't appear to? */
  773 +       /* This is to enable gathering the statistics. Maybe this
  774 +        * should call out to a helper? Or we could do this at init time.
  775 +        */
  776 +       err = mv88e6390_pcs_enable_checker(mpcs);
  777 +       if (err)
  778 +               goto err_free;
  779 +
  780 +       mpcs->port->pcs_private = mpcs;
  781 +
  782 +       return 0;
  783 +
  784 +err_free:
  785 +       kfree(mpcs);
  786 +       return err;
  787 +}
  788 +
  789 +/* Marvell 88E6393X Specific support */
  790 +
  791 +static int mv88e6393x_power_lane(struct mv88e639x_pcs *mpcs, bool enable)
  792 +{
  793 +       u16 val = MV88E6393X_SERDES_CTRL1_TX_PDOWN |
  794 +                 MV88E6393X_SERDES_CTRL1_RX_PDOWN;
  795 +
  796 +       return mv88e639x_modify(mpcs, MV88E6393X_SERDES_CTRL1, val,
  797 +                               enable ? 0 : val);
  798 +}
  799 +
  800 +/* mv88e6393x family errata 4.6:
  801 + * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD mode or
  802 + * P0_mode is configured for [x]MII.
  803 + * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1.
  804 + *
  805 + * It seems that after this workaround the SERDES is automatically powered up
  806 + * (the bit is cleared), so power it down.
  807 + */
  808 +static int mv88e6393x_erratum_4_6(struct mv88e639x_pcs *mpcs)
  809 +{
  810 +       int err;
  811 +
  812 +       err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC,
  813 +                              MV88E6393X_SERDES_POC_PDOWN |
  814 +                              MV88E6393X_SERDES_POC_RESET,
  815 +                              MV88E6393X_SERDES_POC_RESET);
  816 +       if (err)
  817 +               return err;
  818 +
  819 +       err = mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR,
  820 +                              BMCR_PDOWN, BMCR_PDOWN);
  821 +       if (err)
  822 +               return err;
  823 +
  824 +       err = mv88e639x_sgmii_pcs_control_pwr(mpcs, false);
  825 +       if (err)
  826 +               return err;
  827 +
  828 +       return mv88e6393x_power_lane(mpcs, false);
  829 +}
  830 +
  831 +/* mv88e6393x family errata 4.8:
  832 + * When a SERDES port is operating in 1000BASE-X or SGMII mode link may not
  833 + * come up after hardware reset or software reset of SERDES core. Workaround
  834 + * is to write SERDES register 4.F074.14=1 for only those modes and 0 in all
  835 + * other modes.
  836 + */
  837 +static int mv88e6393x_erratum_4_8(struct mv88e639x_pcs *mpcs)
  838 +{
  839 +       u16 reg, poc;
  840 +       int err;
  841 +
  842 +       err = mv88e639x_read(mpcs, MV88E6393X_SERDES_POC, &poc);
  843 +       if (err)
  844 +               return err;
  845 +
  846 +       poc &= MV88E6393X_SERDES_POC_PCS_MASK;
  847 +       if (poc == MV88E6393X_SERDES_POC_PCS_1000BASEX ||
  848 +           poc == MV88E6393X_SERDES_POC_PCS_SGMII_PHY ||
  849 +           poc == MV88E6393X_SERDES_POC_PCS_SGMII_MAC)
  850 +               reg = MV88E6393X_ERRATA_4_8_BIT;
  851 +       else
  852 +               reg = 0;
  853 +
  854 +       return mv88e639x_modify(mpcs, MV88E6393X_ERRATA_4_8_REG,
  855 +                               MV88E6393X_ERRATA_4_8_BIT, reg);
  856 +}
  857 +
  858 +/* mv88e6393x family errata 5.2:
  859 + * For optimal signal integrity the following sequence should be applied to
  860 + * SERDES operating in 10G mode. These registers only apply to 10G operation
  861 + * and have no effect on other speeds.
  862 + */
  863 +static int mv88e6393x_erratum_5_2(struct mv88e639x_pcs *mpcs)
  864 +{
  865 +       static const struct {
  866 +               u16 dev, reg, val, mask;
  867 +       } fixes[] = {
  868 +               { MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff },
  869 +               { MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff },
  870 +               { MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff },
  871 +               { MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f },
  872 +               { MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 },
  873 +               { MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff },
  874 +               { MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC,
  875 +                 MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET },
  876 +       };
  877 +       int err, i;
  878 +
  879 +       for (i = 0; i < ARRAY_SIZE(fixes); ++i) {
  880 +               u32 reg_c45 = mdiobus_c45_addr(fixes[i].dev, fixes[i].reg);
  881 +
  882 +               err = mdiodev_modify(&mpcs->mdio, reg_c45, fixes[i].mask,
  883 +                                    fixes[i].val);
  884 +               if (err)
  885 +                       return err;
  886 +       }
  887 +
  888 +       return 0;
  889 +}
  890 +
  891 +/* Inband AN is broken on Amethyst in 2500base-x mode when set by standard
  892 + * mechanism (via cmode).
  893 + * We can get around this by configuring the PCS mode to 1000base-x and then
  894 + * writing value 0x58 to register 1e.8000. (This must be done while SerDes
  895 + * receiver and transmitter are disabled, which is, when this function is
  896 + * called.)
  897 + * It seem that when we do this configuration to 2500base-x mode (by changing
  898 + * PCS mode to 1000base-x and frequency to 3.125 GHz from 1.25 GHz) and then
  899 + * configure to sgmii or 1000base-x, the device thinks that it already has
  900 + * SerDes at 1.25 GHz and does not change the 1e.8000 register, leaving SerDes
  901 + * at 3.125 GHz.
  902 + * To avoid this, change PCS mode back to 2500base-x when disabling SerDes from
  903 + * 2500base-x mode.
  904 + */
  905 +static int mv88e6393x_fix_2500basex_an(struct mv88e639x_pcs *mpcs, bool on)
  906 +{
  907 +       u16 reg;
  908 +       int err;
  909 +
  910 +       if (on)
  911 +               reg = MV88E6393X_SERDES_POC_PCS_1000BASEX |
  912 +                     MV88E6393X_SERDES_POC_AN;
  913 +       else
  914 +               reg = MV88E6393X_SERDES_POC_PCS_2500BASEX;
  915 +
  916 +       reg |= MV88E6393X_SERDES_POC_RESET;
  917 +
  918 +       err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC,
  919 +                              MV88E6393X_SERDES_POC_PCS_MASK |
  920 +                              MV88E6393X_SERDES_POC_AN |
  921 +                              MV88E6393X_SERDES_POC_RESET, reg);
  922 +       if (err)
  923 +               return err;
  924 +
  925 +       return mdiodev_write(&mpcs->mdio,
  926 +                            mdiobus_c45_addr(MDIO_MMD_VEND1, 0x8000), 0x58);
  927 +}
  928 +
  929 +static int mv88e6393x_sgmii_apply_2500basex_an(struct mv88e639x_pcs *mpcs,
  930 +                                              phy_interface_t interface,
  931 +                                              bool enable)
  932 +{
  933 +       int err;
  934 +
  935 +       if (interface != PHY_INTERFACE_MODE_2500BASEX)
  936 +               return 0;
  937 +
  938 +       err = mv88e6393x_fix_2500basex_an(mpcs, enable);
  939 +       if (err)
  940 +               dev_err(mpcs->mdio.dev.parent,
  941 +                       "failed to %s 2500basex fix: %pe\n",
  942 +                       enable ? "enable" : "disable", ERR_PTR(err));
  943 +
  944 +       return err;
  945 +}
  946 +
  947 +static void mv88e6393x_sgmii_pcs_disable(struct phylink_pcs *pcs)
  948 +{
  949 +       struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
  950 +
  951 +       mv88e639x_sgmii_pcs_disable(pcs);
  952 +       mv88e6393x_power_lane(mpcs, false);
  953 +       mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false);
  954 +}
  955 +
  956 +static void mv88e6393x_sgmii_pcs_pre_config(struct phylink_pcs *pcs,
  957 +                                           phy_interface_t interface)
  958 +{
  959 +       struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
  960 +
  961 +       mv88e639x_sgmii_pcs_pre_config(pcs, interface);
  962 +       mv88e6393x_power_lane(mpcs, false);
  963 +       mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false);
  964 +}
  965 +
  966 +static int mv88e6393x_sgmii_pcs_post_config(struct phylink_pcs *pcs,
  967 +                                           phy_interface_t interface)
  968 +{
  969 +       struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs);
  970 +       int err;
  971 +
  972 +       err = mv88e6393x_erratum_4_8(mpcs);
  973 +       if (err)
  974 +               return err;
  975 +
  976 +       err = mv88e6393x_sgmii_apply_2500basex_an(mpcs, interface, true);
  977 +       if (err)
  978 +               return err;
  979 +
  980 +       err = mv88e6393x_power_lane(mpcs, true);
  981 +       if (err)
  982 +               return err;
  983 +
  984 +       return mv88e639x_sgmii_pcs_post_config(pcs, interface);
  985 +}
  986 +
  987 +static const struct phylink_pcs_ops mv88e6393x_sgmii_pcs_ops = {
  988 +       .pcs_enable = mv88e639x_sgmii_pcs_enable,
  989 +       .pcs_disable = mv88e6393x_sgmii_pcs_disable,
  990 +       .pcs_pre_config = mv88e6393x_sgmii_pcs_pre_config,
  991 +       .pcs_post_config = mv88e6393x_sgmii_pcs_post_config,
  992 +       .pcs_get_state = mv88e639x_sgmii_pcs_get_state,
  993 +       .pcs_an_restart = mv88e639x_sgmii_pcs_an_restart,
  994 +       .pcs_config = mv88e639x_sgmii_pcs_config,
  995 +       .pcs_link_up = mv88e639x_sgmii_pcs_link_up,
  996 +};
  997 +
  998 +static irqreturn_t mv88e6393x_xg_handle_irq(struct mv88e639x_pcs *mpcs)
  999 +{
 1000 +       u16 int_status, stat1;
 1001 +       bool link_down;
 1002 +       int err;
 1003 +
 1004 +       err = mv88e639x_read(mpcs, MV88E6393X_10G_INT_STATUS, &int_status);
 1005 +       if (err)
 1006 +               return IRQ_NONE;
 1007 +
 1008 +       if (int_status & MV88E6393X_10G_INT_LINK_CHANGE) {
 1009 +               err = mv88e639x_read(mpcs, MV88E6390_10G_STAT1, &stat1);
 1010 +               if (err)
 1011 +                       return IRQ_NONE;
 1012 +
 1013 +               link_down = !(stat1 & MDIO_STAT1_LSTATUS);
 1014 +
 1015 +               mv88e639x_pcs_link_change(mpcs, link_down);
 1016 +
 1017 +               return IRQ_HANDLED;
 1018 +       }
 1019 +
 1020 +       return IRQ_NONE;
 1021 +}
 1022 +
 1023 +static int mv88e6393x_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable)
 1024 +{
 1025 +       u16 val = 0;
 1026 +
 1027 +       if (enable)
 1028 +               val = MV88E6393X_10G_INT_LINK_CHANGE;
 1029 +
 1030 +       return mv88e639x_modify(mpcs, MV88E6393X_10G_INT_ENABLE,
 1031 +                               MV88E6393X_10G_INT_LINK_CHANGE, val);
 1032 +}
 1033 +
 1034 +static int mv88e6393x_xg_pcs_enable(struct phylink_pcs *pcs)
 1035 +{
 1036 +       struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
 1037 +
 1038 +       mpcs->handle_irq = mv88e6393x_xg_handle_irq;
 1039 +
 1040 +       return mv88e6393x_xg_control_irq(mpcs, !!mpcs->irq);
 1041 +}
 1042 +
 1043 +static void mv88e6393x_xg_pcs_disable(struct phylink_pcs *pcs)
 1044 +{
 1045 +       struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
 1046 +
 1047 +       mv88e6393x_xg_control_irq(mpcs, false);
 1048 +       mv88e639x_xg_pcs_disable(mpcs);
 1049 +       mv88e6393x_power_lane(mpcs, false);
 1050 +}
 1051 +
 1052 +/* The PCS has to be powered down while CMODE is changed */
 1053 +static void mv88e6393x_xg_pcs_pre_config(struct phylink_pcs *pcs,
 1054 +                                        phy_interface_t interface)
 1055 +{
 1056 +       struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
 1057 +
 1058 +       mv88e639x_xg_pcs_disable(mpcs);
 1059 +       mv88e6393x_power_lane(mpcs, false);
 1060 +}
 1061 +
 1062 +static int mv88e6393x_xg_pcs_post_config(struct phylink_pcs *pcs,
 1063 +                                        phy_interface_t interface)
 1064 +{
 1065 +       struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs);
 1066 +       int err;
 1067 +
 1068 +       if (interface == PHY_INTERFACE_MODE_10GBASER) {
 1069 +               err = mv88e6393x_erratum_5_2(mpcs);
 1070 +               if (err)
 1071 +                       return err;
 1072 +       }
 1073 +
 1074 +       err = mv88e6393x_power_lane(mpcs, true);
 1075 +       if (err)
 1076 +               return err;
 1077 +
 1078 +       return mv88e639x_xg_pcs_enable(mpcs);
 1079 +}
 1080 +
 1081 +static const struct phylink_pcs_ops mv88e6393x_xg_pcs_ops = {
 1082 +       .pcs_enable = mv88e6393x_xg_pcs_enable,
 1083 +       .pcs_disable = mv88e6393x_xg_pcs_disable,
 1084 +       .pcs_pre_config = mv88e6393x_xg_pcs_pre_config,
 1085 +       .pcs_post_config = mv88e6393x_xg_pcs_post_config,
 1086 +       .pcs_get_state = mv88e639x_xg_pcs_get_state,
 1087 +       .pcs_config = mv88e639x_xg_pcs_config,
 1088 +};
 1089 +
 1090 +int mv88e6393x_pcs_init(struct mv88e6xxx_chip *chip, int port)
 1091 +{
 1092 +       struct mv88e639x_pcs *mpcs;
 1093 +       struct mii_bus *bus;
 1094 +       struct device *dev;
 1095 +       int lane, err;
 1096 +
 1097 +       lane = mv88e6xxx_serdes_get_lane(chip, port);
 1098 +       if (lane < 0)
 1099 +               return 0;
 1100 +
 1101 +       bus = mv88e6xxx_default_mdio_bus(chip);
 1102 +       dev = chip->dev;
 1103 +
 1104 +       mpcs = mv88e639x_pcs_alloc(dev, bus, lane, port);
 1105 +       if (!mpcs)
 1106 +               return -ENOMEM;
 1107 +
 1108 +       mpcs->port = &chip->ports[port];
 1109 +       mpcs->sgmii_pcs.ops = &mv88e6393x_sgmii_pcs_ops;
 1110 +       mpcs->xg_pcs.ops = &mv88e6393x_xg_pcs_ops;
 1111 +       mpcs->supports_5g = true;
 1112 +
 1113 +       err = mv88e6393x_erratum_4_6(mpcs);
 1114 +       if (err)
 1115 +               goto err_free;
 1116 +
 1117 +       err = mv88e639x_pcs_setup_irq(mpcs, chip, port);
 1118 +       if (err)
 1119 +               goto err_free;
 1120 +
 1121 +       mpcs->port->pcs_private = mpcs;
 1122 +
 1123 +       return 0;
 1124 +
 1125 +err_free:
 1126 +       kfree(mpcs);
 1127 +       return err;
 1128 +}
 1129 diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c
 1130 index 6cb85d58e0c2..d7484732fcf1 100644
 1131 --- a/drivers/net/dsa/mv88e6xxx/serdes.c
 1132 +++ b/drivers/net/dsa/mv88e6xxx/serdes.c
 1133 @@ -376,57 +376,6 @@ int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 1134         return lane;
 1135  }
 1136  
 1137 -/* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */
 1138 -static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane,
 1139 -                                     bool up)
 1140 -{
 1141 -       u16 val, new_val;
 1142 -       int err;
 1143 -
 1144 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1145 -                                   MV88E6390_10G_CTRL1, &val);
 1146 -
 1147 -       if (err)
 1148 -               return err;
 1149 -
 1150 -       if (up)
 1151 -               new_val = val & ~(MDIO_CTRL1_RESET |
 1152 -                                 MDIO_PCS_CTRL1_LOOPBACK |
 1153 -                                 MDIO_CTRL1_LPOWER);
 1154 -       else
 1155 -               new_val = val | MDIO_CTRL1_LPOWER;
 1156 -
 1157 -       if (val != new_val)
 1158 -               err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 1159 -                                            MV88E6390_10G_CTRL1, new_val);
 1160 -
 1161 -       return err;
 1162 -}
 1163 -
 1164 -/* Set power up/down for SGMII and 1000Base-X */
 1165 -static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane,
 1166 -                                       bool up)
 1167 -{
 1168 -       u16 val, new_val;
 1169 -       int err;
 1170 -
 1171 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1172 -                                   MV88E6390_SGMII_BMCR, &val);
 1173 -       if (err)
 1174 -               return err;
 1175 -
 1176 -       if (up)
 1177 -               new_val = val & ~(BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN);
 1178 -       else
 1179 -               new_val = val | BMCR_PDOWN;
 1180 -
 1181 -       if (val != new_val)
 1182 -               err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 1183 -                                            MV88E6390_SGMII_BMCR, new_val);
 1184 -
 1185 -       return err;
 1186 -}
 1187 -
 1188  struct mv88e6390_serdes_hw_stat {
 1189         char string[ETH_GSTRING_LEN];
 1190         int reg;
 1191 @@ -500,444 +449,6 @@ int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
 1192         return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
 1193  }
 1194  
 1195 -static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, int lane)
 1196 -{
 1197 -       u16 reg;
 1198 -       int err;
 1199 -
 1200 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1201 -                                   MV88E6390_PG_CONTROL, &reg);
 1202 -       if (err)
 1203 -               return err;
 1204 -
 1205 -       reg |= MV88E6390_PG_CONTROL_ENABLE_PC;
 1206 -       return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 1207 -                                     MV88E6390_PG_CONTROL, reg);
 1208 -}
 1209 -
 1210 -int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
 1211 -                          bool up)
 1212 -{
 1213 -       u8 cmode = chip->ports[port].cmode;
 1214 -       int err;
 1215 -
 1216 -       switch (cmode) {
 1217 -       case MV88E6XXX_PORT_STS_CMODE_SGMII:
 1218 -       case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 1219 -       case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
 1220 -               err = mv88e6390_serdes_power_sgmii(chip, lane, up);
 1221 -               break;
 1222 -       case MV88E6XXX_PORT_STS_CMODE_XAUI:
 1223 -       case MV88E6XXX_PORT_STS_CMODE_RXAUI:
 1224 -               err = mv88e6390_serdes_power_10g(chip, lane, up);
 1225 -               break;
 1226 -       default:
 1227 -               err = -EINVAL;
 1228 -               break;
 1229 -       }
 1230 -
 1231 -       if (!err && up)
 1232 -               err = mv88e6390_serdes_enable_checker(chip, lane);
 1233 -
 1234 -       return err;
 1235 -}
 1236 -
 1237 -int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
 1238 -                               int lane, unsigned int mode,
 1239 -                               phy_interface_t interface,
 1240 -                               const unsigned long *advertise)
 1241 -{
 1242 -       u16 val, bmcr, adv;
 1243 -       bool changed;
 1244 -       int err;
 1245 -
 1246 -       switch (interface) {
 1247 -       case PHY_INTERFACE_MODE_SGMII:
 1248 -               adv = 0x0001;
 1249 -               break;
 1250 -
 1251 -       case PHY_INTERFACE_MODE_1000BASEX:
 1252 -               adv = linkmode_adv_to_mii_adv_x(advertise,
 1253 -                                       ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
 1254 -               break;
 1255 -
 1256 -       case PHY_INTERFACE_MODE_2500BASEX:
 1257 -               adv = linkmode_adv_to_mii_adv_x(advertise,
 1258 -                                       ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
 1259 -               break;
 1260 -
 1261 -       default:
 1262 -               return 0;
 1263 -       }
 1264 -
 1265 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1266 -                                   MV88E6390_SGMII_ADVERTISE, &val);
 1267 -       if (err)
 1268 -               return err;
 1269 -
 1270 -       changed = val != adv;
 1271 -       if (changed) {
 1272 -               err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 1273 -                                            MV88E6390_SGMII_ADVERTISE, adv);
 1274 -               if (err)
 1275 -                       return err;
 1276 -       }
 1277 -
 1278 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1279 -                                   MV88E6390_SGMII_BMCR, &val);
 1280 -       if (err)
 1281 -               return err;
 1282 -
 1283 -       if (phylink_autoneg_inband(mode))
 1284 -               bmcr = val | BMCR_ANENABLE;
 1285 -       else
 1286 -               bmcr = val & ~BMCR_ANENABLE;
 1287 -
 1288 -       /* setting ANENABLE triggers a restart of negotiation */
 1289 -       if (bmcr == val)
 1290 -               return changed;
 1291 -
 1292 -       return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 1293 -                                     MV88E6390_SGMII_BMCR, bmcr);
 1294 -}
 1295 -
 1296 -static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip,
 1297 -       int port, int lane, struct phylink_link_state *state)
 1298 -{
 1299 -       u16 bmsr, lpa, status;
 1300 -       int err;
 1301 -
 1302 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1303 -                                   MV88E6390_SGMII_BMSR, &bmsr);
 1304 -       if (err) {
 1305 -               dev_err(chip->dev, "can't read Serdes PHY BMSR: %d\n", err);
 1306 -               return err;
 1307 -       }
 1308 -
 1309 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1310 -                                   MV88E6390_SGMII_PHY_STATUS, &status);
 1311 -       if (err) {
 1312 -               dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
 1313 -               return err;
 1314 -       }
 1315 -
 1316 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1317 -                                   MV88E6390_SGMII_LPA, &lpa);
 1318 -       if (err) {
 1319 -               dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
 1320 -               return err;
 1321 -       }
 1322 -
 1323 -       return mv88e6xxx_pcs_decode_state(chip->dev, bmsr, lpa, status, state);
 1324 -}
 1325 -
 1326 -static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
 1327 -       int port, int lane, struct phylink_link_state *state)
 1328 -{
 1329 -       u16 status;
 1330 -       int err;
 1331 -
 1332 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1333 -                                   MV88E6390_10G_STAT1, &status);
 1334 -       if (err)
 1335 -               return err;
 1336 -
 1337 -       state->link = !!(status & MDIO_STAT1_LSTATUS);
 1338 -       if (state->link) {
 1339 -               state->speed = SPEED_10000;
 1340 -               state->duplex = DUPLEX_FULL;
 1341 -       }
 1342 -
 1343 -       return 0;
 1344 -}
 1345 -
 1346 -static int mv88e6393x_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
 1347 -                                              int port, int lane,
 1348 -                                              struct phylink_link_state *state)
 1349 -{
 1350 -       u16 status;
 1351 -       int err;
 1352 -
 1353 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1354 -                                   MV88E6390_10G_STAT1, &status);
 1355 -       if (err)
 1356 -               return err;
 1357 -
 1358 -       state->link = !!(status & MDIO_STAT1_LSTATUS);
 1359 -       if (state->link) {
 1360 -               if (state->interface == PHY_INTERFACE_MODE_5GBASER)
 1361 -                       state->speed = SPEED_5000;
 1362 -               else
 1363 -                       state->speed = SPEED_10000;
 1364 -               state->duplex = DUPLEX_FULL;
 1365 -       }
 1366 -
 1367 -       return 0;
 1368 -}
 1369 -
 1370 -int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
 1371 -                                  int lane, struct phylink_link_state *state)
 1372 -{
 1373 -       switch (state->interface) {
 1374 -       case PHY_INTERFACE_MODE_SGMII:
 1375 -       case PHY_INTERFACE_MODE_1000BASEX:
 1376 -       case PHY_INTERFACE_MODE_2500BASEX:
 1377 -               return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane,
 1378 -                                                           state);
 1379 -       case PHY_INTERFACE_MODE_XAUI:
 1380 -       case PHY_INTERFACE_MODE_RXAUI:
 1381 -               return mv88e6390_serdes_pcs_get_state_10g(chip, port, lane,
 1382 -                                                         state);
 1383 -
 1384 -       default:
 1385 -               return -EOPNOTSUPP;
 1386 -       }
 1387 -}
 1388 -
 1389 -int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
 1390 -                                   int lane, struct phylink_link_state *state)
 1391 -{
 1392 -       switch (state->interface) {
 1393 -       case PHY_INTERFACE_MODE_SGMII:
 1394 -       case PHY_INTERFACE_MODE_1000BASEX:
 1395 -       case PHY_INTERFACE_MODE_2500BASEX:
 1396 -               return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane,
 1397 -                                                           state);
 1398 -       case PHY_INTERFACE_MODE_5GBASER:
 1399 -       case PHY_INTERFACE_MODE_10GBASER:
 1400 -               return mv88e6393x_serdes_pcs_get_state_10g(chip, port, lane,
 1401 -                                                          state);
 1402 -
 1403 -       default:
 1404 -               return -EOPNOTSUPP;
 1405 -       }
 1406 -}
 1407 -
 1408 -int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
 1409 -                                   int lane)
 1410 -{
 1411 -       u16 bmcr;
 1412 -       int err;
 1413 -
 1414 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1415 -                                   MV88E6390_SGMII_BMCR, &bmcr);
 1416 -       if (err)
 1417 -               return err;
 1418 -
 1419 -       return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 1420 -                                     MV88E6390_SGMII_BMCR,
 1421 -                                     bmcr | BMCR_ANRESTART);
 1422 -}
 1423 -
 1424 -int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
 1425 -                                int lane, int speed, int duplex)
 1426 -{
 1427 -       u16 val, bmcr;
 1428 -       int err;
 1429 -
 1430 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1431 -                                   MV88E6390_SGMII_BMCR, &val);
 1432 -       if (err)
 1433 -               return err;
 1434 -
 1435 -       bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
 1436 -       switch (speed) {
 1437 -       case SPEED_2500:
 1438 -       case SPEED_1000:
 1439 -               bmcr |= BMCR_SPEED1000;
 1440 -               break;
 1441 -       case SPEED_100:
 1442 -               bmcr |= BMCR_SPEED100;
 1443 -               break;
 1444 -       case SPEED_10:
 1445 -               break;
 1446 -       }
 1447 -
 1448 -       if (duplex == DUPLEX_FULL)
 1449 -               bmcr |= BMCR_FULLDPLX;
 1450 -
 1451 -       if (bmcr == val)
 1452 -               return 0;
 1453 -
 1454 -       return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 1455 -                                     MV88E6390_SGMII_BMCR, bmcr);
 1456 -}
 1457 -
 1458 -static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
 1459 -                                           int port, int lane)
 1460 -{
 1461 -       u16 bmsr;
 1462 -       int err;
 1463 -
 1464 -       /* If the link has dropped, we want to know about it. */
 1465 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1466 -                                   MV88E6390_SGMII_BMSR, &bmsr);
 1467 -       if (err) {
 1468 -               dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
 1469 -               return;
 1470 -       }
 1471 -
 1472 -       dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
 1473 -}
 1474 -
 1475 -static void mv88e6393x_serdes_irq_link_10g(struct mv88e6xxx_chip *chip,
 1476 -                                          int port, u8 lane)
 1477 -{
 1478 -       u16 status;
 1479 -       int err;
 1480 -
 1481 -       /* If the link has dropped, we want to know about it. */
 1482 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1483 -                                   MV88E6390_10G_STAT1, &status);
 1484 -       if (err) {
 1485 -               dev_err(chip->dev, "can't read Serdes STAT1: %d\n", err);
 1486 -               return;
 1487 -       }
 1488 -
 1489 -       dsa_port_phylink_mac_change(chip->ds, port, !!(status & MDIO_STAT1_LSTATUS));
 1490 -}
 1491 -
 1492 -static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
 1493 -                                            int lane, bool enable)
 1494 -{
 1495 -       u16 val = 0;
 1496 -
 1497 -       if (enable)
 1498 -               val |= MV88E6390_SGMII_INT_LINK_DOWN |
 1499 -                       MV88E6390_SGMII_INT_LINK_UP;
 1500 -
 1501 -       return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 1502 -                                     MV88E6390_SGMII_INT_ENABLE, val);
 1503 -}
 1504 -
 1505 -int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
 1506 -                               bool enable)
 1507 -{
 1508 -       u8 cmode = chip->ports[port].cmode;
 1509 -
 1510 -       switch (cmode) {
 1511 -       case MV88E6XXX_PORT_STS_CMODE_SGMII:
 1512 -       case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 1513 -       case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
 1514 -               return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
 1515 -       }
 1516 -
 1517 -       return 0;
 1518 -}
 1519 -
 1520 -static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
 1521 -                                            int lane, u16 *status)
 1522 -{
 1523 -       int err;
 1524 -
 1525 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1526 -                                   MV88E6390_SGMII_INT_STATUS, status);
 1527 -
 1528 -       return err;
 1529 -}
 1530 -
 1531 -static int mv88e6393x_serdes_irq_enable_10g(struct mv88e6xxx_chip *chip,
 1532 -                                           u8 lane, bool enable)
 1533 -{
 1534 -       u16 val = 0;
 1535 -
 1536 -       if (enable)
 1537 -               val |= MV88E6393X_10G_INT_LINK_CHANGE;
 1538 -
 1539 -       return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 1540 -                                     MV88E6393X_10G_INT_ENABLE, val);
 1541 -}
 1542 -
 1543 -int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
 1544 -                                int lane, bool enable)
 1545 -{
 1546 -       u8 cmode = chip->ports[port].cmode;
 1547 -
 1548 -       switch (cmode) {
 1549 -       case MV88E6XXX_PORT_STS_CMODE_SGMII:
 1550 -       case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 1551 -       case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
 1552 -               return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
 1553 -       case MV88E6393X_PORT_STS_CMODE_5GBASER:
 1554 -       case MV88E6393X_PORT_STS_CMODE_10GBASER:
 1555 -               return mv88e6393x_serdes_irq_enable_10g(chip, lane, enable);
 1556 -       }
 1557 -
 1558 -       return 0;
 1559 -}
 1560 -
 1561 -static int mv88e6393x_serdes_irq_status_10g(struct mv88e6xxx_chip *chip,
 1562 -                                           u8 lane, u16 *status)
 1563 -{
 1564 -       int err;
 1565 -
 1566 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1567 -                                   MV88E6393X_10G_INT_STATUS, status);
 1568 -
 1569 -       return err;
 1570 -}
 1571 -
 1572 -irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
 1573 -                                        int lane)
 1574 -{
 1575 -       u8 cmode = chip->ports[port].cmode;
 1576 -       irqreturn_t ret = IRQ_NONE;
 1577 -       u16 status;
 1578 -       int err;
 1579 -
 1580 -       switch (cmode) {
 1581 -       case MV88E6XXX_PORT_STS_CMODE_SGMII:
 1582 -       case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 1583 -       case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
 1584 -               err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
 1585 -               if (err)
 1586 -                       return ret;
 1587 -               if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
 1588 -                             MV88E6390_SGMII_INT_LINK_UP)) {
 1589 -                       ret = IRQ_HANDLED;
 1590 -                       mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
 1591 -               }
 1592 -               break;
 1593 -       case MV88E6393X_PORT_STS_CMODE_5GBASER:
 1594 -       case MV88E6393X_PORT_STS_CMODE_10GBASER:
 1595 -               err = mv88e6393x_serdes_irq_status_10g(chip, lane, &status);
 1596 -               if (err)
 1597 -                       return err;
 1598 -               if (status & MV88E6393X_10G_INT_LINK_CHANGE) {
 1599 -                       ret = IRQ_HANDLED;
 1600 -                       mv88e6393x_serdes_irq_link_10g(chip, port, lane);
 1601 -               }
 1602 -               break;
 1603 -       }
 1604 -
 1605 -       return ret;
 1606 -}
 1607 -
 1608 -irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
 1609 -                                       int lane)
 1610 -{
 1611 -       u8 cmode = chip->ports[port].cmode;
 1612 -       irqreturn_t ret = IRQ_NONE;
 1613 -       u16 status;
 1614 -       int err;
 1615 -
 1616 -       switch (cmode) {
 1617 -       case MV88E6XXX_PORT_STS_CMODE_SGMII:
 1618 -       case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 1619 -       case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
 1620 -               err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
 1621 -               if (err)
 1622 -                       return ret;
 1623 -               if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
 1624 -                             MV88E6390_SGMII_INT_LINK_UP)) {
 1625 -                       ret = IRQ_HANDLED;
 1626 -                       mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
 1627 -               }
 1628 -       }
 1629 -
 1630 -       return ret;
 1631 -}
 1632 -
 1633  unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
 1634  {
 1635         return irq_find_mapping(chip->g2_irq.domain, port);
 1636 @@ -1036,257 +547,3 @@ int mv88e6352_serdes_set_tx_amplitude(struct mv88e6xxx_chip *chip, int port,
 1637  
 1638         return mv88e6352_serdes_write(chip, MV88E6352_SERDES_SPEC_CTRL2, ctrl);
 1639  }
 1640 -
 1641 -static int mv88e6393x_serdes_power_lane(struct mv88e6xxx_chip *chip, int lane,
 1642 -                                       bool on)
 1643 -{
 1644 -       u16 reg;
 1645 -       int err;
 1646 -
 1647 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1648 -                                   MV88E6393X_SERDES_CTRL1, &reg);
 1649 -       if (err)
 1650 -               return err;
 1651 -
 1652 -       if (on)
 1653 -               reg &= ~(MV88E6393X_SERDES_CTRL1_TX_PDOWN |
 1654 -                        MV88E6393X_SERDES_CTRL1_RX_PDOWN);
 1655 -       else
 1656 -               reg |= MV88E6393X_SERDES_CTRL1_TX_PDOWN |
 1657 -                      MV88E6393X_SERDES_CTRL1_RX_PDOWN;
 1658 -
 1659 -       return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 1660 -                                     MV88E6393X_SERDES_CTRL1, reg);
 1661 -}
 1662 -
 1663 -static int mv88e6393x_serdes_erratum_4_6(struct mv88e6xxx_chip *chip, int lane)
 1664 -{
 1665 -       u16 reg;
 1666 -       int err;
 1667 -
 1668 -       /* mv88e6393x family errata 4.6:
 1669 -        * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD
 1670 -        * mode or P0_mode is configured for [x]MII.
 1671 -        * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1.
 1672 -        *
 1673 -        * It seems that after this workaround the SERDES is automatically
 1674 -        * powered up (the bit is cleared), so power it down.
 1675 -        */
 1676 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1677 -                                   MV88E6393X_SERDES_POC, &reg);
 1678 -       if (err)
 1679 -               return err;
 1680 -
 1681 -       reg &= ~MV88E6393X_SERDES_POC_PDOWN;
 1682 -       reg |= MV88E6393X_SERDES_POC_RESET;
 1683 -
 1684 -       err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 1685 -                                    MV88E6393X_SERDES_POC, reg);
 1686 -       if (err)
 1687 -               return err;
 1688 -
 1689 -       err = mv88e6390_serdes_power_sgmii(chip, lane, false);
 1690 -       if (err)
 1691 -               return err;
 1692 -
 1693 -       return mv88e6393x_serdes_power_lane(chip, lane, false);
 1694 -}
 1695 -
 1696 -int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip)
 1697 -{
 1698 -       int err;
 1699 -
 1700 -       err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT0_LANE);
 1701 -       if (err)
 1702 -               return err;
 1703 -
 1704 -       err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT9_LANE);
 1705 -       if (err)
 1706 -               return err;
 1707 -
 1708 -       return mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT10_LANE);
 1709 -}
 1710 -
 1711 -static int mv88e6393x_serdes_erratum_4_8(struct mv88e6xxx_chip *chip, int lane)
 1712 -{
 1713 -       u16 reg, pcs;
 1714 -       int err;
 1715 -
 1716 -       /* mv88e6393x family errata 4.8:
 1717 -        * When a SERDES port is operating in 1000BASE-X or SGMII mode link may
 1718 -        * not come up after hardware reset or software reset of SERDES core.
 1719 -        * Workaround is to write SERDES register 4.F074.14=1 for only those
 1720 -        * modes and 0 in all other modes.
 1721 -        */
 1722 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1723 -                                   MV88E6393X_SERDES_POC, &pcs);
 1724 -       if (err)
 1725 -               return err;
 1726 -
 1727 -       pcs &= MV88E6393X_SERDES_POC_PCS_MASK;
 1728 -
 1729 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1730 -                                   MV88E6393X_ERRATA_4_8_REG, &reg);
 1731 -       if (err)
 1732 -               return err;
 1733 -
 1734 -       if (pcs == MV88E6393X_SERDES_POC_PCS_1000BASEX ||
 1735 -           pcs == MV88E6393X_SERDES_POC_PCS_SGMII_PHY ||
 1736 -           pcs == MV88E6393X_SERDES_POC_PCS_SGMII_MAC)
 1737 -               reg |= MV88E6393X_ERRATA_4_8_BIT;
 1738 -       else
 1739 -               reg &= ~MV88E6393X_ERRATA_4_8_BIT;
 1740 -
 1741 -       return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 1742 -                                     MV88E6393X_ERRATA_4_8_REG, reg);
 1743 -}
 1744 -
 1745 -static int mv88e6393x_serdes_erratum_5_2(struct mv88e6xxx_chip *chip, int lane,
 1746 -                                        u8 cmode)
 1747 -{
 1748 -       static const struct {
 1749 -               u16 dev, reg, val, mask;
 1750 -       } fixes[] = {
 1751 -               { MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff },
 1752 -               { MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff },
 1753 -               { MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff },
 1754 -               { MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f },
 1755 -               { MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 },
 1756 -               { MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff },
 1757 -               { MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC,
 1758 -                 MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET },
 1759 -       };
 1760 -       int err, i;
 1761 -       u16 reg;
 1762 -
 1763 -       /* mv88e6393x family errata 5.2:
 1764 -        * For optimal signal integrity the following sequence should be applied
 1765 -        * to SERDES operating in 10G mode. These registers only apply to 10G
 1766 -        * operation and have no effect on other speeds.
 1767 -        */
 1768 -       if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER)
 1769 -               return 0;
 1770 -
 1771 -       for (i = 0; i < ARRAY_SIZE(fixes); ++i) {
 1772 -               err = mv88e6390_serdes_read(chip, lane, fixes[i].dev,
 1773 -                                           fixes[i].reg, &reg);
 1774 -               if (err)
 1775 -                       return err;
 1776 -
 1777 -               reg &= ~fixes[i].mask;
 1778 -               reg |= fixes[i].val;
 1779 -
 1780 -               err = mv88e6390_serdes_write(chip, lane, fixes[i].dev,
 1781 -                                            fixes[i].reg, reg);
 1782 -               if (err)
 1783 -                       return err;
 1784 -       }
 1785 -
 1786 -       return 0;
 1787 -}
 1788 -
 1789 -static int mv88e6393x_serdes_fix_2500basex_an(struct mv88e6xxx_chip *chip,
 1790 -                                             int lane, u8 cmode, bool on)
 1791 -{
 1792 -       u16 reg;
 1793 -       int err;
 1794 -
 1795 -       if (cmode != MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 1796 -               return 0;
 1797 -
 1798 -       /* Inband AN is broken on Amethyst in 2500base-x mode when set by
 1799 -        * standard mechanism (via cmode).
 1800 -        * We can get around this by configuring the PCS mode to 1000base-x
 1801 -        * and then writing value 0x58 to register 1e.8000. (This must be done
 1802 -        * while SerDes receiver and transmitter are disabled, which is, when
 1803 -        * this function is called.)
 1804 -        * It seem that when we do this configuration to 2500base-x mode (by
 1805 -        * changing PCS mode to 1000base-x and frequency to 3.125 GHz from
 1806 -        * 1.25 GHz) and then configure to sgmii or 1000base-x, the device
 1807 -        * thinks that it already has SerDes at 1.25 GHz and does not change
 1808 -        * the 1e.8000 register, leaving SerDes at 3.125 GHz.
 1809 -        * To avoid this, change PCS mode back to 2500base-x when disabling
 1810 -        * SerDes from 2500base-x mode.
 1811 -        */
 1812 -       err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 1813 -                                   MV88E6393X_SERDES_POC, &reg);
 1814 -       if (err)
 1815 -               return err;
 1816 -
 1817 -       reg &= ~(MV88E6393X_SERDES_POC_PCS_MASK | MV88E6393X_SERDES_POC_AN);
 1818 -       if (on)
 1819 -               reg |= MV88E6393X_SERDES_POC_PCS_1000BASEX |
 1820 -                      MV88E6393X_SERDES_POC_AN;
 1821 -       else
 1822 -               reg |= MV88E6393X_SERDES_POC_PCS_2500BASEX;
 1823 -       reg |= MV88E6393X_SERDES_POC_RESET;
 1824 -
 1825 -       err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 1826 -                                    MV88E6393X_SERDES_POC, reg);
 1827 -       if (err)
 1828 -               return err;
 1829 -
 1830 -       err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_VEND1, 0x8000, 0x58);
 1831 -       if (err)
 1832 -               return err;
 1833 -
 1834 -       return 0;
 1835 -}
 1836 -
 1837 -int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
 1838 -                           bool on)
 1839 -{
 1840 -       u8 cmode = chip->ports[port].cmode;
 1841 -       int err;
 1842 -
 1843 -       if (port != 0 && port != 9 && port != 10)
 1844 -               return -EOPNOTSUPP;
 1845 -
 1846 -       if (on) {
 1847 -               err = mv88e6393x_serdes_erratum_4_8(chip, lane);
 1848 -               if (err)
 1849 -                       return err;
 1850 -
 1851 -               err = mv88e6393x_serdes_erratum_5_2(chip, lane, cmode);
 1852 -               if (err)
 1853 -                       return err;
 1854 -
 1855 -               err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode,
 1856 -                                                        true);
 1857 -               if (err)
 1858 -                       return err;
 1859 -
 1860 -               err = mv88e6393x_serdes_power_lane(chip, lane, true);
 1861 -               if (err)
 1862 -                       return err;
 1863 -       }
 1864 -
 1865 -       switch (cmode) {
 1866 -       case MV88E6XXX_PORT_STS_CMODE_SGMII:
 1867 -       case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 1868 -       case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
 1869 -               err = mv88e6390_serdes_power_sgmii(chip, lane, on);
 1870 -               break;
 1871 -       case MV88E6393X_PORT_STS_CMODE_5GBASER:
 1872 -       case MV88E6393X_PORT_STS_CMODE_10GBASER:
 1873 -               err = mv88e6390_serdes_power_10g(chip, lane, on);
 1874 -               break;
 1875 -       default:
 1876 -               err = -EINVAL;
 1877 -               break;
 1878 -       }
 1879 -
 1880 -       if (err)
 1881 -               return err;
 1882 -
 1883 -       if (!on) {
 1884 -               err = mv88e6393x_serdes_power_lane(chip, lane, false);
 1885 -               if (err)
 1886 -                       return err;
 1887 -
 1888 -               err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode,
 1889 -                                                        false);
 1890 -       }
 1891 -
 1892 -       return err;
 1893 -}
 1894 diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h
 1895 index 8d3e068665cf..6d8248592877 100644
 1896 --- a/drivers/net/dsa/mv88e6xxx/serdes.h
 1897 +++ b/drivers/net/dsa/mv88e6xxx/serdes.h
 1898 @@ -46,6 +46,10 @@ struct phylink_link_state;
 1899  /* 10GBASE-R and 10GBASE-X4/X2 */
 1900  #define MV88E6390_10G_CTRL1            (0x1000 + MDIO_CTRL1)
 1901  #define MV88E6390_10G_STAT1            (0x1000 + MDIO_STAT1)
 1902 +#define MV88E6390_10G_INT_ENABLE       0x9001
 1903 +#define MV88E6390_10G_INT_LINK_DOWN    BIT(3)
 1904 +#define MV88E6390_10G_INT_LINK_UP      BIT(2)
 1905 +#define MV88E6390_10G_INT_STATUS       0x9003
 1906  #define MV88E6393X_10G_INT_ENABLE      0x9000
 1907  #define MV88E6393X_10G_INT_LINK_CHANGE BIT(2)
 1908  #define MV88E6393X_10G_INT_STATUS      0x9001
 1909 @@ -112,35 +116,10 @@ int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
 1910  int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
 1911  int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
 1912  int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
 1913 -int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
 1914 -                               int lane, unsigned int mode,
 1915 -                               phy_interface_t interface,
 1916 -                               const unsigned long *advertise);
 1917 -int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
 1918 -                                  int lane, struct phylink_link_state *state);
 1919 -int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
 1920 -                                   int lane, struct phylink_link_state *state);
 1921 -int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
 1922 -                                   int lane);
 1923 -int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
 1924 -                                int lane, int speed, int duplex);
 1925  unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
 1926                                           int port);
 1927  unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
 1928                                           int port);
 1929 -int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
 1930 -                          bool on);
 1931 -int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
 1932 -                           bool on);
 1933 -int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip);
 1934 -int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
 1935 -                               bool enable);
 1936 -int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
 1937 -                                int lane, bool enable);
 1938 -irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
 1939 -                                       int lane);
 1940 -irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
 1941 -                                        int lane);
 1942  int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
 1943  int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
 1944                                  int port, uint8_t *data);
 1945 @@ -230,4 +209,11 @@ void mv88e6185_pcs_teardown(struct mv88e6xxx_chip *chip, int port);
 1946  int mv88e6352_pcs_init(struct mv88e6xxx_chip *chip, int port);
 1947  void mv88e6352_pcs_teardown(struct mv88e6xxx_chip *chip, int port);
 1948  
 1949 +int mv88e6390_pcs_init(struct mv88e6xxx_chip *chip, int port);
 1950 +int mv88e6393x_pcs_init(struct mv88e6xxx_chip *chip, int port);
 1951 +void mv88e639x_pcs_teardown(struct mv88e6xxx_chip *chip, int port);
 1952 +
 1953 +struct phylink_pcs *mv88e639x_pcs_select(struct mv88e6xxx_chip *chip, int port,
 1954 +                                        phy_interface_t mode);
 1955 +
 1956  #endif
 1957 -- 
 1958 2.35.1
 1959