124124#define LAN9303_MAC_RX_CFG_2 0x0c01
125125#define LAN9303_MAC_TX_CFG_2 0x0c40
126126#define LAN9303_SWE_ALR_CMD 0x1800
127+ # define LAN9303_ALR_CMD_MAKE_ENTRY BIT(2)
128+ # define LAN9303_ALR_CMD_GET_FIRST BIT(1)
129+ # define LAN9303_ALR_CMD_GET_NEXT BIT(0)
130+ #define LAN9303_SWE_ALR_WR_DAT_0 0x1801
131+ #define LAN9303_SWE_ALR_WR_DAT_1 0x1802
132+ # define LAN9303_ALR_DAT1_VALID BIT(26)
133+ # define LAN9303_ALR_DAT1_END_OF_TABL BIT(25)
134+ # define LAN9303_ALR_DAT1_AGE_OVERRID BIT(25)
135+ # define LAN9303_ALR_DAT1_STATIC BIT(24)
136+ # define LAN9303_ALR_DAT1_PORT_BITOFFS 16
137+ # define LAN9303_ALR_DAT1_PORT_MASK (7 << LAN9303_ALR_DAT1_PORT_BITOFFS)
138+ #define LAN9303_SWE_ALR_RD_DAT_0 0x1805
139+ #define LAN9303_SWE_ALR_RD_DAT_1 0x1806
140+ #define LAN9303_SWE_ALR_CMD_STS 0x1808
141+ # define ALR_STS_MAKE_PEND BIT(0)
127142#define LAN9303_SWE_VLAN_CMD 0x180b
128143# define LAN9303_SWE_VLAN_CMD_RNW BIT(5)
129144# define LAN9303_SWE_VLAN_CMD_PVIDNVLAN BIT(4)
@@ -478,6 +493,122 @@ static int lan9303_detect_phy_setup(struct lan9303 *chip)
478493 return 0 ;
479494}
480495
496+ /* Map ALR-port bits to port bitmap, and back */
497+ static const int alrport_2_portmap [] = {1 , 2 , 4 , 0 , 3 , 5 , 6 , 7 };
498+ static const int portmap_2_alrport [] = {3 , 0 , 1 , 4 , 2 , 5 , 6 , 7 };
499+
500+ /* Wait a while until mask & reg == value. Otherwise return timeout. */
501+ static int lan9303_csr_reg_wait (struct lan9303 * chip , int regno ,
502+ int mask , char value )
503+ {
504+ int i ;
505+
506+ for (i = 0 ; i < 0x1000 ; i ++ ) {
507+ u32 reg ;
508+
509+ lan9303_read_switch_reg (chip , regno , & reg );
510+ if ((reg & mask ) == value )
511+ return 0 ;
512+ usleep_range (1000 , 2000 );
513+ }
514+ return - ETIMEDOUT ;
515+ }
516+
517+ static int lan9303_alr_make_entry_raw (struct lan9303 * chip , u32 dat0 , u32 dat1 )
518+ {
519+ lan9303_write_switch_reg (chip , LAN9303_SWE_ALR_WR_DAT_0 , dat0 );
520+ lan9303_write_switch_reg (chip , LAN9303_SWE_ALR_WR_DAT_1 , dat1 );
521+ lan9303_write_switch_reg (chip , LAN9303_SWE_ALR_CMD ,
522+ LAN9303_ALR_CMD_MAKE_ENTRY );
523+ lan9303_csr_reg_wait (chip , LAN9303_SWE_ALR_CMD_STS , ALR_STS_MAKE_PEND ,
524+ 0 );
525+ lan9303_write_switch_reg (chip , LAN9303_SWE_ALR_CMD , 0 );
526+
527+ return 0 ;
528+ }
529+
530+ typedef void alr_loop_cb_t (struct lan9303 * chip , u32 dat0 , u32 dat1 ,
531+ int portmap , void * ctx );
532+
533+ static void lan9303_alr_loop (struct lan9303 * chip , alr_loop_cb_t * cb , void * ctx )
534+ {
535+ int i ;
536+
537+ lan9303_write_switch_reg (chip , LAN9303_SWE_ALR_CMD ,
538+ LAN9303_ALR_CMD_GET_FIRST );
539+ lan9303_write_switch_reg (chip , LAN9303_SWE_ALR_CMD , 0 );
540+
541+ for (i = 1 ; i < LAN9303_NUM_ALR_RECORDS ; i ++ ) {
542+ u32 dat0 , dat1 ;
543+ int alrport , portmap ;
544+
545+ lan9303_read_switch_reg (chip , LAN9303_SWE_ALR_RD_DAT_0 , & dat0 );
546+ lan9303_read_switch_reg (chip , LAN9303_SWE_ALR_RD_DAT_1 , & dat1 );
547+ if (dat1 & LAN9303_ALR_DAT1_END_OF_TABL )
548+ break ;
549+
550+ alrport = (dat1 & LAN9303_ALR_DAT1_PORT_MASK ) >>
551+ LAN9303_ALR_DAT1_PORT_BITOFFS ;
552+ portmap = alrport_2_portmap [alrport ];
553+
554+ cb (chip , dat0 , dat1 , portmap , ctx );
555+
556+ lan9303_write_switch_reg (chip , LAN9303_SWE_ALR_CMD ,
557+ LAN9303_ALR_CMD_GET_NEXT );
558+ lan9303_write_switch_reg (chip , LAN9303_SWE_ALR_CMD , 0 );
559+ }
560+ }
561+
562+ static void alr_reg_to_mac (u32 dat0 , u32 dat1 , u8 mac [6 ])
563+ {
564+ mac [0 ] = (dat0 >> 0 ) & 0xff ;
565+ mac [1 ] = (dat0 >> 8 ) & 0xff ;
566+ mac [2 ] = (dat0 >> 16 ) & 0xff ;
567+ mac [3 ] = (dat0 >> 24 ) & 0xff ;
568+ mac [4 ] = (dat1 >> 0 ) & 0xff ;
569+ mac [5 ] = (dat1 >> 8 ) & 0xff ;
570+ }
571+
572+ struct del_port_learned_ctx {
573+ int port ;
574+ };
575+
576+ /* Clear learned (non-static) entry on given port */
577+ static void alr_loop_cb_del_port_learned (struct lan9303 * chip , u32 dat0 ,
578+ u32 dat1 , int portmap , void * ctx )
579+ {
580+ struct del_port_learned_ctx * del_ctx = ctx ;
581+ int port = del_ctx -> port ;
582+
583+ if (((BIT (port ) & portmap ) == 0 ) || (dat1 & LAN9303_ALR_DAT1_STATIC ))
584+ return ;
585+
586+ /* learned entries has only one port, we can just delete */
587+ dat1 &= ~LAN9303_ALR_DAT1_VALID ; /* delete entry */
588+ lan9303_alr_make_entry_raw (chip , dat0 , dat1 );
589+ }
590+
591+ struct port_fdb_dump_ctx {
592+ int port ;
593+ void * data ;
594+ dsa_fdb_dump_cb_t * cb ;
595+ };
596+
597+ static void alr_loop_cb_fdb_port_dump (struct lan9303 * chip , u32 dat0 ,
598+ u32 dat1 , int portmap , void * ctx )
599+ {
600+ struct port_fdb_dump_ctx * dump_ctx = ctx ;
601+ u8 mac [ETH_ALEN ];
602+ bool is_static ;
603+
604+ if ((BIT (dump_ctx -> port ) & portmap ) == 0 )
605+ return ;
606+
607+ alr_reg_to_mac (dat0 , dat1 , mac );
608+ is_static = !!(dat1 & LAN9303_ALR_DAT1_STATIC );
609+ dump_ctx -> cb (mac , 0 , is_static , dump_ctx -> data );
610+ }
611+
481612static int lan9303_disable_processing_port (struct lan9303 * chip ,
482613 unsigned int port )
483614{
@@ -923,6 +1054,33 @@ static void lan9303_port_stp_state_set(struct dsa_switch *ds, int port,
9231054 /* else: touching SWE_PORT_STATE would break port separation */
9241055}
9251056
1057+ static void lan9303_port_fast_age (struct dsa_switch * ds , int port )
1058+ {
1059+ struct lan9303 * chip = ds -> priv ;
1060+ struct del_port_learned_ctx del_ctx = {
1061+ .port = port ,
1062+ };
1063+
1064+ dev_dbg (chip -> dev , "%s(%d)\n" , __func__ , port );
1065+ lan9303_alr_loop (chip , alr_loop_cb_del_port_learned , & del_ctx );
1066+ }
1067+
1068+ static int lan9303_port_fdb_dump (struct dsa_switch * ds , int port ,
1069+ dsa_fdb_dump_cb_t * cb , void * data )
1070+ {
1071+ struct lan9303 * chip = ds -> priv ;
1072+ struct port_fdb_dump_ctx dump_ctx = {
1073+ .port = port ,
1074+ .data = data ,
1075+ .cb = cb ,
1076+ };
1077+
1078+ dev_dbg (chip -> dev , "%s(%d)\n" , __func__ , port );
1079+ lan9303_alr_loop (chip , alr_loop_cb_fdb_port_dump , & dump_ctx );
1080+
1081+ return 0 ;
1082+ }
1083+
9261084static const struct dsa_switch_ops lan9303_switch_ops = {
9271085 .get_tag_protocol = lan9303_get_tag_protocol ,
9281086 .setup = lan9303_setup ,
@@ -937,6 +1095,8 @@ static const struct dsa_switch_ops lan9303_switch_ops = {
9371095 .port_bridge_join = lan9303_port_bridge_join ,
9381096 .port_bridge_leave = lan9303_port_bridge_leave ,
9391097 .port_stp_state_set = lan9303_port_stp_state_set ,
1098+ .port_fast_age = lan9303_port_fast_age ,
1099+ .port_fdb_dump = lan9303_port_fdb_dump ,
9401100};
9411101
9421102static int lan9303_register_switch (struct lan9303 * chip )
0 commit comments