1495 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Marvell 10G 88x3310 PHY driver4 *5 * Based upon the ID registers, this PHY appears to be a mixture of IPs6 * from two different companies.7 *8 * There appears to be several different data paths through the PHY which9 * are automatically managed by the PHY. The following has been determined10 * via observation and experimentation for a setup using single-lane Serdes:11 *12 * SGMII PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for <= 1G)13 * 10GBASE-KR PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for 10G)14 * 10GBASE-KR PHYXS -- BASE-R PCS -- Fiber15 *16 * With XAUI, observation shows:17 *18 * XAUI PHYXS -- <appropriate PCS as above>19 *20 * and no switching of the host interface mode occurs.21 *22 * If both the fiber and copper ports are connected, the first to gain23 * link takes priority and the other port is completely locked out.24 */25#include <linux/bitfield.h>26#include <linux/ctype.h>27#include <linux/delay.h>28#include <linux/hwmon.h>29#include <linux/marvell_phy.h>30#include <linux/phy.h>31#include <linux/sfp.h>32#include <linux/netdevice.h>33 34#define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe35#define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa)36 37#define MV_VERSION(a,b,c,d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))38 39enum {40 MV_PMA_FW_VER0 = 0xc011,41 MV_PMA_FW_VER1 = 0xc012,42 MV_PMA_21X0_PORT_CTRL = 0xc04a,43 MV_PMA_21X0_PORT_CTRL_SWRST = BIT(15),44 MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK = 0x7,45 MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII = 0x0,46 MV_PMA_2180_PORT_CTRL_MACTYPE_DXGMII = 0x1,47 MV_PMA_2180_PORT_CTRL_MACTYPE_QXGMII = 0x2,48 MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER = 0x4,49 MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN = 0x5,50 MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6,51 MV_PMA_BOOT = 0xc050,52 MV_PMA_BOOT_FATAL = BIT(0),53 54 MV_PCS_BASE_T = 0x0000,55 MV_PCS_BASE_R = 0x1000,56 MV_PCS_1000BASEX = 0x2000,57 58 MV_PCS_CSCR1 = 0x8000,59 MV_PCS_CSCR1_ED_MASK = 0x0300,60 MV_PCS_CSCR1_ED_OFF = 0x0000,61 MV_PCS_CSCR1_ED_RX = 0x0200,62 MV_PCS_CSCR1_ED_NLP = 0x0300,63 MV_PCS_CSCR1_MDIX_MASK = 0x0060,64 MV_PCS_CSCR1_MDIX_MDI = 0x0000,65 MV_PCS_CSCR1_MDIX_MDIX = 0x0020,66 MV_PCS_CSCR1_MDIX_AUTO = 0x0060,67 68 MV_PCS_DSC1 = 0x8003,69 MV_PCS_DSC1_ENABLE = BIT(9),70 MV_PCS_DSC1_10GBT = 0x01c0,71 MV_PCS_DSC1_1GBR = 0x0038,72 MV_PCS_DSC1_100BTX = 0x0007,73 MV_PCS_DSC2 = 0x8004,74 MV_PCS_DSC2_2P5G = 0xf000,75 MV_PCS_DSC2_5G = 0x0f00,76 77 MV_PCS_CSSR1 = 0x8008,78 MV_PCS_CSSR1_SPD1_MASK = 0xc000,79 MV_PCS_CSSR1_SPD1_SPD2 = 0xc000,80 MV_PCS_CSSR1_SPD1_1000 = 0x8000,81 MV_PCS_CSSR1_SPD1_100 = 0x4000,82 MV_PCS_CSSR1_SPD1_10 = 0x0000,83 MV_PCS_CSSR1_DUPLEX_FULL= BIT(13),84 MV_PCS_CSSR1_RESOLVED = BIT(11),85 MV_PCS_CSSR1_MDIX = BIT(6),86 MV_PCS_CSSR1_SPD2_MASK = 0x000c,87 MV_PCS_CSSR1_SPD2_5000 = 0x0008,88 MV_PCS_CSSR1_SPD2_2500 = 0x0004,89 MV_PCS_CSSR1_SPD2_10000 = 0x0000,90 91 /* Temperature read register (88E2110 only) */92 MV_PCS_TEMP = 0x8042,93 94 /* Number of ports on the device */95 MV_PCS_PORT_INFO = 0xd00d,96 MV_PCS_PORT_INFO_NPORTS_MASK = 0x0380,97 MV_PCS_PORT_INFO_NPORTS_SHIFT = 7,98 99 /* SerDes reinitialization 88E21X0 */100 MV_AN_21X0_SERDES_CTRL2 = 0x800f,101 MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS = BIT(13),102 MV_AN_21X0_SERDES_CTRL2_RUN_INIT = BIT(15),103 104 /* These registers appear at 0x800X and 0xa00X - the 0xa00X control105 * registers appear to set themselves to the 0x800X when AN is106 * restarted, but status registers appear readable from either.107 */108 MV_AN_CTRL1000 = 0x8000, /* 1000base-T control register */109 MV_AN_STAT1000 = 0x8001, /* 1000base-T status register */110 111 /* Vendor2 MMD registers */112 MV_V2_PORT_CTRL = 0xf001,113 MV_V2_PORT_CTRL_PWRDOWN = BIT(11),114 MV_V2_33X0_PORT_CTRL_SWRST = BIT(15),115 MV_V2_33X0_PORT_CTRL_MACTYPE_MASK = 0x7,116 MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI = 0x0,117 MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH = 0x1,118 MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN = 0x1,119 MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH = 0x2,120 MV_V2_3310_PORT_CTRL_MACTYPE_XAUI = 0x3,121 MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER = 0x4,122 MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN = 0x5,123 MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6,124 MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII = 0x7,125 MV_V2_PORT_INTR_STS = 0xf040,126 MV_V2_PORT_INTR_MASK = 0xf043,127 MV_V2_PORT_INTR_STS_WOL_EN = BIT(8),128 MV_V2_MAGIC_PKT_WORD0 = 0xf06b,129 MV_V2_MAGIC_PKT_WORD1 = 0xf06c,130 MV_V2_MAGIC_PKT_WORD2 = 0xf06d,131 /* Wake on LAN registers */132 MV_V2_WOL_CTRL = 0xf06e,133 MV_V2_WOL_CTRL_CLEAR_STS = BIT(15),134 MV_V2_WOL_CTRL_MAGIC_PKT_EN = BIT(0),135 /* Temperature control/read registers (88X3310 only) */136 MV_V2_TEMP_CTRL = 0xf08a,137 MV_V2_TEMP_CTRL_MASK = 0xc000,138 MV_V2_TEMP_CTRL_SAMPLE = 0x0000,139 MV_V2_TEMP_CTRL_DISABLE = 0xc000,140 MV_V2_TEMP = 0xf08c,141 MV_V2_TEMP_UNKNOWN = 0x9600, /* unknown function */142};143 144struct mv3310_mactype {145 bool valid;146 bool fixed_interface;147 phy_interface_t interface_10g;148};149 150struct mv3310_chip {151 bool (*has_downshift)(struct phy_device *phydev);152 void (*init_supported_interfaces)(unsigned long *mask);153 int (*get_mactype)(struct phy_device *phydev);154 int (*set_mactype)(struct phy_device *phydev, int mactype);155 int (*select_mactype)(unsigned long *interfaces);156 157 const struct mv3310_mactype *mactypes;158 size_t n_mactypes;159 160#ifdef CONFIG_HWMON161 int (*hwmon_read_temp_reg)(struct phy_device *phydev);162#endif163};164 165struct mv3310_priv {166 DECLARE_BITMAP(supported_interfaces, PHY_INTERFACE_MODE_MAX);167 const struct mv3310_mactype *mactype;168 169 u32 firmware_ver;170 bool has_downshift;171 172 struct device *hwmon_dev;173 char *hwmon_name;174};175 176static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev)177{178 return phydev->drv->driver_data;179}180 181#ifdef CONFIG_HWMON182static umode_t mv3310_hwmon_is_visible(const void *data,183 enum hwmon_sensor_types type,184 u32 attr, int channel)185{186 if (type == hwmon_chip && attr == hwmon_chip_update_interval)187 return 0444;188 if (type == hwmon_temp && attr == hwmon_temp_input)189 return 0444;190 return 0;191}192 193static int mv3310_hwmon_read_temp_reg(struct phy_device *phydev)194{195 return phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP);196}197 198static int mv2110_hwmon_read_temp_reg(struct phy_device *phydev)199{200 return phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_TEMP);201}202 203static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type,204 u32 attr, int channel, long *value)205{206 struct phy_device *phydev = dev_get_drvdata(dev);207 const struct mv3310_chip *chip = to_mv3310_chip(phydev);208 int temp;209 210 if (type == hwmon_chip && attr == hwmon_chip_update_interval) {211 *value = MSEC_PER_SEC;212 return 0;213 }214 215 if (type == hwmon_temp && attr == hwmon_temp_input) {216 temp = chip->hwmon_read_temp_reg(phydev);217 if (temp < 0)218 return temp;219 220 *value = ((temp & 0xff) - 75) * 1000;221 222 return 0;223 }224 225 return -EOPNOTSUPP;226}227 228static const struct hwmon_ops mv3310_hwmon_ops = {229 .is_visible = mv3310_hwmon_is_visible,230 .read = mv3310_hwmon_read,231};232 233static u32 mv3310_hwmon_chip_config[] = {234 HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL,235 0,236};237 238static const struct hwmon_channel_info mv3310_hwmon_chip = {239 .type = hwmon_chip,240 .config = mv3310_hwmon_chip_config,241};242 243static u32 mv3310_hwmon_temp_config[] = {244 HWMON_T_INPUT,245 0,246};247 248static const struct hwmon_channel_info mv3310_hwmon_temp = {249 .type = hwmon_temp,250 .config = mv3310_hwmon_temp_config,251};252 253static const struct hwmon_channel_info * const mv3310_hwmon_info[] = {254 &mv3310_hwmon_chip,255 &mv3310_hwmon_temp,256 NULL,257};258 259static const struct hwmon_chip_info mv3310_hwmon_chip_info = {260 .ops = &mv3310_hwmon_ops,261 .info = mv3310_hwmon_info,262};263 264static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)265{266 u16 val;267 int ret;268 269 if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310)270 return 0;271 272 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP,273 MV_V2_TEMP_UNKNOWN);274 if (ret < 0)275 return ret;276 277 val = enable ? MV_V2_TEMP_CTRL_SAMPLE : MV_V2_TEMP_CTRL_DISABLE;278 279 return phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL,280 MV_V2_TEMP_CTRL_MASK, val);281}282 283static int mv3310_hwmon_probe(struct phy_device *phydev)284{285 struct device *dev = &phydev->mdio.dev;286 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);287 int i, j, ret;288 289 priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);290 if (!priv->hwmon_name)291 return -ENODEV;292 293 for (i = j = 0; priv->hwmon_name[i]; i++) {294 if (isalnum(priv->hwmon_name[i])) {295 if (i != j)296 priv->hwmon_name[j] = priv->hwmon_name[i];297 j++;298 }299 }300 priv->hwmon_name[j] = '\0';301 302 ret = mv3310_hwmon_config(phydev, true);303 if (ret)304 return ret;305 306 priv->hwmon_dev = devm_hwmon_device_register_with_info(dev,307 priv->hwmon_name, phydev,308 &mv3310_hwmon_chip_info, NULL);309 310 return PTR_ERR_OR_ZERO(priv->hwmon_dev);311}312#else313static inline int mv3310_hwmon_config(struct phy_device *phydev, bool enable)314{315 return 0;316}317 318static int mv3310_hwmon_probe(struct phy_device *phydev)319{320 return 0;321}322#endif323 324static int mv3310_power_down(struct phy_device *phydev)325{326 return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,327 MV_V2_PORT_CTRL_PWRDOWN);328}329 330static int mv3310_power_up(struct phy_device *phydev)331{332 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);333 int ret;334 335 ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,336 MV_V2_PORT_CTRL_PWRDOWN);337 338 /* Sometimes, the power down bit doesn't clear immediately, and339 * a read of this register causes the bit not to clear. Delay340 * 100us to allow the PHY to come out of power down mode before341 * the next access.342 */343 udelay(100);344 345 if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310 ||346 priv->firmware_ver < 0x00030000)347 return ret;348 349 return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,350 MV_V2_33X0_PORT_CTRL_SWRST);351}352 353static int mv3310_reset(struct phy_device *phydev, u32 unit)354{355 int val, err;356 357 err = phy_modify_mmd(phydev, MDIO_MMD_PCS, unit + MDIO_CTRL1,358 MDIO_CTRL1_RESET, MDIO_CTRL1_RESET);359 if (err < 0)360 return err;361 362 return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,363 unit + MDIO_CTRL1, val,364 !(val & MDIO_CTRL1_RESET),365 5000, 100000, true);366}367 368static int mv3310_get_downshift(struct phy_device *phydev, u8 *ds)369{370 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);371 int val;372 373 if (!priv->has_downshift)374 return -EOPNOTSUPP;375 376 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1);377 if (val < 0)378 return val;379 380 if (val & MV_PCS_DSC1_ENABLE)381 /* assume that all fields are the same */382 *ds = 1 + FIELD_GET(MV_PCS_DSC1_10GBT, (u16)val);383 else384 *ds = DOWNSHIFT_DEV_DISABLE;385 386 return 0;387}388 389static int mv3310_set_downshift(struct phy_device *phydev, u8 ds)390{391 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);392 u16 val;393 int err;394 395 if (!priv->has_downshift)396 return -EOPNOTSUPP;397 398 if (ds == DOWNSHIFT_DEV_DISABLE)399 return phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1,400 MV_PCS_DSC1_ENABLE);401 402 /* DOWNSHIFT_DEV_DEFAULT_COUNT is confusing. It looks like it should403 * set the default settings for the PHY. However, it is used for404 * "ethtool --set-phy-tunable ethN downshift on". The intention is405 * to enable downshift at a default number of retries. The default406 * settings for 88x3310 are for two retries with downshift disabled.407 * So let's use two retries with downshift enabled.408 */409 if (ds == DOWNSHIFT_DEV_DEFAULT_COUNT)410 ds = 2;411 412 if (ds > 8)413 return -E2BIG;414 415 ds -= 1;416 val = FIELD_PREP(MV_PCS_DSC2_2P5G, ds);417 val |= FIELD_PREP(MV_PCS_DSC2_5G, ds);418 err = phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC2,419 MV_PCS_DSC2_2P5G | MV_PCS_DSC2_5G, val);420 if (err < 0)421 return err;422 423 val = MV_PCS_DSC1_ENABLE;424 val |= FIELD_PREP(MV_PCS_DSC1_10GBT, ds);425 val |= FIELD_PREP(MV_PCS_DSC1_1GBR, ds);426 val |= FIELD_PREP(MV_PCS_DSC1_100BTX, ds);427 428 return phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1,429 MV_PCS_DSC1_ENABLE | MV_PCS_DSC1_10GBT |430 MV_PCS_DSC1_1GBR | MV_PCS_DSC1_100BTX, val);431}432 433static int mv3310_get_edpd(struct phy_device *phydev, u16 *edpd)434{435 int val;436 437 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1);438 if (val < 0)439 return val;440 441 switch (val & MV_PCS_CSCR1_ED_MASK) {442 case MV_PCS_CSCR1_ED_NLP:443 *edpd = 1000;444 break;445 case MV_PCS_CSCR1_ED_RX:446 *edpd = ETHTOOL_PHY_EDPD_NO_TX;447 break;448 default:449 *edpd = ETHTOOL_PHY_EDPD_DISABLE;450 break;451 }452 return 0;453}454 455static int mv3310_set_edpd(struct phy_device *phydev, u16 edpd)456{457 u16 val;458 int err;459 460 switch (edpd) {461 case 1000:462 case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS:463 val = MV_PCS_CSCR1_ED_NLP;464 break;465 466 case ETHTOOL_PHY_EDPD_NO_TX:467 val = MV_PCS_CSCR1_ED_RX;468 break;469 470 case ETHTOOL_PHY_EDPD_DISABLE:471 val = MV_PCS_CSCR1_ED_OFF;472 break;473 474 default:475 return -EINVAL;476 }477 478 err = phy_modify_mmd_changed(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1,479 MV_PCS_CSCR1_ED_MASK, val);480 if (err > 0)481 err = mv3310_reset(phydev, MV_PCS_BASE_T);482 483 return err;484}485 486static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)487{488 struct phy_device *phydev = upstream;489 __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };490 DECLARE_PHY_INTERFACE_MASK(interfaces);491 phy_interface_t iface;492 493 sfp_parse_support(phydev->sfp_bus, id, support, interfaces);494 iface = sfp_select_interface(phydev->sfp_bus, support);495 496 if (iface != PHY_INTERFACE_MODE_10GBASER) {497 dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");498 return -EINVAL;499 }500 return 0;501}502 503static const struct sfp_upstream_ops mv3310_sfp_ops = {504 .attach = phy_sfp_attach,505 .detach = phy_sfp_detach,506 .connect_phy = phy_sfp_connect_phy,507 .disconnect_phy = phy_sfp_disconnect_phy,508 .module_insert = mv3310_sfp_insert,509};510 511static int mv3310_probe(struct phy_device *phydev)512{513 const struct mv3310_chip *chip = to_mv3310_chip(phydev);514 struct mv3310_priv *priv;515 u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;516 int ret;517 518 if (!phydev->is_c45 ||519 (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)520 return -ENODEV;521 522 ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT);523 if (ret < 0)524 return ret;525 526 if (ret & MV_PMA_BOOT_FATAL) {527 dev_warn(&phydev->mdio.dev,528 "PHY failed to boot firmware, status=%04x\n", ret);529 return -ENODEV;530 }531 532 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);533 if (!priv)534 return -ENOMEM;535 536 dev_set_drvdata(&phydev->mdio.dev, priv);537 538 ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER0);539 if (ret < 0)540 return ret;541 542 priv->firmware_ver = ret << 16;543 544 ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER1);545 if (ret < 0)546 return ret;547 548 priv->firmware_ver |= ret;549 550 phydev_info(phydev, "Firmware version %u.%u.%u.%u\n",551 priv->firmware_ver >> 24, (priv->firmware_ver >> 16) & 255,552 (priv->firmware_ver >> 8) & 255, priv->firmware_ver & 255);553 554 if (chip->has_downshift)555 priv->has_downshift = chip->has_downshift(phydev);556 557 /* Powering down the port when not in use saves about 600mW */558 ret = mv3310_power_down(phydev);559 if (ret)560 return ret;561 562 ret = mv3310_hwmon_probe(phydev);563 if (ret)564 return ret;565 566 chip->init_supported_interfaces(priv->supported_interfaces);567 568 return phy_sfp_probe(phydev, &mv3310_sfp_ops);569}570 571static void mv3310_remove(struct phy_device *phydev)572{573 mv3310_hwmon_config(phydev, false);574}575 576static int mv3310_suspend(struct phy_device *phydev)577{578 return mv3310_power_down(phydev);579}580 581static int mv3310_resume(struct phy_device *phydev)582{583 int ret;584 585 ret = mv3310_power_up(phydev);586 if (ret)587 return ret;588 589 return mv3310_hwmon_config(phydev, true);590}591 592/* Some PHYs in the Alaska family such as the 88X3310 and the 88E2010593 * don't set bit 14 in PMA Extended Abilities (1.11), although they do594 * support 2.5GBASET and 5GBASET. For these models, we can still read their595 * 2.5G/5G extended abilities register (1.21). We detect these models based on596 * the PMA device identifier, with a mask matching models known to have this597 * issue598 */599static bool mv3310_has_pma_ngbaset_quirk(struct phy_device *phydev)600{601 if (!(phydev->c45_ids.devices_in_package & MDIO_DEVS_PMAPMD))602 return false;603 604 /* Only some revisions of the 88X3310 family PMA seem to be impacted */605 return (phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &606 MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV;607}608 609static int mv2110_get_mactype(struct phy_device *phydev)610{611 int mactype;612 613 mactype = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL);614 if (mactype < 0)615 return mactype;616 617 return mactype & MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;618}619 620static int mv2110_set_mactype(struct phy_device *phydev, int mactype)621{622 int err, val;623 624 mactype &= MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;625 err = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL,626 MV_PMA_21X0_PORT_CTRL_SWRST |627 MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK,628 MV_PMA_21X0_PORT_CTRL_SWRST | mactype);629 if (err)630 return err;631 632 err = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2,633 MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS |634 MV_AN_21X0_SERDES_CTRL2_RUN_INIT);635 if (err)636 return err;637 638 err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_AN,639 MV_AN_21X0_SERDES_CTRL2, val,640 !(val &641 MV_AN_21X0_SERDES_CTRL2_RUN_INIT),642 5000, 100000, true);643 if (err)644 return err;645 646 return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2,647 MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS);648}649 650static int mv2110_select_mactype(unsigned long *interfaces)651{652 if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces))653 return MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII;654 else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) &&655 !test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces))656 return MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER;657 else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces))658 return MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH;659 else660 return -1;661}662 663static int mv3310_get_mactype(struct phy_device *phydev)664{665 int mactype;666 667 mactype = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);668 if (mactype < 0)669 return mactype;670 671 return mactype & MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;672}673 674static int mv3310_set_mactype(struct phy_device *phydev, int mactype)675{676 int ret;677 678 mactype &= MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;679 ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,680 MV_V2_33X0_PORT_CTRL_MACTYPE_MASK,681 mactype);682 if (ret <= 0)683 return ret;684 685 return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,686 MV_V2_33X0_PORT_CTRL_SWRST);687}688 689static int mv3310_select_mactype(unsigned long *interfaces)690{691 if (test_bit(PHY_INTERFACE_MODE_USXGMII, interfaces))692 return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII;693 else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) &&694 test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces))695 return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER;696 else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) &&697 test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces))698 return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI;699 else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces) &&700 test_bit(PHY_INTERFACE_MODE_XAUI, interfaces))701 return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI;702 else if (test_bit(PHY_INTERFACE_MODE_10GBASER, interfaces))703 return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH;704 else if (test_bit(PHY_INTERFACE_MODE_RXAUI, interfaces))705 return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH;706 else if (test_bit(PHY_INTERFACE_MODE_XAUI, interfaces))707 return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH;708 else if (test_bit(PHY_INTERFACE_MODE_SGMII, interfaces))709 return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER;710 else711 return -1;712}713 714static const struct mv3310_mactype mv2110_mactypes[] = {715 [MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII] = {716 .valid = true,717 .fixed_interface = true,718 .interface_10g = PHY_INTERFACE_MODE_USXGMII,719 },720 [MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER] = {721 .valid = true,722 .interface_10g = PHY_INTERFACE_MODE_NA,723 },724 [MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN] = {725 .valid = true,726 .interface_10g = PHY_INTERFACE_MODE_NA,727 },728 [MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH] = {729 .valid = true,730 .fixed_interface = true,731 .interface_10g = PHY_INTERFACE_MODE_10GBASER,732 },733};734 735static const struct mv3310_mactype mv3310_mactypes[] = {736 [MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI] = {737 .valid = true,738 .interface_10g = PHY_INTERFACE_MODE_RXAUI,739 },740 [MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH] = {741 .valid = true,742 .fixed_interface = true,743 .interface_10g = PHY_INTERFACE_MODE_XAUI,744 },745 [MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH] = {746 .valid = true,747 .fixed_interface = true,748 .interface_10g = PHY_INTERFACE_MODE_RXAUI,749 },750 [MV_V2_3310_PORT_CTRL_MACTYPE_XAUI] = {751 .valid = true,752 .interface_10g = PHY_INTERFACE_MODE_XAUI,753 },754 [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER] = {755 .valid = true,756 .interface_10g = PHY_INTERFACE_MODE_10GBASER,757 },758 [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN] = {759 .valid = true,760 .interface_10g = PHY_INTERFACE_MODE_10GBASER,761 },762 [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH] = {763 .valid = true,764 .fixed_interface = true,765 .interface_10g = PHY_INTERFACE_MODE_10GBASER,766 },767 [MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII] = {768 .valid = true,769 .fixed_interface = true,770 .interface_10g = PHY_INTERFACE_MODE_USXGMII,771 },772};773 774static const struct mv3310_mactype mv3340_mactypes[] = {775 [MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI] = {776 .valid = true,777 .interface_10g = PHY_INTERFACE_MODE_RXAUI,778 },779 [MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN] = {780 .valid = true,781 .interface_10g = PHY_INTERFACE_MODE_RXAUI,782 },783 [MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH] = {784 .valid = true,785 .fixed_interface = true,786 .interface_10g = PHY_INTERFACE_MODE_RXAUI,787 },788 [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER] = {789 .valid = true,790 .interface_10g = PHY_INTERFACE_MODE_10GBASER,791 },792 [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN] = {793 .valid = true,794 .interface_10g = PHY_INTERFACE_MODE_10GBASER,795 },796 [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH] = {797 .valid = true,798 .fixed_interface = true,799 .interface_10g = PHY_INTERFACE_MODE_10GBASER,800 },801 [MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII] = {802 .valid = true,803 .fixed_interface = true,804 .interface_10g = PHY_INTERFACE_MODE_USXGMII,805 },806};807 808static void mv3310_fill_possible_interfaces(struct phy_device *phydev)809{810 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);811 unsigned long *possible = phydev->possible_interfaces;812 const struct mv3310_mactype *mactype = priv->mactype;813 814 if (mactype->interface_10g != PHY_INTERFACE_MODE_NA)815 __set_bit(priv->mactype->interface_10g, possible);816 817 if (!mactype->fixed_interface) {818 __set_bit(PHY_INTERFACE_MODE_5GBASER, possible);819 __set_bit(PHY_INTERFACE_MODE_2500BASEX, possible);820 __set_bit(PHY_INTERFACE_MODE_SGMII, possible);821 }822}823 824static int mv3310_config_init(struct phy_device *phydev)825{826 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);827 const struct mv3310_chip *chip = to_mv3310_chip(phydev);828 int err, mactype;829 830 /* Check that the PHY interface type is compatible */831 if (!test_bit(phydev->interface, priv->supported_interfaces))832 return -ENODEV;833 834 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;835 836 /* Power up so reset works */837 err = mv3310_power_up(phydev);838 if (err)839 return err;840 841 /* If host provided host supported interface modes, try to select the842 * best one843 */844 if (!phy_interface_empty(phydev->host_interfaces)) {845 mactype = chip->select_mactype(phydev->host_interfaces);846 if (mactype >= 0) {847 phydev_info(phydev, "Changing MACTYPE to %i\n",848 mactype);849 err = chip->set_mactype(phydev, mactype);850 if (err)851 return err;852 }853 }854 855 mactype = chip->get_mactype(phydev);856 if (mactype < 0)857 return mactype;858 859 if (mactype >= chip->n_mactypes || !chip->mactypes[mactype].valid) {860 phydev_err(phydev, "MACTYPE configuration invalid\n");861 return -EINVAL;862 }863 864 priv->mactype = &chip->mactypes[mactype];865 866 mv3310_fill_possible_interfaces(phydev);867 868 /* Enable EDPD mode - saving 600mW */869 err = mv3310_set_edpd(phydev, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS);870 if (err)871 return err;872 873 /* Allow downshift */874 err = mv3310_set_downshift(phydev, DOWNSHIFT_DEV_DEFAULT_COUNT);875 if (err && err != -EOPNOTSUPP)876 return err;877 878 return 0;879}880 881static int mv3310_get_features(struct phy_device *phydev)882{883 int ret, val;884 885 ret = genphy_c45_pma_read_abilities(phydev);886 if (ret)887 return ret;888 889 if (mv3310_has_pma_ngbaset_quirk(phydev)) {890 val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,891 MDIO_PMA_NG_EXTABLE);892 if (val < 0)893 return val;894 895 linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,896 phydev->supported,897 val & MDIO_PMA_NG_EXTABLE_2_5GBT);898 899 linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,900 phydev->supported,901 val & MDIO_PMA_NG_EXTABLE_5GBT);902 }903 904 return 0;905}906 907static int mv3310_config_mdix(struct phy_device *phydev)908{909 u16 val;910 int err;911 912 switch (phydev->mdix_ctrl) {913 case ETH_TP_MDI_AUTO:914 val = MV_PCS_CSCR1_MDIX_AUTO;915 break;916 case ETH_TP_MDI_X:917 val = MV_PCS_CSCR1_MDIX_MDIX;918 break;919 case ETH_TP_MDI:920 val = MV_PCS_CSCR1_MDIX_MDI;921 break;922 default:923 return -EINVAL;924 }925 926 err = phy_modify_mmd_changed(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1,927 MV_PCS_CSCR1_MDIX_MASK, val);928 if (err > 0)929 err = mv3310_reset(phydev, MV_PCS_BASE_T);930 931 return err;932}933 934static int mv3310_config_aneg(struct phy_device *phydev)935{936 bool changed = false;937 u16 reg;938 int ret;939 940 ret = mv3310_config_mdix(phydev);941 if (ret < 0)942 return ret;943 944 if (phydev->autoneg == AUTONEG_DISABLE)945 return genphy_c45_pma_setup_forced(phydev);946 947 ret = genphy_c45_an_config_aneg(phydev);948 if (ret < 0)949 return ret;950 if (ret > 0)951 changed = true;952 953 /* Clause 45 has no standardized support for 1000BaseT, therefore954 * use vendor registers for this mode.955 */956 reg = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);957 ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,958 ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg);959 if (ret < 0)960 return ret;961 if (ret > 0)962 changed = true;963 964 return genphy_c45_check_and_restart_aneg(phydev, changed);965}966 967static int mv3310_aneg_done(struct phy_device *phydev)968{969 int val;970 971 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);972 if (val < 0)973 return val;974 975 if (val & MDIO_STAT1_LSTATUS)976 return 1;977 978 return genphy_c45_aneg_done(phydev);979}980 981static void mv3310_update_interface(struct phy_device *phydev)982{983 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);984 985 if (!phydev->link)986 return;987 988 /* In all of the "* with Rate Matching" modes the PHY interface is fixed989 * at 10Gb. The PHY adapts the rate to actual wire speed with help of990 * internal 16KB buffer.991 *992 * In USXGMII mode the PHY interface mode is also fixed.993 */994 if (priv->mactype->fixed_interface) {995 phydev->interface = priv->mactype->interface_10g;996 return;997 }998 999 /* The PHY automatically switches its serdes interface (and active PHYXS1000 * instance) between Cisco SGMII, 2500BaseX, 5GBase-R and 10GBase-R /1001 * xaui / rxaui modes according to the speed.1002 * Florian suggests setting phydev->interface to communicate this to the1003 * MAC. Only do this if we are already in one of the above modes.1004 */1005 switch (phydev->speed) {1006 case SPEED_10000:1007 phydev->interface = priv->mactype->interface_10g;1008 break;1009 case SPEED_5000:1010 phydev->interface = PHY_INTERFACE_MODE_5GBASER;1011 break;1012 case SPEED_2500:1013 phydev->interface = PHY_INTERFACE_MODE_2500BASEX;1014 break;1015 case SPEED_1000:1016 case SPEED_100:1017 case SPEED_10:1018 phydev->interface = PHY_INTERFACE_MODE_SGMII;1019 break;1020 default:1021 break;1022 }1023}1024 1025/* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */1026static int mv3310_read_status_10gbaser(struct phy_device *phydev)1027{1028 phydev->link = 1;1029 phydev->speed = SPEED_10000;1030 phydev->duplex = DUPLEX_FULL;1031 phydev->port = PORT_FIBRE;1032 1033 return 0;1034}1035 1036static int mv3310_read_status_copper(struct phy_device *phydev)1037{1038 int cssr1, speed, val;1039 1040 val = genphy_c45_read_link(phydev);1041 if (val < 0)1042 return val;1043 1044 val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);1045 if (val < 0)1046 return val;1047 1048 cssr1 = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_CSSR1);1049 if (cssr1 < 0)1050 return cssr1;1051 1052 /* If the link settings are not resolved, mark the link down */1053 if (!(cssr1 & MV_PCS_CSSR1_RESOLVED)) {1054 phydev->link = 0;1055 return 0;1056 }1057 1058 /* Read the copper link settings */1059 speed = cssr1 & MV_PCS_CSSR1_SPD1_MASK;1060 if (speed == MV_PCS_CSSR1_SPD1_SPD2)1061 speed |= cssr1 & MV_PCS_CSSR1_SPD2_MASK;1062 1063 switch (speed) {1064 case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_10000:1065 phydev->speed = SPEED_10000;1066 break;1067 1068 case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_5000:1069 phydev->speed = SPEED_5000;1070 break;1071 1072 case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_2500:1073 phydev->speed = SPEED_2500;1074 break;1075 1076 case MV_PCS_CSSR1_SPD1_1000:1077 phydev->speed = SPEED_1000;1078 break;1079 1080 case MV_PCS_CSSR1_SPD1_100:1081 phydev->speed = SPEED_100;1082 break;1083 1084 case MV_PCS_CSSR1_SPD1_10:1085 phydev->speed = SPEED_10;1086 break;1087 }1088 1089 phydev->duplex = cssr1 & MV_PCS_CSSR1_DUPLEX_FULL ?1090 DUPLEX_FULL : DUPLEX_HALF;1091 phydev->port = PORT_TP;1092 phydev->mdix = cssr1 & MV_PCS_CSSR1_MDIX ?1093 ETH_TP_MDI_X : ETH_TP_MDI;1094 1095 if (val & MDIO_AN_STAT1_COMPLETE) {1096 val = genphy_c45_read_lpa(phydev);1097 if (val < 0)1098 return val;1099 1100 /* Read the link partner's 1G advertisement */1101 val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_STAT1000);1102 if (val < 0)1103 return val;1104 1105 mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);1106 1107 /* Update the pause status */1108 phy_resolve_aneg_pause(phydev);1109 }1110 1111 return 0;1112}1113 1114static int mv3310_read_status(struct phy_device *phydev)1115{1116 int err, val;1117 1118 phydev->speed = SPEED_UNKNOWN;1119 phydev->duplex = DUPLEX_UNKNOWN;1120 linkmode_zero(phydev->lp_advertising);1121 phydev->link = 0;1122 phydev->pause = 0;1123 phydev->asym_pause = 0;1124 phydev->mdix = ETH_TP_MDI_INVALID;1125 1126 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);1127 if (val < 0)1128 return val;1129 1130 if (val & MDIO_STAT1_LSTATUS)1131 err = mv3310_read_status_10gbaser(phydev);1132 else1133 err = mv3310_read_status_copper(phydev);1134 if (err < 0)1135 return err;1136 1137 if (phydev->link)1138 mv3310_update_interface(phydev);1139 1140 return 0;1141}1142 1143static int mv3310_get_tunable(struct phy_device *phydev,1144 struct ethtool_tunable *tuna, void *data)1145{1146 switch (tuna->id) {1147 case ETHTOOL_PHY_DOWNSHIFT:1148 return mv3310_get_downshift(phydev, data);1149 case ETHTOOL_PHY_EDPD:1150 return mv3310_get_edpd(phydev, data);1151 default:1152 return -EOPNOTSUPP;1153 }1154}1155 1156static int mv3310_set_tunable(struct phy_device *phydev,1157 struct ethtool_tunable *tuna, const void *data)1158{1159 switch (tuna->id) {1160 case ETHTOOL_PHY_DOWNSHIFT:1161 return mv3310_set_downshift(phydev, *(u8 *)data);1162 case ETHTOOL_PHY_EDPD:1163 return mv3310_set_edpd(phydev, *(u16 *)data);1164 default:1165 return -EOPNOTSUPP;1166 }1167}1168 1169static bool mv3310_has_downshift(struct phy_device *phydev)1170{1171 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);1172 1173 /* Fails to downshift with firmware older than v0.3.5.0 */1174 return priv->firmware_ver >= MV_VERSION(0,3,5,0);1175}1176 1177static void mv3310_init_supported_interfaces(unsigned long *mask)1178{1179 __set_bit(PHY_INTERFACE_MODE_SGMII, mask);1180 __set_bit(PHY_INTERFACE_MODE_2500BASEX, mask);1181 __set_bit(PHY_INTERFACE_MODE_5GBASER, mask);1182 __set_bit(PHY_INTERFACE_MODE_XAUI, mask);1183 __set_bit(PHY_INTERFACE_MODE_RXAUI, mask);1184 __set_bit(PHY_INTERFACE_MODE_10GBASER, mask);1185 __set_bit(PHY_INTERFACE_MODE_USXGMII, mask);1186}1187 1188static void mv3340_init_supported_interfaces(unsigned long *mask)1189{1190 __set_bit(PHY_INTERFACE_MODE_SGMII, mask);1191 __set_bit(PHY_INTERFACE_MODE_2500BASEX, mask);1192 __set_bit(PHY_INTERFACE_MODE_5GBASER, mask);1193 __set_bit(PHY_INTERFACE_MODE_RXAUI, mask);1194 __set_bit(PHY_INTERFACE_MODE_10GBASER, mask);1195 __set_bit(PHY_INTERFACE_MODE_USXGMII, mask);1196}1197 1198static void mv2110_init_supported_interfaces(unsigned long *mask)1199{1200 __set_bit(PHY_INTERFACE_MODE_SGMII, mask);1201 __set_bit(PHY_INTERFACE_MODE_2500BASEX, mask);1202 __set_bit(PHY_INTERFACE_MODE_5GBASER, mask);1203 __set_bit(PHY_INTERFACE_MODE_10GBASER, mask);1204 __set_bit(PHY_INTERFACE_MODE_USXGMII, mask);1205}1206 1207static void mv2111_init_supported_interfaces(unsigned long *mask)1208{1209 __set_bit(PHY_INTERFACE_MODE_SGMII, mask);1210 __set_bit(PHY_INTERFACE_MODE_2500BASEX, mask);1211 __set_bit(PHY_INTERFACE_MODE_10GBASER, mask);1212 __set_bit(PHY_INTERFACE_MODE_USXGMII, mask);1213}1214 1215static const struct mv3310_chip mv3310_type = {1216 .has_downshift = mv3310_has_downshift,1217 .init_supported_interfaces = mv3310_init_supported_interfaces,1218 .get_mactype = mv3310_get_mactype,1219 .set_mactype = mv3310_set_mactype,1220 .select_mactype = mv3310_select_mactype,1221 1222 .mactypes = mv3310_mactypes,1223 .n_mactypes = ARRAY_SIZE(mv3310_mactypes),1224 1225#ifdef CONFIG_HWMON1226 .hwmon_read_temp_reg = mv3310_hwmon_read_temp_reg,1227#endif1228};1229 1230static const struct mv3310_chip mv3340_type = {1231 .has_downshift = mv3310_has_downshift,1232 .init_supported_interfaces = mv3340_init_supported_interfaces,1233 .get_mactype = mv3310_get_mactype,1234 .set_mactype = mv3310_set_mactype,1235 .select_mactype = mv3310_select_mactype,1236 1237 .mactypes = mv3340_mactypes,1238 .n_mactypes = ARRAY_SIZE(mv3340_mactypes),1239 1240#ifdef CONFIG_HWMON1241 .hwmon_read_temp_reg = mv3310_hwmon_read_temp_reg,1242#endif1243};1244 1245static const struct mv3310_chip mv2110_type = {1246 .init_supported_interfaces = mv2110_init_supported_interfaces,1247 .get_mactype = mv2110_get_mactype,1248 .set_mactype = mv2110_set_mactype,1249 .select_mactype = mv2110_select_mactype,1250 1251 .mactypes = mv2110_mactypes,1252 .n_mactypes = ARRAY_SIZE(mv2110_mactypes),1253 1254#ifdef CONFIG_HWMON1255 .hwmon_read_temp_reg = mv2110_hwmon_read_temp_reg,1256#endif1257};1258 1259static const struct mv3310_chip mv2111_type = {1260 .init_supported_interfaces = mv2111_init_supported_interfaces,1261 .get_mactype = mv2110_get_mactype,1262 .set_mactype = mv2110_set_mactype,1263 .select_mactype = mv2110_select_mactype,1264 1265 .mactypes = mv2110_mactypes,1266 .n_mactypes = ARRAY_SIZE(mv2110_mactypes),1267 1268#ifdef CONFIG_HWMON1269 .hwmon_read_temp_reg = mv2110_hwmon_read_temp_reg,1270#endif1271};1272 1273static int mv3310_get_number_of_ports(struct phy_device *phydev)1274{1275 int ret;1276 1277 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_PORT_INFO);1278 if (ret < 0)1279 return ret;1280 1281 ret &= MV_PCS_PORT_INFO_NPORTS_MASK;1282 ret >>= MV_PCS_PORT_INFO_NPORTS_SHIFT;1283 1284 return ret + 1;1285}1286 1287static int mv3310_match_phy_device(struct phy_device *phydev)1288{1289 if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &1290 MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)1291 return 0;1292 1293 return mv3310_get_number_of_ports(phydev) == 1;1294}1295 1296static int mv3340_match_phy_device(struct phy_device *phydev)1297{1298 if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &1299 MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)1300 return 0;1301 1302 return mv3310_get_number_of_ports(phydev) == 4;1303}1304 1305static int mv211x_match_phy_device(struct phy_device *phydev, bool has_5g)1306{1307 int val;1308 1309 if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &1310 MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88E2110)1311 return 0;1312 1313 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_SPEED);1314 if (val < 0)1315 return val;1316 1317 return !!(val & MDIO_PCS_SPEED_5G) == has_5g;1318}1319 1320static int mv2110_match_phy_device(struct phy_device *phydev)1321{1322 return mv211x_match_phy_device(phydev, true);1323}1324 1325static int mv2111_match_phy_device(struct phy_device *phydev)1326{1327 return mv211x_match_phy_device(phydev, false);1328}1329 1330static void mv3110_get_wol(struct phy_device *phydev,1331 struct ethtool_wolinfo *wol)1332{1333 int ret;1334 1335 wol->supported = WAKE_MAGIC;1336 wol->wolopts = 0;1337 1338 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_WOL_CTRL);1339 if (ret < 0)1340 return;1341 1342 if (ret & MV_V2_WOL_CTRL_MAGIC_PKT_EN)1343 wol->wolopts |= WAKE_MAGIC;1344}1345 1346static int mv3110_set_wol(struct phy_device *phydev,1347 struct ethtool_wolinfo *wol)1348{1349 int ret;1350 1351 if (wol->wolopts & WAKE_MAGIC) {1352 /* Enable the WOL interrupt */1353 ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,1354 MV_V2_PORT_INTR_MASK,1355 MV_V2_PORT_INTR_STS_WOL_EN);1356 if (ret < 0)1357 return ret;1358 1359 /* Store the device address for the magic packet */1360 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,1361 MV_V2_MAGIC_PKT_WORD2,1362 ((phydev->attached_dev->dev_addr[5] << 8) |1363 phydev->attached_dev->dev_addr[4]));1364 if (ret < 0)1365 return ret;1366 1367 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,1368 MV_V2_MAGIC_PKT_WORD1,1369 ((phydev->attached_dev->dev_addr[3] << 8) |1370 phydev->attached_dev->dev_addr[2]));1371 if (ret < 0)1372 return ret;1373 1374 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,1375 MV_V2_MAGIC_PKT_WORD0,1376 ((phydev->attached_dev->dev_addr[1] << 8) |1377 phydev->attached_dev->dev_addr[0]));1378 if (ret < 0)1379 return ret;1380 1381 /* Clear WOL status and enable magic packet matching */1382 ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,1383 MV_V2_WOL_CTRL,1384 MV_V2_WOL_CTRL_MAGIC_PKT_EN |1385 MV_V2_WOL_CTRL_CLEAR_STS);1386 if (ret < 0)1387 return ret;1388 } else {1389 /* Disable magic packet matching & reset WOL status bit */1390 ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2,1391 MV_V2_WOL_CTRL,1392 MV_V2_WOL_CTRL_MAGIC_PKT_EN,1393 MV_V2_WOL_CTRL_CLEAR_STS);1394 if (ret < 0)1395 return ret;1396 }1397 1398 /* Reset the clear WOL status bit as it does not self-clear */1399 return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,1400 MV_V2_WOL_CTRL,1401 MV_V2_WOL_CTRL_CLEAR_STS);1402}1403 1404static struct phy_driver mv3310_drivers[] = {1405 {1406 .phy_id = MARVELL_PHY_ID_88X3310,1407 .phy_id_mask = MARVELL_PHY_ID_MASK,1408 .match_phy_device = mv3310_match_phy_device,1409 .name = "mv88x3310",1410 .driver_data = &mv3310_type,1411 .get_features = mv3310_get_features,1412 .config_init = mv3310_config_init,1413 .probe = mv3310_probe,1414 .suspend = mv3310_suspend,1415 .resume = mv3310_resume,1416 .config_aneg = mv3310_config_aneg,1417 .aneg_done = mv3310_aneg_done,1418 .read_status = mv3310_read_status,1419 .get_tunable = mv3310_get_tunable,1420 .set_tunable = mv3310_set_tunable,1421 .remove = mv3310_remove,1422 .set_loopback = genphy_c45_loopback,1423 .get_wol = mv3110_get_wol,1424 .set_wol = mv3110_set_wol,1425 },1426 {1427 .phy_id = MARVELL_PHY_ID_88X3310,1428 .phy_id_mask = MARVELL_PHY_ID_MASK,1429 .match_phy_device = mv3340_match_phy_device,1430 .name = "mv88x3340",1431 .driver_data = &mv3340_type,1432 .get_features = mv3310_get_features,1433 .config_init = mv3310_config_init,1434 .probe = mv3310_probe,1435 .suspend = mv3310_suspend,1436 .resume = mv3310_resume,1437 .config_aneg = mv3310_config_aneg,1438 .aneg_done = mv3310_aneg_done,1439 .read_status = mv3310_read_status,1440 .get_tunable = mv3310_get_tunable,1441 .set_tunable = mv3310_set_tunable,1442 .remove = mv3310_remove,1443 .set_loopback = genphy_c45_loopback,1444 },1445 {1446 .phy_id = MARVELL_PHY_ID_88E2110,1447 .phy_id_mask = MARVELL_PHY_ID_MASK,1448 .match_phy_device = mv2110_match_phy_device,1449 .name = "mv88e2110",1450 .driver_data = &mv2110_type,1451 .probe = mv3310_probe,1452 .suspend = mv3310_suspend,1453 .resume = mv3310_resume,1454 .config_init = mv3310_config_init,1455 .config_aneg = mv3310_config_aneg,1456 .aneg_done = mv3310_aneg_done,1457 .read_status = mv3310_read_status,1458 .get_tunable = mv3310_get_tunable,1459 .set_tunable = mv3310_set_tunable,1460 .remove = mv3310_remove,1461 .set_loopback = genphy_c45_loopback,1462 .get_wol = mv3110_get_wol,1463 .set_wol = mv3110_set_wol,1464 },1465 {1466 .phy_id = MARVELL_PHY_ID_88E2110,1467 .phy_id_mask = MARVELL_PHY_ID_MASK,1468 .match_phy_device = mv2111_match_phy_device,1469 .name = "mv88e2111",1470 .driver_data = &mv2111_type,1471 .probe = mv3310_probe,1472 .suspend = mv3310_suspend,1473 .resume = mv3310_resume,1474 .config_init = mv3310_config_init,1475 .config_aneg = mv3310_config_aneg,1476 .aneg_done = mv3310_aneg_done,1477 .read_status = mv3310_read_status,1478 .get_tunable = mv3310_get_tunable,1479 .set_tunable = mv3310_set_tunable,1480 .remove = mv3310_remove,1481 .set_loopback = genphy_c45_loopback,1482 },1483};1484 1485module_phy_driver(mv3310_drivers);1486 1487static struct mdio_device_id __maybe_unused mv3310_tbl[] = {1488 { MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_MASK },1489 { MARVELL_PHY_ID_88E2110, MARVELL_PHY_ID_MASK },1490 { },1491};1492MODULE_DEVICE_TABLE(mdio, mv3310_tbl);1493MODULE_DESCRIPTION("Marvell Alaska X/M multi-gigabit Ethernet PHY driver");1494MODULE_LICENSE("GPL");1495