From ef0a731882a2bf120511072a08d973f65d00d979 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 3 Dec 2016 04:35:16 +0100 Subject: net: dsa: mv88e6xxx: Implement mv88e6390 tag remap The mv88e6390 does not have the two registers to set the frame priority map. Instead it has an indirection registers for setting a number of different priority maps. Refactor the old code into an function, implement the mv88e6390 version, and use an op to call the right one. Signed-off-by: Andrew Lunn Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 37 ++++++++++++-------- drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 12 +++++++ drivers/net/dsa/mv88e6xxx/port.c | 63 +++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 4 files changed, 101 insertions(+), 13 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index ce2f7ff8066e..ff4bd2f74357 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2617,20 +2617,10 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) if (err) return err; } + } - /* Tag Remap: use an identity 802.1p prio -> switch - * prio mapping. - */ - err = mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_0123, - 0x3210); - if (err) - return err; - - /* Tag Remap 2: use an identity 802.1p prio -> switch - * prio mapping. - */ - err = mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_4567, - 0x7654); + if (chip->info->ops->port_tag_remap) { + err = chip->info->ops->port_tag_remap(chip, port); if (err) return err; } @@ -3189,6 +3179,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3217,6 +3208,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = { .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3245,6 +3237,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3259,6 +3252,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3288,6 +3282,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6185_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3305,6 +3300,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6352_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3320,6 +3316,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6185_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3337,6 +3334,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6352_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3366,6 +3364,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390_port_set_speed, + .port_tag_remap = mv88e6390_port_tag_remap, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3382,6 +3381,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390x_port_set_speed, + .port_tag_remap = mv88e6390_port_tag_remap, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3398,6 +3398,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390_port_set_speed, + .port_tag_remap = mv88e6390_port_tag_remap, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3416,6 +3417,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6352_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3431,6 +3433,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390_port_set_speed, + .port_tag_remap = mv88e6390_port_tag_remap, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3448,6 +3451,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6320_stats_get_sset_count, .stats_get_strings = mv88e6320_stats_get_strings, @@ -3464,6 +3468,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6320_stats_get_sset_count, .stats_get_strings = mv88e6320_stats_get_strings, @@ -3479,6 +3484,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6185_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3494,6 +3500,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6185_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3511,6 +3518,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6352_port_set_speed, + .port_tag_remap = mv88e6095_port_tag_remap, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3526,6 +3534,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390_port_set_speed, + .port_tag_remap = mv88e6390_port_tag_remap, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3542,6 +3551,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390x_port_set_speed, + .port_tag_remap = mv88e6390_port_tag_remap, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3558,6 +3568,7 @@ static const struct mv88e6xxx_ops mv88e6391_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390_port_set_speed, + .port_tag_remap = mv88e6390_port_tag_remap, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h index ab52c3772c78..a6e9dba665c1 100644 --- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h @@ -172,6 +172,16 @@ #define PORT_OUT_FILTERED 0x13 #define PORT_TAG_REGMAP_0123 0x18 #define PORT_TAG_REGMAP_4567 0x19 +#define PORT_IEEE_PRIO_MAP_TABLE 0x18 /* 6390 */ +#define PORT_IEEE_PRIO_MAP_TABLE_UPDATE BIT(15) +#define PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP (0x0 << 12) +#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP (0x1 << 12) +#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP (0x2 << 12) +#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP (0x3 << 12) +#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_DSCP (0x5 << 12) +#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_DSCP (0x6 << 12) +#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_DSCP (0x7 << 12) +#define PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT 9 #define GLOBAL_STATUS 0x00 #define GLOBAL_STATUS_PPU_STATE BIT(15) /* 6351 and 6171 */ @@ -800,6 +810,8 @@ struct mv88e6xxx_ops { */ int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed); + int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port); + /* Snapshot the statistics for a port. The statistics can then * be read back a leisure but still with a consistent view. */ diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index af4772d86086..3d03ea3a2c0d 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -496,3 +496,66 @@ int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, return 0; } + +/* Offset 0x18: Port IEEE Priority Remapping Registers [0-3] + * Offset 0x19: Port IEEE Priority Remapping Registers [4-7] + */ + +int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port) +{ + int err; + + /* Use a direct priority mapping for all IEEE tagged frames */ + err = mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_0123, 0x3210); + if (err) + return err; + + return mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_4567, 0x7654); +} + +static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip, + int port, u16 table, + u8 pointer, u16 data) +{ + u16 reg; + + reg = PORT_IEEE_PRIO_MAP_TABLE_UPDATE | + table | + (pointer << PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT) | + data; + + return mv88e6xxx_port_write(chip, port, PORT_IEEE_PRIO_MAP_TABLE, reg); +} + +int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port) +{ + int err, i; + + for (i = 0; i <= 7; i++) { + err = mv88e6xxx_port_ieeepmt_write( + chip, port, PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP, + i, (i | i << 4)); + if (err) + return err; + + err = mv88e6xxx_port_ieeepmt_write( + chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP, + i, i); + if (err) + return err; + + err = mv88e6xxx_port_ieeepmt_write( + chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP, + i, i); + if (err) + return err; + + err = mv88e6xxx_port_ieeepmt_write( + chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP, + i, i); + if (err) + return err; + } + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 499129c1489c..5fab4606662b 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -48,5 +48,7 @@ int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid); int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, u16 mode); +int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port); +int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port); #endif /* _MV88E6XXX_PORT_H */ -- cgit v1.2.3-70-g09d2 From 33641994a676f43f59d5fe02916c3965983522c2 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 3 Dec 2016 04:35:17 +0100 Subject: net: dsa: mv88e6xxx: Monitor and Management tables The mv88e6390 changes the monitor control register into the Monitor and Management control, which is an indirection register to various registers. Add ops to set the CPU port and the ingress/egress port for both register layouts, to global1 Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 68 +++++++++++++++++++++++++++++----- drivers/net/dsa/mv88e6xxx/global1.c | 69 +++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/global1.h | 4 ++ drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 13 +++++++ 4 files changed, 145 insertions(+), 9 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index ff4bd2f74357..6e981bedd028 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2747,15 +2747,17 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip) if (err) return err; - /* Configure the upstream port, and configure it as the port to which - * ingress and egress and ARP monitor frames are to be sent. - */ - reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT | - upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT | - upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT; - err = mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg); - if (err) - return err; + if (chip->info->ops->g1_set_cpu_port) { + err = chip->info->ops->g1_set_cpu_port(chip, upstream_port); + if (err) + return err; + } + + if (chip->info->ops->g1_set_egress_port) { + err = chip->info->ops->g1_set_egress_port(chip, upstream_port); + if (err) + return err; + } /* Disable remote management, and set the switch's DSA device number. */ err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, @@ -3184,6 +3186,8 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6095_ops = { @@ -3213,6 +3217,8 @@ static const struct mv88e6xxx_ops mv88e6097_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6123_ops = { @@ -3227,6 +3233,8 @@ static const struct mv88e6xxx_ops mv88e6123_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6131_ops = { @@ -3242,6 +3250,8 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6161_ops = { @@ -3257,6 +3267,8 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6165_ops = { @@ -3271,6 +3283,8 @@ static const struct mv88e6xxx_ops mv88e6165_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6171_ops = { @@ -3287,6 +3301,8 @@ static const struct mv88e6xxx_ops mv88e6171_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6172_ops = { @@ -3305,6 +3321,8 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6175_ops = { @@ -3321,6 +3339,8 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6176_ops = { @@ -3339,6 +3359,8 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6185_ops = { @@ -3353,6 +3375,8 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6190_ops = { @@ -3370,6 +3394,8 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { .stats_get_sset_count = mv88e6320_stats_get_sset_count, .stats_get_strings = mv88e6320_stats_get_strings, .stats_get_stats = mv88e6390_stats_get_stats, + .g1_set_cpu_port = mv88e6390_g1_set_cpu_port, + .g1_set_egress_port = mv88e6390_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6190x_ops = { @@ -3387,6 +3413,8 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { .stats_get_sset_count = mv88e6320_stats_get_sset_count, .stats_get_strings = mv88e6320_stats_get_strings, .stats_get_stats = mv88e6390_stats_get_stats, + .g1_set_cpu_port = mv88e6390_g1_set_cpu_port, + .g1_set_egress_port = mv88e6390_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6191_ops = { @@ -3404,6 +3432,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { .stats_get_sset_count = mv88e6320_stats_get_sset_count, .stats_get_strings = mv88e6320_stats_get_strings, .stats_get_stats = mv88e6390_stats_get_stats, + .g1_set_cpu_port = mv88e6390_g1_set_cpu_port, + .g1_set_egress_port = mv88e6390_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6240_ops = { @@ -3422,6 +3452,8 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6290_ops = { @@ -3439,6 +3471,8 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { .stats_get_sset_count = mv88e6320_stats_get_sset_count, .stats_get_strings = mv88e6320_stats_get_strings, .stats_get_stats = mv88e6390_stats_get_stats, + .g1_set_cpu_port = mv88e6390_g1_set_cpu_port, + .g1_set_egress_port = mv88e6390_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6320_ops = { @@ -3456,6 +3490,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .stats_get_sset_count = mv88e6320_stats_get_sset_count, .stats_get_strings = mv88e6320_stats_get_strings, .stats_get_stats = mv88e6320_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6321_ops = { @@ -3473,6 +3509,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .stats_get_sset_count = mv88e6320_stats_get_sset_count, .stats_get_strings = mv88e6320_stats_get_strings, .stats_get_stats = mv88e6320_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6350_ops = { @@ -3489,6 +3527,8 @@ static const struct mv88e6xxx_ops mv88e6350_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6351_ops = { @@ -3505,6 +3545,8 @@ static const struct mv88e6xxx_ops mv88e6351_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6352_ops = { @@ -3523,6 +3565,8 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, .stats_get_stats = mv88e6095_stats_get_stats, + .g1_set_cpu_port = mv88e6095_g1_set_cpu_port, + .g1_set_egress_port = mv88e6095_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6390_ops = { @@ -3540,6 +3584,8 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { .stats_get_sset_count = mv88e6320_stats_get_sset_count, .stats_get_strings = mv88e6320_stats_get_strings, .stats_get_stats = mv88e6390_stats_get_stats, + .g1_set_cpu_port = mv88e6390_g1_set_cpu_port, + .g1_set_egress_port = mv88e6390_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6390x_ops = { @@ -3557,6 +3603,8 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { .stats_get_sset_count = mv88e6320_stats_get_sset_count, .stats_get_strings = mv88e6320_stats_get_strings, .stats_get_stats = mv88e6390_stats_get_stats, + .g1_set_cpu_port = mv88e6390_g1_set_cpu_port, + .g1_set_egress_port = mv88e6390_g1_set_egress_port, }; static const struct mv88e6xxx_ops mv88e6391_ops = { @@ -3574,6 +3622,8 @@ static const struct mv88e6xxx_ops mv88e6391_ops = { .stats_get_sset_count = mv88e6320_stats_get_sset_count, .stats_get_strings = mv88e6320_stats_get_strings, .stats_get_stats = mv88e6390_stats_get_stats, + .g1_set_cpu_port = mv88e6390_g1_set_cpu_port, + .g1_set_egress_port = mv88e6390_g1_set_egress_port, }; static const struct mv88e6xxx_info mv88e6xxx_table[] = { diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index 5fcf23dbf04b..688547026e15 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -33,6 +33,75 @@ int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask) return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask); } +/* Offset 0x1a: Monitor Control */ +/* Offset 0x1a: Monitor & MGMT Control on some devices */ + +int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port) +{ + u16 reg; + int err; + + err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, ®); + if (err) + return err; + + reg &= ~(GLOBAL_MONITOR_CONTROL_INGRESS_MASK | + GLOBAL_MONITOR_CONTROL_EGRESS_MASK); + + reg |= port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT | + port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT; + + return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg); +} + +/* Older generations also call this the ARP destination. It has been + * generalized in more modern devices such that more than ARP can + * egress it + */ +int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port) +{ + u16 reg; + int err; + + err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, ®); + if (err) + return err; + + reg &= ~GLOBAL_MONITOR_CONTROL_ARP_MASK; + reg |= port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT; + + return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg); +} + +static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip, + u16 pointer, u8 data) +{ + u16 reg; + + reg = GLOBAL_MONITOR_CONTROL_UPDATE | pointer | data; + + return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg); +} + +int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port) +{ + int err; + + err = mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_INGRESS, + port); + if (err) + return err; + + return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_EGRESS, + port); +} + +int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port) +{ + return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_CPU_DEST, + port); +} + /* Offset 0x1c: Global Control 2 */ int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip) diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h index df3794cdbfb9..0c979550052f 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -25,5 +25,9 @@ int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port); int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port); int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip); void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val); +int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port); +int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port); +int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); +int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); #endif /* _MV88E6XXX_GLOBAL1_H */ diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h index a6e9dba665c1..a6dd192652e8 100644 --- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h @@ -287,10 +287,21 @@ #define GLOBAL_CORE_TAG_TYPE 0x19 #define GLOBAL_MONITOR_CONTROL 0x1a #define GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT 12 +#define GLOBAL_MONITOR_CONTROL_INGRESS_MASK (0xf << 12) #define GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT 8 +#define GLOBAL_MONITOR_CONTROL_EGRESS_MASK (0xf << 8) #define GLOBAL_MONITOR_CONTROL_ARP_SHIFT 4 +#define GLOBAL_MONITOR_CONTROL_ARP_MASK (0xf << 4) #define GLOBAL_MONITOR_CONTROL_MIRROR_SHIFT 0 #define GLOBAL_MONITOR_CONTROL_ARP_DISABLED (0xf0) +#define GLOBAL_MONITOR_CONTROL_UPDATE BIT(15) +#define GLOBAL_MONITOR_CONTROL_0180C280000000XLO (0x00 << 8) +#define GLOBAL_MONITOR_CONTROL_0180C280000000XHI (0x01 << 8) +#define GLOBAL_MONITOR_CONTROL_0180C280000002XLO (0x02 << 8) +#define GLOBAL_MONITOR_CONTROL_0180C280000002XHI (0x03 << 8) +#define GLOBAL_MONITOR_CONTROL_INGRESS (0x20 << 8) +#define GLOBAL_MONITOR_CONTROL_EGRESS (0x21 << 8) +#define GLOBAL_MONITOR_CONTROL_CPU_DEST (0x30 << 8) #define GLOBAL_CONTROL_2 0x1c #define GLOBAL_CONTROL_2_NO_CASCADE 0xe000 #define GLOBAL_CONTROL_2_MULTIPLE_CASCADE 0xf000 @@ -827,6 +838,8 @@ struct mv88e6xxx_ops { void (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data); void (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port, uint64_t *data); + int (*g1_set_cpu_port)(struct mv88e6xxx_chip *chip, int port); + int (*g1_set_egress_port)(struct mv88e6xxx_chip *chip, int port); }; #define STATS_TYPE_PORT BIT(0) -- cgit v1.2.3-70-g09d2 From 443d5a1b7d2a8727a7e7d7836a784a5decd34dc0 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 3 Dec 2016 04:35:18 +0100 Subject: net: dsa: mv88e6xxx: Move the tagging protocol into info Older chips support a single tagging protocol, DSA. New chips support both DSA and EDSA, an enhanced version. Having both as an option changes the register layouts. Up until now, it has been assumed that if EDSA is supported, it will be used. Hence the register layout has been determined by which protocol should be used. However, mv88e6390 has a different implementation of EDSA, which requires we need to use the DSA tagging. Hence separate the selection of the protocol from the register layout. Signed-off-by: Andrew Lunn Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 33 +++++++++++++++++++++++++++------ drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 17 ++++------------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 6e981bedd028..80efee6f5e16 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2482,7 +2482,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) PORT_CONTROL_USE_TAG | PORT_CONTROL_USE_IP | PORT_CONTROL_STATE_FORWARDING; if (dsa_is_cpu_port(ds, port)) { - if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_EDSA)) + if (chip->info->tag_protocol == DSA_TAG_PROTO_EDSA) reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA | PORT_CONTROL_FORWARD_UNKNOWN_MC; else @@ -2611,7 +2611,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) /* Port Ethertype: use the Ethertype DSA Ethertype * value. */ - if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_EDSA)) { + if (chip->info->tag_protocol == DSA_TAG_PROTO_EDSA) { err = mv88e6xxx_port_write(chip, port, PORT_ETH_TYPE, ETH_P_EDSA); if (err) @@ -3637,6 +3637,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 8, + .tag_protocol = DSA_TAG_PROTO_DSA, .flags = MV88E6XXX_FLAGS_FAMILY_6097, .ops = &mv88e6085_ops, }, @@ -3651,6 +3652,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 8, + .tag_protocol = DSA_TAG_PROTO_DSA, .flags = MV88E6XXX_FLAGS_FAMILY_6095, .ops = &mv88e6095_ops, }, @@ -3679,6 +3681,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_DSA, .flags = MV88E6XXX_FLAGS_FAMILY_6165, .ops = &mv88e6123_ops, }, @@ -3693,6 +3696,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_DSA, .flags = MV88E6XXX_FLAGS_FAMILY_6185, .ops = &mv88e6131_ops, }, @@ -3707,6 +3711,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_DSA, .flags = MV88E6XXX_FLAGS_FAMILY_6165, .ops = &mv88e6161_ops, }, @@ -3721,6 +3726,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_DSA, .flags = MV88E6XXX_FLAGS_FAMILY_6165, .ops = &mv88e6165_ops, }, @@ -3735,6 +3741,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_EDSA, .flags = MV88E6XXX_FLAGS_FAMILY_6351, .ops = &mv88e6171_ops, }, @@ -3749,6 +3756,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_EDSA, .flags = MV88E6XXX_FLAGS_FAMILY_6352, .ops = &mv88e6172_ops, }, @@ -3763,6 +3771,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_EDSA, .flags = MV88E6XXX_FLAGS_FAMILY_6351, .ops = &mv88e6175_ops, }, @@ -3777,6 +3786,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_EDSA, .flags = MV88E6XXX_FLAGS_FAMILY_6352, .ops = &mv88e6176_ops, }, @@ -3791,6 +3801,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 8, + .tag_protocol = DSA_TAG_PROTO_EDSA, .flags = MV88E6XXX_FLAGS_FAMILY_6185, .ops = &mv88e6185_ops, }, @@ -3803,6 +3814,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_ports = 11, /* 10 + Z80 */ .port_base_addr = 0x0, .global1_addr = 0x1b, + .tag_protocol = DSA_TAG_PROTO_DSA, .age_time_coeff = 15000, .g1_irqs = 9, .flags = MV88E6XXX_FLAGS_FAMILY_6390, @@ -3819,6 +3831,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_DSA, .flags = MV88E6XXX_FLAGS_FAMILY_6390, .ops = &mv88e6190x_ops, }, @@ -3832,6 +3845,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .port_base_addr = 0x0, .global1_addr = 0x1b, .age_time_coeff = 15000, + .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_DSA, .flags = MV88E6XXX_FLAGS_FAMILY_6390, .ops = &mv88e6391_ops, }, @@ -3846,6 +3861,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_EDSA, .flags = MV88E6XXX_FLAGS_FAMILY_6352, .ops = &mv88e6240_ops, }, @@ -3860,6 +3876,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_DSA, .flags = MV88E6XXX_FLAGS_FAMILY_6390, .ops = &mv88e6290_ops, }, @@ -3874,6 +3891,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 8, + .tag_protocol = DSA_TAG_PROTO_EDSA, .flags = MV88E6XXX_FLAGS_FAMILY_6320, .ops = &mv88e6320_ops, }, @@ -3888,6 +3906,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 8, + .tag_protocol = DSA_TAG_PROTO_EDSA, .flags = MV88E6XXX_FLAGS_FAMILY_6320, .ops = &mv88e6321_ops, }, @@ -3902,6 +3921,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_EDSA, .flags = MV88E6XXX_FLAGS_FAMILY_6351, .ops = &mv88e6350_ops, }, @@ -3916,6 +3936,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_EDSA, .flags = MV88E6XXX_FLAGS_FAMILY_6351, .ops = &mv88e6351_ops, }, @@ -3930,6 +3951,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_EDSA, .flags = MV88E6XXX_FLAGS_FAMILY_6352, .ops = &mv88e6352_ops, }, @@ -3943,6 +3965,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_DSA, .flags = MV88E6XXX_FLAGS_FAMILY_6390, .ops = &mv88e6390_ops, }, @@ -3956,6 +3979,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .age_time_coeff = 15000, .g1_irqs = 9, + .tag_protocol = DSA_TAG_PROTO_DSA, .flags = MV88E6XXX_FLAGS_FAMILY_6390, .ops = &mv88e6390x_ops, }, @@ -4056,10 +4080,7 @@ static enum dsa_tag_protocol mv88e6xxx_get_tag_protocol(struct dsa_switch *ds) { struct mv88e6xxx_chip *chip = ds->priv; - if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_EDSA)) - return DSA_TAG_PROTO_EDSA; - - return DSA_TAG_PROTO_DSA; + return chip->info->tag_protocol; } static const char *mv88e6xxx_drv_probe(struct device *dsa_dev, diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h index a6dd192652e8..2c51e3a8a890 100644 --- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h @@ -438,12 +438,6 @@ enum mv88e6xxx_family { }; enum mv88e6xxx_cap { - /* Two different tag protocols can be used by the driver. All - * switches support DSA, but only later generations support - * EDSA. - */ - MV88E6XXX_CAP_EDSA, - /* Energy Efficient Ethernet. */ MV88E6XXX_CAP_EEE, @@ -506,7 +500,6 @@ enum mv88e6xxx_cap { }; /* Bitmask of capabilities */ -#define MV88E6XXX_FLAG_EDSA BIT_ULL(MV88E6XXX_CAP_EDSA) #define MV88E6XXX_FLAG_EEE BIT_ULL(MV88E6XXX_CAP_EEE) #define MV88E6XXX_FLAG_SMI_CMD BIT_ULL(MV88E6XXX_CAP_SMI_CMD) @@ -601,8 +594,7 @@ enum mv88e6xxx_cap { MV88E6XXX_FLAG_VTU) #define MV88E6XXX_FLAGS_FAMILY_6320 \ - (MV88E6XXX_FLAG_EDSA | \ - MV88E6XXX_FLAG_EEE | \ + (MV88E6XXX_FLAG_EEE | \ MV88E6XXX_FLAG_GLOBAL2 | \ MV88E6XXX_FLAG_G2_MGMT_EN_2X | \ MV88E6XXX_FLAG_G2_MGMT_EN_0X | \ @@ -616,8 +608,7 @@ enum mv88e6xxx_cap { MV88E6XXX_FLAGS_PVT) #define MV88E6XXX_FLAGS_FAMILY_6351 \ - (MV88E6XXX_FLAG_EDSA | \ - MV88E6XXX_FLAG_G1_ATU_FID | \ + (MV88E6XXX_FLAG_G1_ATU_FID | \ MV88E6XXX_FLAG_G1_VTU_FID | \ MV88E6XXX_FLAG_GLOBAL2 | \ MV88E6XXX_FLAG_G2_INT | \ @@ -633,8 +624,7 @@ enum mv88e6xxx_cap { MV88E6XXX_FLAGS_PVT) #define MV88E6XXX_FLAGS_FAMILY_6352 \ - (MV88E6XXX_FLAG_EDSA | \ - MV88E6XXX_FLAG_EEE | \ + (MV88E6XXX_FLAG_EEE | \ MV88E6XXX_FLAG_G1_ATU_FID | \ MV88E6XXX_FLAG_G1_VTU_FID | \ MV88E6XXX_FLAG_GLOBAL2 | \ @@ -676,6 +666,7 @@ struct mv88e6xxx_info { unsigned int global1_addr; unsigned int age_time_coeff; unsigned int g1_irqs; + enum dsa_tag_protocol tag_protocol; unsigned long long flags; const struct mv88e6xxx_ops *ops; }; -- cgit v1.2.3-70-g09d2 From 56995cbc3540797142ebdcd25b55c74bd362c450 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 3 Dec 2016 04:35:19 +0100 Subject: net: dsa: mv88e6xxx: Refactor CPU and DSA port setup Older chips only support DSA tagging. Newer chips have both DSA and EDSA tagging. Refactor the code by adding port functions for setting the frame mode, egress mode, and if to forward unknown frames. This results in the helper mv88e6xxx_6065_family() becoming unused, so remove it. Signed-off-by: Andrew Lunn v3: Verify mandatory ops for port setup Don't set ether type for DSA port. Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 217 ++++++++++++++++++++++++++-------- drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 20 ++++ drivers/net/dsa/mv88e6xxx/port.c | 118 ++++++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 13 ++ 4 files changed, 319 insertions(+), 49 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 80efee6f5e16..9c14aaad5103 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -677,11 +677,6 @@ static int mv88e6xxx_phy_ppu_write(struct mv88e6xxx_chip *chip, int addr, return err; } -static bool mv88e6xxx_6065_family(struct mv88e6xxx_chip *chip) -{ - return chip->info->family == MV88E6XXX_FAMILY_6065; -} - static bool mv88e6xxx_6095_family(struct mv88e6xxx_chip *chip) { return chip->info->family == MV88E6XXX_FAMILY_6095; @@ -2438,6 +2433,72 @@ static int mv88e6xxx_serdes_power_on(struct mv88e6xxx_chip *chip) return err; } +static int mv88e6xxx_setup_port_dsa(struct mv88e6xxx_chip *chip, int port, + int upstream_port) +{ + int err; + + err = chip->info->ops->port_set_frame_mode( + chip, port, MV88E6XXX_FRAME_MODE_DSA); + if (err) + return err; + + return chip->info->ops->port_set_egress_unknowns( + chip, port, port == upstream_port); +} + +static int mv88e6xxx_setup_port_cpu(struct mv88e6xxx_chip *chip, int port) +{ + int err; + + switch (chip->info->tag_protocol) { + case DSA_TAG_PROTO_EDSA: + err = chip->info->ops->port_set_frame_mode( + chip, port, MV88E6XXX_FRAME_MODE_ETHERTYPE); + if (err) + return err; + + err = mv88e6xxx_port_set_egress_mode( + chip, port, PORT_CONTROL_EGRESS_ADD_TAG); + if (err) + return err; + + if (chip->info->ops->port_set_ether_type) + err = chip->info->ops->port_set_ether_type( + chip, port, ETH_P_EDSA); + break; + + case DSA_TAG_PROTO_DSA: + err = chip->info->ops->port_set_frame_mode( + chip, port, MV88E6XXX_FRAME_MODE_DSA); + if (err) + return err; + + err = mv88e6xxx_port_set_egress_mode( + chip, port, PORT_CONTROL_EGRESS_UNMODIFIED); + break; + default: + err = -EINVAL; + } + + if (err) + return err; + + return chip->info->ops->port_set_egress_unknowns(chip, port, true); +} + +static int mv88e6xxx_setup_port_normal(struct mv88e6xxx_chip *chip, int port) +{ + int err; + + err = chip->info->ops->port_set_frame_mode( + chip, port, MV88E6XXX_FRAME_MODE_NORMAL); + if (err) + return err; + + return chip->info->ops->port_set_egress_unknowns(chip, port, false); +} + static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) { struct dsa_switch *ds = chip->ds; @@ -2473,44 +2534,23 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) * If this is the upstream port for this switch, enable * forwarding of unknown unicasts and multicasts. */ - reg = 0; - if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) || - mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) || - mv88e6xxx_6095_family(chip) || mv88e6xxx_6065_family(chip) || - mv88e6xxx_6185_family(chip) || mv88e6xxx_6320_family(chip)) - reg = PORT_CONTROL_IGMP_MLD_SNOOP | + reg = PORT_CONTROL_IGMP_MLD_SNOOP | PORT_CONTROL_USE_TAG | PORT_CONTROL_USE_IP | PORT_CONTROL_STATE_FORWARDING; - if (dsa_is_cpu_port(ds, port)) { - if (chip->info->tag_protocol == DSA_TAG_PROTO_EDSA) - reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA | - PORT_CONTROL_FORWARD_UNKNOWN_MC; - else - reg |= PORT_CONTROL_DSA_TAG; - reg |= PORT_CONTROL_EGRESS_ADD_TAG | - PORT_CONTROL_FORWARD_UNKNOWN; - } - if (dsa_is_dsa_port(ds, port)) { - if (mv88e6xxx_6095_family(chip) || - mv88e6xxx_6185_family(chip)) - reg |= PORT_CONTROL_DSA_TAG; - if (mv88e6xxx_6352_family(chip) || - mv88e6xxx_6351_family(chip) || - mv88e6xxx_6165_family(chip) || - mv88e6xxx_6097_family(chip) || - mv88e6xxx_6320_family(chip)) { - reg |= PORT_CONTROL_FRAME_MODE_DSA; - } + err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); + if (err) + return err; - if (port == dsa_upstream_port(ds)) - reg |= PORT_CONTROL_FORWARD_UNKNOWN | - PORT_CONTROL_FORWARD_UNKNOWN_MC; - } - if (reg) { - err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); - if (err) - return err; + if (dsa_is_cpu_port(ds, port)) { + err = mv88e6xxx_setup_port_cpu(chip, port); + } else if (dsa_is_dsa_port(ds, port)) { + err = mv88e6xxx_setup_port_dsa(chip, port, + dsa_upstream_port(ds)); + } else { + err = mv88e6xxx_setup_port_normal(chip, port); } + if (err) + return err; /* If this port is connected to a SerDes, make sure the SerDes is not * powered down. @@ -2607,16 +2647,6 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) 0x0000); if (err) return err; - - /* Port Ethertype: use the Ethertype DSA Ethertype - * value. - */ - if (chip->info->tag_protocol == DSA_TAG_PROTO_EDSA) { - err = mv88e6xxx_port_write(chip, port, PORT_ETH_TYPE, - ETH_P_EDSA); - if (err) - return err; - } } if (chip->info->ops->port_tag_remap) { @@ -3182,6 +3212,9 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3198,6 +3231,8 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, + .port_set_frame_mode = mv88e6085_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6085_port_set_egress_unknowns, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3213,6 +3248,9 @@ static const struct mv88e6xxx_ops mv88e6097_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3229,6 +3267,8 @@ static const struct mv88e6xxx_ops mv88e6123_ops = { .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, + .port_set_frame_mode = mv88e6085_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6085_port_set_egress_unknowns, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3246,6 +3286,9 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3263,6 +3306,9 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3297,6 +3343,9 @@ static const struct mv88e6xxx_ops mv88e6171_ops = { .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6185_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3317,6 +3366,9 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6352_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3335,6 +3387,9 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6185_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3355,6 +3410,9 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6352_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3371,6 +3429,8 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, + .port_set_frame_mode = mv88e6085_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6085_port_set_egress_unknowns, .stats_snapshot = mv88e6xxx_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3389,6 +3449,9 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390_port_set_speed, .port_tag_remap = mv88e6390_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3408,6 +3471,9 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390x_port_set_speed, .port_tag_remap = mv88e6390_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3427,6 +3493,9 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390_port_set_speed, .port_tag_remap = mv88e6390_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3448,6 +3517,9 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6352_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3466,6 +3538,9 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390_port_set_speed, .port_tag_remap = mv88e6390_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3486,6 +3561,9 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6320_stats_get_sset_count, .stats_get_strings = mv88e6320_stats_get_strings, @@ -3505,6 +3583,9 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .port_set_duplex = mv88e6xxx_port_set_duplex, .port_set_speed = mv88e6185_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6320_stats_get_sset_count, .stats_get_strings = mv88e6320_stats_get_strings, @@ -3523,6 +3604,9 @@ static const struct mv88e6xxx_ops mv88e6350_ops = { .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6185_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3541,6 +3625,9 @@ static const struct mv88e6xxx_ops mv88e6351_ops = { .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6185_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3561,6 +3648,9 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, .port_set_speed = mv88e6352_port_set_speed, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6320_g1_stats_snapshot, .stats_get_sset_count = mv88e6095_stats_get_sset_count, .stats_get_strings = mv88e6095_stats_get_strings, @@ -3579,6 +3669,9 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390_port_set_speed, .port_tag_remap = mv88e6390_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3598,6 +3691,9 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390x_port_set_speed, .port_tag_remap = mv88e6390_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3617,6 +3713,9 @@ static const struct mv88e6xxx_ops mv88e6391_ops = { .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay, .port_set_speed = mv88e6390_port_set_speed, .port_tag_remap = mv88e6390_port_tag_remap, + .port_set_frame_mode = mv88e6351_port_set_frame_mode, + .port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns, + .port_set_ether_type = mv88e6351_port_set_ether_type, .stats_snapshot = mv88e6390_g1_stats_snapshot, .stats_set_histogram = mv88e6390_g1_stats_set_histogram, .stats_get_sset_count = mv88e6320_stats_get_sset_count, @@ -3626,6 +3725,22 @@ static const struct mv88e6xxx_ops mv88e6391_ops = { .g1_set_egress_port = mv88e6390_g1_set_egress_port, }; +static int mv88e6xxx_verify_madatory_ops(struct mv88e6xxx_chip *chip, + const struct mv88e6xxx_ops *ops) +{ + if (!ops->port_set_frame_mode) { + dev_err(chip->dev, "Missing port_set_frame_mode"); + return -EINVAL; + } + + if (!ops->port_set_egress_unknowns) { + dev_err(chip->dev, "Missing port_set_egress_mode"); + return -EINVAL; + } + + return 0; +} + static const struct mv88e6xxx_info mv88e6xxx_table[] = { [MV88E6085] = { .prod_num = PORT_SWITCH_ID_PROD_NUM_6085, @@ -4268,6 +4383,10 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) chip->info = compat_info; + err = mv88e6xxx_verify_madatory_ops(chip, chip->info->ops); + if (err) + return err; + err = mv88e6xxx_smi_init(chip, mdiodev->bus, mdiodev->addr); if (err) return err; diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h index 2c51e3a8a890..9dd94d7f58d6 100644 --- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h @@ -110,6 +110,7 @@ #define PORT_CONTROL_EGRESS_UNTAGGED (0x1 << 12) #define PORT_CONTROL_EGRESS_TAGGED (0x2 << 12) #define PORT_CONTROL_EGRESS_ADD_TAG (0x3 << 12) +#define PORT_CONTROL_EGRESS_MASK (0x3 << 12) #define PORT_CONTROL_HEADER BIT(11) #define PORT_CONTROL_IGMP_MLD_SNOOP BIT(10) #define PORT_CONTROL_DOUBLE_TAG BIT(9) @@ -117,6 +118,7 @@ #define PORT_CONTROL_FRAME_MODE_DSA (0x1 << 8) #define PORT_CONTROL_FRAME_MODE_PROVIDER (0x2 << 8) #define PORT_CONTROL_FRAME_ETHER_TYPE_DSA (0x3 << 8) +#define PORT_CONTROL_FRAME_MASK (0x3 << 8) #define PORT_CONTROL_DSA_TAG BIT(8) #define PORT_CONTROL_VLAN_TUNNEL BIT(7) #define PORT_CONTROL_TAG_IF_BOTH BIT(6) @@ -124,6 +126,10 @@ #define PORT_CONTROL_USE_TAG BIT(4) #define PORT_CONTROL_FORWARD_UNKNOWN_MC BIT(3) #define PORT_CONTROL_FORWARD_UNKNOWN BIT(2) +#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_DA (0x0 << 2) +#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_MULTICAST_DA (0x1 << 2) +#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_UNITCAST_DA (0x2 << 2) +#define PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA (0x3 << 2) #define PORT_CONTROL_STATE_MASK 0x03 #define PORT_CONTROL_STATE_DISABLED 0x00 #define PORT_CONTROL_STATE_BLOCKING 0x01 @@ -396,6 +402,13 @@ #define MV88E6XXX_N_FID 4096 +enum mv88e6xxx_frame_mode { + MV88E6XXX_FRAME_MODE_NORMAL, + MV88E6XXX_FRAME_MODE_DSA, + MV88E6XXX_FRAME_MODE_PROVIDER, + MV88E6XXX_FRAME_MODE_ETHERTYPE, +}; + /* List of supported models */ enum mv88e6xxx_model { MV88E6085, @@ -814,6 +827,13 @@ struct mv88e6xxx_ops { int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port); + int (*port_set_frame_mode)(struct mv88e6xxx_chip *chip, int port, + enum mv88e6xxx_frame_mode mode); + int (*port_set_egress_unknowns)(struct mv88e6xxx_chip *chip, int port, + bool on); + int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port, + u16 etype); + /* Snapshot the statistics for a port. The statistics can then * be read back a leisure but still with a consistent view. */ diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 3d03ea3a2c0d..cf6674911abf 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -335,6 +335,116 @@ int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state) return 0; } +int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port, + u16 mode) +{ + int err; + u16 reg; + + err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, ®); + if (err) + return err; + + reg &= ~PORT_CONTROL_EGRESS_MASK; + reg |= mode; + + return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); +} + +int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port, + enum mv88e6xxx_frame_mode mode) +{ + int err; + u16 reg; + + err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, ®); + if (err) + return err; + + reg &= ~PORT_CONTROL_FRAME_MODE_DSA; + + switch (mode) { + case MV88E6XXX_FRAME_MODE_NORMAL: + reg |= PORT_CONTROL_FRAME_MODE_NORMAL; + break; + case MV88E6XXX_FRAME_MODE_DSA: + reg |= PORT_CONTROL_FRAME_MODE_DSA; + break; + default: + return -EINVAL; + } + + return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); +} + +int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port, + enum mv88e6xxx_frame_mode mode) +{ + int err; + u16 reg; + + err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, ®); + if (err) + return err; + + reg &= ~PORT_CONTROL_FRAME_MASK; + + switch (mode) { + case MV88E6XXX_FRAME_MODE_NORMAL: + reg |= PORT_CONTROL_FRAME_MODE_NORMAL; + break; + case MV88E6XXX_FRAME_MODE_DSA: + reg |= PORT_CONTROL_FRAME_MODE_DSA; + break; + case MV88E6XXX_FRAME_MODE_PROVIDER: + reg |= PORT_CONTROL_FRAME_MODE_PROVIDER; + break; + case MV88E6XXX_FRAME_MODE_ETHERTYPE: + reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA; + break; + default: + return -EINVAL; + } + + return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); +} + +int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, + bool on) +{ + int err; + u16 reg; + + err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, ®); + if (err) + return err; + + if (on) + reg |= PORT_CONTROL_FORWARD_UNKNOWN; + else + reg &= ~PORT_CONTROL_FORWARD_UNKNOWN; + + return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); +} + +int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, + bool on) +{ + int err; + u16 reg; + + err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, ®); + if (err) + return err; + + if (on) + reg |= PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA; + else + reg &= ~PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA; + + return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); +} + /* Offset 0x05: Port Control 1 */ /* Offset 0x06: Port Based VLAN Map */ @@ -497,6 +607,14 @@ int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, return 0; } +/* Offset 0x0f: Port Ether type */ + +int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port, + u16 etype) +{ + return mv88e6xxx_port_write(chip, port, PORT_ETH_TYPE, etype); +} + /* Offset 0x18: Port IEEE Priority Remapping Registers [0-3] * Offset 0x19: Port IEEE Priority Remapping Registers [4-7] */ diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 5fab4606662b..83cb3440e067 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -50,5 +50,18 @@ int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, u16 mode); int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port); int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port); +int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port, + u16 mode); +int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port, + enum mv88e6xxx_frame_mode mode); +int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port, + enum mv88e6xxx_frame_mode mode); +int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, + bool on); +int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port, + bool on); +int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port, + u16 etype); + #endif /* _MV88E6XXX_PORT_H */ -- cgit v1.2.3-70-g09d2