@@ -103,6 +103,64 @@ static int bcm54612e_config_init(struct phy_device *phydev)
103
103
return 0 ;
104
104
}
105
105
106
+ static int bcm54616s_config_init (struct phy_device * phydev )
107
+ {
108
+ int rc , val ;
109
+
110
+ if (phydev -> interface != PHY_INTERFACE_MODE_SGMII &&
111
+ phydev -> interface != PHY_INTERFACE_MODE_1000BASEX )
112
+ return 0 ;
113
+
114
+ /* Ensure proper interface mode is selected. */
115
+ /* Disable RGMII mode */
116
+ val = bcm54xx_auxctl_read (phydev , MII_BCM54XX_AUXCTL_SHDWSEL_MISC );
117
+ if (val < 0 )
118
+ return val ;
119
+ val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_EN ;
120
+ val |= MII_BCM54XX_AUXCTL_MISC_WREN ;
121
+ rc = bcm54xx_auxctl_write (phydev , MII_BCM54XX_AUXCTL_SHDWSEL_MISC ,
122
+ val );
123
+ if (rc < 0 )
124
+ return rc ;
125
+
126
+ /* Select 1000BASE-X register set (primary SerDes) */
127
+ val = bcm_phy_read_shadow (phydev , BCM54XX_SHD_MODE );
128
+ if (val < 0 )
129
+ return val ;
130
+ val |= BCM54XX_SHD_MODE_1000BX ;
131
+ rc = bcm_phy_write_shadow (phydev , BCM54XX_SHD_MODE , val );
132
+ if (rc < 0 )
133
+ return rc ;
134
+
135
+ /* Power down SerDes interface */
136
+ rc = phy_set_bits (phydev , MII_BMCR , BMCR_PDOWN );
137
+ if (rc < 0 )
138
+ return rc ;
139
+
140
+ /* Select proper interface mode */
141
+ val &= ~BCM54XX_SHD_INTF_SEL_MASK ;
142
+ val |= phydev -> interface == PHY_INTERFACE_MODE_SGMII ?
143
+ BCM54XX_SHD_INTF_SEL_SGMII :
144
+ BCM54XX_SHD_INTF_SEL_GBIC ;
145
+ rc = bcm_phy_write_shadow (phydev , BCM54XX_SHD_MODE , val );
146
+ if (rc < 0 )
147
+ return rc ;
148
+
149
+ /* Power up SerDes interface */
150
+ rc = phy_clear_bits (phydev , MII_BMCR , BMCR_PDOWN );
151
+ if (rc < 0 )
152
+ return rc ;
153
+
154
+ /* Select copper register set */
155
+ val &= ~BCM54XX_SHD_MODE_1000BX ;
156
+ rc = bcm_phy_write_shadow (phydev , BCM54XX_SHD_MODE , val );
157
+ if (rc < 0 )
158
+ return rc ;
159
+
160
+ /* Power up copper interface */
161
+ return phy_clear_bits (phydev , MII_BMCR , BMCR_PDOWN );
162
+ }
163
+
106
164
/* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
107
165
static int bcm50610_a0_workaround (struct phy_device * phydev )
108
166
{
@@ -283,40 +341,49 @@ static int bcm54xx_config_init(struct phy_device *phydev)
283
341
284
342
bcm54xx_adjust_rxrefclk (phydev );
285
343
286
- if (BRCM_PHY_MODEL (phydev ) == PHY_ID_BCM54210E ) {
344
+ switch (BRCM_PHY_MODEL (phydev )) {
345
+ case PHY_ID_BCM54210E :
287
346
err = bcm54210e_config_init (phydev );
288
- if (err )
289
- return err ;
290
- } else if (BRCM_PHY_MODEL (phydev ) == PHY_ID_BCM54612E ) {
347
+ break ;
348
+ case PHY_ID_BCM54612E :
291
349
err = bcm54612e_config_init (phydev );
292
- if (err )
293
- return err ;
294
- } else if (BRCM_PHY_MODEL (phydev ) == PHY_ID_BCM54810 ) {
350
+ break ;
351
+ case PHY_ID_BCM54616S :
352
+ err = bcm54616s_config_init (phydev );
353
+ break ;
354
+ case PHY_ID_BCM54810 :
295
355
/* For BCM54810, we need to disable BroadR-Reach function */
296
356
val = bcm_phy_read_exp (phydev ,
297
357
BCM54810_EXP_BROADREACH_LRE_MISC_CTL );
298
358
val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN ;
299
359
err = bcm_phy_write_exp (phydev ,
300
360
BCM54810_EXP_BROADREACH_LRE_MISC_CTL ,
301
361
val );
302
- if (err < 0 )
303
- return err ;
362
+ break ;
304
363
}
364
+ if (err )
365
+ return err ;
305
366
306
367
bcm54xx_phydsp_config (phydev );
307
368
308
- /* Encode link speed into LED1 and LED3 pair (green/amber).
369
+ /* For non-SFP setups, encode link speed into LED1 and LED3 pair
370
+ * (green/amber).
309
371
* Also flash these two LEDs on activity. This means configuring
310
372
* them for MULTICOLOR and encoding link/activity into them.
373
+ * Don't do this for devices on an SFP module, since some of these
374
+ * use the LED outputs to control the SFP LOS signal, and changing
375
+ * these settings will cause LOS to malfunction.
311
376
*/
312
- val = BCM5482_SHD_LEDS1_LED1 (BCM_LED_SRC_MULTICOLOR1 ) |
313
- BCM5482_SHD_LEDS1_LED3 (BCM_LED_SRC_MULTICOLOR1 );
314
- bcm_phy_write_shadow (phydev , BCM5482_SHD_LEDS1 , val );
315
-
316
- val = BCM_LED_MULTICOLOR_IN_PHASE |
317
- BCM5482_SHD_LEDS1_LED1 (BCM_LED_MULTICOLOR_LINK_ACT ) |
318
- BCM5482_SHD_LEDS1_LED3 (BCM_LED_MULTICOLOR_LINK_ACT );
319
- bcm_phy_write_exp (phydev , BCM_EXP_MULTICOLOR , val );
377
+ if (!phy_on_sfp (phydev )) {
378
+ val = BCM5482_SHD_LEDS1_LED1 (BCM_LED_SRC_MULTICOLOR1 ) |
379
+ BCM5482_SHD_LEDS1_LED3 (BCM_LED_SRC_MULTICOLOR1 );
380
+ bcm_phy_write_shadow (phydev , BCM5482_SHD_LEDS1 , val );
381
+
382
+ val = BCM_LED_MULTICOLOR_IN_PHASE |
383
+ BCM5482_SHD_LEDS1_LED1 (BCM_LED_MULTICOLOR_LINK_ACT ) |
384
+ BCM5482_SHD_LEDS1_LED3 (BCM_LED_MULTICOLOR_LINK_ACT );
385
+ bcm_phy_write_exp (phydev , BCM_EXP_MULTICOLOR , val );
386
+ }
320
387
321
388
return 0 ;
322
389
}
@@ -390,7 +457,7 @@ struct bcm54616s_phy_priv {
390
457
static int bcm54616s_probe (struct phy_device * phydev )
391
458
{
392
459
struct bcm54616s_phy_priv * priv ;
393
- int val , intf_sel ;
460
+ int val ;
394
461
395
462
priv = devm_kzalloc (& phydev -> mdio .dev , sizeof (* priv ), GFP_KERNEL );
396
463
if (!priv )
@@ -408,8 +475,7 @@ static int bcm54616s_probe(struct phy_device *phydev)
408
475
* RGMII-1000Base-X is properly supported, but RGMII-100Base-FX
409
476
* support is still missing as of now.
410
477
*/
411
- intf_sel = (val & BCM54XX_SHD_INTF_SEL_MASK ) >> 1 ;
412
- if (intf_sel == 1 ) {
478
+ if ((val & BCM54XX_SHD_INTF_SEL_MASK ) == BCM54XX_SHD_INTF_SEL_RGMII ) {
413
479
val = bcm_phy_read_shadow (phydev , BCM54616S_SHD_100FX_CTRL );
414
480
if (val < 0 )
415
481
return val ;
0 commit comments