diff options
author | Andrew Lunn <andrew@lunn.ch> | 2018-08-09 09:38:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-08-09 14:08:20 -0400 |
commit | 07ffbd74d1786d13a4f3a6bc01400ea59e8b19c0 (patch) | |
tree | ec91b8129811e3e997a270b801dde49f5209f7fb | |
parent | a8c01c0d941d2f220a5a31ded77a67d89ddec3b0 (diff) |
net: dsa: mv88e6xxx: 6390 vs 6390X SERDES support
The 6390 has two SERDES interfaces, used by ports 9 and 10. The 6390X
has eight SERDES interfaces. These allow ports 9 and 10 to do 10G. Or
if lower speeds are used, some of the SERDES interfaces can be used by
ports 2-8 for 1000Base-X.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 4 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/serdes.c | 51 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/serdes.h | 1 |
3 files changed, 53 insertions, 3 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 1427541df316..4c9ae5b9440b 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c | |||
@@ -3234,7 +3234,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { | |||
3234 | .rmu_disable = mv88e6390_g1_rmu_disable, | 3234 | .rmu_disable = mv88e6390_g1_rmu_disable, |
3235 | .vtu_getnext = mv88e6390_g1_vtu_getnext, | 3235 | .vtu_getnext = mv88e6390_g1_vtu_getnext, |
3236 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, | 3236 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, |
3237 | .serdes_power = mv88e6390_serdes_power, | 3237 | .serdes_power = mv88e6390x_serdes_power, |
3238 | .gpio_ops = &mv88e6352_gpio_ops, | 3238 | .gpio_ops = &mv88e6352_gpio_ops, |
3239 | .phylink_validate = mv88e6390x_phylink_validate, | 3239 | .phylink_validate = mv88e6390x_phylink_validate, |
3240 | }; | 3240 | }; |
@@ -3697,7 +3697,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { | |||
3697 | .rmu_disable = mv88e6390_g1_rmu_disable, | 3697 | .rmu_disable = mv88e6390_g1_rmu_disable, |
3698 | .vtu_getnext = mv88e6390_g1_vtu_getnext, | 3698 | .vtu_getnext = mv88e6390_g1_vtu_getnext, |
3699 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, | 3699 | .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, |
3700 | .serdes_power = mv88e6390_serdes_power, | 3700 | .serdes_power = mv88e6390x_serdes_power, |
3701 | .gpio_ops = &mv88e6352_gpio_ops, | 3701 | .gpio_ops = &mv88e6352_gpio_ops, |
3702 | .avb_ops = &mv88e6390_avb_ops, | 3702 | .avb_ops = &mv88e6390_avb_ops, |
3703 | .ptp_ops = &mv88e6352_ptp_ops, | 3703 | .ptp_ops = &mv88e6352_ptp_ops, |
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index a218870971fe..c534749fb1b6 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c | |||
@@ -174,11 +174,41 @@ int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, | |||
174 | return ARRAY_SIZE(mv88e6352_serdes_hw_stats); | 174 | return ARRAY_SIZE(mv88e6352_serdes_hw_stats); |
175 | } | 175 | } |
176 | 176 | ||
177 | /* Return the SERDES lane address a port is using. Only Ports 9 and 10 | ||
178 | * have SERDES lanes. Returns -ENODEV if a port does not have a lane. | ||
179 | */ | ||
180 | static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) | ||
181 | { | ||
182 | u8 cmode; | ||
183 | int err; | ||
184 | |||
185 | err = mv88e6xxx_port_get_cmode(chip, port, &cmode); | ||
186 | if (err) | ||
187 | return err; | ||
188 | |||
189 | switch (port) { | ||
190 | case 9: | ||
191 | if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || | ||
192 | cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || | ||
193 | cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) | ||
194 | return MV88E6390_PORT9_LANE0; | ||
195 | return -ENODEV; | ||
196 | case 10: | ||
197 | if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASE_X || | ||
198 | cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || | ||
199 | cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX) | ||
200 | return MV88E6390_PORT10_LANE0; | ||
201 | return -ENODEV; | ||
202 | default: | ||
203 | return -ENODEV; | ||
204 | } | ||
205 | } | ||
206 | |||
177 | /* Return the SERDES lane address a port is using. Ports 9 and 10 can | 207 | /* Return the SERDES lane address a port is using. Ports 9 and 10 can |
178 | * use multiple lanes. If so, return the first lane the port uses. | 208 | * use multiple lanes. If so, return the first lane the port uses. |
179 | * Returns -ENODEV if a port does not have a lane. | 209 | * Returns -ENODEV if a port does not have a lane. |
180 | */ | 210 | */ |
181 | static int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) | 211 | static int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) |
182 | { | 212 | { |
183 | u8 cmode_port9, cmode_port10, cmode_port; | 213 | u8 cmode_port9, cmode_port10, cmode_port; |
184 | int err; | 214 | int err; |
@@ -351,6 +381,25 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) | |||
351 | return lane; | 381 | return lane; |
352 | 382 | ||
353 | switch (port) { | 383 | switch (port) { |
384 | case 9 ... 10: | ||
385 | return mv88e6390_serdes_power_lane(chip, port, lane, on); | ||
386 | } | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on) | ||
392 | { | ||
393 | int lane; | ||
394 | |||
395 | lane = mv88e6390x_serdes_get_lane(chip, port); | ||
396 | if (lane == -ENODEV) | ||
397 | return 0; | ||
398 | |||
399 | if (lane < 0) | ||
400 | return lane; | ||
401 | |||
402 | switch (port) { | ||
354 | case 2 ... 4: | 403 | case 2 ... 4: |
355 | case 5 ... 7: | 404 | case 5 ... 7: |
356 | case 9 ... 10: | 405 | case 9 ... 10: |
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index b6e5fbd46b5e..05c4825c36e4 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h | |||
@@ -47,6 +47,7 @@ | |||
47 | int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); | 47 | int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); |
48 | int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); | 48 | int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); |
49 | int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); | 49 | int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); |
50 | int mv88e6390x_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); | ||
50 | int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port); | 51 | int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port); |
51 | int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, | 52 | int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, |
52 | int port, uint8_t *data); | 53 | int port, uint8_t *data); |