@@ -526,6 +526,7 @@ struct mvneta_port {
526526 unsigned int tx_csum_limit ;
527527 struct phylink * phylink ;
528528 struct phylink_config phylink_config ;
529+ struct phylink_pcs phylink_pcs ;
529530 struct phy * comphy ;
530531
531532 struct mvneta_bm * bm_priv ;
@@ -3846,29 +3847,31 @@ static int mvneta_set_mac_addr(struct net_device *dev, void *addr)
38463847 return 0 ;
38473848}
38483849
3849- static void mvneta_validate (struct phylink_config * config ,
3850- unsigned long * supported ,
3851- struct phylink_link_state * state )
3850+ static struct mvneta_port * mvneta_pcs_to_port (struct phylink_pcs * pcs )
3851+ {
3852+ return container_of (pcs , struct mvneta_port , phylink_pcs );
3853+ }
3854+
3855+ static int mvneta_pcs_validate (struct phylink_pcs * pcs ,
3856+ unsigned long * supported ,
3857+ const struct phylink_link_state * state )
38523858{
38533859 /* We only support QSGMII, SGMII, 802.3z and RGMII modes.
38543860 * When in 802.3z mode, we must have AN enabled:
38553861 * "Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
38563862 * When <PortType> = 1 (1000BASE-X) this field must be set to 1."
38573863 */
38583864 if (phy_interface_mode_is_8023z (state -> interface ) &&
3859- !phylink_test (state -> advertising , Autoneg )) {
3860- linkmode_zero (supported );
3861- return ;
3862- }
3865+ !phylink_test (state -> advertising , Autoneg ))
3866+ return - EINVAL ;
38633867
3864- phylink_generic_validate ( config , supported , state ) ;
3868+ return 0 ;
38653869}
38663870
3867- static void mvneta_mac_pcs_get_state (struct phylink_config * config ,
3868- struct phylink_link_state * state )
3871+ static void mvneta_pcs_get_state (struct phylink_pcs * pcs ,
3872+ struct phylink_link_state * state )
38693873{
3870- struct net_device * ndev = to_net_dev (config -> dev );
3871- struct mvneta_port * pp = netdev_priv (ndev );
3874+ struct mvneta_port * pp = mvneta_pcs_to_port (pcs );
38723875 u32 gmac_stat ;
38733876
38743877 gmac_stat = mvreg_read (pp , MVNETA_GMAC_STATUS );
@@ -3886,17 +3889,71 @@ static void mvneta_mac_pcs_get_state(struct phylink_config *config,
38863889 state -> link = !!(gmac_stat & MVNETA_GMAC_LINK_UP );
38873890 state -> duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX );
38883891
3889- state -> pause = 0 ;
38903892 if (gmac_stat & MVNETA_GMAC_RX_FLOW_CTRL_ENABLE )
38913893 state -> pause |= MLO_PAUSE_RX ;
38923894 if (gmac_stat & MVNETA_GMAC_TX_FLOW_CTRL_ENABLE )
38933895 state -> pause |= MLO_PAUSE_TX ;
38943896}
38953897
3896- static void mvneta_mac_an_restart (struct phylink_config * config )
3898+ static int mvneta_pcs_config (struct phylink_pcs * pcs ,
3899+ unsigned int mode , phy_interface_t interface ,
3900+ const unsigned long * advertising ,
3901+ bool permit_pause_to_mac )
38973902{
3898- struct net_device * ndev = to_net_dev (config -> dev );
3899- struct mvneta_port * pp = netdev_priv (ndev );
3903+ struct mvneta_port * pp = mvneta_pcs_to_port (pcs );
3904+ u32 mask , val , an , old_an , changed ;
3905+
3906+ mask = MVNETA_GMAC_INBAND_AN_ENABLE |
3907+ MVNETA_GMAC_INBAND_RESTART_AN |
3908+ MVNETA_GMAC_AN_SPEED_EN |
3909+ MVNETA_GMAC_AN_FLOW_CTRL_EN |
3910+ MVNETA_GMAC_AN_DUPLEX_EN ;
3911+
3912+ if (phylink_autoneg_inband (mode )) {
3913+ mask |= MVNETA_GMAC_CONFIG_MII_SPEED |
3914+ MVNETA_GMAC_CONFIG_GMII_SPEED |
3915+ MVNETA_GMAC_CONFIG_FULL_DUPLEX ;
3916+ val = MVNETA_GMAC_INBAND_AN_ENABLE ;
3917+
3918+ if (interface == PHY_INTERFACE_MODE_SGMII ) {
3919+ /* SGMII mode receives the speed and duplex from PHY */
3920+ val |= MVNETA_GMAC_AN_SPEED_EN |
3921+ MVNETA_GMAC_AN_DUPLEX_EN ;
3922+ } else {
3923+ /* 802.3z mode has fixed speed and duplex */
3924+ val |= MVNETA_GMAC_CONFIG_GMII_SPEED |
3925+ MVNETA_GMAC_CONFIG_FULL_DUPLEX ;
3926+
3927+ /* The FLOW_CTRL_EN bit selects either the hardware
3928+ * automatically or the CONFIG_FLOW_CTRL manually
3929+ * controls the GMAC pause mode.
3930+ */
3931+ if (permit_pause_to_mac )
3932+ val |= MVNETA_GMAC_AN_FLOW_CTRL_EN ;
3933+
3934+ /* Update the advertisement bits */
3935+ mask |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL ;
3936+ if (phylink_test (advertising , Pause ))
3937+ val |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL ;
3938+ }
3939+ } else {
3940+ /* Phy or fixed speed - disable in-band AN modes */
3941+ val = 0 ;
3942+ }
3943+
3944+ old_an = an = mvreg_read (pp , MVNETA_GMAC_AUTONEG_CONFIG );
3945+ an = (an & ~mask ) | val ;
3946+ changed = old_an ^ an ;
3947+ if (changed )
3948+ mvreg_write (pp , MVNETA_GMAC_AUTONEG_CONFIG , an );
3949+
3950+ /* We are only interested in the advertisement bits changing */
3951+ return !!(changed & MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL );
3952+ }
3953+
3954+ static void mvneta_pcs_an_restart (struct phylink_pcs * pcs )
3955+ {
3956+ struct mvneta_port * pp = mvneta_pcs_to_port (pcs );
39003957 u32 gmac_an = mvreg_read (pp , MVNETA_GMAC_AUTONEG_CONFIG );
39013958
39023959 mvreg_write (pp , MVNETA_GMAC_AUTONEG_CONFIG ,
@@ -3905,6 +3962,47 @@ static void mvneta_mac_an_restart(struct phylink_config *config)
39053962 gmac_an & ~MVNETA_GMAC_INBAND_RESTART_AN );
39063963}
39073964
3965+ static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = {
3966+ .pcs_validate = mvneta_pcs_validate ,
3967+ .pcs_get_state = mvneta_pcs_get_state ,
3968+ .pcs_config = mvneta_pcs_config ,
3969+ .pcs_an_restart = mvneta_pcs_an_restart ,
3970+ };
3971+
3972+ static int mvneta_mac_prepare (struct phylink_config * config , unsigned int mode ,
3973+ phy_interface_t interface )
3974+ {
3975+ struct net_device * ndev = to_net_dev (config -> dev );
3976+ struct mvneta_port * pp = netdev_priv (ndev );
3977+ u32 val ;
3978+
3979+ if (pp -> phy_interface != interface ||
3980+ phylink_autoneg_inband (mode )) {
3981+ /* Force the link down when changing the interface or if in
3982+ * in-band mode. According to Armada 370 documentation, we
3983+ * can only change the port mode and in-band enable when the
3984+ * link is down.
3985+ */
3986+ val = mvreg_read (pp , MVNETA_GMAC_AUTONEG_CONFIG );
3987+ val &= ~MVNETA_GMAC_FORCE_LINK_PASS ;
3988+ val |= MVNETA_GMAC_FORCE_LINK_DOWN ;
3989+ mvreg_write (pp , MVNETA_GMAC_AUTONEG_CONFIG , val );
3990+ }
3991+
3992+ if (pp -> phy_interface != interface )
3993+ WARN_ON (phy_power_off (pp -> comphy ));
3994+
3995+ /* Enable the 1ms clock */
3996+ if (phylink_autoneg_inband (mode )) {
3997+ unsigned long rate = clk_get_rate (pp -> clk );
3998+
3999+ mvreg_write (pp , MVNETA_GMAC_CLOCK_DIVIDER ,
4000+ MVNETA_GMAC_1MS_CLOCK_ENABLE | (rate / 1000 ));
4001+ }
4002+
4003+ return 0 ;
4004+ }
4005+
39084006static void mvneta_mac_config (struct phylink_config * config , unsigned int mode ,
39094007 const struct phylink_link_state * state )
39104008{
@@ -3913,20 +4011,11 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode,
39134011 u32 new_ctrl0 , gmac_ctrl0 = mvreg_read (pp , MVNETA_GMAC_CTRL_0 );
39144012 u32 new_ctrl2 , gmac_ctrl2 = mvreg_read (pp , MVNETA_GMAC_CTRL_2 );
39154013 u32 new_ctrl4 , gmac_ctrl4 = mvreg_read (pp , MVNETA_GMAC_CTRL_4 );
3916- u32 new_clk , gmac_clk = mvreg_read (pp , MVNETA_GMAC_CLOCK_DIVIDER );
3917- u32 new_an , gmac_an = mvreg_read (pp , MVNETA_GMAC_AUTONEG_CONFIG );
39184014
39194015 new_ctrl0 = gmac_ctrl0 & ~MVNETA_GMAC0_PORT_1000BASE_X ;
39204016 new_ctrl2 = gmac_ctrl2 & ~(MVNETA_GMAC2_INBAND_AN_ENABLE |
39214017 MVNETA_GMAC2_PORT_RESET );
39224018 new_ctrl4 = gmac_ctrl4 & ~(MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE );
3923- new_clk = gmac_clk & ~MVNETA_GMAC_1MS_CLOCK_ENABLE ;
3924- new_an = gmac_an & ~(MVNETA_GMAC_INBAND_AN_ENABLE |
3925- MVNETA_GMAC_INBAND_RESTART_AN |
3926- MVNETA_GMAC_AN_SPEED_EN |
3927- MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL |
3928- MVNETA_GMAC_AN_FLOW_CTRL_EN |
3929- MVNETA_GMAC_AN_DUPLEX_EN );
39304019
39314020 /* Even though it might look weird, when we're configured in
39324021 * SGMII or QSGMII mode, the RGMII bit needs to be set.
@@ -3938,80 +4027,30 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode,
39384027 phy_interface_mode_is_8023z (state -> interface ))
39394028 new_ctrl2 |= MVNETA_GMAC2_PCS_ENABLE ;
39404029
3941- if (phylink_test (state -> advertising , Pause ))
3942- new_an |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL ;
3943-
39444030 if (!phylink_autoneg_inband (mode )) {
39454031 /* Phy or fixed speed - nothing to do, leave the
39464032 * configured speed, duplex and flow control as-is.
39474033 */
39484034 } else if (state -> interface == PHY_INTERFACE_MODE_SGMII ) {
39494035 /* SGMII mode receives the state from the PHY */
39504036 new_ctrl2 |= MVNETA_GMAC2_INBAND_AN_ENABLE ;
3951- new_clk = MVNETA_GMAC_1MS_CLOCK_ENABLE ;
3952- new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN |
3953- MVNETA_GMAC_FORCE_LINK_PASS |
3954- MVNETA_GMAC_CONFIG_MII_SPEED |
3955- MVNETA_GMAC_CONFIG_GMII_SPEED |
3956- MVNETA_GMAC_CONFIG_FULL_DUPLEX )) |
3957- MVNETA_GMAC_INBAND_AN_ENABLE |
3958- MVNETA_GMAC_AN_SPEED_EN |
3959- MVNETA_GMAC_AN_DUPLEX_EN ;
39604037 } else {
39614038 /* 802.3z negotiation - only 1000base-X */
39624039 new_ctrl0 |= MVNETA_GMAC0_PORT_1000BASE_X ;
3963- new_clk = MVNETA_GMAC_1MS_CLOCK_ENABLE ;
3964- new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN |
3965- MVNETA_GMAC_FORCE_LINK_PASS |
3966- MVNETA_GMAC_CONFIG_MII_SPEED )) |
3967- MVNETA_GMAC_INBAND_AN_ENABLE |
3968- MVNETA_GMAC_CONFIG_GMII_SPEED |
3969- /* The MAC only supports FD mode */
3970- MVNETA_GMAC_CONFIG_FULL_DUPLEX ;
3971-
3972- if (state -> pause & MLO_PAUSE_AN && state -> an_enabled )
3973- new_an |= MVNETA_GMAC_AN_FLOW_CTRL_EN ;
39744040 }
39754041
3976- /* Set the 1ms clock divisor */
3977- if (new_clk == MVNETA_GMAC_1MS_CLOCK_ENABLE )
3978- new_clk |= clk_get_rate (pp -> clk ) / 1000 ;
3979-
3980- /* Armada 370 documentation says we can only change the port mode
3981- * and in-band enable when the link is down, so force it down
3982- * while making these changes. We also do this for GMAC_CTRL2
3983- */
3984- if ((new_ctrl0 ^ gmac_ctrl0 ) & MVNETA_GMAC0_PORT_1000BASE_X ||
3985- (new_ctrl2 ^ gmac_ctrl2 ) & MVNETA_GMAC2_INBAND_AN_ENABLE ||
3986- (new_an ^ gmac_an ) & MVNETA_GMAC_INBAND_AN_ENABLE ) {
3987- mvreg_write (pp , MVNETA_GMAC_AUTONEG_CONFIG ,
3988- (gmac_an & ~MVNETA_GMAC_FORCE_LINK_PASS ) |
3989- MVNETA_GMAC_FORCE_LINK_DOWN );
3990- }
3991-
3992-
39934042 /* When at 2.5G, the link partner can send frames with shortened
39944043 * preambles.
39954044 */
39964045 if (state -> interface == PHY_INTERFACE_MODE_2500BASEX )
39974046 new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE ;
39984047
3999- if (pp -> phy_interface != state -> interface ) {
4000- if (pp -> comphy )
4001- WARN_ON (phy_power_off (pp -> comphy ));
4002- WARN_ON (mvneta_config_interface (pp , state -> interface ));
4003- }
4004-
40054048 if (new_ctrl0 != gmac_ctrl0 )
40064049 mvreg_write (pp , MVNETA_GMAC_CTRL_0 , new_ctrl0 );
40074050 if (new_ctrl2 != gmac_ctrl2 )
40084051 mvreg_write (pp , MVNETA_GMAC_CTRL_2 , new_ctrl2 );
40094052 if (new_ctrl4 != gmac_ctrl4 )
40104053 mvreg_write (pp , MVNETA_GMAC_CTRL_4 , new_ctrl4 );
4011- if (new_clk != gmac_clk )
4012- mvreg_write (pp , MVNETA_GMAC_CLOCK_DIVIDER , new_clk );
4013- if (new_an != gmac_an )
4014- mvreg_write (pp , MVNETA_GMAC_AUTONEG_CONFIG , new_an );
40154054
40164055 if (gmac_ctrl2 & MVNETA_GMAC2_PORT_RESET ) {
40174056 while ((mvreg_read (pp , MVNETA_GMAC_CTRL_2 ) &
@@ -4020,6 +4059,36 @@ static void mvneta_mac_config(struct phylink_config *config, unsigned int mode,
40204059 }
40214060}
40224061
4062+ static int mvneta_mac_finish (struct phylink_config * config , unsigned int mode ,
4063+ phy_interface_t interface )
4064+ {
4065+ struct net_device * ndev = to_net_dev (config -> dev );
4066+ struct mvneta_port * pp = netdev_priv (ndev );
4067+ u32 val , clk ;
4068+
4069+ /* Disable 1ms clock if not in in-band mode */
4070+ if (!phylink_autoneg_inband (mode )) {
4071+ clk = mvreg_read (pp , MVNETA_GMAC_CLOCK_DIVIDER );
4072+ clk &= ~MVNETA_GMAC_1MS_CLOCK_ENABLE ;
4073+ mvreg_write (pp , MVNETA_GMAC_CLOCK_DIVIDER , clk );
4074+ }
4075+
4076+ if (pp -> phy_interface != interface )
4077+ /* Enable the Serdes PHY */
4078+ WARN_ON (mvneta_config_interface (pp , interface ));
4079+
4080+ /* Allow the link to come up if in in-band mode, otherwise the
4081+ * link is forced via mac_link_down()/mac_link_up()
4082+ */
4083+ if (phylink_autoneg_inband (mode )) {
4084+ val = mvreg_read (pp , MVNETA_GMAC_AUTONEG_CONFIG );
4085+ val &= ~MVNETA_GMAC_FORCE_LINK_DOWN ;
4086+ mvreg_write (pp , MVNETA_GMAC_AUTONEG_CONFIG , val );
4087+ }
4088+
4089+ return 0 ;
4090+ }
4091+
40234092static void mvneta_set_eee (struct mvneta_port * pp , bool enable )
40244093{
40254094 u32 lpi_ctl1 ;
@@ -4106,10 +4175,10 @@ static void mvneta_mac_link_up(struct phylink_config *config,
41064175}
41074176
41084177static const struct phylink_mac_ops mvneta_phylink_ops = {
4109- .validate = mvneta_validate ,
4110- .mac_pcs_get_state = mvneta_mac_pcs_get_state ,
4111- .mac_an_restart = mvneta_mac_an_restart ,
4178+ .validate = phylink_generic_validate ,
4179+ .mac_prepare = mvneta_mac_prepare ,
41124180 .mac_config = mvneta_mac_config ,
4181+ .mac_finish = mvneta_mac_finish ,
41134182 .mac_link_down = mvneta_mac_link_down ,
41144183 .mac_link_up = mvneta_mac_link_up ,
41154184};
@@ -5275,7 +5344,6 @@ static int mvneta_probe(struct platform_device *pdev)
52755344
52765345 pp -> phylink_config .dev = & dev -> dev ;
52775346 pp -> phylink_config .type = PHYLINK_NETDEV ;
5278- pp -> phylink_config .legacy_pre_march2020 = true;
52795347 pp -> phylink_config .mac_capabilities = MAC_SYM_PAUSE | MAC_10 |
52805348 MAC_100 | MAC_1000FD | MAC_2500FD ;
52815349
@@ -5350,6 +5418,9 @@ static int mvneta_probe(struct platform_device *pdev)
53505418 goto err_clk ;
53515419 }
53525420
5421+ pp -> phylink_pcs .ops = & mvneta_phylink_pcs_ops ;
5422+ phylink_set_pcs (phylink , & pp -> phylink_pcs );
5423+
53535424 /* Alloc per-cpu port structure */
53545425 pp -> ports = alloc_percpu (struct mvneta_pcpu_port );
53555426 if (!pp -> ports ) {
0 commit comments