|
71 | 71 | #define AM65_CPSW_PORT_REG_RX_PRI_MAP 0x020 |
72 | 72 | #define AM65_CPSW_PORT_REG_RX_MAXLEN 0x024 |
73 | 73 |
|
| 74 | +#define AM65_CPSW_PORTN_REG_CTL 0x004 |
| 75 | +#define AM65_CPSW_PORTN_REG_DSCP_MAP 0x120 |
74 | 76 | #define AM65_CPSW_PORTN_REG_SA_L 0x308 |
75 | 77 | #define AM65_CPSW_PORTN_REG_SA_H 0x30c |
76 | 78 | #define AM65_CPSW_PORTN_REG_TS_CTL 0x310 |
|
94 | 96 | /* AM65_CPSW_PORT_REG_PRI_CTL */ |
95 | 97 | #define AM65_CPSW_PORT_REG_PRI_CTL_RX_PTYPE_RROBIN BIT(8) |
96 | 98 |
|
| 99 | +/* AM65_CPSW_PN_REG_CTL */ |
| 100 | +#define AM65_CPSW_PN_REG_CTL_DSCP_IPV4_EN BIT(1) |
| 101 | +#define AM65_CPSW_PN_REG_CTL_DSCP_IPV6_EN BIT(2) |
| 102 | + |
97 | 103 | /* AM65_CPSW_PN_TS_CTL register fields */ |
98 | 104 | #define AM65_CPSW_PN_TS_CTL_TX_ANX_F_EN BIT(4) |
99 | 105 | #define AM65_CPSW_PN_TS_CTL_TX_VLAN_LT1_EN BIT(5) |
@@ -176,6 +182,99 @@ static void am65_cpsw_port_set_sl_mac(struct am65_cpsw_port *slave, |
176 | 182 | writel(mac_lo, slave->port_base + AM65_CPSW_PORTN_REG_SA_L); |
177 | 183 | } |
178 | 184 |
|
| 185 | +#define AM65_CPSW_DSCP_MAX GENMASK(5, 0) |
| 186 | +#define AM65_CPSW_PRI_MAX GENMASK(2, 0) |
| 187 | +#define AM65_CPSW_DSCP_PRI_PER_REG 8 |
| 188 | +#define AM65_CPSW_DSCP_PRI_SIZE 4 /* in bits */ |
| 189 | +static int am65_cpsw_port_set_dscp_map(struct am65_cpsw_port *slave, u8 dscp, u8 pri) |
| 190 | +{ |
| 191 | + int reg_ofs; |
| 192 | + int bit_ofs; |
| 193 | + u32 val; |
| 194 | + |
| 195 | + if (dscp > AM65_CPSW_DSCP_MAX) |
| 196 | + return -EINVAL; |
| 197 | + |
| 198 | + if (pri > AM65_CPSW_PRI_MAX) |
| 199 | + return -EINVAL; |
| 200 | + |
| 201 | + /* 32-bit register offset to this dscp */ |
| 202 | + reg_ofs = (dscp / AM65_CPSW_DSCP_PRI_PER_REG) * 4; |
| 203 | + /* bit field offset to this dscp */ |
| 204 | + bit_ofs = AM65_CPSW_DSCP_PRI_SIZE * (dscp % AM65_CPSW_DSCP_PRI_PER_REG); |
| 205 | + |
| 206 | + val = readl(slave->port_base + AM65_CPSW_PORTN_REG_DSCP_MAP + reg_ofs); |
| 207 | + val &= ~(AM65_CPSW_PRI_MAX << bit_ofs); /* clear */ |
| 208 | + val |= pri << bit_ofs; /* set */ |
| 209 | + writel(val, slave->port_base + AM65_CPSW_PORTN_REG_DSCP_MAP + reg_ofs); |
| 210 | + |
| 211 | + return 0; |
| 212 | +} |
| 213 | + |
| 214 | +static void am65_cpsw_port_enable_dscp_map(struct am65_cpsw_port *slave) |
| 215 | +{ |
| 216 | + int dscp, pri; |
| 217 | + u32 val; |
| 218 | + |
| 219 | + /* Default DSCP to User Priority mapping as per: |
| 220 | + * https://datatracker.ietf.org/doc/html/rfc8325#section-4.3 |
| 221 | + * and |
| 222 | + * https://datatracker.ietf.org/doc/html/rfc8622#section-11 |
| 223 | + */ |
| 224 | + for (dscp = 0; dscp <= AM65_CPSW_DSCP_MAX; dscp++) { |
| 225 | + switch (dscp) { |
| 226 | + case 56: /* CS7 */ |
| 227 | + case 48: /* CS6 */ |
| 228 | + pri = 7; |
| 229 | + break; |
| 230 | + case 46: /* EF */ |
| 231 | + case 44: /* VA */ |
| 232 | + pri = 6; |
| 233 | + break; |
| 234 | + case 40: /* CS5 */ |
| 235 | + pri = 5; |
| 236 | + break; |
| 237 | + case 34: /* AF41 */ |
| 238 | + case 36: /* AF42 */ |
| 239 | + case 38: /* AF43 */ |
| 240 | + case 32: /* CS4 */ |
| 241 | + case 26: /* AF31 */ |
| 242 | + case 28: /* AF32 */ |
| 243 | + case 30: /* AF33 */ |
| 244 | + case 24: /* CS3 */ |
| 245 | + pri = 4; |
| 246 | + break; |
| 247 | + case 18: /* AF21 */ |
| 248 | + case 20: /* AF22 */ |
| 249 | + case 22: /* AF23 */ |
| 250 | + pri = 3; |
| 251 | + break; |
| 252 | + case 16: /* CS2 */ |
| 253 | + case 10: /* AF11 */ |
| 254 | + case 12: /* AF12 */ |
| 255 | + case 14: /* AF13 */ |
| 256 | + case 0: /* DF */ |
| 257 | + pri = 0; |
| 258 | + break; |
| 259 | + case 8: /* CS1 */ |
| 260 | + case 1: /* LE */ |
| 261 | + pri = 1; |
| 262 | + break; |
| 263 | + default: |
| 264 | + pri = 0; |
| 265 | + break; |
| 266 | + } |
| 267 | + |
| 268 | + am65_cpsw_port_set_dscp_map(slave, dscp, pri); |
| 269 | + } |
| 270 | + |
| 271 | + /* enable port IPV4 and IPV6 DSCP for this port */ |
| 272 | + val = readl(slave->port_base + AM65_CPSW_PORTN_REG_CTL); |
| 273 | + val |= AM65_CPSW_PN_REG_CTL_DSCP_IPV4_EN | |
| 274 | + AM65_CPSW_PN_REG_CTL_DSCP_IPV6_EN; |
| 275 | + writel(val, slave->port_base + AM65_CPSW_PORTN_REG_CTL); |
| 276 | +} |
| 277 | + |
179 | 278 | static void am65_cpsw_sl_ctl_reset(struct am65_cpsw_port *port) |
180 | 279 | { |
181 | 280 | cpsw_sl_reset(port->slave.mac_sl, 100); |
@@ -916,6 +1015,7 @@ static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev) |
916 | 1015 | common->usage_count++; |
917 | 1016 |
|
918 | 1017 | am65_cpsw_port_set_sl_mac(port, ndev->dev_addr); |
| 1018 | + am65_cpsw_port_enable_dscp_map(port); |
919 | 1019 |
|
920 | 1020 | if (common->is_emac_mode) |
921 | 1021 | am65_cpsw_init_port_emac_ale(port); |
|
0 commit comments