Commit 2a99283c authored by David S. Miller's avatar David S. Miller

Merge branch 'net-dsa-mv88e6xxx-support-for-mv88e6250'

Rasmus Villemoes says:

====================
net: dsa: mv88e6xxx: support for mv88e6250

This adds support for the mv88e6250 chip. Initially based on the
mv88e6240, this time around, I've been through each ->ops callback and
checked that it makes sense, either replacing with a 6250 specific
variant or dropping it if no equivalent functionality seems to exist
for the 6250. Along the way, I found a few oddities in the existing
code, mostly sent as separate patches/questions.

The one relevant to the 6250 is the ieee_pri_map callback, where the
existing mv88e6085_g1_ieee_pri_map() is actually wrong for many of the
existing users. I've put the mv88e6250_g1_ieee_pri_map() patch first
in case some of the existing chips get switched over to use that and
it is deemed important enough for -stable.

v4:
- fix style issue in 1/10
- add Andrew's reviewed-by to 1,6,7,8,9,10.

v3:
- rebase on top of net-next/master
- add reviewed-bys to patches unchanged from v2 (2,3,4,5)
- add 6250-specific ->ieee_pri_map, ->port_set_speed, ->port_link_state (1,6,7)
- in addition, use mv88e6065_phylink_validate for ->phylink_validate,
  and don't implement ->port_get_cmode, ->port_set_jumbo_size,
  ->port_disable_learn_limit, ->rmu_disable
- drop ptp support
- add patch adding the compatible string to the DT binding (9)
- add small refactoring patch (10)

v2:
- rebase on top of net-next/master
- add reviewed-by to two patches unchanged from v1 (2,3)
- add separate watchdog_ops
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3dd7400b 7358fd80
...@@ -21,10 +21,13 @@ which is at a different MDIO base address in different switch families. ...@@ -21,10 +21,13 @@ which is at a different MDIO base address in different switch families.
6341, 6350, 6351, 6352 6341, 6350, 6351, 6352
- "marvell,mv88e6190" : Switch has base address 0x00. Use with models: - "marvell,mv88e6190" : Switch has base address 0x00. Use with models:
6190, 6190X, 6191, 6290, 6390, 6390X 6190, 6190X, 6191, 6290, 6390, 6390X
- "marvell,mv88e6250" : Switch has base address 0x08 or 0x18. Use with model:
6250
Required properties: Required properties:
- compatible : Should be one of "marvell,mv88e6085" or - compatible : Should be one of "marvell,mv88e6085",
"marvell,mv88e6190" as indicated above "marvell,mv88e6190" or "marvell,mv88e6250" as
indicated above
- reg : Address on the MII bus for the switch. - reg : Address on the MII bus for the switch.
Optional properties: Optional properties:
......
...@@ -829,6 +829,12 @@ static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip, ...@@ -829,6 +829,12 @@ static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
STATS_TYPE_BANK0 | STATS_TYPE_PORT); STATS_TYPE_BANK0 | STATS_TYPE_PORT);
} }
static int mv88e6250_stats_get_strings(struct mv88e6xxx_chip *chip,
uint8_t *data)
{
return mv88e6xxx_stats_get_strings(chip, data, STATS_TYPE_BANK0);
}
static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip, static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
uint8_t *data) uint8_t *data)
{ {
...@@ -899,6 +905,11 @@ static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip) ...@@ -899,6 +905,11 @@ static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip)
STATS_TYPE_PORT); STATS_TYPE_PORT);
} }
static int mv88e6250_stats_get_sset_count(struct mv88e6xxx_chip *chip)
{
return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0);
}
static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip) static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
{ {
return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 | 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,6 +977,13 @@ static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX); 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
} }
static int mv88e6250_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
{
return mv88e6xxx_stats_get_stats(chip, port, data, STATS_TYPE_BANK0,
0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
}
static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port, static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data) uint64_t *data)
{ {
...@@ -3448,6 +3466,44 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { ...@@ -3448,6 +3466,44 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.phylink_validate = mv88e6352_phylink_validate, .phylink_validate = mv88e6352_phylink_validate,
}; };
static const struct mv88e6xxx_ops mv88e6250_ops = {
/* MV88E6XXX_FAMILY_6250 */
.ieee_pri_map = mv88e6250_g1_ieee_pri_map,
.ip_pri_map = mv88e6085_g1_ip_pri_map,
.irl_init_all = mv88e6352_g2_irl_init_all,
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
.port_set_speed = mv88e6250_port_set_speed,
.port_tag_remap = mv88e6095_port_tag_remap,
.port_set_frame_mode = mv88e6351_port_set_frame_mode,
.port_set_egress_floods = mv88e6352_port_set_egress_floods,
.port_set_ether_type = mv88e6351_port_set_ether_type,
.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
.port_pause_limit = mv88e6097_port_pause_limit,
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6250_port_link_state,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6250_stats_get_sset_count,
.stats_get_strings = mv88e6250_stats_get_strings,
.stats_get_stats = mv88e6250_stats_get_stats,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6250_watchdog_ops,
.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
.pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6250_g1_reset,
.vtu_getnext = mv88e6250_g1_vtu_getnext,
.vtu_loadpurge = mv88e6250_g1_vtu_loadpurge,
.phylink_validate = mv88e6065_phylink_validate,
};
static const struct mv88e6xxx_ops mv88e6290_ops = { static const struct mv88e6xxx_ops mv88e6290_ops = {
/* MV88E6XXX_FAMILY_6390 */ /* MV88E6XXX_FAMILY_6390 */
.setup_errata = mv88e6390_setup_errata, .setup_errata = mv88e6390_setup_errata,
...@@ -4233,6 +4289,27 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { ...@@ -4233,6 +4289,27 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.ops = &mv88e6240_ops, .ops = &mv88e6240_ops,
}, },
[MV88E6250] = {
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6250,
.family = MV88E6XXX_FAMILY_6250,
.name = "Marvell 88E6250",
.num_databases = 64,
.num_ports = 7,
.num_internal_phys = 5,
.max_vid = 4095,
.port_base_addr = 0x08,
.phy_base_addr = 0x00,
.global1_addr = 0x0f,
.global2_addr = 0x07,
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
.atu_move_port_mask = 0xf,
.dual_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA,
.ops = &mv88e6250_ops,
},
[MV88E6290] = { [MV88E6290] = {
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290, .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290,
.family = MV88E6XXX_FAMILY_6390, .family = MV88E6XXX_FAMILY_6390,
...@@ -4841,6 +4918,10 @@ static const struct of_device_id mv88e6xxx_of_match[] = { ...@@ -4841,6 +4918,10 @@ static const struct of_device_id mv88e6xxx_of_match[] = {
.compatible = "marvell,mv88e6190", .compatible = "marvell,mv88e6190",
.data = &mv88e6xxx_table[MV88E6190], .data = &mv88e6xxx_table[MV88E6190],
}, },
{
.compatible = "marvell,mv88e6250",
.data = &mv88e6xxx_table[MV88E6250],
},
{ /* sentinel */ }, { /* sentinel */ },
}; };
......
...@@ -62,6 +62,7 @@ enum mv88e6xxx_model { ...@@ -62,6 +62,7 @@ enum mv88e6xxx_model {
MV88E6190X, MV88E6190X,
MV88E6191, MV88E6191,
MV88E6240, MV88E6240,
MV88E6250,
MV88E6290, MV88E6290,
MV88E6320, MV88E6320,
MV88E6321, MV88E6321,
...@@ -80,6 +81,7 @@ enum mv88e6xxx_family { ...@@ -80,6 +81,7 @@ enum mv88e6xxx_family {
MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */ MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */
MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */ MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */
MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */ MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */
MV88E6XXX_FAMILY_6250, /* 6250 */
MV88E6XXX_FAMILY_6320, /* 6320 6321 */ MV88E6XXX_FAMILY_6320, /* 6320 6321 */
MV88E6XXX_FAMILY_6341, /* 6141 6341 */ MV88E6XXX_FAMILY_6341, /* 6141 6341 */
MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */
...@@ -112,6 +114,12 @@ struct mv88e6xxx_info { ...@@ -112,6 +114,12 @@ struct mv88e6xxx_info {
* when it is non-zero, and use indirect access to internal registers. * when it is non-zero, and use indirect access to internal registers.
*/ */
bool multi_chip; bool multi_chip;
/* Dual-chip Addressing Mode
* Some chips respond to only half of the 32 SMI addresses,
* allowing two to coexist on the same SMI interface.
*/
bool dual_chip;
enum dsa_tag_protocol tag_protocol; enum dsa_tag_protocol tag_protocol;
/* Mask for FromPort and ToPort value of PortVec used in ATU Move /* Mask for FromPort and ToPort value of PortVec used in ATU Move
......
...@@ -182,7 +182,7 @@ int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip) ...@@ -182,7 +182,7 @@ int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip)
return mv88e6185_g1_wait_ppu_polling(chip); return mv88e6185_g1_wait_ppu_polling(chip);
} }
int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip) int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip)
{ {
u16 val; u16 val;
int err; int err;
...@@ -198,7 +198,14 @@ int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip) ...@@ -198,7 +198,14 @@ int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
if (err) if (err)
return err; return err;
err = mv88e6xxx_g1_wait_init_ready(chip); return mv88e6xxx_g1_wait_init_ready(chip);
}
int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
{
int err;
err = mv88e6250_g1_reset(chip);
if (err) if (err)
return err; return err;
...@@ -299,6 +306,12 @@ int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip) ...@@ -299,6 +306,12 @@ int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip)
return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IEEE_PRI, 0xfa41); return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IEEE_PRI, 0xfa41);
} }
int mv88e6250_g1_ieee_pri_map(struct mv88e6xxx_chip *chip)
{
/* Reset the IEEE Tag priorities to defaults */
return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IEEE_PRI, 0xfa50);
}
/* Offset 0x1a: Monitor Control */ /* Offset 0x1a: Monitor Control */
/* Offset 0x1a: Monitor & MGMT Control on some devices */ /* Offset 0x1a: Monitor & MGMT Control on some devices */
......
...@@ -259,6 +259,7 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr); ...@@ -259,6 +259,7 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr);
int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip);
int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip);
int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip);
int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip);
int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip); 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,7 +278,9 @@ int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port);
int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip); int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
int mv88e6085_g1_ip_pri_map(struct mv88e6xxx_chip *chip); int mv88e6085_g1_ip_pri_map(struct mv88e6xxx_chip *chip);
int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip); int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip);
int mv88e6250_g1_ieee_pri_map(struct mv88e6xxx_chip *chip);
int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port); int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port);
...@@ -304,6 +307,10 @@ int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip, ...@@ -304,6 +307,10 @@ int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry); struct mv88e6xxx_vtu_entry *entry);
int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry); struct mv88e6xxx_vtu_entry *entry);
int mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry);
int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry);
int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip, int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry); struct mv88e6xxx_vtu_entry *entry);
int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
......
...@@ -94,7 +94,7 @@ static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op) ...@@ -94,7 +94,7 @@ static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op)
if (err) if (err)
return err; return err;
} else { } else {
if (mv88e6xxx_num_databases(chip) > 16) { if (mv88e6xxx_num_databases(chip) > 64) {
/* ATU DBNum[7:4] are located in ATU Control 15:12 */ /* ATU DBNum[7:4] are located in ATU Control 15:12 */
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL, err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL,
&val); &val);
...@@ -106,6 +106,9 @@ static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op) ...@@ -106,6 +106,9 @@ static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op)
val); val);
if (err) if (err)
return err; return err;
} else if (mv88e6xxx_num_databases(chip) > 16) {
/* ATU DBNum[5:4] are located in ATU Operation 9:8 */
op |= (fid & 0x30) << 4;
} }
/* ATU DBNum[3:0] are located in ATU Operation 3:0 */ /* ATU DBNum[3:0] are located in ATU Operation 3:0 */
......
...@@ -307,6 +307,35 @@ static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip, ...@@ -307,6 +307,35 @@ static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
return mv88e6xxx_g1_vtu_vid_read(chip, entry); return mv88e6xxx_g1_vtu_vid_read(chip, entry);
} }
int mv88e6250_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry)
{
u16 val;
int err;
err = mv88e6xxx_g1_vtu_getnext(chip, entry);
if (err)
return err;
if (entry->valid) {
err = mv88e6185_g1_vtu_data_read(chip, entry);
if (err)
return err;
/* VTU DBNum[3:0] are located in VTU Operation 3:0
* VTU DBNum[5:4] are located in VTU Operation 9:8
*/
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
if (err)
return err;
entry->fid = val & 0x000f;
entry->fid |= (val & 0x0300) >> 4;
}
return 0;
}
int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip, int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry) struct mv88e6xxx_vtu_entry *entry)
{ {
...@@ -396,6 +425,35 @@ int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip, ...@@ -396,6 +425,35 @@ int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
return 0; return 0;
} }
int mv88e6250_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry)
{
u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
int err;
err = mv88e6xxx_g1_vtu_op_wait(chip);
if (err)
return err;
err = mv88e6xxx_g1_vtu_vid_write(chip, entry);
if (err)
return err;
if (entry->valid) {
err = mv88e6185_g1_vtu_data_write(chip, entry);
if (err)
return err;
/* VTU DBNum[3:0] are located in VTU Operation 3:0
* VTU DBNum[5:4] are located in VTU Operation 9:8
*/
op |= entry->fid & 0x000f;
op |= (entry->fid & 0x0030) << 8;
}
return mv88e6xxx_g1_vtu_op(chip, op);
}
int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry) struct mv88e6xxx_vtu_entry *entry)
{ {
......
...@@ -816,6 +816,32 @@ const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = { ...@@ -816,6 +816,32 @@ const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {
.irq_free = mv88e6097_watchdog_free, .irq_free = mv88e6097_watchdog_free,
}; };
static void mv88e6250_watchdog_free(struct mv88e6xxx_chip *chip)
{
u16 reg;
mv88e6xxx_g2_read(chip, MV88E6250_G2_WDOG_CTL, &reg);
reg &= ~(MV88E6250_G2_WDOG_CTL_EGRESS_ENABLE |
MV88E6250_G2_WDOG_CTL_QC_ENABLE);
mv88e6xxx_g2_write(chip, MV88E6250_G2_WDOG_CTL, reg);
}
static int mv88e6250_watchdog_setup(struct mv88e6xxx_chip *chip)
{
return mv88e6xxx_g2_write(chip, MV88E6250_G2_WDOG_CTL,
MV88E6250_G2_WDOG_CTL_EGRESS_ENABLE |
MV88E6250_G2_WDOG_CTL_QC_ENABLE |
MV88E6250_G2_WDOG_CTL_SWRESET);
}
const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops = {
.irq_action = mv88e6097_watchdog_action,
.irq_setup = mv88e6250_watchdog_setup,
.irq_free = mv88e6250_watchdog_free,
};
static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip) static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip)
{ {
return mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL, return mv88e6xxx_g2_update(chip, MV88E6390_G2_WDOG_CTL,
......
...@@ -205,6 +205,18 @@ ...@@ -205,6 +205,18 @@
#define MV88E6XXX_G2_SCRATCH_MISC_PTR_MASK 0x7f00 #define MV88E6XXX_G2_SCRATCH_MISC_PTR_MASK 0x7f00
#define MV88E6XXX_G2_SCRATCH_MISC_DATA_MASK 0x00ff #define MV88E6XXX_G2_SCRATCH_MISC_DATA_MASK 0x00ff
/* Offset 0x1B: Watch Dog Control Register */
#define MV88E6250_G2_WDOG_CTL 0x1b
#define MV88E6250_G2_WDOG_CTL_QC_HISTORY 0x0100
#define MV88E6250_G2_WDOG_CTL_QC_EVENT 0x0080
#define MV88E6250_G2_WDOG_CTL_QC_ENABLE 0x0040
#define MV88E6250_G2_WDOG_CTL_EGRESS_HISTORY 0x0020
#define MV88E6250_G2_WDOG_CTL_EGRESS_EVENT 0x0010
#define MV88E6250_G2_WDOG_CTL_EGRESS_ENABLE 0x0008
#define MV88E6250_G2_WDOG_CTL_FORCE_IRQ 0x0004
#define MV88E6250_G2_WDOG_CTL_HISTORY 0x0002
#define MV88E6250_G2_WDOG_CTL_SWRESET 0x0001
/* Offset 0x1B: Watch Dog Control Register */ /* Offset 0x1B: Watch Dog Control Register */
#define MV88E6352_G2_WDOG_CTL 0x1b #define MV88E6352_G2_WDOG_CTL 0x1b
#define MV88E6352_G2_WDOG_CTL_EGRESS_EVENT 0x0080 #define MV88E6352_G2_WDOG_CTL_EGRESS_EVENT 0x0080
...@@ -334,6 +346,7 @@ int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, ...@@ -334,6 +346,7 @@ int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target,
int port); int port);
extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops;
extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops;
extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops; extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops;
extern const struct mv88e6xxx_avb_ops mv88e6165_avb_ops; 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,6 +497,7 @@ static inline int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip)
} }
static const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {}; static const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {};
static const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops = {};
static const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {}; static const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {};
static const struct mv88e6xxx_avb_ops mv88e6165_avb_ops = {}; static const struct mv88e6xxx_avb_ops mv88e6165_avb_ops = {};
......
...@@ -294,6 +294,18 @@ int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) ...@@ -294,6 +294,18 @@ int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
return mv88e6xxx_port_set_speed(chip, port, speed, false, false); return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
} }
/* Support 10, 100 Mbps (e.g. 88E6250 family) */
int mv88e6250_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
{
if (speed == SPEED_MAX)
speed = 100;
if (speed > 100)
return -EOPNOTSUPP;
return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
}
/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6341) */ /* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6341) */
int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed) int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
{ {
...@@ -521,6 +533,71 @@ int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode) ...@@ -521,6 +533,71 @@ int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
return 0; return 0;
} }
int mv88e6250_port_link_state(struct mv88e6xxx_chip *chip, int port,
struct phylink_link_state *state)
{
int err;
u16 reg;
err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
if (err)
return err;
if (port < 5) {
switch (reg & MV88E6250_PORT_STS_PORTMODE_MASK) {
case MV88E6250_PORT_STS_PORTMODE_PHY_10_HALF:
state->speed = SPEED_10;
state->duplex = DUPLEX_HALF;
break;
case MV88E6250_PORT_STS_PORTMODE_PHY_100_HALF:
state->speed = SPEED_100;
state->duplex = DUPLEX_HALF;
break;
case MV88E6250_PORT_STS_PORTMODE_PHY_10_FULL:
state->speed = SPEED_10;
state->duplex = DUPLEX_FULL;
break;
case MV88E6250_PORT_STS_PORTMODE_PHY_100_FULL:
state->speed = SPEED_100;
state->duplex = DUPLEX_FULL;
break;
default:
state->speed = SPEED_UNKNOWN;
state->duplex = DUPLEX_UNKNOWN;
break;
}
} else {
switch (reg & MV88E6250_PORT_STS_PORTMODE_MASK) {
case MV88E6250_PORT_STS_PORTMODE_MII_10_HALF:
state->speed = SPEED_10;
state->duplex = DUPLEX_HALF;
break;
case MV88E6250_PORT_STS_PORTMODE_MII_100_HALF:
state->speed = SPEED_100;
state->duplex = DUPLEX_HALF;
break;
case MV88E6250_PORT_STS_PORTMODE_MII_10_FULL:
state->speed = SPEED_10;
state->duplex = DUPLEX_FULL;
break;
case MV88E6250_PORT_STS_PORTMODE_MII_100_FULL:
state->speed = SPEED_100;
state->duplex = DUPLEX_FULL;
break;
default:
state->speed = SPEED_UNKNOWN;
state->duplex = DUPLEX_UNKNOWN;
break;
}
}
state->link = !!(reg & MV88E6250_PORT_STS_LINK);
state->an_enabled = 1;
state->an_complete = state->link;
return 0;
}
int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port, int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port,
struct phylink_link_state *state) struct phylink_link_state *state)
{ {
......
...@@ -23,6 +23,16 @@ ...@@ -23,6 +23,16 @@
#define MV88E6XXX_PORT_STS_MY_PAUSE 0x4000 #define MV88E6XXX_PORT_STS_MY_PAUSE 0x4000
#define MV88E6XXX_PORT_STS_HD_FLOW 0x2000 #define MV88E6XXX_PORT_STS_HD_FLOW 0x2000
#define MV88E6XXX_PORT_STS_PHY_DETECT 0x1000 #define MV88E6XXX_PORT_STS_PHY_DETECT 0x1000
#define MV88E6250_PORT_STS_LINK 0x1000
#define MV88E6250_PORT_STS_PORTMODE_MASK 0x0f00
#define MV88E6250_PORT_STS_PORTMODE_PHY_10_HALF 0x0800
#define MV88E6250_PORT_STS_PORTMODE_PHY_100_HALF 0x0900
#define MV88E6250_PORT_STS_PORTMODE_PHY_10_FULL 0x0a00
#define MV88E6250_PORT_STS_PORTMODE_PHY_100_FULL 0x0b00
#define MV88E6250_PORT_STS_PORTMODE_MII_10_HALF 0x0c00
#define MV88E6250_PORT_STS_PORTMODE_MII_100_HALF 0x0d00
#define MV88E6250_PORT_STS_PORTMODE_MII_10_FULL 0x0e00
#define MV88E6250_PORT_STS_PORTMODE_MII_100_FULL 0x0f00
#define MV88E6XXX_PORT_STS_LINK 0x0800 #define MV88E6XXX_PORT_STS_LINK 0x0800
#define MV88E6XXX_PORT_STS_DUPLEX 0x0400 #define MV88E6XXX_PORT_STS_DUPLEX 0x0400
#define MV88E6XXX_PORT_STS_SPEED_MASK 0x0300 #define MV88E6XXX_PORT_STS_SPEED_MASK 0x0300
...@@ -112,6 +122,7 @@ ...@@ -112,6 +122,7 @@
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6191 0x1910 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6191 0x1910
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6185 0x1a70 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6185 0x1a70
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400 #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,6 +290,7 @@ int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup);
int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
int mv88e6250_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); int mv88e6341_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed); 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,6 +344,8 @@ int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode); int mv88e6352_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
int mv88e6185_port_link_state(struct mv88e6xxx_chip *chip, int port, int mv88e6185_port_link_state(struct mv88e6xxx_chip *chip, int port,
struct phylink_link_state *state); struct phylink_link_state *state);
int mv88e6250_port_link_state(struct mv88e6xxx_chip *chip, int port,
struct phylink_link_state *state);
int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port, int mv88e6352_port_link_state(struct mv88e6xxx_chip *chip, int port,
struct phylink_link_state *state); struct phylink_link_state *state);
int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port); int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port);
......
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
* When ADDR is non-zero, the chip uses Multi-chip Addressing Mode, allowing * When ADDR is non-zero, the chip uses Multi-chip Addressing Mode, allowing
* multiple devices to share the SMI interface. In this mode it responds to only * multiple devices to share the SMI interface. In this mode it responds to only
* 2 registers, used to indirectly access the internal SMI devices. * 2 registers, used to indirectly access the internal SMI devices.
*
* Some chips use a different scheme: Only the ADDR4 pin is used for
* configuration, and the device responds to 16 of the 32 SMI
* addresses, allowing two to coexist on the same SMI interface.
*/ */
static int mv88e6xxx_smi_direct_read(struct mv88e6xxx_chip *chip, 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,6 +80,23 @@ static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_direct_ops = {
.write = mv88e6xxx_smi_direct_write, .write = mv88e6xxx_smi_direct_write,
}; };
static int mv88e6xxx_smi_dual_direct_read(struct mv88e6xxx_chip *chip,
int dev, int reg, u16 *data)
{
return mv88e6xxx_smi_direct_read(chip, chip->sw_addr + dev, reg, data);
}
static int mv88e6xxx_smi_dual_direct_write(struct mv88e6xxx_chip *chip,
int dev, int reg, u16 data)
{
return mv88e6xxx_smi_direct_write(chip, chip->sw_addr + dev, reg, data);
}
static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_dual_direct_ops = {
.read = mv88e6xxx_smi_dual_direct_read,
.write = mv88e6xxx_smi_dual_direct_write,
};
/* Offset 0x00: SMI Command Register /* Offset 0x00: SMI Command Register
* Offset 0x01: SMI Data Register * Offset 0x01: SMI Data Register
*/ */
...@@ -144,7 +165,9 @@ static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_indirect_ops = { ...@@ -144,7 +165,9 @@ static const struct mv88e6xxx_bus_ops mv88e6xxx_smi_indirect_ops = {
int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip, int mv88e6xxx_smi_init(struct mv88e6xxx_chip *chip,
struct mii_bus *bus, int sw_addr) struct mii_bus *bus, int sw_addr)
{ {
if (sw_addr == 0) if (chip->info->dual_chip)
chip->smi_ops = &mv88e6xxx_smi_dual_direct_ops;
else if (sw_addr == 0)
chip->smi_ops = &mv88e6xxx_smi_direct_ops; chip->smi_ops = &mv88e6xxx_smi_direct_ops;
else if (chip->info->multi_chip) else if (chip->info->multi_chip)
chip->smi_ops = &mv88e6xxx_smi_indirect_ops; chip->smi_ops = &mv88e6xxx_smi_indirect_ops;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment