aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/net/dsa/marvell.txt7
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c81
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.h8
-rw-r--r--drivers/net/dsa/mv88e6xxx/global1.c17
-rw-r--r--drivers/net/dsa/mv88e6xxx/global1.h7
-rw-r--r--drivers/net/dsa/mv88e6xxx/global1_atu.c5
-rw-r--r--drivers/net/dsa/mv88e6xxx/global1_vtu.c58
-rw-r--r--drivers/net/dsa/mv88e6xxx/global2.c26
-rw-r--r--drivers/net/dsa/mv88e6xxx/global2.h14
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.c77
-rw-r--r--drivers/net/dsa/mv88e6xxx/port.h14
-rw-r--r--drivers/net/dsa/mv88e6xxx/smi.c25
12 files changed, 333 insertions, 6 deletions
diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt
index feb007af13cb..6f9538974bb9 100644
--- a/Documentation/devicetree/bindings/net/dsa/marvell.txt
+++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt
@@ -21,10 +21,13 @@ which is at a different MDIO base address in different switch families.
21 6341, 6350, 6351, 6352 21 6341, 6350, 6351, 6352
22- "marvell,mv88e6190" : Switch has base address 0x00. Use with models: 22- "marvell,mv88e6190" : Switch has base address 0x00. Use with models:
23 6190, 6190X, 6191, 6290, 6390, 6390X 23 6190, 6190X, 6191, 6290, 6390, 6390X
24- "marvell,mv88e6250" : Switch has base address 0x08 or 0x18. Use with model:
25 6250
24 26
25Required properties: 27Required properties:
26- compatible : Should be one of "marvell,mv88e6085" or 28- compatible : Should be one of "marvell,mv88e6085",
27 "marvell,mv88e6190" as indicated above 29 "marvell,mv88e6190" or "marvell,mv88e6250" as
30 indicated above
28- reg : Address on the MII bus for the switch. 31- reg : Address on the MII bus for the switch.
29 32
30Optional properties: 33Optional properties:
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 12f165a71a6c..df9c51da7733 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -829,6 +829,12 @@ static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
829 STATS_TYPE_BANK0 | STATS_TYPE_PORT); 829 STATS_TYPE_BANK0 | STATS_TYPE_PORT);
830} 830}
831 831
832static int mv88e6250_stats_get_strings(struct mv88e6xxx_chip *chip,
833 uint8_t *data)
834{
835 return mv88e6xxx_stats_get_strings(chip, data, STATS_TYPE_BANK0);
836}
837
832static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip, 838static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
833 uint8_t *data) 839 uint8_t *data)
834{ 840{
@@ -899,6 +905,11 @@ static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip)
899 STATS_TYPE_PORT); 905 STATS_TYPE_PORT);
900} 906}
901 907
908static int mv88e6250_stats_get_sset_count(struct mv88e6xxx_chip *chip)
909{
910 return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0);
911}
912
902static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip) 913static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
903{ 914{
904 return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 | 915 return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
@@ -966,6 +977,13 @@ static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
966 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX); 977 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
967} 978}
968 979
980static int mv88e6250_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
981 uint64_t *data)
982{
983 return mv88e6xxx_stats_get_stats(chip, port, data, STATS_TYPE_BANK0,
984 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
985}
986
969static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port, 987static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
970 uint64_t *data) 988 uint64_t *data)
971{ 989{
@@ -3448,6 +3466,44 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
3448 .phylink_validate = mv88e6352_phylink_validate, 3466 .phylink_validate = mv88e6352_phylink_validate,
3449}; 3467};
3450 3468
3469static const struct mv88e6xxx_ops mv88e6250_ops = {
3470 /* MV88E6XXX_FAMILY_6250 */
3471 .ieee_pri_map = mv88e6250_g1_ieee_pri_map,
3472 .ip_pri_map = mv88e6085_g1_ip_pri_map,
3473 .irl_init_all = mv88e6352_g2_irl_init_all,
3474 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3475 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
3476 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3477 .phy_read = mv88e6xxx_g2_smi_phy_read,
3478 .phy_write = mv88e6xxx_g2_smi_phy_write,
3479 .port_set_link = mv88e6xxx_port_set_link,
3480 .port_set_duplex = mv88e6xxx_port_set_duplex,
3481 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3482 .port_set_speed = mv88e6250_port_set_speed,
3483 .port_tag_remap = mv88e6095_port_tag_remap,
3484 .port_set_frame_mode = mv88e6351_port_set_frame_mode,
3485 .port_set_egress_floods = mv88e6352_port_set_egress_floods,
3486 .port_set_ether_type = mv88e6351_port_set_ether_type,
3487 .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
3488 .port_pause_limit = mv88e6097_port_pause_limit,
3489 .port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
3490 .port_link_state = mv88e6250_port_link_state,
3491 .stats_snapshot = mv88e6320_g1_stats_snapshot,
3492 .stats_set_histogram = mv88e6095_g1_stats_set_histogram,
3493 .stats_get_sset_count = mv88e6250_stats_get_sset_count,
3494 .stats_get_strings = mv88e6250_stats_get_strings,
3495 .stats_get_stats = mv88e6250_stats_get_stats,
3496 .set_cpu_port = mv88e6095_g1_set_cpu_port,
3497 .set_egress_port = mv88e6095_g1_set_egress_port,
3498 .watchdog_ops = &mv88e6250_watchdog_ops,
3499 .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
3500 .pot_clear = mv88e6xxx_g2_pot_clear,
3501 .reset = mv88e6250_g1_reset,
3502 .vtu_getnext = mv88e6250_g1_vtu_getnext,
3503 .vtu_loadpurge = mv88e6250_g1_vtu_loadpurge,
3504 .phylink_validate = mv88e6065_phylink_validate,
3505};
3506
3451static const struct mv88e6xxx_ops mv88e6290_ops = { 3507static const struct mv88e6xxx_ops mv88e6290_ops = {
3452 /* MV88E6XXX_FAMILY_6390 */ 3508 /* MV88E6XXX_FAMILY_6390 */
3453 .setup_errata = mv88e6390_setup_errata, 3509 .setup_errata = mv88e6390_setup_errata,
@@ -4233,6 +4289,27 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
4233 .ops = &mv88e6240_ops, 4289 .ops = &mv88e6240_ops,
4234 }, 4290 },
4235 4291
4292 [MV88E6250] = {
4293 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6250,
4294 .family = MV88E6XXX_FAMILY_6250,
4295 .name = "Marvell 88E6250",
4296 .num_databases = 64,
4297 .num_ports = 7,
4298 .num_internal_phys = 5,
4299 .max_vid = 4095,
4300 .port_base_addr = 0x08,
4301 .phy_base_addr = 0x00,
4302 .global1_addr = 0x0f,
4303 .global2_addr = 0x07,
4304 .age_time_coeff = 15000,
4305 .g1_irqs = 9,
4306 .g2_irqs = 10,
4307 .atu_move_port_mask = 0xf,
4308 .dual_chip = true,
4309 .tag_protocol = DSA_TAG_PROTO_DSA,
4310 .ops = &mv88e6250_ops,
4311 },
4312
4236 [MV88E6290] = { 4313 [MV88E6290] = {
4237 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290, 4314 .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290,
4238 .family = MV88E6XXX_FAMILY_6390, 4315 .family = MV88E6XXX_FAMILY_6390,
@@ -4841,6 +4918,10 @@ static const struct of_device_id mv88e6xxx_of_match[] = {
4841 .compatible = "marvell,mv88e6190", 4918 .compatible = "marvell,mv88e6190",
4842 .data = &mv88e6xxx_table[MV88E6190], 4919 .data = &mv88e6xxx_table[MV88E6190],
4843 }, 4920 },
4921 {
4922 .compatible = "marvell,mv88e6250",
4923 .data = &mv88e6xxx_table[MV88E6250],
4924 },
4844 { /* sentinel */ }, 4925 { /* sentinel */ },
4845}; 4926};
4846 4927
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index faa3fa889f19..2fbe72b7587b 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -62,6 +62,7 @@ enum mv88e6xxx_model {
62 MV88E6190X, 62 MV88E6190X,
63 MV88E6191, 63 MV88E6191,
64 MV88E6240, 64 MV88E6240,
65 MV88E6250,
65 MV88E6290, 66 MV88E6290,
66 MV88E6320, 67 MV88E6320,
67 MV88E6321, 68 MV88E6321,
@@ -80,6 +81,7 @@ enum mv88e6xxx_family {
80 MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */ 81 MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */
81 MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */ 82 MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */
82 MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */ 83 MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */
84 MV88E6XXX_FAMILY_6250, /* 6250 */
83 MV88E6XXX_FAMILY_6320, /* 6320 6321 */ 85 MV88E6XXX_FAMILY_6320, /* 6320 6321 */
84 MV88E6XXX_FAMILY_6341, /* 6141 6341 */ 86 MV88E6XXX_FAMILY_6341, /* 6141 6341 */
85 MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ 87 MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */
@@ -112,6 +114,12 @@ struct mv88e6xxx_info {
112 * when it is non-zero, and use indirect access to internal registers. 114 * when it is non-zero, and use indirect access to internal registers.
113 */ 115 */
114 bool multi_chip; 116 bool multi_chip;
117 /* Dual-chip Addressing Mode
118 * Some chips respond to only half of the 32 SMI addresses,
119 * allowing two to coexist on the same SMI interface.
120 */
121 bool dual_chip;
122
115 enum dsa_tag_protocol tag_protocol; 123 enum dsa_tag_protocol tag_protocol;
116 124
117 /* Mask for FromPort and ToPort value of PortVec used in ATU Move 125 /* Mask for FromPort and ToPort value of PortVec used in ATU Move
diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c
index 770c03406033..41c0792a2e2b 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.c
+++ b/drivers/net/dsa/mv88e6xxx/global1.c
@@ -182,7 +182,7 @@ int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip)
182 return mv88e6185_g1_wait_ppu_polling(chip); 182 return mv88e6185_g1_wait_ppu_polling(chip);
183} 183}
184 184
185int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip) 185int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip)
186{ 186{
187 u16 val; 187 u16 val;
188 int err; 188 int err;
@@ -198,7 +198,14 @@ int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
198 if (err) 198 if (err)
199 return err; 199 return err;
200 200
201 err = mv88e6xxx_g1_wait_init_ready(chip); 201 return mv88e6xxx_g1_wait_init_ready(chip);
202}
203
204int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
205{
206 int err;
207
208 err = mv88e6250_g1_reset(chip);
202 if (err) 209 if (err)
203 return err; 210 return err;
204 211
@@ -299,6 +306,12 @@ int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip)
299 return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IEEE_PRI, 0xfa41); 306 return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IEEE_PRI, 0xfa41);
300} 307}
301 308
309int mv88e6250_g1_ieee_pri_map(struct mv88e6xxx_chip *chip)
310{
311 /* Reset the IEEE Tag priorities to defaults */
312 return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IEEE_PRI, 0xfa50);
313}
314
302/* Offset 0x1a: Monitor Control */ 315/* Offset 0x1a: Monitor Control */
303/* Offset 0x1a: Monitor & MGMT Control on some devices */ 316/* Offset 0x1a: Monitor & MGMT Control on some devices */
304 317
diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h
index bb92a130cbef..9681ce25598a 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.h
+++ b/drivers/net/dsa/mv88e6xxx/global1.h
@@ -259,6 +259,7 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr);
259 259
260int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); 260int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip);
261int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); 261int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip);
262int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip);
262 263
263int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); 264int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip);
264int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip); 265int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip);
@@ -277,7 +278,9 @@ int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port);
277int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); 278int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
278 279
279int mv88e6085_g1_ip_pri_map(struct mv88e6xxx_chip *chip); 280int mv88e6085_g1_ip_pri_map(struct mv88e6xxx_chip *chip);
281
280int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip); 282int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip);
283int mv88e6250_g1_ieee_pri_map(struct mv88e6xxx_chip *chip);
281 284
282int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port); 285int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port);
283 286
@@ -304,6 +307,10 @@ int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
304 struct mv88e6xxx_vtu_entry *entry); 307 struct mv88e6xxx_vtu_entry *entry);
305int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, 308int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
306 struct mv88e6xxx_vtu_entry *entry); 309 struct mv88e6xxx_vtu_entry *entry);
310int mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
311 struct mv88e6xxx_vtu_entry *entry);
312int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
313 struct mv88e6xxx_vtu_entry *entry);
307int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip, 314int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
308 struct mv88e6xxx_vtu_entry *entry); 315 struct mv88e6xxx_vtu_entry *entry);
309int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, 316int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
diff --git a/drivers/net/dsa/mv88e6xxx/global1_atu.c b/drivers/net/dsa/mv88e6xxx/global1_atu.c
index ea243840ee0f..1ae680bc0eff 100644
--- a/drivers/net/dsa/mv88e6xxx/global1_atu.c
+++ b/drivers/net/dsa/mv88e6xxx/global1_atu.c
@@ -94,7 +94,7 @@ static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op)
94 if (err) 94 if (err)
95 return err; 95 return err;
96 } else { 96 } else {
97 if (mv88e6xxx_num_databases(chip) > 16) { 97 if (mv88e6xxx_num_databases(chip) > 64) {
98 /* ATU DBNum[7:4] are located in ATU Control 15:12 */ 98 /* ATU DBNum[7:4] are located in ATU Control 15:12 */
99 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL, 99 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL,
100 &val); 100 &val);
@@ -106,6 +106,9 @@ static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op)
106 val); 106 val);
107 if (err) 107 if (err)
108 return err; 108 return err;
109 } else if (mv88e6xxx_num_databases(chip) > 16) {
110 /* ATU DBNum[5:4] are located in ATU Operation 9:8 */
111 op |= (fid & 0x30) << 4;
109 } 112 }
110 113
111 /* ATU DBNum[3:0] are located in ATU Operation 3:0 */ 114 /* ATU DBNum[3:0] are located in ATU Operation 3:0 */
diff --git a/drivers/net/dsa/mv88e6xxx/global1_vtu.c b/drivers/net/dsa/mv88e6xxx/global1_vtu.c
index 058326924f3e..a8ef268c32cb 100644
--- a/drivers/net/dsa/mv88e6xxx/global1_vtu.c
+++ b/drivers/net/dsa/mv88e6xxx/global1_vtu.c
@@ -307,6 +307,35 @@ static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
307 return mv88e6xxx_g1_vtu_vid_read(chip, entry); 307 return mv88e6xxx_g1_vtu_vid_read(chip, entry);
308} 308}
309 309
310int mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
311 struct mv88e6xxx_vtu_entry *entry)
312{
313 u16 val;
314 int err;
315
316 err = mv88e6xxx_g1_vtu_getnext(chip, entry);
317 if (err)
318 return err;
319
320 if (entry->valid) {
321 err = mv88e6185_g1_vtu_data_read(chip, entry);
322 if (err)
323 return err;
324
325 /* VTU DBNum[3:0] are located in VTU Operation 3:0
326 * VTU DBNum[5:4] are located in VTU Operation 9:8
327 */
328 err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
329 if (err)
330 return err;
331
332 entry->fid = val & 0x000f;
333 entry->fid |= (val & 0x0300) >> 4;
334 }
335
336 return 0;
337}
338
310int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip, 339int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
311 struct mv88e6xxx_vtu_entry *entry) 340 struct mv88e6xxx_vtu_entry *entry)
312{ 341{
@@ -396,6 +425,35 @@ int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
396 return 0; 425 return 0;
397} 426}
398 427
428int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
429 struct mv88e6xxx_vtu_entry *entry)
430{
431 u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
432 int err;
433
434 err = mv88e6xxx_g1_vtu_op_wait(chip);
435 if (err)
436 return err;
437
438 err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
439 if (err)
440 return err;
441
442 if (entry->valid) {
443 err = mv88e6185_g1_vtu_data_write(chip, entry);
444 if (err)
445 return err;
446
447 /* VTU DBNum[3:0] are located in VTU Operation 3:0
448 * VTU DBNum[5:4] are located in VTU Operation 9:8
449 */
450 op |= entry->fid & 0x000f;
451 op |= (entry->fid & 0x0030) << 8;
452 }
453
454 return mv88e6xxx_g1_vtu_op(chip, op);
455}
456
399int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, 457int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
400 struct mv88e6xxx_vtu_entry *entry) 458 struct mv88e6xxx_vtu_entry *entry)
401{ 459{
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index 91a3cb2452ac..85984eb69ffd 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -816,6 +816,32 @@ const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {
816 .irq_free = mv88e6097_watchdog_free, 816 .irq_free = mv88e6097_watchdog_free,
817}; 817};
818 818
819static void mv88e6250_watchdog_free(struct mv88e6xxx_chip *chip)
820{
821 u16 reg;
822
823 mv88e6xxx_g2_read(chip, MV88E6250_G2_WDOG_CTL, &reg);
824
825 reg &= ~(MV88E6250_G2_WDOG_CTL_EGRESS_ENABLE |
826 MV88E6250_G2_WDOG_CTL_QC_ENABLE);
827
828 mv88e6xxx_g2_write(chip, MV88E6250_G2_WDOG_CTL, reg);
829}
830
831static int mv88e6250_watchdog_setup(struct mv88e6xxx_chip *chip)
832{
833 return mv88e6xxx_g2_write(chip, MV88E6250_G2_WDOG_CTL,
834 MV88E6250_G2_WDOG_CTL_EGRESS_ENABLE |
835 MV88E6250_G2_WDOG_CTL_QC_ENABLE |
836 MV88E6250_G2_WDOG_CTL_SWRESET);
837}
838
839const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops = {
840 .irq_action = mv88e6097_watchdog_action,
841 .irq_setup = mv88e6250_watchdog_setup,
842 .irq_free = mv88e6250_watchdog_free,
843};
844
819static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip) 845static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip)
820{ 846{
821 return mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL, 847 return mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL,
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h
index 194660d8c783..6205c6b75bc7 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -206,6 +206,18 @@
206#define MV88E6XXX_G2_SCRATCH_MISC_DATA_MASK 0x00ff 206#define MV88E6XXX_G2_SCRATCH_MISC_DATA_MASK 0x00ff
207 207
208/* Offset 0x1B: Watch Dog Control Register */ 208/* Offset 0x1B: Watch Dog Control Register */
209#define MV88E6250_G2_WDOG_CTL 0x1b
210#define MV88E6250_G2_WDOG_CTL_QC_HISTORY 0x0100
211#define MV88E6250_G2_WDOG_CTL_QC_EVENT 0x0080
212#define MV88E6250_G2_WDOG_CTL_QC_ENABLE 0x0040
213#define MV88E6250_G2_WDOG_CTL_EGRESS_HISTORY 0x0020
214#define MV88E6250_G2_WDOG_CTL_EGRESS_EVENT 0x0010
215#define MV88E6250_G2_WDOG_CTL_EGRESS_ENABLE 0x0008
216#define MV88E6250_G2_WDOG_CTL_FORCE_IRQ 0x0004
217#define MV88E6250_G2_WDOG_CTL_HISTORY 0x0002
218#define MV88E6250_G2_WDOG_CTL_SWRESET 0x0001
219
220/* Offset 0x1B: Watch Dog Control Register */
209#define MV88E6352_G2_WDOG_CTL 0x1b 221#define MV88E6352_G2_WDOG_CTL 0x1b
210#define MV88E6352_G2_WDOG_CTL_EGRESS_EVENT 0x0080 222#define MV88E6352_G2_WDOG_CTL_EGRESS_EVENT 0x0080
211#define MV88E6352_G2_WDOG_CTL_RMU_TIMEOUT 0x0040 223#define MV88E6352_G2_WDOG_CTL_RMU_TIMEOUT 0x0040
@@ -334,6 +346,7 @@ int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target,
334 int port); 346 int port);
335 347
336extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; 348extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops;
349extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops;
337extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops; 350extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops;
338 351
339extern const struct mv88e6xxx_avb_ops mv88e6165_avb_ops; 352extern const struct mv88e6xxx_avb_ops mv88e6165_avb_ops;
@@ -484,6 +497,7 @@ static inline int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip)
484} 497}
485 498
486static const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {}; 499static const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {};
500static const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops = {};
487static const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {}; 501static const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {};
488 502
489static const struct mv88e6xxx_avb_ops mv88e6165_avb_ops = {}; 503static const struct mv88e6xxx_avb_ops mv88e6165_avb_ops = {};
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index c44b2822e4dd..a9a308051d7c 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -294,6 +294,18 @@ int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
294 return mv88e6xxx_port_set_speed(chip, port, speed, false, false); 294 return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
295} 295}
296 296
297/* Support 10, 100 Mbps (e.g. 88E6250 family) */
298int mv88e6250_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
299{
300 if (speed == SPEED_MAX)
301 speed = 100;
302
303 if (speed > 100)
304 return -EOPNOTSUPP;
305
306 return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
307}
308
297/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6341) */ 309/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6341) */
298int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) 310int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
299{ 311{
@@ -521,6 +533,71 @@ int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
521 return 0; 533 return 0;
522} 534}
523 535
536int mv88e6250_port_link_state(struct mv88e6xxx_chip *chip, int port,
537 struct phylink_link_state *state)
538{
539 int err;
540 u16 reg;
541
542 err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
543 if (err)
544 return err;
545
546 if (port < 5) {
547 switch (reg & MV88E6250_PORT_STS_PORTMODE_MASK) {
548 case MV88E6250_PORT_STS_PORTMODE_PHY_10_HALF:
549 state->speed = SPEED_10;
550 state->duplex = DUPLEX_HALF;
551 break;
552 case MV88E6250_PORT_STS_PORTMODE_PHY_100_HALF:
553 state->speed = SPEED_100;
554 state->duplex = DUPLEX_HALF;
555 break;
556 case MV88E6250_PORT_STS_PORTMODE_PHY_10_FULL:
557 state->speed = SPEED_10;
558 state->duplex = DUPLEX_FULL;
559 break;
560 case MV88E6250_PORT_STS_PORTMODE_PHY_100_FULL:
561 state->speed = SPEED_100;
562 state->duplex = DUPLEX_FULL;
563 break;
564 default:
565 state->speed = SPEED_UNKNOWN;
566 state->duplex = DUPLEX_UNKNOWN;
567 break;
568 }
569 } else {
570 switch (reg & MV88E6250_PORT_STS_PORTMODE_MASK) {
571 case MV88E6250_PORT_STS_PORTMODE_MII_10_HALF:
572 state->speed = SPEED_10;
573 state->duplex = DUPLEX_HALF;
574 break;
575 case MV88E6250_PORT_STS_PORTMODE_MII_100_HALF:
576 state->speed = SPEED_100;
577 state->duplex = DUPLEX_HALF;
578 break;
579 case MV88E6250_PORT_STS_PORTMODE_MII_10_FULL:
580 state->speed = SPEED_10;
581 state->duplex = DUPLEX_FULL;
582 break;
583 case MV88E6250_PORT_STS_PORTMODE_MII_100_FULL:
584 state->speed = SPEED_100;
585 state->duplex = DUPLEX_FULL;
586 break;
587 default:
588 state->speed = SPEED_UNKNOWN;
589 state->duplex = DUPLEX_UNKNOWN;
590 break;
591 }
592 }
593
594 state->link = !!(reg & MV88E6250_PORT_STS_LINK);
595 state->an_enabled = 1;
596 state->an_complete = state->link;
597
598 return 0;
599}
600
524int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port, 601int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port,
525 struct phylink_link_state *state) 602 struct phylink_link_state *state)
526{ 603{
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 39c85e98fb92..b3b57ea6ef07 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -23,6 +23,16 @@
23#define MV88E6XXX_PORT_STS_MY_PAUSE 0x4000 23#define MV88E6XXX_PORT_STS_MY_PAUSE 0x4000
24#define MV88E6XXX_PORT_STS_HD_FLOW 0x2000 24#define MV88E6XXX_PORT_STS_HD_FLOW 0x2000
25#define MV88E6XXX_PORT_STS_PHY_DETECT 0x1000 25#define MV88E6XXX_PORT_STS_PHY_DETECT 0x1000
26#define MV88E6250_PORT_STS_LINK 0x1000
27#define MV88E6250_PORT_STS_PORTMODE_MASK 0x0f00
28#define MV88E6250_PORT_STS_PORTMODE_PHY_10_HALF 0x0800
29#define MV88E6250_PORT_STS_PORTMODE_PHY_100_HALF 0x0900
30#define MV88E6250_PORT_STS_PORTMODE_PHY_10_FULL 0x0a00
31#define MV88E6250_PORT_STS_PORTMODE_PHY_100_FULL 0x0b00
32#define MV88E6250_PORT_STS_PORTMODE_MII_10_HALF 0x0c00
33#define MV88E6250_PORT_STS_PORTMODE_MII_100_HALF 0x0d00
34#define MV88E6250_PORT_STS_PORTMODE_MII_10_FULL 0x0e00
35#define MV88E6250_PORT_STS_PORTMODE_MII_100_FULL 0x0f00
26#define MV88E6XXX_PORT_STS_LINK 0x0800 36#define MV88E6XXX_PORT_STS_LINK 0x0800
27#define MV88E6XXX_PORT_STS_DUPLEX 0x0400 37#define MV88E6XXX_PORT_STS_DUPLEX 0x0400
28#define MV88E6XXX_PORT_STS_SPEED_MASK 0x0300 38#define MV88E6XXX_PORT_STS_SPEED_MASK 0x0300
@@ -112,6 +122,7 @@
112#define MV88E6XXX_PORT_SWITCH_ID_PROD_6191 0x1910 122#define MV88E6XXX_PORT_SWITCH_ID_PROD_6191 0x1910
113#define MV88E6XXX_PORT_SWITCH_ID_PROD_6185 0x1a70 123#define MV88E6XXX_PORT_SWITCH_ID_PROD_6185 0x1a70
114#define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400 124#define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400
125#define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500
115#define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900 126#define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900
116#define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100 127#define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100
117#define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400 128#define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400
@@ -279,6 +290,7 @@ int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup);
279 290
280int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); 291int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
281int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); 292int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
293int mv88e6250_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
282int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); 294int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
283int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); 295int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
284int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); 296int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
@@ -332,6 +344,8 @@ int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
332int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode); 344int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
333int mv88e6185_port_link_state(struct mv88e6xxx_chip *chip, int port, 345int mv88e6185_port_link_state(struct mv88e6xxx_chip *chip, int port,
334 struct phylink_link_state *state); 346 struct phylink_link_state *state);
347int mv88e6250_port_link_state(struct mv88e6xxx_chip *chip, int port,
348 struct phylink_link_state *state);
335int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port, 349int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port,
336 struct phylink_link_state *state); 350 struct phylink_link_state *state);
337int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port); 351int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port);
diff --git a/drivers/net/dsa/mv88e6xxx/smi.c b/drivers/net/dsa/mv88e6xxx/smi.c
index 96f7d2685bdc..775f8d55a962 100644
--- a/drivers/net/dsa/mv88e6xxx/smi.c
+++ b/drivers/net/dsa/mv88e6xxx/smi.c
@@ -24,6 +24,10 @@
24 * When ADDR is non-zero, the chip uses Multi-chip Addressing Mode, allowing 24 * When ADDR is non-zero, the chip uses Multi-chip Addressing Mode, allowing
25 * multiple devices to share the SMI interface. In this mode it responds to only 25 * multiple devices to share the SMI interface. In this mode it responds to only
26 * 2 registers, used to indirectly access the internal SMI devices. 26 * 2 registers, used to indirectly access the internal SMI devices.
27 *
28 * Some chips use a different scheme: Only the ADDR4 pin is used for
29 * configuration, and the device responds to 16 of the 32 SMI
30 * addresses, allowing two to coexist on the same SMI interface.
27 */ 31 */
28 32
29static int mv88e6xxx_smi_direct_read(struct mv88e6xxx_chip *chip, 33static int mv88e6xxx_smi_direct_read(struct mv88e6xxx_chip *chip,
@@ -76,6 +80,23 @@ static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_direct_ops = {
76 .write = mv88e6xxx_smi_direct_write, 80 .write = mv88e6xxx_smi_direct_write,
77}; 81};
78 82
83static int mv88e6xxx_smi_dual_direct_read(struct mv88e6xxx_chip *chip,
84 int dev, int reg, u16 *data)
85{
86 return mv88e6xxx_smi_direct_read(chip, chip->sw_addr + dev, reg, data);
87}
88
89static int mv88e6xxx_smi_dual_direct_write(struct mv88e6xxx_chip *chip,
90 int dev, int reg, u16 data)
91{
92 return mv88e6xxx_smi_direct_write(chip, chip->sw_addr + dev, reg, data);
93}
94
95static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_dual_direct_ops = {
96 .read = mv88e6xxx_smi_dual_direct_read,
97 .write = mv88e6xxx_smi_dual_direct_write,
98};
99
79/* Offset 0x00: SMI Command Register 100/* Offset 0x00: SMI Command Register
80 * Offset 0x01: SMI Data Register 101 * Offset 0x01: SMI Data Register
81 */ 102 */
@@ -144,7 +165,9 @@ static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_indirect_ops = {
144int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip, 165int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip,
145 struct mii_bus *bus, int sw_addr) 166 struct mii_bus *bus, int sw_addr)
146{ 167{
147 if (sw_addr == 0) 168 if (chip->info->dual_chip)
169 chip->smi_ops = &mv88e6xxx_smi_dual_direct_ops;
170 else if (sw_addr == 0)
148 chip->smi_ops = &mv88e6xxx_smi_direct_ops; 171 chip->smi_ops = &mv88e6xxx_smi_direct_ops;
149 else if (chip->info->multi_chip) 172 else if (chip->info->multi_chip)
150 chip->smi_ops = &mv88e6xxx_smi_indirect_ops; 173 chip->smi_ops = &mv88e6xxx_smi_indirect_ops;