@@ -3448,95 +3448,92 @@ static int rtpcs_931x_sds_cmu_page_get(enum rtpcs_sds_mode hw_mode)
34483448 }
34493449}
34503450
3451- static int rtpcs_931x_sds_config_cmu (struct rtpcs_serdes * sds , enum rtpcs_sds_mode hw_mode )
3451+ static int rtpcs_931x_sds_get_pll_select (struct rtpcs_serdes * sds , enum rtpcs_sds_pll_type * pll )
3452+ {
3453+ int cmu_page , pll_sel ;
3454+
3455+ cmu_page = rtpcs_931x_sds_cmu_page_get (sds -> hw_mode );
3456+ if (cmu_page < 0 )
3457+ return cmu_page ;
3458+
3459+ pll_sel = rtpcs_sds_read_bits (sds , cmu_page , 0x7 , 15 , 15 );
3460+ if (pll_sel < 0 )
3461+ return pll_sel ;
3462+
3463+ * pll = (enum rtpcs_sds_pll_type )pll_sel ;
3464+ return 0 ;
3465+ }
3466+
3467+ static int rtpcs_931x_sds_set_pll_select (struct rtpcs_serdes * sds , enum rtpcs_sds_mode hw_mode ,
3468+ enum rtpcs_sds_pll_type pll )
34523469{
34533470 struct rtpcs_serdes * even_sds = rtpcs_sds_get_even (sds );
3454- u32 force_lc_mode_bit , force_lc_mode_val_bit ;
3455- enum rtpcs_sds_pll_type pll_type ; /* SDK calls this cmu_type */
3456- bool force_pll_spd ;
3457- int cmu_page = 0 ;
3471+ int cmu_page , ret , val ;
3472+ int frc_lc_mode_bit ;
34583473
3459- switch (hw_mode ) {
3460- case RTPCS_SDS_MODE_OFF :
3461- case RTPCS_SDS_MODE_XSGMII :
3462- case RTPCS_SDS_MODE_10GBASER :
3463- case RTPCS_SDS_MODE_USXGMII_10GSXGMII :
3464- case RTPCS_SDS_MODE_USXGMII_10GDXGMII :
3465- case RTPCS_SDS_MODE_USXGMII_10GQXGMII :
3466- case RTPCS_SDS_MODE_USXGMII_5GSXGMII :
3467- case RTPCS_SDS_MODE_USXGMII_5GDXGMII :
3468- case RTPCS_SDS_MODE_USXGMII_2_5GSXGMII :
3469- return 0 ;
3474+ cmu_page = rtpcs_931x_sds_cmu_page_get (hw_mode );
3475+ if (cmu_page < 0 )
3476+ return cmu_page ;
34703477
3471- case RTPCS_SDS_MODE_QSGMII :
3472- pll_type = RTPCS_SDS_PLL_TYPE_RING ;
3473- force_pll_spd = false;
3474- break ;
3478+ /*
3479+ * bits [5:4] (even) / [7:6] (odd) are used by RTL930x as selector. The selector
3480+ * for RTL931x SerDes is in the CMU page of each SerDes, depending on the hardware
3481+ * mode.
3482+ *
3483+ * Here, the SDK calls them 'frc_lc_mode' and 'frc_lc_mode_val'. However, they don't
3484+ * seem to have any effect and thus their purpose is unknown. So just set them as
3485+ * the SDK does.
3486+ */
3487+ val = (pll == RTPCS_SDS_PLL_TYPE_LC ) ? 0x3 : 0x1 ;
3488+ frc_lc_mode_bit = (sds == even_sds ) ? 4 : 6 ;
3489+ ret = rtpcs_sds_write_bits (even_sds , 0x20 , 0x12 , frc_lc_mode_bit + 1 ,
3490+ frc_lc_mode_bit , val );
3491+ if (ret < 0 )
3492+ return ret ;
34753493
3476- case RTPCS_SDS_MODE_1000BASEX :
3477- pll_type = RTPCS_SDS_PLL_TYPE_RING ;
3478- force_pll_spd = false;
3479- break ;
3494+ return rtpcs_sds_write_bits (sds , cmu_page , 0x7 , 15 , 15 , pll );
3495+ }
34803496
3481- /* case MII_1000BX100BX_AUTO:
3482- pll_type = RTPCS_SDS_PLL_TYPE_RING;
3483- force_pll_spd = false;
3484- break; */
3497+ static int rtpcs_931x_sds_reconfigure_to_pll (struct rtpcs_serdes * sds , enum rtpcs_sds_pll_type pll )
3498+ {
3499+ enum rtpcs_sds_pll_type tmp_pll ;
3500+ enum rtpcs_sds_pll_speed speed ;
3501+ enum rtpcs_sds_mode tmp_mode ;
3502+ int ret ;
34853503
3486- case RTPCS_SDS_MODE_SGMII :
3487- pll_type = RTPCS_SDS_PLL_TYPE_RING ;
3488- force_pll_spd = false;
3489- break ;
3504+ /* assume we always reconfigure to the other PLL */
3505+ tmp_pll = (pll == RTPCS_SDS_PLL_TYPE_LC ) ? RTPCS_SDS_PLL_TYPE_RING : RTPCS_SDS_PLL_TYPE_LC ;
34903506
3491- case RTPCS_SDS_MODE_2500BASEX :
3492- pll_type = RTPCS_SDS_PLL_TYPE_RING ;
3493- force_pll_spd = true;
3494- break ;
3507+ ret = rtpcs_93xx_sds_get_pll_config (sds , tmp_pll , & speed );
3508+ if (ret < 0 )
3509+ return ret ;
34953510
3496- default :
3497- pr_info ("SerDes %d mode is invalid\n" , sds -> id );
3498- return - EINVAL ;
3499- }
3511+ tmp_mode = sds -> hw_mode ;
35003512
3501- cmu_page = rtpcs_931x_sds_cmu_page_get (hw_mode );
3502- if (cmu_page < 0 )
3503- return - EINVAL ;
3513+ /* turn off SerDes for reconfiguration */
3514+ ret = rtpcs_931x_sds_power (sds , false);
3515+ if (ret < 0 )
3516+ return ret ;
35043517
3505- if (sds == even_sds ) {
3506- force_lc_mode_bit = 4 ;
3507- force_lc_mode_val_bit = 5 ;
3508- } else {
3509- force_lc_mode_bit = 6 ;
3510- force_lc_mode_val_bit = 7 ;
3511- }
3518+ ret = rtpcs_931x_sds_set_mode (sds , RTPCS_SDS_MODE_OFF );
3519+ if (ret < 0 )
3520+ return ret ;
35123521
3513- pr_info ("%s: pll_type %s cmu_page %x force_pll_spd %d even_sds %d sds %d\n" ,
3514- __func__ , pll_type == RTPCS_SDS_PLL_TYPE_LC ? "LC" : "ring" , cmu_page ,
3515- force_pll_spd , even_sds -> id , sds -> id );
3516-
3517- if (pll_type == RTPCS_SDS_PLL_TYPE_RING ) {
3518- rtpcs_sds_write_bits (sds , cmu_page , 0x7 , 15 , 15 , 0x0 );
3519-
3520- rtpcs_sds_write_bits (even_sds , 0x20 , 0x12 , 3 , 2 , 0x3 );
3521- rtpcs_sds_write_bits (even_sds , 0x20 , 0x12 , force_lc_mode_bit ,
3522- force_lc_mode_bit , 0x1 );
3523- rtpcs_sds_write_bits (even_sds , 0x20 , 0x12 , force_lc_mode_val_bit ,
3524- force_lc_mode_val_bit , 0x0 );
3525- rtpcs_sds_write_bits (even_sds , 0x20 , 0x12 , 12 , 12 , 0x1 );
3526- rtpcs_sds_write_bits (even_sds , 0x20 , 0x12 , 15 , 13 , force_pll_spd ? 0x1 : 0x0 );
3527- } else if (pll_type == RTPCS_SDS_PLL_TYPE_LC ) {
3528- rtpcs_sds_write_bits (sds , cmu_page , 0x7 , 15 , 15 , 0x1 );
3529-
3530- rtpcs_sds_write_bits (even_sds , 0x20 , 0x12 , 1 , 0 , 0x3 );
3531- rtpcs_sds_write_bits (even_sds , 0x20 , 0x12 , force_lc_mode_bit ,
3532- force_lc_mode_bit , 0x1 );
3533- rtpcs_sds_write_bits (even_sds , 0x20 , 0x12 , force_lc_mode_val_bit ,
3534- force_lc_mode_val_bit , 0x1 );
3535- rtpcs_sds_write_bits (even_sds , 0x20 , 0x12 , 8 , 8 , 0x1 );
3536- rtpcs_sds_write_bits (even_sds , 0x20 , 0x12 , 11 , 9 , force_pll_spd ? 0x1 : 0x0 );
3537- }
3522+ /* reconfigure to other PLL */
3523+ ret = rtpcs_93xx_sds_set_pll_config (sds , pll , speed );
3524+ if (ret < 0 )
3525+ return ret ;
35383526
3539- return 0 ;
3527+ ret = rtpcs_931x_sds_set_pll_select (sds , sds -> hw_mode , pll );
3528+ if (ret < 0 )
3529+ return ret ;
3530+
3531+ /* turn on SerDes again */
3532+ ret = rtpcs_931x_sds_set_mode (sds , tmp_mode );
3533+ if (ret < 0 )
3534+ return ret ;
3535+
3536+ return rtpcs_931x_sds_power (sds , true);
35403537}
35413538
35423539static int rtpcs_931x_sds_cmu_band_set (struct rtpcs_serdes * sds ,
@@ -3865,7 +3862,7 @@ static int rtpcs_931x_setup_serdes(struct rtpcs_serdes *sds,
38653862 if (ret < 0 )
38663863 return ret ;
38673864
3868- ret = rtpcs_931x_sds_config_cmu (sds , hw_mode );
3865+ ret = rtpcs_93xx_sds_config_cmu (sds , hw_mode );
38693866 if (ret < 0 )
38703867 return ret ;
38713868
@@ -4350,6 +4347,9 @@ static const struct rtpcs_serdes_ops rtpcs_931x_sds_ops = {
43504347 .xsg_write = rtpcs_931x_sds_op_xsg_write ,
43514348 .set_autoneg = rtpcs_93xx_sds_set_autoneg ,
43524349 .restart_autoneg = rtpcs_generic_sds_restart_autoneg ,
4350+ .get_pll_select = rtpcs_931x_sds_get_pll_select ,
4351+ .set_pll_select = rtpcs_931x_sds_set_pll_select ,
4352+ .reconfigure_to_pll = rtpcs_931x_sds_reconfigure_to_pll ,
43534353};
43544354
43554355static const struct rtpcs_sds_regs rtpcs_931x_sds_regs = {
0 commit comments