@@ -103,6 +103,64 @@ static int bcm54612e_config_init(struct phy_device *phydev)
103103 return 0 ;
104104}
105105
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+
106164/* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
107165static int bcm50610_a0_workaround (struct phy_device * phydev )
108166{
@@ -283,40 +341,49 @@ static int bcm54xx_config_init(struct phy_device *phydev)
283341
284342 bcm54xx_adjust_rxrefclk (phydev );
285343
286- if (BRCM_PHY_MODEL (phydev ) == PHY_ID_BCM54210E ) {
344+ switch (BRCM_PHY_MODEL (phydev )) {
345+ case PHY_ID_BCM54210E :
287346 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 :
291349 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 :
295355 /* For BCM54810, we need to disable BroadR-Reach function */
296356 val = bcm_phy_read_exp (phydev ,
297357 BCM54810_EXP_BROADREACH_LRE_MISC_CTL );
298358 val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN ;
299359 err = bcm_phy_write_exp (phydev ,
300360 BCM54810_EXP_BROADREACH_LRE_MISC_CTL ,
301361 val );
302- if (err < 0 )
303- return err ;
362+ break ;
304363 }
364+ if (err )
365+ return err ;
305366
306367 bcm54xx_phydsp_config (phydev );
307368
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).
309371 * Also flash these two LEDs on activity. This means configuring
310372 * 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.
311376 */
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+ }
320387
321388 return 0 ;
322389}
@@ -390,7 +457,7 @@ struct bcm54616s_phy_priv {
390457static int bcm54616s_probe (struct phy_device * phydev )
391458{
392459 struct bcm54616s_phy_priv * priv ;
393- int val , intf_sel ;
460+ int val ;
394461
395462 priv = devm_kzalloc (& phydev -> mdio .dev , sizeof (* priv ), GFP_KERNEL );
396463 if (!priv )
@@ -408,8 +475,7 @@ static int bcm54616s_probe(struct phy_device *phydev)
408475 * RGMII-1000Base-X is properly supported, but RGMII-100Base-FX
409476 * support is still missing as of now.
410477 */
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 ) {
413479 val = bcm_phy_read_shadow (phydev , BCM54616S_SHD_100FX_CTRL );
414480 if (val < 0 )
415481 return val ;
0 commit comments