^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Marvell 88E6xxx SERDES manipulation, via SMI bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2008 Marvell Semiconductor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/irqdomain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/mii.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "chip.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "global2.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "phy.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "port.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "serdes.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) u16 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) return mv88e6xxx_phy_page_read(chip, MV88E6352_ADDR_SERDES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) MV88E6352_SERDES_PAGE_FIBER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return mv88e6xxx_phy_page_write(chip, MV88E6352_ADDR_SERDES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) MV88E6352_SERDES_PAGE_FIBER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int lane, int device, int reg, u16 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return mv88e6xxx_phy_read(chip, lane, reg_c45, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int lane, int device, int reg, u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return mv88e6xxx_phy_write(chip, lane, reg_c45, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u16 status, u16 lpa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) state->duplex = status &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) DUPLEX_FULL : DUPLEX_HALF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (status & MV88E6390_SGMII_PHY_STATUS_TX_PAUSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) state->pause |= MLO_PAUSE_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (status & MV88E6390_SGMII_PHY_STATUS_RX_PAUSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) state->pause |= MLO_PAUSE_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) state->speed = SPEED_2500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) state->speed = SPEED_1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) state->speed = SPEED_100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) case MV88E6390_SGMII_PHY_STATUS_SPEED_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) state->speed = SPEED_10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) dev_err(chip->dev, "invalid PHY speed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) state->link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) else if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) bool up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) u16 val, new_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) new_val = val & ~BMCR_PDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) new_val = val | BMCR_PDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (val != new_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) err = mv88e6352_serdes_write(chip, MII_BMCR, new_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u8 lane, unsigned int mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) phy_interface_t interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) const unsigned long *advertise)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) u16 adv, bmcr, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) bool changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) switch (interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) case PHY_INTERFACE_MODE_SGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) adv = 0x0001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case PHY_INTERFACE_MODE_1000BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) adv = linkmode_adv_to_mii_adv_x(advertise,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) err = mv88e6352_serdes_read(chip, MII_ADVERTISE, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) changed = val != adv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (changed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) err = mv88e6352_serdes_write(chip, MII_ADVERTISE, adv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (phylink_autoneg_inband(mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) bmcr = val | BMCR_ANENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) bmcr = val & ~BMCR_ANENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (bmcr == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return mv88e6352_serdes_write(chip, MII_BMCR, bmcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) u8 lane, struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u16 lpa, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) err = mv88e6352_serdes_read(chip, 0x11, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) err = mv88e6352_serdes_read(chip, MII_LPA, &lpa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) u8 lane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u16 bmcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) err = mv88e6352_serdes_read(chip, MII_BMCR, &bmcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return mv88e6352_serdes_write(chip, MII_BMCR, bmcr | BMCR_ANRESTART);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int mv88e6352_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) u8 lane, int speed, int duplex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) u16 val, bmcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) switch (speed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) case SPEED_1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) bmcr |= BMCR_SPEED1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) case SPEED_100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) bmcr |= BMCR_SPEED100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) case SPEED_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (duplex == DUPLEX_FULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) bmcr |= BMCR_FULLDPLX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (bmcr == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return mv88e6352_serdes_write(chip, MII_BMCR, bmcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) u8 mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) u8 cmode = chip->ports[port].cmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u8 lane = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) lane = 0xff; /* Unused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return lane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (mv88e6xxx_serdes_get_lane(chip, port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) struct mv88e6352_serdes_hw_stat {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) char string[ETH_GSTRING_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) int sizeof_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) { "serdes_fibre_rx_error", 16, 21 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) { "serdes_PRBS_error", 32, 24 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (mv88e6352_port_has_serdes(chip, port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) int port, uint8_t *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct mv88e6352_serdes_hw_stat *stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (!mv88e6352_port_has_serdes(chip, port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) stat = &mv88e6352_serdes_hw_stats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) memcpy(data + i * ETH_GSTRING_LEN, stat->string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) ETH_GSTRING_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct mv88e6352_serdes_hw_stat *stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) u64 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) err = mv88e6352_serdes_read(chip, stat->reg, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) dev_err(chip->dev, "failed to read statistic\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) val = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (stat->sizeof_stat == 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) err = mv88e6352_serdes_read(chip, stat->reg + 1, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) dev_err(chip->dev, "failed to read statistic\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) val = val << 16 | reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) uint64_t *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct mv88e6352_serdes_hw_stat *stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) u64 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (!mv88e6352_port_has_serdes(chip, port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) stat = &mv88e6352_serdes_hw_stats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) value = mv88e6352_serdes_get_stat(chip, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) mv88e6xxx_port->serdes_stats[i] += value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) data[i] = mv88e6xxx_port->serdes_stats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) u16 bmsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* If the link has dropped, we want to know about it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) err = mv88e6352_serdes_read(chip, MII_BMSR, &bmsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) u8 lane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) irqreturn_t ret = IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) u16 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (status & MV88E6352_SERDES_INT_LINK_CHANGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ret = IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) mv88e6352_serdes_irq_link(chip, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) u16 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) val |= MV88E6352_SERDES_INT_LINK_CHANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!mv88e6352_port_has_serdes(chip, port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return 32 * sizeof(u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) u16 *p = _p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (!mv88e6352_port_has_serdes(chip, port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) for (i = 0 ; i < 32; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) mv88e6352_serdes_read(chip, i, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) p[i] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) u8 cmode = chip->ports[port].cmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) u8 lane = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) switch (port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) lane = MV88E6341_PORT5_LANE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return lane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) u8 mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) u8 cmode = chip->ports[port].cmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) u8 lane = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) switch (port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) case 9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) lane = MV88E6390_PORT9_LANE0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) case 10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) lane = MV88E6390_PORT10_LANE0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return lane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) u8 mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) u8 cmode_port = chip->ports[port].cmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) u8 cmode_port10 = chip->ports[10].cmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) u8 cmode_port9 = chip->ports[9].cmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) u8 lane = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) switch (port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) lane = MV88E6390_PORT9_LANE1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) lane = MV88E6390_PORT9_LANE2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) lane = MV88E6390_PORT9_LANE3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) lane = MV88E6390_PORT10_LANE1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) lane = MV88E6390_PORT10_LANE2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) lane = MV88E6390_PORT10_LANE3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) case 9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) lane = MV88E6390_PORT9_LANE0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) case 10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) lane = MV88E6390_PORT10_LANE0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return lane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, u8 lane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) bool up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) u16 val, new_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) MV88E6390_10G_CTRL1, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) new_val = val & ~(MDIO_CTRL1_RESET |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) MDIO_PCS_CTRL1_LOOPBACK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) MDIO_CTRL1_LPOWER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) new_val = val | MDIO_CTRL1_LPOWER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (val != new_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) MV88E6390_10G_CTRL1, new_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) /* Set power up/down for SGMII and 1000Base-X */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, u8 lane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) bool up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) u16 val, new_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) MV88E6390_SGMII_BMCR, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) new_val = val & ~(BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) new_val = val | BMCR_PDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (val != new_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) MV88E6390_SGMII_BMCR, new_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct mv88e6390_serdes_hw_stat {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) char string[ETH_GSTRING_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) { "serdes_rx_pkts", 0xf021 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) { "serdes_rx_bytes", 0xf024 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) { "serdes_rx_pkts_error", 0xf027 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (mv88e6xxx_serdes_get_lane(chip, port) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) int port, uint8_t *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) struct mv88e6390_serdes_hw_stat *stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (mv88e6xxx_serdes_get_lane(chip, port) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) stat = &mv88e6390_serdes_hw_stats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) memcpy(data + i * ETH_GSTRING_LEN, stat->string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ETH_GSTRING_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) struct mv88e6390_serdes_hw_stat *stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) u16 reg[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) stat->reg + i, ®[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) dev_err(chip->dev, "failed to read statistic\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) uint64_t *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) struct mv88e6390_serdes_hw_stat *stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) int lane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) lane = mv88e6xxx_serdes_get_lane(chip, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (lane == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) stat = &mv88e6390_serdes_hw_stats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) data[i] = mv88e6390_serdes_get_stat(chip, lane, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, u8 lane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) MV88E6390_PG_CONTROL, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) reg |= MV88E6390_PG_CONTROL_ENABLE_PC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) MV88E6390_PG_CONTROL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, u8 lane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) bool up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) u8 cmode = chip->ports[port].cmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) switch (cmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) case MV88E6XXX_PORT_STS_CMODE_SGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) err = mv88e6390_serdes_power_sgmii(chip, lane, up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) case MV88E6XXX_PORT_STS_CMODE_XAUI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) case MV88E6XXX_PORT_STS_CMODE_RXAUI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) err = mv88e6390_serdes_power_10g(chip, lane, up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (!err && up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) err = mv88e6390_serdes_enable_checker(chip, lane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) u8 lane, unsigned int mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) phy_interface_t interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) const unsigned long *advertise)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) u16 val, bmcr, adv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) bool changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) switch (interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) case PHY_INTERFACE_MODE_SGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) adv = 0x0001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) case PHY_INTERFACE_MODE_1000BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) adv = linkmode_adv_to_mii_adv_x(advertise,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) case PHY_INTERFACE_MODE_2500BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) adv = linkmode_adv_to_mii_adv_x(advertise,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) MV88E6390_SGMII_ADVERTISE, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) changed = val != adv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (changed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) MV88E6390_SGMII_ADVERTISE, adv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) MV88E6390_SGMII_BMCR, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (phylink_autoneg_inband(mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) bmcr = val | BMCR_ANENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) bmcr = val & ~BMCR_ANENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) /* setting ANENABLE triggers a restart of negotiation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (bmcr == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) MV88E6390_SGMII_BMCR, bmcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) int port, u8 lane, struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) u16 lpa, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) MV88E6390_SGMII_PHY_STATUS, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) MV88E6390_SGMII_LPA, &lpa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) int port, u8 lane, struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) u16 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) MV88E6390_10G_STAT1, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) state->link = !!(status & MDIO_STAT1_LSTATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (state->link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) state->speed = SPEED_10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) state->duplex = DUPLEX_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) u8 lane, struct phylink_link_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) switch (state->interface) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) case PHY_INTERFACE_MODE_SGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) case PHY_INTERFACE_MODE_1000BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) case PHY_INTERFACE_MODE_2500BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) case PHY_INTERFACE_MODE_XAUI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) case PHY_INTERFACE_MODE_RXAUI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return mv88e6390_serdes_pcs_get_state_10g(chip, port, lane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) u8 lane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) u16 bmcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) MV88E6390_SGMII_BMCR, &bmcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) MV88E6390_SGMII_BMCR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) bmcr | BMCR_ANRESTART);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) u8 lane, int speed, int duplex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) u16 val, bmcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) MV88E6390_SGMII_BMCR, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) switch (speed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) case SPEED_2500:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) case SPEED_1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) bmcr |= BMCR_SPEED1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) case SPEED_100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) bmcr |= BMCR_SPEED100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) case SPEED_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (duplex == DUPLEX_FULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) bmcr |= BMCR_FULLDPLX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (bmcr == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) MV88E6390_SGMII_BMCR, bmcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) int port, u8 lane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) u16 bmsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) /* If the link has dropped, we want to know about it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) MV88E6390_SGMII_BMSR, &bmsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) u8 lane, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) u16 val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) val |= MV88E6390_SGMII_INT_LINK_DOWN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) MV88E6390_SGMII_INT_LINK_UP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) MV88E6390_SGMII_INT_ENABLE, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, u8 lane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) u8 cmode = chip->ports[port].cmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) switch (cmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) case MV88E6XXX_PORT_STS_CMODE_SGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) u8 lane, u16 *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) MV88E6390_SGMII_INT_STATUS, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) u8 lane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) u8 cmode = chip->ports[port].cmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) irqreturn_t ret = IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) u16 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) switch (cmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) case MV88E6XXX_PORT_STS_CMODE_SGMII:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) MV88E6390_SGMII_INT_LINK_UP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) ret = IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return irq_find_mapping(chip->g2_irq.domain, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) static const u16 mv88e6390_serdes_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) /* SERDES common registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) 0xf00a, 0xf00b, 0xf00c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) 0xf010, 0xf011, 0xf012, 0xf013,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) 0xf016, 0xf017, 0xf018,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) 0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) 0xf028, 0xf029,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) 0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) 0xf038, 0xf039,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) /* SGMII */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) 0x2008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) 0x200f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) 0xa000, 0xa001, 0xa002, 0xa003,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) /* 10Gbase-X */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) 0x1008,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) 0x100e, 0x100f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) 0x1018, 0x1019,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) 0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) 0x9006,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) 0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) /* 10Gbase-R */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) 0x1028, 0x1029, 0x102a, 0x102b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (mv88e6xxx_serdes_get_lane(chip, port) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) u16 *p = _p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) int lane;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) u16 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) lane = mv88e6xxx_serdes_get_lane(chip, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (lane == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) mv88e6390_serdes_regs[i], ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) p[i] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }