@@ -61,30 +61,10 @@ static void bcm_sf2_imp_vlan_setup(struct dsa_switch *ds, int cpu_port)
61
61
}
62
62
}
63
63
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 )
65
65
{
66
- struct bcm_sf2_priv * priv = bcm_sf2_to_priv (ds );
67
66
u32 reg , val ;
68
67
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
-
88
68
/* Resolve which bit controls the Broadcom tag */
89
69
switch (port ) {
90
70
case 8 :
@@ -119,11 +99,43 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
119
99
reg = core_readl (priv , CORE_BRCM_HDR_TX_DIS );
120
100
reg &= ~(1 << port );
121
101
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 );
122
134
123
135
/* Force link status for IMP port */
124
- reg = core_readl (priv , CORE_STS_OVERRIDE_IMP );
136
+ reg = core_readl (priv , offset );
125
137
reg |= (MII_SW_OR | LINK_STS );
126
- core_writel (priv , reg , CORE_STS_OVERRIDE_IMP );
138
+ core_writel (priv , reg , offset );
127
139
}
128
140
129
141
static 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,
224
236
reg &= ~P_TXQ_PSM_VDD (port );
225
237
core_writel (priv , reg , CORE_MEM_PSM_VDD_CTRL );
226
238
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
+
227
243
/* Clear the Rx and Tx disable bits and set to no spanning tree */
228
244
core_writel (priv , 0 , CORE_G_PCTL_PORT (port ));
229
245
@@ -503,6 +519,9 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv *priv,
503
519
504
520
if (mode == PHY_INTERFACE_MODE_MOCA )
505
521
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 ;
506
525
}
507
526
}
508
527
@@ -591,7 +610,12 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
591
610
struct ethtool_eee * p = & priv -> port_sts [port ].eee ;
592
611
u32 id_mode_dis = 0 , port_mode ;
593
612
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 );
595
619
596
620
switch (phydev -> interface ) {
597
621
case PHY_INTERFACE_MODE_RGMII :
@@ -662,7 +686,7 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
662
686
if (phydev -> duplex == DUPLEX_FULL )
663
687
reg |= DUPLX_MODE ;
664
688
665
- core_writel (priv , reg , CORE_STS_OVERRIDE_GMIIP_PORT ( port ) );
689
+ core_writel (priv , reg , offset );
666
690
667
691
if (!phydev -> is_pseudo_fixed_link )
668
692
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,
672
696
struct fixed_phy_status * status )
673
697
{
674
698
struct bcm_sf2_priv * priv = bcm_sf2_to_priv (ds );
675
- u32 duplex , pause ;
699
+ u32 duplex , pause , offset ;
676
700
u32 reg ;
677
701
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
+
678
707
duplex = core_readl (priv , CORE_DUPSTS );
679
708
pause = core_readl (priv , CORE_PAUSESTS );
680
709
@@ -703,13 +732,13 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
703
732
status -> duplex = !!(duplex & (1 << port ));
704
733
}
705
734
706
- reg = core_readl (priv , CORE_STS_OVERRIDE_GMIIP_PORT ( port ) );
735
+ reg = core_readl (priv , offset );
707
736
reg |= SW_OVERRIDE ;
708
737
if (status -> link )
709
738
reg |= LINK_STS ;
710
739
else
711
740
reg &= ~LINK_STS ;
712
- core_writel (priv , reg , CORE_STS_OVERRIDE_GMIIP_PORT ( port ) );
741
+ core_writel (priv , reg , offset );
713
742
714
743
if ((pause & (1 << port )) &&
715
744
(pause & (1 << (port + PAUSESTS_TX_PAUSE_SHIFT )))) {
@@ -1009,10 +1038,74 @@ static const struct dsa_switch_ops bcm_sf2_ops = {
1009
1038
.port_fdb_del = b53_fdb_del ,
1010
1039
};
1011
1040
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
+
1012
1103
static int bcm_sf2_sw_probe (struct platform_device * pdev )
1013
1104
{
1014
1105
const char * reg_names [BCM_SF2_REGS_NUM ] = BCM_SF2_REGS_NAME ;
1015
1106
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 ;
1016
1109
struct b53_platform_data * pdata ;
1017
1110
struct dsa_switch_ops * ops ;
1018
1111
struct bcm_sf2_priv * priv ;
@@ -1040,11 +1133,22 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
1040
1133
if (!pdata )
1041
1134
return - ENOMEM ;
1042
1135
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
+
1043
1147
/* Auto-detection using standard registers will not work, so
1044
1148
* provide an indication of what kind of device we are for
1045
1149
* b53_common to work with
1046
1150
*/
1047
- pdata -> chip_id = BCM7445_DEVICE_ID ;
1151
+ pdata -> chip_id = priv -> type ;
1048
1152
dev -> pdata = pdata ;
1049
1153
1050
1154
priv -> dev = dev ;
@@ -1190,11 +1294,6 @@ static int bcm_sf2_resume(struct device *dev)
1190
1294
static SIMPLE_DEV_PM_OPS (bcm_sf2_pm_ops ,
1191
1295
bcm_sf2_suspend , bcm_sf2_resume ) ;
1192
1296
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 );
1198
1297
1199
1298
static struct platform_driver bcm_sf2_driver = {
1200
1299
.probe = bcm_sf2_sw_probe ,
0 commit comments