diff options
| -rw-r--r-- | Documentation/devicetree/bindings/net/dsa/marvell.txt | 7 | ||||
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 81 | ||||
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.h | 8 | ||||
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/global1.c | 17 | ||||
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/global1.h | 7 | ||||
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/global1_atu.c | 5 | ||||
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/global1_vtu.c | 58 | ||||
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/global2.c | 26 | ||||
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/global2.h | 14 | ||||
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/port.c | 77 | ||||
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/port.h | 14 | ||||
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/smi.c | 25 |
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 | ||
| 25 | Required properties: | 27 | Required 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 | ||
| 30 | Optional properties: | 33 | Optional 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 | ||
| 832 | static 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 | |||
| 832 | static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip, | 838 | static 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 | ||
| 908 | static int mv88e6250_stats_get_sset_count(struct mv88e6xxx_chip *chip) | ||
| 909 | { | ||
| 910 | return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0); | ||
| 911 | } | ||
| 912 | |||
| 902 | static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip) | 913 | static 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 | ||
| 980 | static 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 | |||
| 969 | static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port, | 987 | static 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 | ||
| 3469 | static 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 | |||
| 3451 | static const struct mv88e6xxx_ops mv88e6290_ops = { | 3507 | static 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 | ||
| 185 | int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip) | 185 | int 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 | |||
| 204 | int 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 | ||
| 309 | int 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 | ||
| 260 | int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); | 260 | int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); |
| 261 | int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); | 261 | int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); |
| 262 | int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip); | ||
| 262 | 263 | ||
| 263 | int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); | 264 | int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); |
| 264 | int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip); | 265 | int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip); |
| @@ -277,7 +278,9 @@ int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port); | |||
| 277 | int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); | 278 | int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); |
| 278 | 279 | ||
| 279 | int mv88e6085_g1_ip_pri_map(struct mv88e6xxx_chip *chip); | 280 | int mv88e6085_g1_ip_pri_map(struct mv88e6xxx_chip *chip); |
| 281 | |||
| 280 | int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip); | 282 | int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip); |
| 283 | int mv88e6250_g1_ieee_pri_map(struct mv88e6xxx_chip *chip); | ||
| 281 | 284 | ||
| 282 | int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port); | 285 | int 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); |
| 305 | int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, | 308 | int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, |
| 306 | struct mv88e6xxx_vtu_entry *entry); | 309 | struct mv88e6xxx_vtu_entry *entry); |
| 310 | int mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip *chip, | ||
| 311 | struct mv88e6xxx_vtu_entry *entry); | ||
| 312 | int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, | ||
| 313 | struct mv88e6xxx_vtu_entry *entry); | ||
| 307 | int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip, | 314 | int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip, |
| 308 | struct mv88e6xxx_vtu_entry *entry); | 315 | struct mv88e6xxx_vtu_entry *entry); |
| 309 | int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, | 316 | int 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 | ||
| 310 | int 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 | |||
| 310 | int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip, | 339 | int 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 | ||
| 428 | int 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 | |||
| 399 | int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, | 457 | int 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 | ||
| 819 | static void mv88e6250_watchdog_free(struct mv88e6xxx_chip *chip) | ||
| 820 | { | ||
| 821 | u16 reg; | ||
| 822 | |||
| 823 | mv88e6xxx_g2_read(chip, MV88E6250_G2_WDOG_CTL, ®); | ||
| 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 | |||
| 831 | static 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 | |||
| 839 | const 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 | |||
| 819 | static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip) | 845 | static 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 | ||
| 336 | extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; | 348 | extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; |
| 349 | extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops; | ||
| 337 | extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops; | 350 | extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops; |
| 338 | 351 | ||
| 339 | extern const struct mv88e6xxx_avb_ops mv88e6165_avb_ops; | 352 | extern 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 | ||
| 486 | static const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {}; | 499 | static const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {}; |
| 500 | static const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops = {}; | ||
| 487 | static const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {}; | 501 | static const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {}; |
| 488 | 502 | ||
| 489 | static const struct mv88e6xxx_avb_ops mv88e6165_avb_ops = {}; | 503 | static 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) */ | ||
| 298 | int 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) */ |
| 298 | int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) | 310 | int 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 | ||
| 536 | int 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, ®); | ||
| 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 | |||
| 524 | int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port, | 601 | int 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 | ||
| 280 | int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); | 291 | int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); |
| 281 | int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); | 292 | int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); |
| 293 | int mv88e6250_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); | ||
| 282 | int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); | 294 | int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); |
| 283 | int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); | 295 | int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); |
| 284 | int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); | 296 | int 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); | |||
| 332 | int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode); | 344 | int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode); |
| 333 | int mv88e6185_port_link_state(struct mv88e6xxx_chip *chip, int port, | 345 | int mv88e6185_port_link_state(struct mv88e6xxx_chip *chip, int port, |
| 334 | struct phylink_link_state *state); | 346 | struct phylink_link_state *state); |
| 347 | int mv88e6250_port_link_state(struct mv88e6xxx_chip *chip, int port, | ||
| 348 | struct phylink_link_state *state); | ||
| 335 | int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port, | 349 | int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port, |
| 336 | struct phylink_link_state *state); | 350 | struct phylink_link_state *state); |
| 337 | int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port); | 351 | int 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 | ||
| 29 | static int mv88e6xxx_smi_direct_read(struct mv88e6xxx_chip *chip, | 33 | static 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 | ||
| 83 | static 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 | |||
| 89 | static 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 | |||
| 95 | static 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 = { | |||
| 144 | int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip, | 165 | int 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; |
