dt-bindings: mtd: ingenic: Use standard ecc-engine property
[linux/fpc-iii.git] / drivers / net / phy / marvell10g.c
blob100b401b1f4a125343afbf880a1ced60cc033d42
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Marvell 10G 88x3310 PHY driver
5 * Based upon the ID registers, this PHY appears to be a mixture of IPs
6 * from two different companies.
8 * There appears to be several different data paths through the PHY which
9 * are automatically managed by the PHY. The following has been determined
10 * via observation and experimentation for a setup using single-lane Serdes:
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 -- Fiber
16 * With XAUI, observation shows:
18 * XAUI PHYXS -- <appropriate PCS as above>
20 * and no switching of the host interface mode occurs.
22 * If both the fiber and copper ports are connected, the first to gain
23 * link takes priority and the other port is completely locked out.
25 #include <linux/ctype.h>
26 #include <linux/hwmon.h>
27 #include <linux/marvell_phy.h>
28 #include <linux/phy.h>
30 #define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe
31 #define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa)
33 enum {
34 MV_PCS_BASE_T = 0x0000,
35 MV_PCS_BASE_R = 0x1000,
36 MV_PCS_1000BASEX = 0x2000,
38 MV_PCS_PAIRSWAP = 0x8182,
39 MV_PCS_PAIRSWAP_MASK = 0x0003,
40 MV_PCS_PAIRSWAP_AB = 0x0002,
41 MV_PCS_PAIRSWAP_NONE = 0x0003,
43 /* These registers appear at 0x800X and 0xa00X - the 0xa00X control
44 * registers appear to set themselves to the 0x800X when AN is
45 * restarted, but status registers appear readable from either.
47 MV_AN_CTRL1000 = 0x8000, /* 1000base-T control register */
48 MV_AN_STAT1000 = 0x8001, /* 1000base-T status register */
50 /* Vendor2 MMD registers */
51 MV_V2_TEMP_CTRL = 0xf08a,
52 MV_V2_TEMP_CTRL_MASK = 0xc000,
53 MV_V2_TEMP_CTRL_SAMPLE = 0x0000,
54 MV_V2_TEMP_CTRL_DISABLE = 0xc000,
55 MV_V2_TEMP = 0xf08c,
56 MV_V2_TEMP_UNKNOWN = 0x9600, /* unknown function */
59 struct mv3310_priv {
60 struct device *hwmon_dev;
61 char *hwmon_name;
64 #ifdef CONFIG_HWMON
65 static umode_t mv3310_hwmon_is_visible(const void *data,
66 enum hwmon_sensor_types type,
67 u32 attr, int channel)
69 if (type == hwmon_chip && attr == hwmon_chip_update_interval)
70 return 0444;
71 if (type == hwmon_temp && attr == hwmon_temp_input)
72 return 0444;
73 return 0;
76 static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
77 u32 attr, int channel, long *value)
79 struct phy_device *phydev = dev_get_drvdata(dev);
80 int temp;
82 if (type == hwmon_chip && attr == hwmon_chip_update_interval) {
83 *value = MSEC_PER_SEC;
84 return 0;
87 if (type == hwmon_temp && attr == hwmon_temp_input) {
88 temp = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP);
89 if (temp < 0)
90 return temp;
92 *value = ((temp & 0xff) - 75) * 1000;
94 return 0;
97 return -EOPNOTSUPP;
100 static const struct hwmon_ops mv3310_hwmon_ops = {
101 .is_visible = mv3310_hwmon_is_visible,
102 .read = mv3310_hwmon_read,
105 static u32 mv3310_hwmon_chip_config[] = {
106 HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL,
110 static const struct hwmon_channel_info mv3310_hwmon_chip = {
111 .type = hwmon_chip,
112 .config = mv3310_hwmon_chip_config,
115 static u32 mv3310_hwmon_temp_config[] = {
116 HWMON_T_INPUT,
120 static const struct hwmon_channel_info mv3310_hwmon_temp = {
121 .type = hwmon_temp,
122 .config = mv3310_hwmon_temp_config,
125 static const struct hwmon_channel_info *mv3310_hwmon_info[] = {
126 &mv3310_hwmon_chip,
127 &mv3310_hwmon_temp,
128 NULL,
131 static const struct hwmon_chip_info mv3310_hwmon_chip_info = {
132 .ops = &mv3310_hwmon_ops,
133 .info = mv3310_hwmon_info,
136 static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
138 u16 val;
139 int ret;
141 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP,
142 MV_V2_TEMP_UNKNOWN);
143 if (ret < 0)
144 return ret;
146 val = enable ? MV_V2_TEMP_CTRL_SAMPLE : MV_V2_TEMP_CTRL_DISABLE;
148 return phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL,
149 MV_V2_TEMP_CTRL_MASK, val);
152 static void mv3310_hwmon_disable(void *data)
154 struct phy_device *phydev = data;
156 mv3310_hwmon_config(phydev, false);
159 static int mv3310_hwmon_probe(struct phy_device *phydev)
161 struct device *dev = &phydev->mdio.dev;
162 struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
163 int i, j, ret;
165 priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
166 if (!priv->hwmon_name)
167 return -ENODEV;
169 for (i = j = 0; priv->hwmon_name[i]; i++) {
170 if (isalnum(priv->hwmon_name[i])) {
171 if (i != j)
172 priv->hwmon_name[j] = priv->hwmon_name[i];
173 j++;
176 priv->hwmon_name[j] = '\0';
178 ret = mv3310_hwmon_config(phydev, true);
179 if (ret)
180 return ret;
182 ret = devm_add_action_or_reset(dev, mv3310_hwmon_disable, phydev);
183 if (ret)
184 return ret;
186 priv->hwmon_dev = devm_hwmon_device_register_with_info(dev,
187 priv->hwmon_name, phydev,
188 &mv3310_hwmon_chip_info, NULL);
190 return PTR_ERR_OR_ZERO(priv->hwmon_dev);
192 #else
193 static inline int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
195 return 0;
198 static int mv3310_hwmon_probe(struct phy_device *phydev)
200 return 0;
202 #endif
204 static int mv3310_probe(struct phy_device *phydev)
206 struct mv3310_priv *priv;
207 u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
208 int ret;
210 if (!phydev->is_c45 ||
211 (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
212 return -ENODEV;
214 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
215 if (!priv)
216 return -ENOMEM;
218 dev_set_drvdata(&phydev->mdio.dev, priv);
220 ret = mv3310_hwmon_probe(phydev);
221 if (ret)
222 return ret;
224 return 0;
227 static int mv3310_suspend(struct phy_device *phydev)
229 return 0;
232 static int mv3310_resume(struct phy_device *phydev)
234 return mv3310_hwmon_config(phydev, true);
237 /* Some PHYs in the Alaska family such as the 88X3310 and the 88E2010
238 * don't set bit 14 in PMA Extended Abilities (1.11), although they do
239 * support 2.5GBASET and 5GBASET. For these models, we can still read their
240 * 2.5G/5G extended abilities register (1.21). We detect these models based on
241 * the PMA device identifier, with a mask matching models known to have this
242 * issue
244 static bool mv3310_has_pma_ngbaset_quirk(struct phy_device *phydev)
246 if (!(phydev->c45_ids.devices_in_package & MDIO_DEVS_PMAPMD))
247 return false;
249 /* Only some revisions of the 88X3310 family PMA seem to be impacted */
250 return (phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
251 MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV;
254 static int mv3310_config_init(struct phy_device *phydev)
256 /* Check that the PHY interface type is compatible */
257 if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
258 phydev->interface != PHY_INTERFACE_MODE_2500BASEX &&
259 phydev->interface != PHY_INTERFACE_MODE_XAUI &&
260 phydev->interface != PHY_INTERFACE_MODE_RXAUI &&
261 phydev->interface != PHY_INTERFACE_MODE_10GKR)
262 return -ENODEV;
264 return 0;
267 static int mv3310_get_features(struct phy_device *phydev)
269 int ret, val;
271 ret = genphy_c45_pma_read_abilities(phydev);
272 if (ret)
273 return ret;
275 if (mv3310_has_pma_ngbaset_quirk(phydev)) {
276 val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
277 MDIO_PMA_NG_EXTABLE);
278 if (val < 0)
279 return val;
281 linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
282 phydev->supported,
283 val & MDIO_PMA_NG_EXTABLE_2_5GBT);
285 linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
286 phydev->supported,
287 val & MDIO_PMA_NG_EXTABLE_5GBT);
290 return 0;
293 static int mv3310_config_aneg(struct phy_device *phydev)
295 bool changed = false;
296 u16 reg;
297 int ret;
299 /* We don't support manual MDI control */
300 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
302 if (phydev->autoneg == AUTONEG_DISABLE)
303 return genphy_c45_pma_setup_forced(phydev);
305 ret = genphy_c45_an_config_aneg(phydev);
306 if (ret < 0)
307 return ret;
308 if (ret > 0)
309 changed = true;
311 /* Clause 45 has no standardized support for 1000BaseT, therefore
312 * use vendor registers for this mode.
314 reg = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
315 ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
316 ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg);
317 if (ret < 0)
318 return ret;
319 if (ret > 0)
320 changed = true;
322 return genphy_c45_check_and_restart_aneg(phydev, changed);
325 static int mv3310_aneg_done(struct phy_device *phydev)
327 int val;
329 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
330 if (val < 0)
331 return val;
333 if (val & MDIO_STAT1_LSTATUS)
334 return 1;
336 return genphy_c45_aneg_done(phydev);
339 static void mv3310_update_interface(struct phy_device *phydev)
341 if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
342 phydev->interface == PHY_INTERFACE_MODE_2500BASEX ||
343 phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
344 /* The PHY automatically switches its serdes interface (and
345 * active PHYXS instance) between Cisco SGMII, 10GBase-KR and
346 * 2500BaseX modes according to the speed. Florian suggests
347 * setting phydev->interface to communicate this to the MAC.
348 * Only do this if we are already in one of the above modes.
350 switch (phydev->speed) {
351 case SPEED_10000:
352 phydev->interface = PHY_INTERFACE_MODE_10GKR;
353 break;
354 case SPEED_2500:
355 phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
356 break;
357 case SPEED_1000:
358 case SPEED_100:
359 case SPEED_10:
360 phydev->interface = PHY_INTERFACE_MODE_SGMII;
361 break;
362 default:
363 break;
368 /* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */
369 static int mv3310_read_10gbr_status(struct phy_device *phydev)
371 phydev->link = 1;
372 phydev->speed = SPEED_10000;
373 phydev->duplex = DUPLEX_FULL;
375 mv3310_update_interface(phydev);
377 return 0;
380 static int mv3310_read_status(struct phy_device *phydev)
382 int val;
384 phydev->speed = SPEED_UNKNOWN;
385 phydev->duplex = DUPLEX_UNKNOWN;
386 linkmode_zero(phydev->lp_advertising);
387 phydev->link = 0;
388 phydev->pause = 0;
389 phydev->asym_pause = 0;
390 phydev->mdix = 0;
392 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
393 if (val < 0)
394 return val;
396 if (val & MDIO_STAT1_LSTATUS)
397 return mv3310_read_10gbr_status(phydev);
399 val = genphy_c45_read_link(phydev);
400 if (val < 0)
401 return val;
403 val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
404 if (val < 0)
405 return val;
407 if (val & MDIO_AN_STAT1_COMPLETE) {
408 val = genphy_c45_read_lpa(phydev);
409 if (val < 0)
410 return val;
412 /* Read the link partner's 1G advertisement */
413 val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_STAT1000);
414 if (val < 0)
415 return val;
417 mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);
419 if (phydev->autoneg == AUTONEG_ENABLE)
420 phy_resolve_aneg_linkmode(phydev);
423 if (phydev->autoneg != AUTONEG_ENABLE) {
424 val = genphy_c45_read_pma(phydev);
425 if (val < 0)
426 return val;
429 if (phydev->speed == SPEED_10000) {
430 val = genphy_c45_read_mdix(phydev);
431 if (val < 0)
432 return val;
433 } else {
434 val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_PAIRSWAP);
435 if (val < 0)
436 return val;
438 switch (val & MV_PCS_PAIRSWAP_MASK) {
439 case MV_PCS_PAIRSWAP_AB:
440 phydev->mdix = ETH_TP_MDI_X;
441 break;
442 case MV_PCS_PAIRSWAP_NONE:
443 phydev->mdix = ETH_TP_MDI;
444 break;
445 default:
446 phydev->mdix = ETH_TP_MDI_INVALID;
447 break;
451 mv3310_update_interface(phydev);
453 return 0;
456 static struct phy_driver mv3310_drivers[] = {
458 .phy_id = MARVELL_PHY_ID_88X3310,
459 .phy_id_mask = MARVELL_PHY_ID_MASK,
460 .name = "mv88x3310",
461 .get_features = mv3310_get_features,
462 .soft_reset = genphy_no_soft_reset,
463 .config_init = mv3310_config_init,
464 .probe = mv3310_probe,
465 .suspend = mv3310_suspend,
466 .resume = mv3310_resume,
467 .config_aneg = mv3310_config_aneg,
468 .aneg_done = mv3310_aneg_done,
469 .read_status = mv3310_read_status,
472 .phy_id = MARVELL_PHY_ID_88E2110,
473 .phy_id_mask = MARVELL_PHY_ID_MASK,
474 .name = "mv88x2110",
475 .get_features = genphy_c45_pma_read_abilities,
476 .probe = mv3310_probe,
477 .soft_reset = genphy_no_soft_reset,
478 .config_init = mv3310_config_init,
479 .config_aneg = mv3310_config_aneg,
480 .aneg_done = mv3310_aneg_done,
481 .read_status = mv3310_read_status,
485 module_phy_driver(mv3310_drivers);
487 static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
488 { MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_MASK },
489 { MARVELL_PHY_ID_88E2110, MARVELL_PHY_ID_MASK },
490 { },
492 MODULE_DEVICE_TABLE(mdio, mv3310_tbl);
493 MODULE_DESCRIPTION("Marvell Alaska X 10Gigabit Ethernet PHY driver (MV88X3310)");
494 MODULE_LICENSE("GPL");