GNU Linux-libre 4.14.290-gnu1
[releases.git] / drivers / net / phy / marvell10g.c
1 /*
2  * Marvell 10G 88x3310 PHY driver
3  *
4  * Based upon the ID registers, this PHY appears to be a mixture of IPs
5  * from two different companies.
6  *
7  * There appears to be several different data paths through the PHY which
8  * are automatically managed by the PHY.  The following has been determined
9  * via observation and experimentation:
10  *
11  *       SGMII PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for <= 1G)
12  *  10GBASE-KR PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for 10G)
13  *  10GBASE-KR PHYXS -- BASE-R PCS -- Fiber
14  *
15  * If both the fiber and copper ports are connected, the first to gain
16  * link takes priority and the other port is completely locked out.
17  */
18 #include <linux/phy.h>
19 #include <linux/marvell_phy.h>
20
21 enum {
22         MV_PMA_BOOT             = 0xc050,
23         MV_PMA_BOOT_FATAL       = BIT(0),
24
25         MV_PCS_BASE_T           = 0x0000,
26         MV_PCS_BASE_R           = 0x1000,
27         MV_PCS_1000BASEX        = 0x2000,
28
29         /* These registers appear at 0x800X and 0xa00X - the 0xa00X control
30          * registers appear to set themselves to the 0x800X when AN is
31          * restarted, but status registers appear readable from either.
32          */
33         MV_AN_CTRL1000          = 0x8000, /* 1000base-T control register */
34         MV_AN_STAT1000          = 0x8001, /* 1000base-T status register */
35
36         /* This register appears to reflect the copper status */
37         MV_AN_RESULT            = 0xa016,
38         MV_AN_RESULT_SPD_10     = BIT(12),
39         MV_AN_RESULT_SPD_100    = BIT(13),
40         MV_AN_RESULT_SPD_1000   = BIT(14),
41         MV_AN_RESULT_SPD_10000  = BIT(15),
42 };
43
44 static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
45                          u16 mask, u16 bits)
46 {
47         int old, val, ret;
48
49         old = phy_read_mmd(phydev, devad, reg);
50         if (old < 0)
51                 return old;
52
53         val = (old & ~mask) | (bits & mask);
54         if (val == old)
55                 return 0;
56
57         ret = phy_write_mmd(phydev, devad, reg, val);
58
59         return ret < 0 ? ret : 1;
60 }
61
62 static int mv3310_probe(struct phy_device *phydev)
63 {
64         u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
65         int ret;
66
67         if (!phydev->is_c45 ||
68             (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
69                 return -ENODEV;
70
71         ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT);
72         if (ret < 0)
73                 return ret;
74
75         if (ret & MV_PMA_BOOT_FATAL) {
76                 dev_warn(&phydev->mdio.dev,
77                          "PHY failed to boot firmware, status=%04x\n", ret);
78                 return -ENODEV;
79         }
80
81         return 0;
82 }
83
84 /*
85  * Resetting the MV88X3310 causes it to become non-responsive.  Avoid
86  * setting the reset bit(s).
87  */
88 static int mv3310_soft_reset(struct phy_device *phydev)
89 {
90         return 0;
91 }
92
93 static int mv3310_config_init(struct phy_device *phydev)
94 {
95         __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
96         u32 mask;
97         int val;
98
99         /* Check that the PHY interface type is compatible */
100         if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
101             phydev->interface != PHY_INTERFACE_MODE_XGMII &&
102             phydev->interface != PHY_INTERFACE_MODE_XAUI &&
103             phydev->interface != PHY_INTERFACE_MODE_RXAUI &&
104             phydev->interface != PHY_INTERFACE_MODE_10GKR)
105                 return -ENODEV;
106
107         __set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
108         __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, supported);
109
110         if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
111                 val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
112                 if (val < 0)
113                         return val;
114
115                 if (val & MDIO_AN_STAT1_ABLE)
116                         __set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported);
117         }
118
119         val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
120         if (val < 0)
121                 return val;
122
123         /* Ethtool does not support the WAN mode bits */
124         if (val & (MDIO_PMA_STAT2_10GBSR | MDIO_PMA_STAT2_10GBLR |
125                    MDIO_PMA_STAT2_10GBER | MDIO_PMA_STAT2_10GBLX4 |
126                    MDIO_PMA_STAT2_10GBSW | MDIO_PMA_STAT2_10GBLW |
127                    MDIO_PMA_STAT2_10GBEW))
128                 __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
129         if (val & MDIO_PMA_STAT2_10GBSR)
130                 __set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, supported);
131         if (val & MDIO_PMA_STAT2_10GBLR)
132                 __set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, supported);
133         if (val & MDIO_PMA_STAT2_10GBER)
134                 __set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, supported);
135
136         if (val & MDIO_PMA_STAT2_EXTABLE) {
137                 val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
138                 if (val < 0)
139                         return val;
140
141                 if (val & (MDIO_PMA_EXTABLE_10GBT | MDIO_PMA_EXTABLE_1000BT |
142                            MDIO_PMA_EXTABLE_100BTX | MDIO_PMA_EXTABLE_10BT))
143                         __set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported);
144                 if (val & MDIO_PMA_EXTABLE_10GBLRM)
145                         __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
146                 if (val & (MDIO_PMA_EXTABLE_10GBKX4 | MDIO_PMA_EXTABLE_10GBKR |
147                            MDIO_PMA_EXTABLE_1000BKX))
148                         __set_bit(ETHTOOL_LINK_MODE_Backplane_BIT, supported);
149                 if (val & MDIO_PMA_EXTABLE_10GBLRM)
150                         __set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
151                                   supported);
152                 if (val & MDIO_PMA_EXTABLE_10GBT)
153                         __set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
154                                   supported);
155                 if (val & MDIO_PMA_EXTABLE_10GBKX4)
156                         __set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
157                                   supported);
158                 if (val & MDIO_PMA_EXTABLE_10GBKR)
159                         __set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
160                                   supported);
161                 if (val & MDIO_PMA_EXTABLE_1000BT)
162                         __set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
163                                   supported);
164                 if (val & MDIO_PMA_EXTABLE_1000BKX)
165                         __set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
166                                   supported);
167                 if (val & MDIO_PMA_EXTABLE_100BTX)
168                         __set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
169                                   supported);
170                 if (val & MDIO_PMA_EXTABLE_10BT)
171                         __set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
172                                   supported);
173         }
174
175         if (!ethtool_convert_link_mode_to_legacy_u32(&mask, supported))
176                 dev_warn(&phydev->mdio.dev,
177                          "PHY supports (%*pb) more modes than phylib supports, some modes not supported.\n",
178                          __ETHTOOL_LINK_MODE_MASK_NBITS, supported);
179
180         phydev->supported &= mask;
181         phydev->advertising &= phydev->supported;
182
183         return 0;
184 }
185
186 static int mv3310_config_aneg(struct phy_device *phydev)
187 {
188         bool changed = false;
189         u32 advertising;
190         int ret;
191
192         if (phydev->autoneg == AUTONEG_DISABLE) {
193                 ret = genphy_c45_pma_setup_forced(phydev);
194                 if (ret < 0)
195                         return ret;
196
197                 return genphy_c45_an_disable_aneg(phydev);
198         }
199
200         phydev->advertising &= phydev->supported;
201         advertising = phydev->advertising;
202
203         ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
204                             ADVERTISE_ALL | ADVERTISE_100BASE4 |
205                             ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
206                             ethtool_adv_to_mii_adv_t(advertising));
207         if (ret < 0)
208                 return ret;
209         if (ret > 0)
210                 changed = true;
211
212         ret = mv3310_modify(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
213                             ADVERTISE_1000FULL | ADVERTISE_1000HALF,
214                             ethtool_adv_to_mii_ctrl1000_t(advertising));
215         if (ret < 0)
216                 return ret;
217         if (ret > 0)
218                 changed = true;
219
220         /* 10G control register */
221         ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
222                             MDIO_AN_10GBT_CTRL_ADV10G,
223                             advertising & ADVERTISED_10000baseT_Full ?
224                                 MDIO_AN_10GBT_CTRL_ADV10G : 0);
225         if (ret < 0)
226                 return ret;
227         if (ret > 0)
228                 changed = true;
229
230         if (changed)
231                 ret = genphy_c45_restart_aneg(phydev);
232
233         return ret;
234 }
235
236 static int mv3310_aneg_done(struct phy_device *phydev)
237 {
238         int val;
239
240         val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
241         if (val < 0)
242                 return val;
243
244         if (val & MDIO_STAT1_LSTATUS)
245                 return 1;
246
247         return genphy_c45_aneg_done(phydev);
248 }
249
250 /* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */
251 static int mv3310_read_10gbr_status(struct phy_device *phydev)
252 {
253         phydev->link = 1;
254         phydev->speed = SPEED_10000;
255         phydev->duplex = DUPLEX_FULL;
256
257         if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
258                 phydev->interface = PHY_INTERFACE_MODE_10GKR;
259
260         return 0;
261 }
262
263 static int mv3310_read_status(struct phy_device *phydev)
264 {
265         u32 mmd_mask = phydev->c45_ids.devices_in_package;
266         int val;
267
268         /* The vendor devads do not report link status.  Avoid the PHYXS
269          * instance as there are three, and its status depends on the MAC
270          * being appropriately configured for the negotiated speed.
271          */
272         mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2) |
273                       BIT(MDIO_MMD_PHYXS));
274
275         phydev->speed = SPEED_UNKNOWN;
276         phydev->duplex = DUPLEX_UNKNOWN;
277         phydev->lp_advertising = 0;
278         phydev->link = 0;
279         phydev->pause = 0;
280         phydev->asym_pause = 0;
281
282         val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
283         if (val < 0)
284                 return val;
285
286         if (val & MDIO_STAT1_LSTATUS)
287                 return mv3310_read_10gbr_status(phydev);
288
289         val = genphy_c45_read_link(phydev, mmd_mask);
290         if (val < 0)
291                 return val;
292
293         phydev->link = val > 0 ? 1 : 0;
294
295         val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
296         if (val < 0)
297                 return val;
298
299         if (val & MDIO_AN_STAT1_COMPLETE) {
300                 val = genphy_c45_read_lpa(phydev);
301                 if (val < 0)
302                         return val;
303
304                 /* Read the link partner's 1G advertisment */
305                 val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_STAT1000);
306                 if (val < 0)
307                         return val;
308
309                 phydev->lp_advertising |= mii_stat1000_to_ethtool_lpa_t(val);
310
311                 if (phydev->autoneg == AUTONEG_ENABLE) {
312                         val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_RESULT);
313                         if (val < 0)
314                                 return val;
315
316                         if (val & MV_AN_RESULT_SPD_10000)
317                                 phydev->speed = SPEED_10000;
318                         else if (val & MV_AN_RESULT_SPD_1000)
319                                 phydev->speed = SPEED_1000;
320                         else if (val & MV_AN_RESULT_SPD_100)
321                                 phydev->speed = SPEED_100;
322                         else if (val & MV_AN_RESULT_SPD_10)
323                                 phydev->speed = SPEED_10;
324
325                         phydev->duplex = DUPLEX_FULL;
326                 }
327         }
328
329         if (phydev->autoneg != AUTONEG_ENABLE) {
330                 val = genphy_c45_read_pma(phydev);
331                 if (val < 0)
332                         return val;
333         }
334
335         if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
336              phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
337                 /* The PHY automatically switches its serdes interface (and
338                  * active PHYXS instance) between Cisco SGMII and 10GBase-KR
339                  * modes according to the speed.  Florian suggests setting
340                  * phydev->interface to communicate this to the MAC. Only do
341                  * this if we are already in either SGMII or 10GBase-KR mode.
342                  */
343                 if (phydev->speed == SPEED_10000)
344                         phydev->interface = PHY_INTERFACE_MODE_10GKR;
345                 else if (phydev->speed >= SPEED_10 &&
346                          phydev->speed < SPEED_10000)
347                         phydev->interface = PHY_INTERFACE_MODE_SGMII;
348         }
349
350         return 0;
351 }
352
353 static struct phy_driver mv3310_drivers[] = {
354         {
355                 .phy_id         = 0x002b09aa,
356                 .phy_id_mask    = MARVELL_PHY_ID_MASK,
357                 .name           = "mv88x3310",
358                 .features       = SUPPORTED_10baseT_Full |
359                                   SUPPORTED_100baseT_Full |
360                                   SUPPORTED_1000baseT_Full |
361                                   SUPPORTED_Autoneg |
362                                   SUPPORTED_TP |
363                                   SUPPORTED_FIBRE |
364                                   SUPPORTED_10000baseT_Full |
365                                   SUPPORTED_Backplane,
366                 .probe          = mv3310_probe,
367                 .soft_reset     = mv3310_soft_reset,
368                 .config_init    = mv3310_config_init,
369                 .config_aneg    = mv3310_config_aneg,
370                 .aneg_done      = mv3310_aneg_done,
371                 .read_status    = mv3310_read_status,
372         },
373 };
374
375 module_phy_driver(mv3310_drivers);
376
377 static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
378         { 0x002b09aa, MARVELL_PHY_ID_MASK },
379         { },
380 };
381 MODULE_DEVICE_TABLE(mdio, mv3310_tbl);
382 MODULE_DESCRIPTION("Marvell Alaska X 10Gigabit Ethernet PHY driver (MV88X3310)");
383 MODULE_LICENSE("GPL");