@@ -1163,6 +1163,181 @@ static void dwxgmac2_enable_vlan(struct mac_device_info *hw, u32 type)
11631163 writel (value , ioaddr + XGMAC_VLAN_INCL );
11641164}
11651165
1166+ static int dwxgmac2_filter_wait (struct mac_device_info * hw )
1167+ {
1168+ void __iomem * ioaddr = hw -> pcsr ;
1169+ u32 value ;
1170+
1171+ if (readl_poll_timeout (ioaddr + XGMAC_L3L4_ADDR_CTRL , value ,
1172+ !(value & XGMAC_XB ), 100 , 10000 ))
1173+ return - EBUSY ;
1174+ return 0 ;
1175+ }
1176+
1177+ static int dwxgmac2_filter_read (struct mac_device_info * hw , u32 filter_no ,
1178+ u8 reg , u32 * data )
1179+ {
1180+ void __iomem * ioaddr = hw -> pcsr ;
1181+ u32 value ;
1182+ int ret ;
1183+
1184+ ret = dwxgmac2_filter_wait (hw );
1185+ if (ret )
1186+ return ret ;
1187+
1188+ value = ((filter_no << XGMAC_IDDR_FNUM ) | reg ) << XGMAC_IDDR_SHIFT ;
1189+ value |= XGMAC_TT | XGMAC_XB ;
1190+ writel (value , ioaddr + XGMAC_L3L4_ADDR_CTRL );
1191+
1192+ ret = dwxgmac2_filter_wait (hw );
1193+ if (ret )
1194+ return ret ;
1195+
1196+ * data = readl (ioaddr + XGMAC_L3L4_DATA );
1197+ return 0 ;
1198+ }
1199+
1200+ static int dwxgmac2_filter_write (struct mac_device_info * hw , u32 filter_no ,
1201+ u8 reg , u32 data )
1202+ {
1203+ void __iomem * ioaddr = hw -> pcsr ;
1204+ u32 value ;
1205+ int ret ;
1206+
1207+ ret = dwxgmac2_filter_wait (hw );
1208+ if (ret )
1209+ return ret ;
1210+
1211+ writel (data , ioaddr + XGMAC_L3L4_DATA );
1212+
1213+ value = ((filter_no << XGMAC_IDDR_FNUM ) | reg ) << XGMAC_IDDR_SHIFT ;
1214+ value |= XGMAC_XB ;
1215+ writel (value , ioaddr + XGMAC_L3L4_ADDR_CTRL );
1216+
1217+ return dwxgmac2_filter_wait (hw );
1218+ }
1219+
1220+ static int dwxgmac2_config_l3_filter (struct mac_device_info * hw , u32 filter_no ,
1221+ bool en , bool ipv6 , bool sa , bool inv ,
1222+ u32 match )
1223+ {
1224+ void __iomem * ioaddr = hw -> pcsr ;
1225+ u32 value ;
1226+ int ret ;
1227+
1228+ value = readl (ioaddr + XGMAC_PACKET_FILTER );
1229+ value |= XGMAC_FILTER_IPFE ;
1230+ writel (value , ioaddr + XGMAC_PACKET_FILTER );
1231+
1232+ ret = dwxgmac2_filter_read (hw , filter_no , XGMAC_L3L4_CTRL , & value );
1233+ if (ret )
1234+ return ret ;
1235+
1236+ /* For IPv6 not both SA/DA filters can be active */
1237+ if (ipv6 ) {
1238+ value |= XGMAC_L3PEN0 ;
1239+ value &= ~(XGMAC_L3SAM0 | XGMAC_L3SAIM0 );
1240+ value &= ~(XGMAC_L3DAM0 | XGMAC_L3DAIM0 );
1241+ if (sa ) {
1242+ value |= XGMAC_L3SAM0 ;
1243+ if (inv )
1244+ value |= XGMAC_L3SAIM0 ;
1245+ } else {
1246+ value |= XGMAC_L3DAM0 ;
1247+ if (inv )
1248+ value |= XGMAC_L3DAIM0 ;
1249+ }
1250+ } else {
1251+ value &= ~XGMAC_L3PEN0 ;
1252+ if (sa ) {
1253+ value |= XGMAC_L3SAM0 ;
1254+ if (inv )
1255+ value |= XGMAC_L3SAIM0 ;
1256+ } else {
1257+ value |= XGMAC_L3DAM0 ;
1258+ if (inv )
1259+ value |= XGMAC_L3DAIM0 ;
1260+ }
1261+ }
1262+
1263+ ret = dwxgmac2_filter_write (hw , filter_no , XGMAC_L3L4_CTRL , value );
1264+ if (ret )
1265+ return ret ;
1266+
1267+ if (sa ) {
1268+ ret = dwxgmac2_filter_write (hw , filter_no , XGMAC_L3_ADDR0 , match );
1269+ if (ret )
1270+ return ret ;
1271+ } else {
1272+ ret = dwxgmac2_filter_write (hw , filter_no , XGMAC_L3_ADDR1 , match );
1273+ if (ret )
1274+ return ret ;
1275+ }
1276+
1277+ if (!en )
1278+ return dwxgmac2_filter_write (hw , filter_no , XGMAC_L3L4_CTRL , 0 );
1279+
1280+ return 0 ;
1281+ }
1282+
1283+ static int dwxgmac2_config_l4_filter (struct mac_device_info * hw , u32 filter_no ,
1284+ bool en , bool udp , bool sa , bool inv ,
1285+ u32 match )
1286+ {
1287+ void __iomem * ioaddr = hw -> pcsr ;
1288+ u32 value ;
1289+ int ret ;
1290+
1291+ value = readl (ioaddr + XGMAC_PACKET_FILTER );
1292+ value |= XGMAC_FILTER_IPFE ;
1293+ writel (value , ioaddr + XGMAC_PACKET_FILTER );
1294+
1295+ ret = dwxgmac2_filter_read (hw , filter_no , XGMAC_L3L4_CTRL , & value );
1296+ if (ret )
1297+ return ret ;
1298+
1299+ if (udp ) {
1300+ value |= XGMAC_L4PEN0 ;
1301+ } else {
1302+ value &= ~XGMAC_L4PEN0 ;
1303+ }
1304+
1305+ value &= ~(XGMAC_L4SPM0 | XGMAC_L4SPIM0 );
1306+ value &= ~(XGMAC_L4DPM0 | XGMAC_L4DPIM0 );
1307+ if (sa ) {
1308+ value |= XGMAC_L4SPM0 ;
1309+ if (inv )
1310+ value |= XGMAC_L4SPIM0 ;
1311+ } else {
1312+ value |= XGMAC_L4DPM0 ;
1313+ if (inv )
1314+ value |= XGMAC_L4DPIM0 ;
1315+ }
1316+
1317+ ret = dwxgmac2_filter_write (hw , filter_no , XGMAC_L3L4_CTRL , value );
1318+ if (ret )
1319+ return ret ;
1320+
1321+ if (sa ) {
1322+ value = match & XGMAC_L4SP0 ;
1323+
1324+ ret = dwxgmac2_filter_write (hw , filter_no , XGMAC_L4_ADDR , value );
1325+ if (ret )
1326+ return ret ;
1327+ } else {
1328+ value = (match << XGMAC_L4DP0_SHIFT ) & XGMAC_L4DP0 ;
1329+
1330+ ret = dwxgmac2_filter_write (hw , filter_no , XGMAC_L4_ADDR , value );
1331+ if (ret )
1332+ return ret ;
1333+ }
1334+
1335+ if (!en )
1336+ return dwxgmac2_filter_write (hw , filter_no , XGMAC_L3L4_CTRL , 0 );
1337+
1338+ return 0 ;
1339+ }
1340+
11661341const struct stmmac_ops dwxgmac210_ops = {
11671342 .core_init = dwxgmac2_core_init ,
11681343 .set_mac = dwxgmac2_set_mac ,
@@ -1203,6 +1378,8 @@ const struct stmmac_ops dwxgmac210_ops = {
12031378 .flex_pps_config = dwxgmac2_flex_pps_config ,
12041379 .sarc_configure = dwxgmac2_sarc_configure ,
12051380 .enable_vlan = dwxgmac2_enable_vlan ,
1381+ .config_l3_filter = dwxgmac2_config_l3_filter ,
1382+ .config_l4_filter = dwxgmac2_config_l4_filter ,
12061383};
12071384
12081385int dwxgmac2_setup (struct stmmac_priv * priv )
0 commit comments