Commit c1b18f20 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mv88e6xxx-Add-SERDES-PCS-registers-to-ethtool-dump'



Andrew Lunn says:

====================
mv88e6xxx: Add SERDES/PCS registers to ethtool -d

ethtool -d will dump the registers of an interface. For mv88e6xxx
switch ports, this dump covers the port specific registers. Extend
this with the SERDES/PCS registers, if a port has a SERDES.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 27aa6228 bf3504ce
Loading
Loading
Loading
Loading
+31 −1
Original line number Diff line number Diff line
@@ -1018,7 +1018,14 @@ static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,

static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
{
	return 32 * sizeof(u16);
	struct mv88e6xxx_chip *chip = ds->priv;
	int len;

	len = 32 * sizeof(u16);
	if (chip->info->ops->serdes_get_regs_len)
		len += chip->info->ops->serdes_get_regs_len(chip, port);

	return len;
}

static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
@@ -1043,6 +1050,9 @@ static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
			p[i] = reg;
	}

	if (chip->info->ops->serdes_get_regs)
		chip->info->ops->serdes_get_regs(chip, port, &p[i]);

	mv88e6xxx_reg_unlock(chip);
}

@@ -3664,6 +3674,8 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.serdes_get_lane = mv88e6352_serdes_get_lane,
	.serdes_power = mv88e6352_serdes_power,
	.serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
	.serdes_get_regs = mv88e6352_serdes_get_regs,
	.gpio_ops = &mv88e6352_gpio_ops,
	.phylink_validate = mv88e6352_phylink_validate,
};
@@ -3758,6 +3770,8 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
	.serdes_irq_status = mv88e6352_serdes_irq_status,
	.serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
	.serdes_get_regs = mv88e6352_serdes_get_regs,
	.gpio_ops = &mv88e6352_gpio_ops,
	.phylink_validate = mv88e6352_phylink_validate,
};
@@ -3847,6 +3861,8 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
	.serdes_irq_status = mv88e6390_serdes_irq_status,
	.serdes_get_strings = mv88e6390_serdes_get_strings,
	.serdes_get_stats = mv88e6390_serdes_get_stats,
	.serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
	.serdes_get_regs = mv88e6390_serdes_get_regs,
	.phylink_validate = mv88e6390_phylink_validate,
	.gpio_ops = &mv88e6352_gpio_ops,
	.phylink_validate = mv88e6390_phylink_validate,
@@ -3901,6 +3917,8 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
	.serdes_irq_status = mv88e6390_serdes_irq_status,
	.serdes_get_strings = mv88e6390_serdes_get_strings,
	.serdes_get_stats = mv88e6390_serdes_get_stats,
	.serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
	.serdes_get_regs = mv88e6390_serdes_get_regs,
	.phylink_validate = mv88e6390_phylink_validate,
	.gpio_ops = &mv88e6352_gpio_ops,
	.phylink_validate = mv88e6390x_phylink_validate,
@@ -3954,6 +3972,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
	.serdes_irq_status = mv88e6390_serdes_irq_status,
	.serdes_get_strings = mv88e6390_serdes_get_strings,
	.serdes_get_stats = mv88e6390_serdes_get_stats,
	.serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
	.serdes_get_regs = mv88e6390_serdes_get_regs,
	.phylink_validate = mv88e6390_phylink_validate,
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
@@ -4008,6 +4028,8 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
	.serdes_irq_mapping = mv88e6352_serdes_irq_mapping,
	.serdes_irq_enable = mv88e6352_serdes_irq_enable,
	.serdes_irq_status = mv88e6352_serdes_irq_status,
	.serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
	.serdes_get_regs = mv88e6352_serdes_get_regs,
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6352_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
@@ -4103,6 +4125,8 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
	.serdes_irq_status = mv88e6390_serdes_irq_status,
	.serdes_get_strings = mv88e6390_serdes_get_strings,
	.serdes_get_stats = mv88e6390_serdes_get_stats,
	.serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
	.serdes_get_regs = mv88e6390_serdes_get_regs,
	.phylink_validate = mv88e6390_phylink_validate,
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6390_avb_ops,
@@ -4388,6 +4412,8 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
	.serdes_get_sset_count = mv88e6352_serdes_get_sset_count,
	.serdes_get_strings = mv88e6352_serdes_get_strings,
	.serdes_get_stats = mv88e6352_serdes_get_stats,
	.serdes_get_regs_len = mv88e6352_serdes_get_regs_len,
	.serdes_get_regs = mv88e6352_serdes_get_regs,
	.phylink_validate = mv88e6352_phylink_validate,
};

@@ -4446,6 +4472,8 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
	.serdes_get_sset_count = mv88e6390_serdes_get_sset_count,
	.serdes_get_strings = mv88e6390_serdes_get_strings,
	.serdes_get_stats = mv88e6390_serdes_get_stats,
	.serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
	.serdes_get_regs = mv88e6390_serdes_get_regs,
	.phylink_validate = mv88e6390_phylink_validate,
};

@@ -4501,6 +4529,8 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
	.serdes_get_sset_count = mv88e6390_serdes_get_sset_count,
	.serdes_get_strings = mv88e6390_serdes_get_strings,
	.serdes_get_stats = mv88e6390_serdes_get_stats,
	.serdes_get_regs_len = mv88e6390_serdes_get_regs_len,
	.serdes_get_regs = mv88e6390_serdes_get_regs,
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
+5 −0
Original line number Diff line number Diff line
@@ -517,6 +517,11 @@ struct mv88e6xxx_ops {
	int (*serdes_get_stats)(struct mv88e6xxx_chip *chip,  int port,
				uint64_t *data);

	/* SERDES registers for ethtool */
	int (*serdes_get_regs_len)(struct mv88e6xxx_chip *chip,  int port);
	void (*serdes_get_regs)(struct mv88e6xxx_chip *chip, int port,
				void *_p);

	/* Address Translation Unit operations */
	int (*atu_get_hash)(struct mv88e6xxx_chip *chip, u8 *hash);
	int (*atu_set_hash)(struct mv88e6xxx_chip *chip, u8 hash);
+77 −0
Original line number Diff line number Diff line
@@ -237,6 +237,29 @@ unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
	return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ);
}

int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
{
	if (!mv88e6352_port_has_serdes(chip, port))
		return 0;

	return 32 * sizeof(u16);
}

void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
{
	u16 *p = _p;
	u16 reg;
	int i;

	if (!mv88e6352_port_has_serdes(chip, port))
		return;

	for (i = 0 ; i < 32; i++) {
		mv88e6352_serdes_read(chip, i, &reg);
		p[i] = reg;
	}
}

u8 mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
{
	u8 cmode = chip->ports[port].cmode;
@@ -652,3 +675,57 @@ unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
{
	return irq_find_mapping(chip->g2_irq.domain, port);
}

static const u16 mv88e6390_serdes_regs[] = {
	/* SERDES common registers */
	0xf00a, 0xf00b, 0xf00c,
	0xf010, 0xf011, 0xf012, 0xf013,
	0xf016, 0xf017, 0xf018,
	0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
	0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
	0xf028, 0xf029,
	0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
	0xf038, 0xf039,
	/* SGMII */
	0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
	0x2008,
	0x200f,
	0xa000, 0xa001, 0xa002, 0xa003,
	/* 10Gbase-X */
	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
	0x1008,
	0x100e, 0x100f,
	0x1018, 0x1019,
	0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
	0x9006,
	0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
	/* 10Gbase-R */
	0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
	0x1028, 0x1029, 0x102a, 0x102b,
};

int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
{
	if (mv88e6xxx_serdes_get_lane(chip, port) == 0)
		return 0;

	return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
}

void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
{
	u16 *p = _p;
	int lane;
	u16 reg;
	int i;

	lane = mv88e6xxx_serdes_get_lane(chip, port);
	if (lane == 0)
		return;

	for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
		mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
				      mv88e6390_serdes_regs[i], &reg);
		p[i] = reg;
	}
}
+5 −0
Original line number Diff line number Diff line
@@ -109,6 +109,11 @@ int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
			       uint64_t *data);

int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port);
void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p);
int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port);
void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p);

/* Return the (first) SERDES lane address a port is using, 0 otherwise. */
static inline u8 mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
					   int port)