@@ -61,30 +61,10 @@ static void bcm_sf2_imp_vlan_setup(struct dsa_switch *ds, int cpu_port)
6161 }
6262}
6363
64- static void bcm_sf2_imp_setup (struct dsa_switch * ds , int port )
64+ static void bcm_sf2_brcm_hdr_setup (struct bcm_sf2_priv * priv , int port )
6565{
66- struct bcm_sf2_priv * priv = bcm_sf2_to_priv (ds );
6766 u32 reg , val ;
6867
69- /* Enable the port memories */
70- reg = core_readl (priv , CORE_MEM_PSM_VDD_CTRL );
71- reg &= ~P_TXQ_PSM_VDD (port );
72- core_writel (priv , reg , CORE_MEM_PSM_VDD_CTRL );
73-
74- /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
75- reg = core_readl (priv , CORE_IMP_CTL );
76- reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN );
77- reg &= ~(RX_DIS | TX_DIS );
78- core_writel (priv , reg , CORE_IMP_CTL );
79-
80- /* Enable forwarding */
81- core_writel (priv , SW_FWDG_EN , CORE_SWMODE );
82-
83- /* Enable IMP port in dumb mode */
84- reg = core_readl (priv , CORE_SWITCH_CTRL );
85- reg |= MII_DUMB_FWDG_EN ;
86- core_writel (priv , reg , CORE_SWITCH_CTRL );
87-
8868 /* Resolve which bit controls the Broadcom tag */
8969 switch (port ) {
9070 case 8 :
@@ -119,11 +99,43 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
11999 reg = core_readl (priv , CORE_BRCM_HDR_TX_DIS );
120100 reg &= ~(1 << port );
121101 core_writel (priv , reg , CORE_BRCM_HDR_TX_DIS );
102+ }
103+
104+ static void bcm_sf2_imp_setup (struct dsa_switch * ds , int port )
105+ {
106+ struct bcm_sf2_priv * priv = bcm_sf2_to_priv (ds );
107+ u32 reg , offset ;
108+
109+ if (priv -> type == BCM7445_DEVICE_ID )
110+ offset = CORE_STS_OVERRIDE_IMP ;
111+ else
112+ offset = CORE_STS_OVERRIDE_IMP2 ;
113+
114+ /* Enable the port memories */
115+ reg = core_readl (priv , CORE_MEM_PSM_VDD_CTRL );
116+ reg &= ~P_TXQ_PSM_VDD (port );
117+ core_writel (priv , reg , CORE_MEM_PSM_VDD_CTRL );
118+
119+ /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
120+ reg = core_readl (priv , CORE_IMP_CTL );
121+ reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN );
122+ reg &= ~(RX_DIS | TX_DIS );
123+ core_writel (priv , reg , CORE_IMP_CTL );
124+
125+ /* Enable forwarding */
126+ core_writel (priv , SW_FWDG_EN , CORE_SWMODE );
127+
128+ /* Enable IMP port in dumb mode */
129+ reg = core_readl (priv , CORE_SWITCH_CTRL );
130+ reg |= MII_DUMB_FWDG_EN ;
131+ core_writel (priv , reg , CORE_SWITCH_CTRL );
132+
133+ bcm_sf2_brcm_hdr_setup (priv , port );
122134
123135 /* Force link status for IMP port */
124- reg = core_readl (priv , CORE_STS_OVERRIDE_IMP );
136+ reg = core_readl (priv , offset );
125137 reg |= (MII_SW_OR | LINK_STS );
126- core_writel (priv , reg , CORE_STS_OVERRIDE_IMP );
138+ core_writel (priv , reg , offset );
127139}
128140
129141static void bcm_sf2_eee_enable_set (struct dsa_switch * ds , int port , bool enable )
@@ -224,6 +236,10 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
224236 reg &= ~P_TXQ_PSM_VDD (port );
225237 core_writel (priv , reg , CORE_MEM_PSM_VDD_CTRL );
226238
239+ /* Enable Broadcom tags for that port if requested */
240+ if (priv -> brcm_tag_mask & BIT (port ))
241+ bcm_sf2_brcm_hdr_setup (priv , port );
242+
227243 /* Clear the Rx and Tx disable bits and set to no spanning tree */
228244 core_writel (priv , 0 , CORE_G_PCTL_PORT (port ));
229245
@@ -503,6 +519,9 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv *priv,
503519
504520 if (mode == PHY_INTERFACE_MODE_MOCA )
505521 priv -> moca_port = port_num ;
522+
523+ if (of_property_read_bool (port , "brcm,use-bcm-hdr" ))
524+ priv -> brcm_tag_mask |= 1 << port_num ;
506525 }
507526}
508527
@@ -591,7 +610,12 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
591610 struct ethtool_eee * p = & priv -> port_sts [port ].eee ;
592611 u32 id_mode_dis = 0 , port_mode ;
593612 const char * str = NULL ;
594- u32 reg ;
613+ u32 reg , offset ;
614+
615+ if (priv -> type == BCM7445_DEVICE_ID )
616+ offset = CORE_STS_OVERRIDE_GMIIP_PORT (port );
617+ else
618+ offset = CORE_STS_OVERRIDE_GMIIP2_PORT (port );
595619
596620 switch (phydev -> interface ) {
597621 case PHY_INTERFACE_MODE_RGMII :
@@ -662,7 +686,7 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
662686 if (phydev -> duplex == DUPLEX_FULL )
663687 reg |= DUPLX_MODE ;
664688
665- core_writel (priv , reg , CORE_STS_OVERRIDE_GMIIP_PORT ( port ) );
689+ core_writel (priv , reg , offset );
666690
667691 if (!phydev -> is_pseudo_fixed_link )
668692 p -> eee_enabled = bcm_sf2_eee_init (ds , port , phydev );
@@ -672,9 +696,14 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
672696 struct fixed_phy_status * status )
673697{
674698 struct bcm_sf2_priv * priv = bcm_sf2_to_priv (ds );
675- u32 duplex , pause ;
699+ u32 duplex , pause , offset ;
676700 u32 reg ;
677701
702+ if (priv -> type == BCM7445_DEVICE_ID )
703+ offset = CORE_STS_OVERRIDE_GMIIP_PORT (port );
704+ else
705+ offset = CORE_STS_OVERRIDE_GMIIP2_PORT (port );
706+
678707 duplex = core_readl (priv , CORE_DUPSTS );
679708 pause = core_readl (priv , CORE_PAUSESTS );
680709
@@ -703,13 +732,13 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
703732 status -> duplex = !!(duplex & (1 << port ));
704733 }
705734
706- reg = core_readl (priv , CORE_STS_OVERRIDE_GMIIP_PORT ( port ) );
735+ reg = core_readl (priv , offset );
707736 reg |= SW_OVERRIDE ;
708737 if (status -> link )
709738 reg |= LINK_STS ;
710739 else
711740 reg &= ~LINK_STS ;
712- core_writel (priv , reg , CORE_STS_OVERRIDE_GMIIP_PORT ( port ) );
741+ core_writel (priv , reg , offset );
713742
714743 if ((pause & (1 << port )) &&
715744 (pause & (1 << (port + PAUSESTS_TX_PAUSE_SHIFT )))) {
@@ -1009,10 +1038,74 @@ static const struct dsa_switch_ops bcm_sf2_ops = {
10091038 .port_fdb_del = b53_fdb_del ,
10101039};
10111040
1041+ struct bcm_sf2_of_data {
1042+ u32 type ;
1043+ const u16 * reg_offsets ;
1044+ unsigned int core_reg_align ;
1045+ };
1046+
1047+ /* Register offsets for the SWITCH_REG_* block */
1048+ static const u16 bcm_sf2_7445_reg_offsets [] = {
1049+ [REG_SWITCH_CNTRL ] = 0x00 ,
1050+ [REG_SWITCH_STATUS ] = 0x04 ,
1051+ [REG_DIR_DATA_WRITE ] = 0x08 ,
1052+ [REG_DIR_DATA_READ ] = 0x0C ,
1053+ [REG_SWITCH_REVISION ] = 0x18 ,
1054+ [REG_PHY_REVISION ] = 0x1C ,
1055+ [REG_SPHY_CNTRL ] = 0x2C ,
1056+ [REG_RGMII_0_CNTRL ] = 0x34 ,
1057+ [REG_RGMII_1_CNTRL ] = 0x40 ,
1058+ [REG_RGMII_2_CNTRL ] = 0x4c ,
1059+ [REG_LED_0_CNTRL ] = 0x90 ,
1060+ [REG_LED_1_CNTRL ] = 0x94 ,
1061+ [REG_LED_2_CNTRL ] = 0x98 ,
1062+ };
1063+
1064+ static const struct bcm_sf2_of_data bcm_sf2_7445_data = {
1065+ .type = BCM7445_DEVICE_ID ,
1066+ .core_reg_align = 0 ,
1067+ .reg_offsets = bcm_sf2_7445_reg_offsets ,
1068+ };
1069+
1070+ static const u16 bcm_sf2_7278_reg_offsets [] = {
1071+ [REG_SWITCH_CNTRL ] = 0x00 ,
1072+ [REG_SWITCH_STATUS ] = 0x04 ,
1073+ [REG_DIR_DATA_WRITE ] = 0x08 ,
1074+ [REG_DIR_DATA_READ ] = 0x0c ,
1075+ [REG_SWITCH_REVISION ] = 0x10 ,
1076+ [REG_PHY_REVISION ] = 0x14 ,
1077+ [REG_SPHY_CNTRL ] = 0x24 ,
1078+ [REG_RGMII_0_CNTRL ] = 0xe0 ,
1079+ [REG_RGMII_1_CNTRL ] = 0xec ,
1080+ [REG_RGMII_2_CNTRL ] = 0xf8 ,
1081+ [REG_LED_0_CNTRL ] = 0x40 ,
1082+ [REG_LED_1_CNTRL ] = 0x4c ,
1083+ [REG_LED_2_CNTRL ] = 0x58 ,
1084+ };
1085+
1086+ static const struct bcm_sf2_of_data bcm_sf2_7278_data = {
1087+ .type = BCM7278_DEVICE_ID ,
1088+ .core_reg_align = 1 ,
1089+ .reg_offsets = bcm_sf2_7278_reg_offsets ,
1090+ };
1091+
1092+ static const struct of_device_id bcm_sf2_of_match [] = {
1093+ { .compatible = "brcm,bcm7445-switch-v4.0" ,
1094+ .data = & bcm_sf2_7445_data
1095+ },
1096+ { .compatible = "brcm,bcm7278-switch-v4.0" ,
1097+ .data = & bcm_sf2_7278_data
1098+ },
1099+ { /* sentinel */ },
1100+ };
1101+ MODULE_DEVICE_TABLE (of , bcm_sf2_of_match );
1102+
10121103static int bcm_sf2_sw_probe (struct platform_device * pdev )
10131104{
10141105 const char * reg_names [BCM_SF2_REGS_NUM ] = BCM_SF2_REGS_NAME ;
10151106 struct device_node * dn = pdev -> dev .of_node ;
1107+ const struct of_device_id * of_id = NULL ;
1108+ const struct bcm_sf2_of_data * data ;
10161109 struct b53_platform_data * pdata ;
10171110 struct dsa_switch_ops * ops ;
10181111 struct bcm_sf2_priv * priv ;
@@ -1040,11 +1133,22 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
10401133 if (!pdata )
10411134 return - ENOMEM ;
10421135
1136+ of_id = of_match_node (bcm_sf2_of_match , dn );
1137+ if (!of_id || !of_id -> data )
1138+ return - EINVAL ;
1139+
1140+ data = of_id -> data ;
1141+
1142+ /* Set SWITCH_REG register offsets and SWITCH_CORE align factor */
1143+ priv -> type = data -> type ;
1144+ priv -> reg_offsets = data -> reg_offsets ;
1145+ priv -> core_reg_align = data -> core_reg_align ;
1146+
10431147 /* Auto-detection using standard registers will not work, so
10441148 * provide an indication of what kind of device we are for
10451149 * b53_common to work with
10461150 */
1047- pdata -> chip_id = BCM7445_DEVICE_ID ;
1151+ pdata -> chip_id = priv -> type ;
10481152 dev -> pdata = pdata ;
10491153
10501154 priv -> dev = dev ;
@@ -1190,11 +1294,6 @@ static int bcm_sf2_resume(struct device *dev)
11901294static SIMPLE_DEV_PM_OPS (bcm_sf2_pm_ops ,
11911295 bcm_sf2_suspend , bcm_sf2_resume ) ;
11921296
1193- static const struct of_device_id bcm_sf2_of_match [] = {
1194- { .compatible = "brcm,bcm7445-switch-v4.0" },
1195- { /* sentinel */ },
1196- };
1197- MODULE_DEVICE_TABLE (of , bcm_sf2_of_match );
11981297
11991298static struct platform_driver bcm_sf2_driver = {
12001299 .probe = bcm_sf2_sw_probe ,
0 commit comments