0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include <linux/bitfield.h>
0026 #include <linux/ctype.h>
0027 #include <linux/delay.h>
0028 #include <linux/hwmon.h>
0029 #include <linux/marvell_phy.h>
0030 #include <linux/phy.h>
0031 #include <linux/sfp.h>
0032 #include <linux/netdevice.h>
0033
0034 #define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe
0035 #define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa)
0036
0037 #define MV_VERSION(a,b,c,d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
0038
0039 enum {
0040 MV_PMA_FW_VER0 = 0xc011,
0041 MV_PMA_FW_VER1 = 0xc012,
0042 MV_PMA_21X0_PORT_CTRL = 0xc04a,
0043 MV_PMA_21X0_PORT_CTRL_SWRST = BIT(15),
0044 MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK = 0x7,
0045 MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII = 0x0,
0046 MV_PMA_2180_PORT_CTRL_MACTYPE_DXGMII = 0x1,
0047 MV_PMA_2180_PORT_CTRL_MACTYPE_QXGMII = 0x2,
0048 MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER = 0x4,
0049 MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN = 0x5,
0050 MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6,
0051 MV_PMA_BOOT = 0xc050,
0052 MV_PMA_BOOT_FATAL = BIT(0),
0053
0054 MV_PCS_BASE_T = 0x0000,
0055 MV_PCS_BASE_R = 0x1000,
0056 MV_PCS_1000BASEX = 0x2000,
0057
0058 MV_PCS_CSCR1 = 0x8000,
0059 MV_PCS_CSCR1_ED_MASK = 0x0300,
0060 MV_PCS_CSCR1_ED_OFF = 0x0000,
0061 MV_PCS_CSCR1_ED_RX = 0x0200,
0062 MV_PCS_CSCR1_ED_NLP = 0x0300,
0063 MV_PCS_CSCR1_MDIX_MASK = 0x0060,
0064 MV_PCS_CSCR1_MDIX_MDI = 0x0000,
0065 MV_PCS_CSCR1_MDIX_MDIX = 0x0020,
0066 MV_PCS_CSCR1_MDIX_AUTO = 0x0060,
0067
0068 MV_PCS_DSC1 = 0x8003,
0069 MV_PCS_DSC1_ENABLE = BIT(9),
0070 MV_PCS_DSC1_10GBT = 0x01c0,
0071 MV_PCS_DSC1_1GBR = 0x0038,
0072 MV_PCS_DSC1_100BTX = 0x0007,
0073 MV_PCS_DSC2 = 0x8004,
0074 MV_PCS_DSC2_2P5G = 0xf000,
0075 MV_PCS_DSC2_5G = 0x0f00,
0076
0077 MV_PCS_CSSR1 = 0x8008,
0078 MV_PCS_CSSR1_SPD1_MASK = 0xc000,
0079 MV_PCS_CSSR1_SPD1_SPD2 = 0xc000,
0080 MV_PCS_CSSR1_SPD1_1000 = 0x8000,
0081 MV_PCS_CSSR1_SPD1_100 = 0x4000,
0082 MV_PCS_CSSR1_SPD1_10 = 0x0000,
0083 MV_PCS_CSSR1_DUPLEX_FULL= BIT(13),
0084 MV_PCS_CSSR1_RESOLVED = BIT(11),
0085 MV_PCS_CSSR1_MDIX = BIT(6),
0086 MV_PCS_CSSR1_SPD2_MASK = 0x000c,
0087 MV_PCS_CSSR1_SPD2_5000 = 0x0008,
0088 MV_PCS_CSSR1_SPD2_2500 = 0x0004,
0089 MV_PCS_CSSR1_SPD2_10000 = 0x0000,
0090
0091
0092 MV_PCS_TEMP = 0x8042,
0093
0094
0095 MV_PCS_PORT_INFO = 0xd00d,
0096 MV_PCS_PORT_INFO_NPORTS_MASK = 0x0380,
0097 MV_PCS_PORT_INFO_NPORTS_SHIFT = 7,
0098
0099
0100
0101
0102
0103 MV_AN_CTRL1000 = 0x8000,
0104 MV_AN_STAT1000 = 0x8001,
0105
0106
0107 MV_V2_PORT_CTRL = 0xf001,
0108 MV_V2_PORT_CTRL_PWRDOWN = BIT(11),
0109 MV_V2_33X0_PORT_CTRL_SWRST = BIT(15),
0110 MV_V2_33X0_PORT_CTRL_MACTYPE_MASK = 0x7,
0111 MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI = 0x0,
0112 MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH = 0x1,
0113 MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN = 0x1,
0114 MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH = 0x2,
0115 MV_V2_3310_PORT_CTRL_MACTYPE_XAUI = 0x3,
0116 MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER = 0x4,
0117 MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN = 0x5,
0118 MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH = 0x6,
0119 MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII = 0x7,
0120 MV_V2_PORT_INTR_STS = 0xf040,
0121 MV_V2_PORT_INTR_MASK = 0xf043,
0122 MV_V2_PORT_INTR_STS_WOL_EN = BIT(8),
0123 MV_V2_MAGIC_PKT_WORD0 = 0xf06b,
0124 MV_V2_MAGIC_PKT_WORD1 = 0xf06c,
0125 MV_V2_MAGIC_PKT_WORD2 = 0xf06d,
0126
0127 MV_V2_WOL_CTRL = 0xf06e,
0128 MV_V2_WOL_CTRL_CLEAR_STS = BIT(15),
0129 MV_V2_WOL_CTRL_MAGIC_PKT_EN = BIT(0),
0130
0131 MV_V2_TEMP_CTRL = 0xf08a,
0132 MV_V2_TEMP_CTRL_MASK = 0xc000,
0133 MV_V2_TEMP_CTRL_SAMPLE = 0x0000,
0134 MV_V2_TEMP_CTRL_DISABLE = 0xc000,
0135 MV_V2_TEMP = 0xf08c,
0136 MV_V2_TEMP_UNKNOWN = 0x9600,
0137 };
0138
0139 struct mv3310_chip {
0140 bool (*has_downshift)(struct phy_device *phydev);
0141 void (*init_supported_interfaces)(unsigned long *mask);
0142 int (*get_mactype)(struct phy_device *phydev);
0143 int (*init_interface)(struct phy_device *phydev, int mactype);
0144
0145 #ifdef CONFIG_HWMON
0146 int (*hwmon_read_temp_reg)(struct phy_device *phydev);
0147 #endif
0148 };
0149
0150 struct mv3310_priv {
0151 DECLARE_BITMAP(supported_interfaces, PHY_INTERFACE_MODE_MAX);
0152
0153 u32 firmware_ver;
0154 bool has_downshift;
0155 bool rate_match;
0156 phy_interface_t const_interface;
0157
0158 struct device *hwmon_dev;
0159 char *hwmon_name;
0160 };
0161
0162 static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev)
0163 {
0164 return phydev->drv->driver_data;
0165 }
0166
0167 #ifdef CONFIG_HWMON
0168 static umode_t mv3310_hwmon_is_visible(const void *data,
0169 enum hwmon_sensor_types type,
0170 u32 attr, int channel)
0171 {
0172 if (type == hwmon_chip && attr == hwmon_chip_update_interval)
0173 return 0444;
0174 if (type == hwmon_temp && attr == hwmon_temp_input)
0175 return 0444;
0176 return 0;
0177 }
0178
0179 static int mv3310_hwmon_read_temp_reg(struct phy_device *phydev)
0180 {
0181 return phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP);
0182 }
0183
0184 static int mv2110_hwmon_read_temp_reg(struct phy_device *phydev)
0185 {
0186 return phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_TEMP);
0187 }
0188
0189 static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
0190 u32 attr, int channel, long *value)
0191 {
0192 struct phy_device *phydev = dev_get_drvdata(dev);
0193 const struct mv3310_chip *chip = to_mv3310_chip(phydev);
0194 int temp;
0195
0196 if (type == hwmon_chip && attr == hwmon_chip_update_interval) {
0197 *value = MSEC_PER_SEC;
0198 return 0;
0199 }
0200
0201 if (type == hwmon_temp && attr == hwmon_temp_input) {
0202 temp = chip->hwmon_read_temp_reg(phydev);
0203 if (temp < 0)
0204 return temp;
0205
0206 *value = ((temp & 0xff) - 75) * 1000;
0207
0208 return 0;
0209 }
0210
0211 return -EOPNOTSUPP;
0212 }
0213
0214 static const struct hwmon_ops mv3310_hwmon_ops = {
0215 .is_visible = mv3310_hwmon_is_visible,
0216 .read = mv3310_hwmon_read,
0217 };
0218
0219 static u32 mv3310_hwmon_chip_config[] = {
0220 HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL,
0221 0,
0222 };
0223
0224 static const struct hwmon_channel_info mv3310_hwmon_chip = {
0225 .type = hwmon_chip,
0226 .config = mv3310_hwmon_chip_config,
0227 };
0228
0229 static u32 mv3310_hwmon_temp_config[] = {
0230 HWMON_T_INPUT,
0231 0,
0232 };
0233
0234 static const struct hwmon_channel_info mv3310_hwmon_temp = {
0235 .type = hwmon_temp,
0236 .config = mv3310_hwmon_temp_config,
0237 };
0238
0239 static const struct hwmon_channel_info *mv3310_hwmon_info[] = {
0240 &mv3310_hwmon_chip,
0241 &mv3310_hwmon_temp,
0242 NULL,
0243 };
0244
0245 static const struct hwmon_chip_info mv3310_hwmon_chip_info = {
0246 .ops = &mv3310_hwmon_ops,
0247 .info = mv3310_hwmon_info,
0248 };
0249
0250 static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
0251 {
0252 u16 val;
0253 int ret;
0254
0255 if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310)
0256 return 0;
0257
0258 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP,
0259 MV_V2_TEMP_UNKNOWN);
0260 if (ret < 0)
0261 return ret;
0262
0263 val = enable ? MV_V2_TEMP_CTRL_SAMPLE : MV_V2_TEMP_CTRL_DISABLE;
0264
0265 return phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL,
0266 MV_V2_TEMP_CTRL_MASK, val);
0267 }
0268
0269 static int mv3310_hwmon_probe(struct phy_device *phydev)
0270 {
0271 struct device *dev = &phydev->mdio.dev;
0272 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
0273 int i, j, ret;
0274
0275 priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
0276 if (!priv->hwmon_name)
0277 return -ENODEV;
0278
0279 for (i = j = 0; priv->hwmon_name[i]; i++) {
0280 if (isalnum(priv->hwmon_name[i])) {
0281 if (i != j)
0282 priv->hwmon_name[j] = priv->hwmon_name[i];
0283 j++;
0284 }
0285 }
0286 priv->hwmon_name[j] = '\0';
0287
0288 ret = mv3310_hwmon_config(phydev, true);
0289 if (ret)
0290 return ret;
0291
0292 priv->hwmon_dev = devm_hwmon_device_register_with_info(dev,
0293 priv->hwmon_name, phydev,
0294 &mv3310_hwmon_chip_info, NULL);
0295
0296 return PTR_ERR_OR_ZERO(priv->hwmon_dev);
0297 }
0298 #else
0299 static inline int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
0300 {
0301 return 0;
0302 }
0303
0304 static int mv3310_hwmon_probe(struct phy_device *phydev)
0305 {
0306 return 0;
0307 }
0308 #endif
0309
0310 static int mv3310_power_down(struct phy_device *phydev)
0311 {
0312 return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
0313 MV_V2_PORT_CTRL_PWRDOWN);
0314 }
0315
0316 static int mv3310_power_up(struct phy_device *phydev)
0317 {
0318 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
0319 int ret;
0320
0321 ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
0322 MV_V2_PORT_CTRL_PWRDOWN);
0323
0324 if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310 ||
0325 priv->firmware_ver < 0x00030000)
0326 return ret;
0327
0328 return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
0329 MV_V2_33X0_PORT_CTRL_SWRST);
0330 }
0331
0332 static int mv3310_reset(struct phy_device *phydev, u32 unit)
0333 {
0334 int val, err;
0335
0336 err = phy_modify_mmd(phydev, MDIO_MMD_PCS, unit + MDIO_CTRL1,
0337 MDIO_CTRL1_RESET, MDIO_CTRL1_RESET);
0338 if (err < 0)
0339 return err;
0340
0341 return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,
0342 unit + MDIO_CTRL1, val,
0343 !(val & MDIO_CTRL1_RESET),
0344 5000, 100000, true);
0345 }
0346
0347 static int mv3310_get_downshift(struct phy_device *phydev, u8 *ds)
0348 {
0349 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
0350 int val;
0351
0352 if (!priv->has_downshift)
0353 return -EOPNOTSUPP;
0354
0355 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1);
0356 if (val < 0)
0357 return val;
0358
0359 if (val & MV_PCS_DSC1_ENABLE)
0360
0361 *ds = 1 + FIELD_GET(MV_PCS_DSC1_10GBT, (u16)val);
0362 else
0363 *ds = DOWNSHIFT_DEV_DISABLE;
0364
0365 return 0;
0366 }
0367
0368 static int mv3310_set_downshift(struct phy_device *phydev, u8 ds)
0369 {
0370 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
0371 u16 val;
0372 int err;
0373
0374 if (!priv->has_downshift)
0375 return -EOPNOTSUPP;
0376
0377 if (ds == DOWNSHIFT_DEV_DISABLE)
0378 return phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1,
0379 MV_PCS_DSC1_ENABLE);
0380
0381
0382
0383
0384
0385
0386
0387
0388 if (ds == DOWNSHIFT_DEV_DEFAULT_COUNT)
0389 ds = 2;
0390
0391 if (ds > 8)
0392 return -E2BIG;
0393
0394 ds -= 1;
0395 val = FIELD_PREP(MV_PCS_DSC2_2P5G, ds);
0396 val |= FIELD_PREP(MV_PCS_DSC2_5G, ds);
0397 err = phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC2,
0398 MV_PCS_DSC2_2P5G | MV_PCS_DSC2_5G, val);
0399 if (err < 0)
0400 return err;
0401
0402 val = MV_PCS_DSC1_ENABLE;
0403 val |= FIELD_PREP(MV_PCS_DSC1_10GBT, ds);
0404 val |= FIELD_PREP(MV_PCS_DSC1_1GBR, ds);
0405 val |= FIELD_PREP(MV_PCS_DSC1_100BTX, ds);
0406
0407 return phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1,
0408 MV_PCS_DSC1_ENABLE | MV_PCS_DSC1_10GBT |
0409 MV_PCS_DSC1_1GBR | MV_PCS_DSC1_100BTX, val);
0410 }
0411
0412 static int mv3310_get_edpd(struct phy_device *phydev, u16 *edpd)
0413 {
0414 int val;
0415
0416 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1);
0417 if (val < 0)
0418 return val;
0419
0420 switch (val & MV_PCS_CSCR1_ED_MASK) {
0421 case MV_PCS_CSCR1_ED_NLP:
0422 *edpd = 1000;
0423 break;
0424 case MV_PCS_CSCR1_ED_RX:
0425 *edpd = ETHTOOL_PHY_EDPD_NO_TX;
0426 break;
0427 default:
0428 *edpd = ETHTOOL_PHY_EDPD_DISABLE;
0429 break;
0430 }
0431 return 0;
0432 }
0433
0434 static int mv3310_set_edpd(struct phy_device *phydev, u16 edpd)
0435 {
0436 u16 val;
0437 int err;
0438
0439 switch (edpd) {
0440 case 1000:
0441 case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS:
0442 val = MV_PCS_CSCR1_ED_NLP;
0443 break;
0444
0445 case ETHTOOL_PHY_EDPD_NO_TX:
0446 val = MV_PCS_CSCR1_ED_RX;
0447 break;
0448
0449 case ETHTOOL_PHY_EDPD_DISABLE:
0450 val = MV_PCS_CSCR1_ED_OFF;
0451 break;
0452
0453 default:
0454 return -EINVAL;
0455 }
0456
0457 err = phy_modify_mmd_changed(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1,
0458 MV_PCS_CSCR1_ED_MASK, val);
0459 if (err > 0)
0460 err = mv3310_reset(phydev, MV_PCS_BASE_T);
0461
0462 return err;
0463 }
0464
0465 static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
0466 {
0467 struct phy_device *phydev = upstream;
0468 __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
0469 phy_interface_t iface;
0470
0471 sfp_parse_support(phydev->sfp_bus, id, support);
0472 iface = sfp_select_interface(phydev->sfp_bus, support);
0473
0474 if (iface != PHY_INTERFACE_MODE_10GBASER) {
0475 dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
0476 return -EINVAL;
0477 }
0478 return 0;
0479 }
0480
0481 static const struct sfp_upstream_ops mv3310_sfp_ops = {
0482 .attach = phy_sfp_attach,
0483 .detach = phy_sfp_detach,
0484 .module_insert = mv3310_sfp_insert,
0485 };
0486
0487 static int mv3310_probe(struct phy_device *phydev)
0488 {
0489 const struct mv3310_chip *chip = to_mv3310_chip(phydev);
0490 struct mv3310_priv *priv;
0491 u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
0492 int ret;
0493
0494 if (!phydev->is_c45 ||
0495 (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
0496 return -ENODEV;
0497
0498 ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT);
0499 if (ret < 0)
0500 return ret;
0501
0502 if (ret & MV_PMA_BOOT_FATAL) {
0503 dev_warn(&phydev->mdio.dev,
0504 "PHY failed to boot firmware, status=%04x\n", ret);
0505 return -ENODEV;
0506 }
0507
0508 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
0509 if (!priv)
0510 return -ENOMEM;
0511
0512 dev_set_drvdata(&phydev->mdio.dev, priv);
0513
0514 ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER0);
0515 if (ret < 0)
0516 return ret;
0517
0518 priv->firmware_ver = ret << 16;
0519
0520 ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER1);
0521 if (ret < 0)
0522 return ret;
0523
0524 priv->firmware_ver |= ret;
0525
0526 phydev_info(phydev, "Firmware version %u.%u.%u.%u\n",
0527 priv->firmware_ver >> 24, (priv->firmware_ver >> 16) & 255,
0528 (priv->firmware_ver >> 8) & 255, priv->firmware_ver & 255);
0529
0530 if (chip->has_downshift)
0531 priv->has_downshift = chip->has_downshift(phydev);
0532
0533
0534 ret = mv3310_power_down(phydev);
0535 if (ret)
0536 return ret;
0537
0538 ret = mv3310_hwmon_probe(phydev);
0539 if (ret)
0540 return ret;
0541
0542 chip->init_supported_interfaces(priv->supported_interfaces);
0543
0544 return phy_sfp_probe(phydev, &mv3310_sfp_ops);
0545 }
0546
0547 static void mv3310_remove(struct phy_device *phydev)
0548 {
0549 mv3310_hwmon_config(phydev, false);
0550 }
0551
0552 static int mv3310_suspend(struct phy_device *phydev)
0553 {
0554 return mv3310_power_down(phydev);
0555 }
0556
0557 static int mv3310_resume(struct phy_device *phydev)
0558 {
0559 int ret;
0560
0561 ret = mv3310_power_up(phydev);
0562 if (ret)
0563 return ret;
0564
0565 return mv3310_hwmon_config(phydev, true);
0566 }
0567
0568
0569
0570
0571
0572
0573
0574
0575 static bool mv3310_has_pma_ngbaset_quirk(struct phy_device *phydev)
0576 {
0577 if (!(phydev->c45_ids.devices_in_package & MDIO_DEVS_PMAPMD))
0578 return false;
0579
0580
0581 return (phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
0582 MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV;
0583 }
0584
0585 static int mv2110_get_mactype(struct phy_device *phydev)
0586 {
0587 int mactype;
0588
0589 mactype = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL);
0590 if (mactype < 0)
0591 return mactype;
0592
0593 return mactype & MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
0594 }
0595
0596 static int mv3310_get_mactype(struct phy_device *phydev)
0597 {
0598 int mactype;
0599
0600 mactype = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
0601 if (mactype < 0)
0602 return mactype;
0603
0604 return mactype & MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
0605 }
0606
0607 static int mv2110_init_interface(struct phy_device *phydev, int mactype)
0608 {
0609 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
0610
0611 priv->rate_match = false;
0612
0613 if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
0614 priv->rate_match = true;
0615
0616 if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII)
0617 priv->const_interface = PHY_INTERFACE_MODE_USXGMII;
0618 else if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
0619 priv->const_interface = PHY_INTERFACE_MODE_10GBASER;
0620 else if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER ||
0621 mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN)
0622 priv->const_interface = PHY_INTERFACE_MODE_NA;
0623 else
0624 return -EINVAL;
0625
0626 return 0;
0627 }
0628
0629 static int mv3310_init_interface(struct phy_device *phydev, int mactype)
0630 {
0631 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
0632
0633 priv->rate_match = false;
0634
0635 if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
0636 mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
0637 mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH)
0638 priv->rate_match = true;
0639
0640 if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII)
0641 priv->const_interface = PHY_INTERFACE_MODE_USXGMII;
0642 else if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
0643 mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN ||
0644 mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER)
0645 priv->const_interface = PHY_INTERFACE_MODE_10GBASER;
0646 else if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
0647 mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI)
0648 priv->const_interface = PHY_INTERFACE_MODE_RXAUI;
0649 else if (mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH ||
0650 mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI)
0651 priv->const_interface = PHY_INTERFACE_MODE_XAUI;
0652 else
0653 return -EINVAL;
0654
0655 return 0;
0656 }
0657
0658 static int mv3340_init_interface(struct phy_device *phydev, int mactype)
0659 {
0660 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
0661 int err = 0;
0662
0663 priv->rate_match = false;
0664
0665 if (mactype == MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN)
0666 priv->const_interface = PHY_INTERFACE_MODE_RXAUI;
0667 else
0668 err = mv3310_init_interface(phydev, mactype);
0669
0670 return err;
0671 }
0672
0673 static int mv3310_config_init(struct phy_device *phydev)
0674 {
0675 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
0676 const struct mv3310_chip *chip = to_mv3310_chip(phydev);
0677 int err, mactype;
0678
0679
0680 if (!test_bit(phydev->interface, priv->supported_interfaces))
0681 return -ENODEV;
0682
0683 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
0684
0685
0686 err = mv3310_power_up(phydev);
0687 if (err)
0688 return err;
0689
0690 mactype = chip->get_mactype(phydev);
0691 if (mactype < 0)
0692 return mactype;
0693
0694 err = chip->init_interface(phydev, mactype);
0695 if (err) {
0696 phydev_err(phydev, "MACTYPE configuration invalid\n");
0697 return err;
0698 }
0699
0700
0701 err = mv3310_set_edpd(phydev, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS);
0702 if (err)
0703 return err;
0704
0705
0706 err = mv3310_set_downshift(phydev, DOWNSHIFT_DEV_DEFAULT_COUNT);
0707 if (err && err != -EOPNOTSUPP)
0708 return err;
0709
0710 return 0;
0711 }
0712
0713 static int mv3310_get_features(struct phy_device *phydev)
0714 {
0715 int ret, val;
0716
0717 ret = genphy_c45_pma_read_abilities(phydev);
0718 if (ret)
0719 return ret;
0720
0721 if (mv3310_has_pma_ngbaset_quirk(phydev)) {
0722 val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
0723 MDIO_PMA_NG_EXTABLE);
0724 if (val < 0)
0725 return val;
0726
0727 linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
0728 phydev->supported,
0729 val & MDIO_PMA_NG_EXTABLE_2_5GBT);
0730
0731 linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
0732 phydev->supported,
0733 val & MDIO_PMA_NG_EXTABLE_5GBT);
0734 }
0735
0736 return 0;
0737 }
0738
0739 static int mv3310_config_mdix(struct phy_device *phydev)
0740 {
0741 u16 val;
0742 int err;
0743
0744 switch (phydev->mdix_ctrl) {
0745 case ETH_TP_MDI_AUTO:
0746 val = MV_PCS_CSCR1_MDIX_AUTO;
0747 break;
0748 case ETH_TP_MDI_X:
0749 val = MV_PCS_CSCR1_MDIX_MDIX;
0750 break;
0751 case ETH_TP_MDI:
0752 val = MV_PCS_CSCR1_MDIX_MDI;
0753 break;
0754 default:
0755 return -EINVAL;
0756 }
0757
0758 err = phy_modify_mmd_changed(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1,
0759 MV_PCS_CSCR1_MDIX_MASK, val);
0760 if (err > 0)
0761 err = mv3310_reset(phydev, MV_PCS_BASE_T);
0762
0763 return err;
0764 }
0765
0766 static int mv3310_config_aneg(struct phy_device *phydev)
0767 {
0768 bool changed = false;
0769 u16 reg;
0770 int ret;
0771
0772 ret = mv3310_config_mdix(phydev);
0773 if (ret < 0)
0774 return ret;
0775
0776 if (phydev->autoneg == AUTONEG_DISABLE)
0777 return genphy_c45_pma_setup_forced(phydev);
0778
0779 ret = genphy_c45_an_config_aneg(phydev);
0780 if (ret < 0)
0781 return ret;
0782 if (ret > 0)
0783 changed = true;
0784
0785
0786
0787
0788 reg = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
0789 ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
0790 ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg);
0791 if (ret < 0)
0792 return ret;
0793 if (ret > 0)
0794 changed = true;
0795
0796 return genphy_c45_check_and_restart_aneg(phydev, changed);
0797 }
0798
0799 static int mv3310_aneg_done(struct phy_device *phydev)
0800 {
0801 int val;
0802
0803 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
0804 if (val < 0)
0805 return val;
0806
0807 if (val & MDIO_STAT1_LSTATUS)
0808 return 1;
0809
0810 return genphy_c45_aneg_done(phydev);
0811 }
0812
0813 static void mv3310_update_interface(struct phy_device *phydev)
0814 {
0815 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
0816
0817 if (!phydev->link)
0818 return;
0819
0820
0821
0822
0823
0824
0825
0826 if (priv->rate_match ||
0827 priv->const_interface == PHY_INTERFACE_MODE_USXGMII) {
0828 phydev->interface = priv->const_interface;
0829 return;
0830 }
0831
0832
0833
0834
0835
0836
0837
0838 switch (phydev->speed) {
0839 case SPEED_10000:
0840 phydev->interface = priv->const_interface;
0841 break;
0842 case SPEED_5000:
0843 phydev->interface = PHY_INTERFACE_MODE_5GBASER;
0844 break;
0845 case SPEED_2500:
0846 phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
0847 break;
0848 case SPEED_1000:
0849 case SPEED_100:
0850 case SPEED_10:
0851 phydev->interface = PHY_INTERFACE_MODE_SGMII;
0852 break;
0853 default:
0854 break;
0855 }
0856 }
0857
0858
0859 static int mv3310_read_status_10gbaser(struct phy_device *phydev)
0860 {
0861 phydev->link = 1;
0862 phydev->speed = SPEED_10000;
0863 phydev->duplex = DUPLEX_FULL;
0864 phydev->port = PORT_FIBRE;
0865
0866 return 0;
0867 }
0868
0869 static int mv3310_read_status_copper(struct phy_device *phydev)
0870 {
0871 int cssr1, speed, val;
0872
0873 val = genphy_c45_read_link(phydev);
0874 if (val < 0)
0875 return val;
0876
0877 val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
0878 if (val < 0)
0879 return val;
0880
0881 cssr1 = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_CSSR1);
0882 if (cssr1 < 0)
0883 return cssr1;
0884
0885
0886 if (!(cssr1 & MV_PCS_CSSR1_RESOLVED)) {
0887 phydev->link = 0;
0888 return 0;
0889 }
0890
0891
0892 speed = cssr1 & MV_PCS_CSSR1_SPD1_MASK;
0893 if (speed == MV_PCS_CSSR1_SPD1_SPD2)
0894 speed |= cssr1 & MV_PCS_CSSR1_SPD2_MASK;
0895
0896 switch (speed) {
0897 case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_10000:
0898 phydev->speed = SPEED_10000;
0899 break;
0900
0901 case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_5000:
0902 phydev->speed = SPEED_5000;
0903 break;
0904
0905 case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_2500:
0906 phydev->speed = SPEED_2500;
0907 break;
0908
0909 case MV_PCS_CSSR1_SPD1_1000:
0910 phydev->speed = SPEED_1000;
0911 break;
0912
0913 case MV_PCS_CSSR1_SPD1_100:
0914 phydev->speed = SPEED_100;
0915 break;
0916
0917 case MV_PCS_CSSR1_SPD1_10:
0918 phydev->speed = SPEED_10;
0919 break;
0920 }
0921
0922 phydev->duplex = cssr1 & MV_PCS_CSSR1_DUPLEX_FULL ?
0923 DUPLEX_FULL : DUPLEX_HALF;
0924 phydev->port = PORT_TP;
0925 phydev->mdix = cssr1 & MV_PCS_CSSR1_MDIX ?
0926 ETH_TP_MDI_X : ETH_TP_MDI;
0927
0928 if (val & MDIO_AN_STAT1_COMPLETE) {
0929 val = genphy_c45_read_lpa(phydev);
0930 if (val < 0)
0931 return val;
0932
0933
0934 val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_STAT1000);
0935 if (val < 0)
0936 return val;
0937
0938 mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);
0939
0940
0941 phy_resolve_aneg_pause(phydev);
0942 }
0943
0944 return 0;
0945 }
0946
0947 static int mv3310_read_status(struct phy_device *phydev)
0948 {
0949 int err, val;
0950
0951 phydev->speed = SPEED_UNKNOWN;
0952 phydev->duplex = DUPLEX_UNKNOWN;
0953 linkmode_zero(phydev->lp_advertising);
0954 phydev->link = 0;
0955 phydev->pause = 0;
0956 phydev->asym_pause = 0;
0957 phydev->mdix = ETH_TP_MDI_INVALID;
0958
0959 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
0960 if (val < 0)
0961 return val;
0962
0963 if (val & MDIO_STAT1_LSTATUS)
0964 err = mv3310_read_status_10gbaser(phydev);
0965 else
0966 err = mv3310_read_status_copper(phydev);
0967 if (err < 0)
0968 return err;
0969
0970 if (phydev->link)
0971 mv3310_update_interface(phydev);
0972
0973 return 0;
0974 }
0975
0976 static int mv3310_get_tunable(struct phy_device *phydev,
0977 struct ethtool_tunable *tuna, void *data)
0978 {
0979 switch (tuna->id) {
0980 case ETHTOOL_PHY_DOWNSHIFT:
0981 return mv3310_get_downshift(phydev, data);
0982 case ETHTOOL_PHY_EDPD:
0983 return mv3310_get_edpd(phydev, data);
0984 default:
0985 return -EOPNOTSUPP;
0986 }
0987 }
0988
0989 static int mv3310_set_tunable(struct phy_device *phydev,
0990 struct ethtool_tunable *tuna, const void *data)
0991 {
0992 switch (tuna->id) {
0993 case ETHTOOL_PHY_DOWNSHIFT:
0994 return mv3310_set_downshift(phydev, *(u8 *)data);
0995 case ETHTOOL_PHY_EDPD:
0996 return mv3310_set_edpd(phydev, *(u16 *)data);
0997 default:
0998 return -EOPNOTSUPP;
0999 }
1000 }
1001
1002 static bool mv3310_has_downshift(struct phy_device *phydev)
1003 {
1004 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
1005
1006
1007 return priv->firmware_ver >= MV_VERSION(0,3,5,0);
1008 }
1009
1010 static void mv3310_init_supported_interfaces(unsigned long *mask)
1011 {
1012 __set_bit(PHY_INTERFACE_MODE_SGMII, mask);
1013 __set_bit(PHY_INTERFACE_MODE_2500BASEX, mask);
1014 __set_bit(PHY_INTERFACE_MODE_5GBASER, mask);
1015 __set_bit(PHY_INTERFACE_MODE_XAUI, mask);
1016 __set_bit(PHY_INTERFACE_MODE_RXAUI, mask);
1017 __set_bit(PHY_INTERFACE_MODE_10GBASER, mask);
1018 __set_bit(PHY_INTERFACE_MODE_USXGMII, mask);
1019 }
1020
1021 static void mv3340_init_supported_interfaces(unsigned long *mask)
1022 {
1023 __set_bit(PHY_INTERFACE_MODE_SGMII, mask);
1024 __set_bit(PHY_INTERFACE_MODE_2500BASEX, mask);
1025 __set_bit(PHY_INTERFACE_MODE_5GBASER, mask);
1026 __set_bit(PHY_INTERFACE_MODE_RXAUI, mask);
1027 __set_bit(PHY_INTERFACE_MODE_10GBASER, mask);
1028 __set_bit(PHY_INTERFACE_MODE_USXGMII, mask);
1029 }
1030
1031 static void mv2110_init_supported_interfaces(unsigned long *mask)
1032 {
1033 __set_bit(PHY_INTERFACE_MODE_SGMII, mask);
1034 __set_bit(PHY_INTERFACE_MODE_2500BASEX, mask);
1035 __set_bit(PHY_INTERFACE_MODE_5GBASER, mask);
1036 __set_bit(PHY_INTERFACE_MODE_10GBASER, mask);
1037 __set_bit(PHY_INTERFACE_MODE_USXGMII, mask);
1038 }
1039
1040 static void mv2111_init_supported_interfaces(unsigned long *mask)
1041 {
1042 __set_bit(PHY_INTERFACE_MODE_SGMII, mask);
1043 __set_bit(PHY_INTERFACE_MODE_2500BASEX, mask);
1044 __set_bit(PHY_INTERFACE_MODE_10GBASER, mask);
1045 __set_bit(PHY_INTERFACE_MODE_USXGMII, mask);
1046 }
1047
1048 static const struct mv3310_chip mv3310_type = {
1049 .has_downshift = mv3310_has_downshift,
1050 .init_supported_interfaces = mv3310_init_supported_interfaces,
1051 .get_mactype = mv3310_get_mactype,
1052 .init_interface = mv3310_init_interface,
1053
1054 #ifdef CONFIG_HWMON
1055 .hwmon_read_temp_reg = mv3310_hwmon_read_temp_reg,
1056 #endif
1057 };
1058
1059 static const struct mv3310_chip mv3340_type = {
1060 .has_downshift = mv3310_has_downshift,
1061 .init_supported_interfaces = mv3340_init_supported_interfaces,
1062 .get_mactype = mv3310_get_mactype,
1063 .init_interface = mv3340_init_interface,
1064
1065 #ifdef CONFIG_HWMON
1066 .hwmon_read_temp_reg = mv3310_hwmon_read_temp_reg,
1067 #endif
1068 };
1069
1070 static const struct mv3310_chip mv2110_type = {
1071 .init_supported_interfaces = mv2110_init_supported_interfaces,
1072 .get_mactype = mv2110_get_mactype,
1073 .init_interface = mv2110_init_interface,
1074
1075 #ifdef CONFIG_HWMON
1076 .hwmon_read_temp_reg = mv2110_hwmon_read_temp_reg,
1077 #endif
1078 };
1079
1080 static const struct mv3310_chip mv2111_type = {
1081 .init_supported_interfaces = mv2111_init_supported_interfaces,
1082 .get_mactype = mv2110_get_mactype,
1083 .init_interface = mv2110_init_interface,
1084
1085 #ifdef CONFIG_HWMON
1086 .hwmon_read_temp_reg = mv2110_hwmon_read_temp_reg,
1087 #endif
1088 };
1089
1090 static int mv3310_get_number_of_ports(struct phy_device *phydev)
1091 {
1092 int ret;
1093
1094 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_PORT_INFO);
1095 if (ret < 0)
1096 return ret;
1097
1098 ret &= MV_PCS_PORT_INFO_NPORTS_MASK;
1099 ret >>= MV_PCS_PORT_INFO_NPORTS_SHIFT;
1100
1101 return ret + 1;
1102 }
1103
1104 static int mv3310_match_phy_device(struct phy_device *phydev)
1105 {
1106 if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
1107 MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)
1108 return 0;
1109
1110 return mv3310_get_number_of_ports(phydev) == 1;
1111 }
1112
1113 static int mv3340_match_phy_device(struct phy_device *phydev)
1114 {
1115 if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
1116 MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)
1117 return 0;
1118
1119 return mv3310_get_number_of_ports(phydev) == 4;
1120 }
1121
1122 static int mv211x_match_phy_device(struct phy_device *phydev, bool has_5g)
1123 {
1124 int val;
1125
1126 if ((phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
1127 MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88E2110)
1128 return 0;
1129
1130 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_SPEED);
1131 if (val < 0)
1132 return val;
1133
1134 return !!(val & MDIO_PCS_SPEED_5G) == has_5g;
1135 }
1136
1137 static int mv2110_match_phy_device(struct phy_device *phydev)
1138 {
1139 return mv211x_match_phy_device(phydev, true);
1140 }
1141
1142 static int mv2111_match_phy_device(struct phy_device *phydev)
1143 {
1144 return mv211x_match_phy_device(phydev, false);
1145 }
1146
1147 static void mv3110_get_wol(struct phy_device *phydev,
1148 struct ethtool_wolinfo *wol)
1149 {
1150 int ret;
1151
1152 wol->supported = WAKE_MAGIC;
1153 wol->wolopts = 0;
1154
1155 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_WOL_CTRL);
1156 if (ret < 0)
1157 return;
1158
1159 if (ret & MV_V2_WOL_CTRL_MAGIC_PKT_EN)
1160 wol->wolopts |= WAKE_MAGIC;
1161 }
1162
1163 static int mv3110_set_wol(struct phy_device *phydev,
1164 struct ethtool_wolinfo *wol)
1165 {
1166 int ret;
1167
1168 if (wol->wolopts & WAKE_MAGIC) {
1169
1170 ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
1171 MV_V2_PORT_INTR_MASK,
1172 MV_V2_PORT_INTR_STS_WOL_EN);
1173 if (ret < 0)
1174 return ret;
1175
1176
1177 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
1178 MV_V2_MAGIC_PKT_WORD2,
1179 ((phydev->attached_dev->dev_addr[5] << 8) |
1180 phydev->attached_dev->dev_addr[4]));
1181 if (ret < 0)
1182 return ret;
1183
1184 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
1185 MV_V2_MAGIC_PKT_WORD1,
1186 ((phydev->attached_dev->dev_addr[3] << 8) |
1187 phydev->attached_dev->dev_addr[2]));
1188 if (ret < 0)
1189 return ret;
1190
1191 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
1192 MV_V2_MAGIC_PKT_WORD0,
1193 ((phydev->attached_dev->dev_addr[1] << 8) |
1194 phydev->attached_dev->dev_addr[0]));
1195 if (ret < 0)
1196 return ret;
1197
1198
1199 ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
1200 MV_V2_WOL_CTRL,
1201 MV_V2_WOL_CTRL_MAGIC_PKT_EN |
1202 MV_V2_WOL_CTRL_CLEAR_STS);
1203 if (ret < 0)
1204 return ret;
1205 } else {
1206
1207 ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2,
1208 MV_V2_WOL_CTRL,
1209 MV_V2_WOL_CTRL_MAGIC_PKT_EN,
1210 MV_V2_WOL_CTRL_CLEAR_STS);
1211 if (ret < 0)
1212 return ret;
1213 }
1214
1215
1216 return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
1217 MV_V2_WOL_CTRL,
1218 MV_V2_WOL_CTRL_CLEAR_STS);
1219 }
1220
1221 static struct phy_driver mv3310_drivers[] = {
1222 {
1223 .phy_id = MARVELL_PHY_ID_88X3310,
1224 .phy_id_mask = MARVELL_PHY_ID_MASK,
1225 .match_phy_device = mv3310_match_phy_device,
1226 .name = "mv88x3310",
1227 .driver_data = &mv3310_type,
1228 .get_features = mv3310_get_features,
1229 .config_init = mv3310_config_init,
1230 .probe = mv3310_probe,
1231 .suspend = mv3310_suspend,
1232 .resume = mv3310_resume,
1233 .config_aneg = mv3310_config_aneg,
1234 .aneg_done = mv3310_aneg_done,
1235 .read_status = mv3310_read_status,
1236 .get_tunable = mv3310_get_tunable,
1237 .set_tunable = mv3310_set_tunable,
1238 .remove = mv3310_remove,
1239 .set_loopback = genphy_c45_loopback,
1240 .get_wol = mv3110_get_wol,
1241 .set_wol = mv3110_set_wol,
1242 },
1243 {
1244 .phy_id = MARVELL_PHY_ID_88X3310,
1245 .phy_id_mask = MARVELL_PHY_ID_MASK,
1246 .match_phy_device = mv3340_match_phy_device,
1247 .name = "mv88x3340",
1248 .driver_data = &mv3340_type,
1249 .get_features = mv3310_get_features,
1250 .config_init = mv3310_config_init,
1251 .probe = mv3310_probe,
1252 .suspend = mv3310_suspend,
1253 .resume = mv3310_resume,
1254 .config_aneg = mv3310_config_aneg,
1255 .aneg_done = mv3310_aneg_done,
1256 .read_status = mv3310_read_status,
1257 .get_tunable = mv3310_get_tunable,
1258 .set_tunable = mv3310_set_tunable,
1259 .remove = mv3310_remove,
1260 .set_loopback = genphy_c45_loopback,
1261 },
1262 {
1263 .phy_id = MARVELL_PHY_ID_88E2110,
1264 .phy_id_mask = MARVELL_PHY_ID_MASK,
1265 .match_phy_device = mv2110_match_phy_device,
1266 .name = "mv88e2110",
1267 .driver_data = &mv2110_type,
1268 .probe = mv3310_probe,
1269 .suspend = mv3310_suspend,
1270 .resume = mv3310_resume,
1271 .config_init = mv3310_config_init,
1272 .config_aneg = mv3310_config_aneg,
1273 .aneg_done = mv3310_aneg_done,
1274 .read_status = mv3310_read_status,
1275 .get_tunable = mv3310_get_tunable,
1276 .set_tunable = mv3310_set_tunable,
1277 .remove = mv3310_remove,
1278 .set_loopback = genphy_c45_loopback,
1279 .get_wol = mv3110_get_wol,
1280 .set_wol = mv3110_set_wol,
1281 },
1282 {
1283 .phy_id = MARVELL_PHY_ID_88E2110,
1284 .phy_id_mask = MARVELL_PHY_ID_MASK,
1285 .match_phy_device = mv2111_match_phy_device,
1286 .name = "mv88e2111",
1287 .driver_data = &mv2111_type,
1288 .probe = mv3310_probe,
1289 .suspend = mv3310_suspend,
1290 .resume = mv3310_resume,
1291 .config_init = mv3310_config_init,
1292 .config_aneg = mv3310_config_aneg,
1293 .aneg_done = mv3310_aneg_done,
1294 .read_status = mv3310_read_status,
1295 .get_tunable = mv3310_get_tunable,
1296 .set_tunable = mv3310_set_tunable,
1297 .remove = mv3310_remove,
1298 .set_loopback = genphy_c45_loopback,
1299 },
1300 };
1301
1302 module_phy_driver(mv3310_drivers);
1303
1304 static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
1305 { MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_MASK },
1306 { MARVELL_PHY_ID_88E2110, MARVELL_PHY_ID_MASK },
1307 { },
1308 };
1309 MODULE_DEVICE_TABLE(mdio, mv3310_tbl);
1310 MODULE_DESCRIPTION("Marvell Alaska X/M multi-gigabit Ethernet PHY driver");
1311 MODULE_LICENSE("GPL");