@@ -2968,19 +2968,140 @@ static int mxl862xx_setup_mdio(struct dsa_switch *ds)
29682968 return ret ;
29692969}
29702970
2971+ static struct mxl862xx_pcs * pcs_to_mxl862xx_pcs (struct phylink_pcs * pcs )
2972+ {
2973+ return container_of (pcs , struct mxl862xx_pcs , pcs );
2974+ }
2975+
2976+ static void mxl862xx_pcs_get_state (struct phylink_pcs * pcs ,
2977+ struct phylink_link_state * state )
2978+ {
2979+ struct mxl862xx_priv * priv = pcs_to_mxl862xx_pcs (pcs )-> priv ;
2980+ int port = pcs_to_mxl862xx_pcs (pcs )-> port ;
2981+
2982+ struct mxl862xx_port_link_cfg port_link_cfg = {
2983+ .port_id = port ,
2984+ };
2985+ struct mxl862xx_port_cfg port_cfg = {
2986+ .port_id = port ,
2987+ };
2988+ int ret ;
2989+
2990+ ret = MXL862XX_API_READ (priv , MXL862XX_COMMON_PORTLINKCFGGET , port_link_cfg );
2991+ if (ret ) {
2992+ dev_err (priv -> dev , "failed to read link configuration on port %d\n" , port );
2993+ return ;
2994+ }
2995+ ret = MXL862XX_API_READ (priv , MXL862XX_COMMON_PORTCFGGET , port_cfg );
2996+ if (ret ) {
2997+ dev_err (priv -> dev , "failed to read configuration on port %d\n" , port );
2998+ return ;
2999+ }
3000+
3001+ if (port_link_cfg .link == MXL862XX_PORT_LINK_UP )
3002+ state -> link = 1 ;
3003+ else
3004+ state -> link = 0 ;
3005+ state -> an_complete = state -> link ;
3006+
3007+ switch (port_link_cfg .speed ) {
3008+ case MXL862XX_PORT_SPEED_10 :
3009+ state -> speed = SPEED_10 ;
3010+ break ;
3011+ case MXL862XX_PORT_SPEED_100 :
3012+ state -> speed = SPEED_100 ;
3013+ break ;
3014+ case MXL862XX_PORT_SPEED_1000 :
3015+ state -> speed = SPEED_1000 ;
3016+ break ;
3017+ case MXL862XX_PORT_SPEED_2500 :
3018+ state -> speed = SPEED_2500 ;
3019+ break ;
3020+ case MXL862XX_PORT_SPEED_5000 :
3021+ state -> speed = SPEED_5000 ;
3022+ break ;
3023+ case MXL862XX_PORT_SPEED_10000 :
3024+ state -> speed = SPEED_10000 ;
3025+ break ;
3026+ default :
3027+ state -> speed = SPEED_UNKNOWN ;
3028+ dev_err (priv -> dev , "unsupported links speed on port %d\n" , port );
3029+ break ;
3030+ }
3031+
3032+ switch (port_link_cfg .duplex ) {
3033+ case MXL862XX_DUPLEX_HALF :
3034+ state -> duplex = DUPLEX_HALF ;
3035+ break ;
3036+ case MXL862XX_DUPLEX_FULL :
3037+ state -> duplex = DUPLEX_FULL ;
3038+ break ;
3039+ default :
3040+ state -> duplex = DUPLEX_UNKNOWN ;
3041+ break ;
3042+ }
3043+
3044+ state -> pause &= ~(MLO_PAUSE_RX | MLO_PAUSE_TX );
3045+ switch (port_cfg .flow_ctrl ) {
3046+ case MXL862XX_FLOW_RXTX :
3047+ state -> pause |= MLO_PAUSE_TXRX_MASK ;
3048+ break ;
3049+ case MXL862XX_FLOW_TX :
3050+ state -> pause |= MLO_PAUSE_TX ;
3051+ break ;
3052+ case MXL862XX_FLOW_RX :
3053+ state -> pause |= MLO_PAUSE_RX ;
3054+ break ;
3055+ case MXL862XX_FLOW_OFF :
3056+ default :
3057+ break ;
3058+ }
3059+ }
3060+
3061+ static int mxl862xx_pcs_config (struct phylink_pcs * pcs , unsigned int neg_mode ,
3062+ phy_interface_t interface ,
3063+ const unsigned long * advertising ,
3064+ bool permit_pause_to_mac )
3065+ {
3066+ return 0 ;
3067+ }
3068+
3069+ static const struct phylink_pcs_ops mxl862xx_pcs_ops = {
3070+ .pcs_get_state = mxl862xx_pcs_get_state ,
3071+ .pcs_config = mxl862xx_pcs_config ,
3072+ };
3073+
3074+ static void mxl862xx_setup_pcs (struct mxl862xx_priv * priv , struct mxl862xx_pcs * pcs ,
3075+ int port )
3076+ {
3077+ pcs -> pcs .ops = & mxl862xx_pcs_ops ;
3078+
3079+ /* poll link changes */
3080+ pcs -> pcs .poll = true;
3081+ pcs -> priv = priv ;
3082+ pcs -> port = port ;
3083+ }
3084+
29713085static int mxl862xx_setup (struct dsa_switch * ds )
29723086{
29733087 struct mxl862xx_priv * priv = ds -> priv ;
29743088 unsigned int cpu_port , j ;
29753089 int ret ;
29763090 u8 i ;
3091+ struct mxl862xx_bridge_port_config br_port_cfg = {
3092+ .mask = MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_PORT_MAP ,
3093+ };
29773094
29783095 priv -> user_pnum = 0 ;
29793096 for (j = 0 ; j < ds -> num_ports ; j ++ ) {
29803097 if (dsa_is_user_port (ds , j ))
29813098 priv -> user_pnum ++ ;
29823099 else if (dsa_is_cpu_port (ds , j ))
29833100 priv -> cpu_port = cpu_port = j ;
3101+
3102+ if (DSA_MXL_PORT (j ) == 13 ) {
3103+ mxl862xx_setup_pcs (priv , & priv -> pcs_port_1 , 13 );
3104+ }
29843105 }
29853106 dev_info (ds -> dev , "\tMxl862xx CPU Port %u, User Port number %u\n" ,
29863107 cpu_port , priv -> user_pnum );
@@ -3014,7 +3135,7 @@ static int mxl862xx_setup(struct dsa_switch *ds)
30143135
30153136 mxl862xx_mac_learning (ds , cpu_port , true);
30163137
3017- for (i = 0 ; i < MAX_BRIDGES ; i ++ )
3138+ for (i = 1 ; i < MAX_BRIDGES ; i ++ )
30183139 priv -> bridge_portmap [i ] = BIT (DSA_MXL_PORT (cpu_port ));
30193140
30203141 mxl862xx_set_vlan_filter_limits (ds );
@@ -3035,6 +3156,16 @@ static int mxl862xx_setup(struct dsa_switch *ds)
30353156 mxl862xx_port_state (ds , i , false);
30363157 mxl862xx_isolate_port (ds , i );
30373158 mxl862xx_port_fast_age (ds , i );
3159+ priv -> bridge_portmap [0 ] |= BIT (DSA_MXL_PORT (i ));
3160+ }
3161+
3162+ /* Update CPU bridge port */
3163+ br_port_cfg .bridge_port_id = DSA_MXL_PORT (cpu_port ),
3164+ br_port_cfg .bridge_port_map [0 ] = priv -> bridge_portmap [0 ];
3165+ ret = MXL862XX_API_WRITE (priv , MXL862XX_BRIDGEPORT_CONFIGSET , br_port_cfg );
3166+ if (ret ) {
3167+ dev_err (ds -> dev , "failed to set the cpu portmap\n" );
3168+ return ret ;
30383169 }
30393170
30403171 mxl862xx_port_fast_age (ds , cpu_port );
@@ -3105,16 +3236,93 @@ static void mxl862xx_phylink_mac_config(struct phylink_config *config, unsigned
31053236 const struct phylink_link_state * state )
31063237{
31073238 struct dsa_port * dp = dsa_phylink_to_port (config );
3239+ int hw_port = DSA_MXL_PORT (dp -> index );
3240+ int ret ;
3241+
3242+ if (dsa_is_cpu_port (dp -> ds , dp -> index ))
3243+ return ;
3244+
3245+ if (hw_port == 9 || hw_port == 13 ) {
3246+ struct mxl862xx_sys_sfp_cfg ser_intf = {
3247+ .option = 0 ,
3248+ .mode = 1 ,
3249+ };
31083250
3109- switch (state -> interface ) {
3110- case PHY_INTERFACE_MODE_INTERNAL :
3251+ if (hw_port == 9 )
3252+ ser_intf .port_id = 0 ;
3253+ else
3254+ ser_intf .port_id = 1 ;
3255+
3256+ /** select speed when mode is 1
3257+ * 0 - 10G Quad USXGMII
3258+ * 1 - 1000BaseX ANeg
3259+ * 2 - 10G XFI
3260+ * 3 - 10G Single USXGMII
3261+ * 4 - 2.5G SGMII
3262+ * 5 - 2500 Single USXGMI
3263+ * 6 - 2500BaseX NonANeg
3264+ * 7 - 1000BaseX NonANeg
3265+ * 8 - 1G SGMI
3266+ */
3267+ switch (state -> interface ) {
3268+ case PHY_INTERFACE_MODE_SGMII :
3269+ ser_intf .speed = 8 ;
3270+ break ;
3271+ case PHY_INTERFACE_MODE_1000BASEX :
3272+ ser_intf .speed = 7 ;
3273+ break ;
3274+ case PHY_INTERFACE_MODE_2500BASEX :
3275+ ser_intf .speed = 4 ;
3276+ break ;
3277+ case PHY_INTERFACE_MODE_10GBASER :
3278+ ser_intf .speed = 2 ;
3279+ break ;
3280+ case PHY_INTERFACE_MODE_USXGMII :
3281+ ser_intf .speed = 3 ;
3282+ break ;
3283+ default :
3284+ dev_err (dp -> ds -> dev , "Unsupported interface: %d\n" , state -> interface );
3285+ return ;
3286+ }
3287+
3288+ ret = MXL862XX_API_WRITE (dp -> ds -> priv , SYS_MISC_SFP_SET , ser_intf );
3289+ if (ret )
3290+ dev_err (dp -> ds -> dev , "failed to set intf on port %d\n" , dp -> index );
3291+ } else {
3292+ /* Internal phy */
3293+ if (state -> interface != PHY_INTERFACE_MODE_INTERNAL ) {
3294+ dev_err (dp -> ds -> dev , "Unsupported interface: %d\n" , state -> interface );
3295+ return ;
3296+ }
3297+ }
3298+ }
3299+
3300+ static struct phylink_pcs *
3301+ mxl862xx_phylink_mac_select_pcs (struct phylink_config * config ,
3302+ phy_interface_t interface )
3303+ {
3304+ struct dsa_port * dp = dsa_phylink_to_port (config );
3305+ struct mxl862xx_priv * priv = dp -> ds -> priv ;
3306+ struct phylink_pcs * pcs = NULL ;
3307+
3308+ switch (interface ) {
31113309 case PHY_INTERFACE_MODE_SGMII :
3310+ case PHY_INTERFACE_MODE_1000BASEX :
3311+ case PHY_INTERFACE_MODE_2500BASEX :
3312+ case PHY_INTERFACE_MODE_10GBASER :
31123313 case PHY_INTERFACE_MODE_USXGMII :
3113- return ;
3314+ switch (DSA_MXL_PORT (dp -> index )) {
3315+ case 13 :
3316+ pcs = & priv -> pcs_port_1 .pcs ;
3317+ break ;
3318+ }
3319+ break ;
3320+
31143321 default :
3115- dev_err (dp -> ds -> dev , "Unsupported interface: %d\n" , state -> interface );
3116- return ;
3322+ break ;
31173323 }
3324+
3325+ return pcs ;
31183326}
31193327
31203328static void mxl862xx_phylink_mac_link_down (struct phylink_config * config , unsigned int mode ,
@@ -3445,6 +3653,7 @@ static const struct phylink_mac_ops mxl862xx_phylink_mac_ops = {
34453653 .mac_config = mxl862xx_phylink_mac_config ,
34463654 .mac_link_down = mxl862xx_phylink_mac_link_down ,
34473655 .mac_link_up = mxl862xx_phylink_mac_link_up ,
3656+ .mac_select_pcs = mxl862xx_phylink_mac_select_pcs ,
34483657};
34493658
34503659static const struct dsa_switch_ops mxl862xx_switch_ops = {
0 commit comments