@@ -419,9 +419,9 @@ static int mv88e6xxx_port_config_interface(struct mv88e6xxx_chip *chip,
419419 return 0 ;
420420}
421421
422- int mv88e6xxx_port_setup_mac (struct mv88e6xxx_chip * chip , int port , int link ,
423- int speed , int duplex , int pause ,
424- phy_interface_t mode )
422+ static int mv88e6xxx_port_setup_mac (struct mv88e6xxx_chip * chip , int port ,
423+ int link , int speed , int duplex , int pause ,
424+ phy_interface_t mode )
425425{
426426 struct phylink_link_state state ;
427427 int err ;
@@ -488,6 +488,81 @@ static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port)
488488 return port < chip -> info -> num_internal_phys ;
489489}
490490
491+ static int mv88e6xxx_serdes_pcs_get_state (struct dsa_switch * ds , int port ,
492+ struct phylink_link_state * state )
493+ {
494+ struct mv88e6xxx_chip * chip = ds -> priv ;
495+ u8 lane ;
496+ int err ;
497+
498+ mv88e6xxx_reg_lock (chip );
499+ lane = mv88e6xxx_serdes_get_lane (chip , port );
500+ if (lane && chip -> info -> ops -> serdes_pcs_get_state )
501+ err = chip -> info -> ops -> serdes_pcs_get_state (chip , port , lane ,
502+ state );
503+ else
504+ err = - EOPNOTSUPP ;
505+ mv88e6xxx_reg_unlock (chip );
506+
507+ return err ;
508+ }
509+
510+ static int mv88e6xxx_serdes_pcs_config (struct mv88e6xxx_chip * chip , int port ,
511+ unsigned int mode ,
512+ phy_interface_t interface ,
513+ const unsigned long * advertise )
514+ {
515+ const struct mv88e6xxx_ops * ops = chip -> info -> ops ;
516+ u8 lane ;
517+
518+ if (ops -> serdes_pcs_config ) {
519+ lane = mv88e6xxx_serdes_get_lane (chip , port );
520+ if (lane )
521+ return ops -> serdes_pcs_config (chip , port , lane , mode ,
522+ interface , advertise );
523+ }
524+
525+ return 0 ;
526+ }
527+
528+ static void mv88e6xxx_serdes_pcs_an_restart (struct dsa_switch * ds , int port )
529+ {
530+ struct mv88e6xxx_chip * chip = ds -> priv ;
531+ const struct mv88e6xxx_ops * ops ;
532+ int err = 0 ;
533+ u8 lane ;
534+
535+ ops = chip -> info -> ops ;
536+
537+ if (ops -> serdes_pcs_an_restart ) {
538+ mv88e6xxx_reg_lock (chip );
539+ lane = mv88e6xxx_serdes_get_lane (chip , port );
540+ if (lane )
541+ err = ops -> serdes_pcs_an_restart (chip , port , lane );
542+ mv88e6xxx_reg_unlock (chip );
543+
544+ if (err )
545+ dev_err (ds -> dev , "p%d: failed to restart AN\n" , port );
546+ }
547+ }
548+
549+ static int mv88e6xxx_serdes_pcs_link_up (struct mv88e6xxx_chip * chip , int port ,
550+ unsigned int mode ,
551+ int speed , int duplex )
552+ {
553+ const struct mv88e6xxx_ops * ops = chip -> info -> ops ;
554+ u8 lane ;
555+
556+ if (!phylink_autoneg_inband (mode ) && ops -> serdes_pcs_link_up ) {
557+ lane = mv88e6xxx_serdes_get_lane (chip , port );
558+ if (lane )
559+ return ops -> serdes_pcs_link_up (chip , port , lane ,
560+ speed , duplex );
561+ }
562+
563+ return 0 ;
564+ }
565+
491566static void mv88e6065_phylink_validate (struct mv88e6xxx_chip * chip , int port ,
492567 unsigned long * mask ,
493568 struct phylink_link_state * state )
@@ -592,22 +667,6 @@ static void mv88e6xxx_validate(struct dsa_switch *ds, int port,
592667 phylink_helper_basex_speed (state );
593668}
594669
595- static int mv88e6xxx_link_state (struct dsa_switch * ds , int port ,
596- struct phylink_link_state * state )
597- {
598- struct mv88e6xxx_chip * chip = ds -> priv ;
599- int err ;
600-
601- mv88e6xxx_reg_lock (chip );
602- if (chip -> info -> ops -> port_link_state )
603- err = chip -> info -> ops -> port_link_state (chip , port , state );
604- else
605- err = - EOPNOTSUPP ;
606- mv88e6xxx_reg_unlock (chip );
607-
608- return err ;
609- }
610-
611670static void mv88e6xxx_mac_config (struct dsa_switch * ds , int port ,
612671 unsigned int mode ,
613672 const struct phylink_link_state * state )
@@ -629,6 +688,18 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
629688 * gets in the way.
630689 */
631690 err = mv88e6xxx_port_config_interface (chip , port , state -> interface );
691+ if (err && err != - EOPNOTSUPP )
692+ goto err_unlock ;
693+
694+ err = mv88e6xxx_serdes_pcs_config (chip , port , mode , state -> interface ,
695+ state -> advertising );
696+ /* FIXME: we should restart negotiation if something changed - which
697+ * is something we get if we convert to using phylinks PCS operations.
698+ */
699+ if (err > 0 )
700+ err = 0 ;
701+
702+ err_unlock :
632703 mv88e6xxx_reg_unlock (chip );
633704
634705 if (err && err != - EOPNOTSUPP )
@@ -683,9 +754,14 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port,
683754 /* FIXME: for an automedia port, should we force the link
684755 * down here - what if the link comes up due to "other" media
685756 * while we're bringing the port up, how is the exclusivity
686- * handled in the Marvell hardware? E.g. port 4 on 88E6532
757+ * handled in the Marvell hardware? E.g. port 2 on 88E6390
687758 * shared between internal PHY and Serdes.
688759 */
760+ err = mv88e6xxx_serdes_pcs_link_up (chip , port , mode , speed ,
761+ duplex );
762+ if (err )
763+ goto error ;
764+
689765 if (ops -> port_set_speed ) {
690766 err = ops -> port_set_speed (chip , port , speed );
691767 if (err && err != - EOPNOTSUPP )
@@ -3557,6 +3633,11 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
35573633 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge ,
35583634 .serdes_power = mv88e6390_serdes_power ,
35593635 .serdes_get_lane = mv88e6341_serdes_get_lane ,
3636+ /* Check status register pause & lpa register */
3637+ .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state ,
3638+ .serdes_pcs_config = mv88e6390_serdes_pcs_config ,
3639+ .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart ,
3640+ .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up ,
35603641 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping ,
35613642 .serdes_irq_enable = mv88e6390_serdes_irq_enable ,
35623643 .serdes_irq_status = mv88e6390_serdes_irq_status ,
@@ -3729,6 +3810,10 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
37293810 .vtu_getnext = mv88e6352_g1_vtu_getnext ,
37303811 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge ,
37313812 .serdes_get_lane = mv88e6352_serdes_get_lane ,
3813+ .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state ,
3814+ .serdes_pcs_config = mv88e6352_serdes_pcs_config ,
3815+ .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart ,
3816+ .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up ,
37323817 .serdes_power = mv88e6352_serdes_power ,
37333818 .serdes_get_regs_len = mv88e6352_serdes_get_regs_len ,
37343819 .serdes_get_regs = mv88e6352_serdes_get_regs ,
@@ -3822,6 +3907,10 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
38223907 .vtu_getnext = mv88e6352_g1_vtu_getnext ,
38233908 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge ,
38243909 .serdes_get_lane = mv88e6352_serdes_get_lane ,
3910+ .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state ,
3911+ .serdes_pcs_config = mv88e6352_serdes_pcs_config ,
3912+ .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart ,
3913+ .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up ,
38253914 .serdes_power = mv88e6352_serdes_power ,
38263915 .serdes_irq_mapping = mv88e6352_serdes_irq_mapping ,
38273916 .serdes_irq_enable = mv88e6352_serdes_irq_enable ,
@@ -3912,6 +4001,11 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
39124001 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge ,
39134002 .serdes_power = mv88e6390_serdes_power ,
39144003 .serdes_get_lane = mv88e6390_serdes_get_lane ,
4004+ /* Check status register pause & lpa register */
4005+ .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state ,
4006+ .serdes_pcs_config = mv88e6390_serdes_pcs_config ,
4007+ .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart ,
4008+ .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up ,
39154009 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping ,
39164010 .serdes_irq_enable = mv88e6390_serdes_irq_enable ,
39174011 .serdes_irq_status = mv88e6390_serdes_irq_status ,
@@ -3968,6 +4062,11 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
39684062 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge ,
39694063 .serdes_power = mv88e6390_serdes_power ,
39704064 .serdes_get_lane = mv88e6390x_serdes_get_lane ,
4065+ /* Check status register pause & lpa register */
4066+ .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state ,
4067+ .serdes_pcs_config = mv88e6390_serdes_pcs_config ,
4068+ .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart ,
4069+ .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up ,
39714070 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping ,
39724071 .serdes_irq_enable = mv88e6390_serdes_irq_enable ,
39734072 .serdes_irq_status = mv88e6390_serdes_irq_status ,
@@ -4023,6 +4122,11 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
40234122 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge ,
40244123 .serdes_power = mv88e6390_serdes_power ,
40254124 .serdes_get_lane = mv88e6390_serdes_get_lane ,
4125+ /* Check status register pause & lpa register */
4126+ .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state ,
4127+ .serdes_pcs_config = mv88e6390_serdes_pcs_config ,
4128+ .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart ,
4129+ .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up ,
40264130 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping ,
40274131 .serdes_irq_enable = mv88e6390_serdes_irq_enable ,
40284132 .serdes_irq_status = mv88e6390_serdes_irq_status ,
@@ -4080,6 +4184,10 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
40804184 .vtu_getnext = mv88e6352_g1_vtu_getnext ,
40814185 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge ,
40824186 .serdes_get_lane = mv88e6352_serdes_get_lane ,
4187+ .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state ,
4188+ .serdes_pcs_config = mv88e6352_serdes_pcs_config ,
4189+ .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart ,
4190+ .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up ,
40834191 .serdes_power = mv88e6352_serdes_power ,
40844192 .serdes_irq_mapping = mv88e6352_serdes_irq_mapping ,
40854193 .serdes_irq_enable = mv88e6352_serdes_irq_enable ,
@@ -4176,6 +4284,11 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
41764284 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge ,
41774285 .serdes_power = mv88e6390_serdes_power ,
41784286 .serdes_get_lane = mv88e6390_serdes_get_lane ,
4287+ /* Check status register pause & lpa register */
4288+ .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state ,
4289+ .serdes_pcs_config = mv88e6390_serdes_pcs_config ,
4290+ .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart ,
4291+ .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up ,
41794292 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping ,
41804293 .serdes_irq_enable = mv88e6390_serdes_irq_enable ,
41814294 .serdes_irq_status = mv88e6390_serdes_irq_status ,
@@ -4319,6 +4432,11 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
43194432 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge ,
43204433 .serdes_power = mv88e6390_serdes_power ,
43214434 .serdes_get_lane = mv88e6341_serdes_get_lane ,
4435+ /* Check status register pause & lpa register */
4436+ .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state ,
4437+ .serdes_pcs_config = mv88e6390_serdes_pcs_config ,
4438+ .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart ,
4439+ .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up ,
43224440 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping ,
43234441 .serdes_irq_enable = mv88e6390_serdes_irq_enable ,
43244442 .serdes_irq_status = mv88e6390_serdes_irq_status ,
@@ -4458,6 +4576,10 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
44584576 .vtu_getnext = mv88e6352_g1_vtu_getnext ,
44594577 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge ,
44604578 .serdes_get_lane = mv88e6352_serdes_get_lane ,
4579+ .serdes_pcs_get_state = mv88e6352_serdes_pcs_get_state ,
4580+ .serdes_pcs_config = mv88e6352_serdes_pcs_config ,
4581+ .serdes_pcs_an_restart = mv88e6352_serdes_pcs_an_restart ,
4582+ .serdes_pcs_link_up = mv88e6352_serdes_pcs_link_up ,
44614583 .serdes_power = mv88e6352_serdes_power ,
44624584 .serdes_irq_mapping = mv88e6352_serdes_irq_mapping ,
44634585 .serdes_irq_enable = mv88e6352_serdes_irq_enable ,
@@ -4519,6 +4641,11 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
45194641 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge ,
45204642 .serdes_power = mv88e6390_serdes_power ,
45214643 .serdes_get_lane = mv88e6390_serdes_get_lane ,
4644+ /* Check status register pause & lpa register */
4645+ .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state ,
4646+ .serdes_pcs_config = mv88e6390_serdes_pcs_config ,
4647+ .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart ,
4648+ .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up ,
45224649 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping ,
45234650 .serdes_irq_enable = mv88e6390_serdes_irq_enable ,
45244651 .serdes_irq_status = mv88e6390_serdes_irq_status ,
@@ -4579,6 +4706,10 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
45794706 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge ,
45804707 .serdes_power = mv88e6390_serdes_power ,
45814708 .serdes_get_lane = mv88e6390x_serdes_get_lane ,
4709+ .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state ,
4710+ .serdes_pcs_config = mv88e6390_serdes_pcs_config ,
4711+ .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart ,
4712+ .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up ,
45824713 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping ,
45834714 .serdes_irq_enable = mv88e6390_serdes_irq_enable ,
45844715 .serdes_irq_status = mv88e6390_serdes_irq_status ,
@@ -5457,8 +5588,9 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
54575588 .setup = mv88e6xxx_setup ,
54585589 .teardown = mv88e6xxx_teardown ,
54595590 .phylink_validate = mv88e6xxx_validate ,
5460- .phylink_mac_link_state = mv88e6xxx_link_state ,
5591+ .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state ,
54615592 .phylink_mac_config = mv88e6xxx_mac_config ,
5593+ .phylink_mac_an_restart = mv88e6xxx_serdes_pcs_an_restart ,
54625594 .phylink_mac_link_down = mv88e6xxx_mac_link_down ,
54635595 .phylink_mac_link_up = mv88e6xxx_mac_link_up ,
54645596 .get_strings = mv88e6xxx_get_strings ,
0 commit comments