All of lore.kernel.org
 help / color / mirror / Atom feed
* [net-next 0/8] More MV88E6390 patches
@ 2017-01-20 23:30 Andrew Lunn
  2017-01-20 23:30 ` [PATCH net-next 1/8] net: dsa: mv88e6xxx: Implement external MDIO bus on mv88e6390 Andrew Lunn
                   ` (8 more replies)
  0 siblings, 9 replies; 22+ messages in thread
From: Andrew Lunn @ 2017-01-20 23:30 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Vivien Didelot, Andrew Lunn

This is the ongoing work to add support for the Marvell 9390 family of
switches. There are now two MDIO busses, one for the internal PHYs and
an external bus for external PHYs. Add support for this external bus.

This switch supports 2Gbps, 2.5Gbps and 10Gbps ports. Add phy-modes
for these speeds/interfaces. These modes are then used to configure
ports 9 and 10, which support these speeds.

The internal PHYs oddly use a Marvell Vendor ID, but have empty
product ID. Trap reads of the product ID, and if it returns 0,
instead return the switch family ID. The Marvell PHY driver is then
extended to support this ID, treating the PHY as compatible with the
1540.

Both the internal and external MDIO busses are capable of clause 45
addressing, and is required to accessing the SERDES
interfaces. Implement support for clause 45.

And two fixes are included. There is no need to port these to stable,
the current support for the 6390 is not sufficient to be usable.

Andrew Lunn (8):
  net: dsa: mv88e6xxx: Implement external MDIO bus on mv88e6390
  net: phy: Add 2000base-x, 2500base-x and rxaui modes
  net: dsa: mv88e6xxx: Fix ATU age timer for MV88E6390
  net: dsa: mv88e6xxx: Set the CMODE for mv88e6390 ports 9 & 10
  net: dsa: mv88e6xxx: Workaround missing PHY ID on mv88e6390
  net: phy: Marvell: Add mv88e6390 internal PHY
  net: dsa: mv88e6xxx: Implement Clause 45 access to SMI devices
  net: dsa: mv88e6xxx: Fix typ0 when configuring 2.5Gbps

 .../devicetree/bindings/net/dsa/marvell.txt        |   4 +
 Documentation/devicetree/bindings/net/ethernet.txt |   3 +
 drivers/net/dsa/mv88e6xxx/chip.c                   | 168 ++++++++++++++++-----
 drivers/net/dsa/mv88e6xxx/global2.c                | 130 +++++++++++++++-
 drivers/net/dsa/mv88e6xxx/global2.h                |   4 +-
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h              |  55 +++++--
 drivers/net/dsa/mv88e6xxx/port.c                   |  66 +++++++-
 drivers/net/dsa/mv88e6xxx/port.h                   |   3 +
 drivers/net/phy/marvell.c                          |  20 +++
 include/linux/marvell_phy.h                        |   6 +
 include/linux/phy.h                                |   9 ++
 11 files changed, 409 insertions(+), 59 deletions(-)

-- 
2.11.0

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH net-next 1/8] net: dsa: mv88e6xxx: Implement external MDIO bus on mv88e6390
  2017-01-20 23:30 [net-next 0/8] More MV88E6390 patches Andrew Lunn
@ 2017-01-20 23:30 ` Andrew Lunn
  2017-01-21  0:01   ` Florian Fainelli
  2017-01-21  0:04   ` Vivien Didelot
  2017-01-20 23:30 ` [PATCH net-next 2/8] net: phy: Add 2000base-x, 2500base-x and rxaui modes Andrew Lunn
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 22+ messages in thread
From: Andrew Lunn @ 2017-01-20 23:30 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Vivien Didelot, Andrew Lunn

The mv88e6390 has two MDIO busses. The internal MDIO bus is used for
the internal PHYs. The external MDIO can be used for external PHYs.
The external MDIO bus will be instantiated if there is an
"mdio-external" node in the device tree.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 .../devicetree/bindings/net/dsa/marvell.txt        |   4 +
 drivers/net/dsa/mv88e6xxx/chip.c                   | 136 +++++++++++++++++----
 drivers/net/dsa/mv88e6xxx/global2.c                |  10 +-
 drivers/net/dsa/mv88e6xxx/global2.h                |   4 +-
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h              |  35 ++++--
 5 files changed, 148 insertions(+), 41 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt
index b3dd6b40e0de..51b881f1645e 100644
--- a/Documentation/devicetree/bindings/net/dsa/marvell.txt
+++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt
@@ -28,6 +28,10 @@ Optional properties:
 #interrupt-cells = <2>	: Controller uses two cells, number and flag
 - mdio			: container of PHY and devices on the switches MDIO
 			  bus
+
+Optional for the "marvell,mv88e6390"
+- mdio-external		: A collection of PHY nodes on external bus
+
 Example:
 
        mdio {
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index c7e08e13bb54..77e960826402 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -206,6 +206,12 @@ int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val)
 	return 0;
 }
 
+static int mv88e6xxx_read_phy(struct mv88e6xxx_chip *chip, int addr, int reg,
+			      u16 *val, bool external)
+{
+	return mv88e6xxx_read(chip, addr, reg, val);
+}
+
 int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)
 {
 	int err;
@@ -222,26 +228,32 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)
 	return 0;
 }
 
+static int mv88e6xxx_write_phy(struct mv88e6xxx_chip *chip, int addr, int reg,
+			       u16 val, bool external)
+{
+	return mv88e6xxx_write(chip, addr, reg, val);
+}
+
 static int mv88e6xxx_phy_read(struct mv88e6xxx_chip *chip, int phy,
-			      int reg, u16 *val)
+			      int reg, u16 *val, bool external)
 {
 	int addr = phy; /* PHY devices addresses start at 0x0 */
 
 	if (!chip->info->ops->phy_read)
 		return -EOPNOTSUPP;
 
-	return chip->info->ops->phy_read(chip, addr, reg, val);
+	return chip->info->ops->phy_read(chip, addr, reg, val, external);
 }
 
 static int mv88e6xxx_phy_write(struct mv88e6xxx_chip *chip, int phy,
-			       int reg, u16 val)
+			       int reg, u16 val, bool external)
 {
 	int addr = phy; /* PHY devices addresses start at 0x0 */
 
 	if (!chip->info->ops->phy_write)
 		return -EOPNOTSUPP;
 
-	return chip->info->ops->phy_write(chip, addr, reg, val);
+	return chip->info->ops->phy_write(chip, addr, reg, val, external);
 }
 
 static int mv88e6xxx_phy_page_get(struct mv88e6xxx_chip *chip, int phy, u8 page)
@@ -249,7 +261,7 @@ static int mv88e6xxx_phy_page_get(struct mv88e6xxx_chip *chip, int phy, u8 page)
 	if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_PHY_PAGE))
 		return -EOPNOTSUPP;
 
-	return mv88e6xxx_phy_write(chip, phy, PHY_PAGE, page);
+	return mv88e6xxx_phy_write(chip, phy, PHY_PAGE, page, false);
 }
 
 static void mv88e6xxx_phy_page_put(struct mv88e6xxx_chip *chip, int phy)
@@ -257,7 +269,7 @@ static void mv88e6xxx_phy_page_put(struct mv88e6xxx_chip *chip, int phy)
 	int err;
 
 	/* Restore PHY page Copper 0x0 for access via the registered MDIO bus */
-	err = mv88e6xxx_phy_write(chip, phy, PHY_PAGE, PHY_PAGE_COPPER);
+	err = mv88e6xxx_phy_write(chip, phy, PHY_PAGE, PHY_PAGE_COPPER, false);
 	if (unlikely(err)) {
 		dev_err(chip->dev, "failed to restore PHY %d page Copper (%d)\n",
 			phy, err);
@@ -275,7 +287,7 @@ static int mv88e6xxx_phy_page_read(struct mv88e6xxx_chip *chip, int phy,
 
 	err = mv88e6xxx_phy_page_get(chip, phy, page);
 	if (!err) {
-		err = mv88e6xxx_phy_read(chip, phy, reg, val);
+		err = mv88e6xxx_phy_read(chip, phy, reg, val, false);
 		mv88e6xxx_phy_page_put(chip, phy);
 	}
 
@@ -293,7 +305,7 @@ static int mv88e6xxx_phy_page_write(struct mv88e6xxx_chip *chip, int phy,
 
 	err = mv88e6xxx_phy_page_get(chip, phy, page);
 	if (!err) {
-		err = mv88e6xxx_phy_write(chip, phy, PHY_PAGE, page);
+		err = mv88e6xxx_phy_write(chip, phy, PHY_PAGE, page, false);
 		mv88e6xxx_phy_page_put(chip, phy);
 	}
 
@@ -612,7 +624,7 @@ static void mv88e6xxx_ppu_state_destroy(struct mv88e6xxx_chip *chip)
 }
 
 static int mv88e6xxx_phy_ppu_read(struct mv88e6xxx_chip *chip, int addr,
-				  int reg, u16 *val)
+				  int reg, u16 *val, bool external)
 {
 	int err;
 
@@ -626,7 +638,7 @@ static int mv88e6xxx_phy_ppu_read(struct mv88e6xxx_chip *chip, int addr,
 }
 
 static int mv88e6xxx_phy_ppu_write(struct mv88e6xxx_chip *chip, int addr,
-				   int reg, u16 val)
+				   int reg, u16 val, bool external)
 {
 	int err;
 
@@ -1044,7 +1056,7 @@ static int mv88e6xxx_get_eee(struct dsa_switch *ds, int port,
 
 	mutex_lock(&chip->reg_lock);
 
-	err = mv88e6xxx_phy_read(chip, port, 16, &reg);
+	err = mv88e6xxx_phy_read(chip, port, 16, &reg, false);
 	if (err)
 		goto out;
 
@@ -1074,7 +1086,7 @@ static int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
 
 	mutex_lock(&chip->reg_lock);
 
-	err = mv88e6xxx_phy_read(chip, port, 16, &reg);
+	err = mv88e6xxx_phy_read(chip, port, 16, &reg, false);
 	if (err)
 		goto out;
 
@@ -1084,7 +1096,7 @@ static int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
 	if (e->tx_lpi_enabled)
 		reg |= 0x0100;
 
-	err = mv88e6xxx_phy_write(chip, port, 16, reg);
+	err = mv88e6xxx_phy_write(chip, port, 16, reg, false);
 out:
 	mutex_unlock(&chip->reg_lock);
 
@@ -2878,7 +2890,8 @@ static int mv88e6xxx_set_addr(struct dsa_switch *ds, u8 *addr)
 
 static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
 {
-	struct mv88e6xxx_chip *chip = bus->priv;
+	struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
+	struct mv88e6xxx_chip *chip = mdio_bus->chip;
 	u16 val;
 	int err;
 
@@ -2886,7 +2899,7 @@ static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
 		return 0xffff;
 
 	mutex_lock(&chip->reg_lock);
-	err = mv88e6xxx_phy_read(chip, phy, reg, &val);
+	err = mv88e6xxx_phy_read(chip, phy, reg, &val, mdio_bus->external);
 	mutex_unlock(&chip->reg_lock);
 
 	return err ? err : val;
@@ -2894,34 +2907,90 @@ static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
 
 static int mv88e6xxx_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
 {
-	struct mv88e6xxx_chip *chip = bus->priv;
+	struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
+	struct mv88e6xxx_chip *chip = mdio_bus->chip;
 	int err;
 
 	if (phy >= mv88e6xxx_num_ports(chip))
 		return 0xffff;
 
 	mutex_lock(&chip->reg_lock);
-	err = mv88e6xxx_phy_write(chip, phy, reg, val);
+	err = mv88e6xxx_phy_write(chip, phy, reg, val, mdio_bus->external);
 	mutex_unlock(&chip->reg_lock);
 
 	return err;
 }
 
+static int mv88e6xxx_external_mdio_register(struct mv88e6xxx_chip *chip,
+					    struct device_node *np)
+{
+	struct mv88e6xxx_mdio_bus *mdio_bus;
+	struct mii_bus *bus;
+	int err;
+
+	chip->external_mdio_np = of_get_child_by_name(np, "mdio-external");
+
+	if (!chip->external_mdio_np)
+		return 0;
+
+	bus = devm_mdiobus_alloc_size(chip->dev, sizeof(*bus));
+	if (!bus)
+		return -ENOMEM;
+
+	mdio_bus = bus->priv;
+	mdio_bus->chip = chip;
+	mdio_bus->external = true;
+
+	bus->name = np->full_name;
+	snprintf(bus->id, MII_BUS_ID_SIZE, "ext-%s", np->full_name);
+
+	bus->read = mv88e6xxx_mdio_read;
+	bus->write = mv88e6xxx_mdio_write;
+	bus->parent = chip->dev;
+
+	err = of_mdiobus_register(bus, chip->external_mdio_np);
+	if (err) {
+		dev_err(chip->dev, "Cannot register external MDIO bus (%d)\n",
+			err);
+		of_node_put(chip->mdio_np);
+		return err;
+	}
+
+	chip->external_mdio_bus = bus;
+
+	return 0;
+}
+
+static void mv88e6xxx_external_mdio_unregister(struct mv88e6xxx_chip *chip)
+{
+	struct mii_bus *bus = chip->external_mdio_bus;
+
+	if (bus) {
+		mdiobus_unregister(bus);
+
+		of_node_put(chip->external_mdio_np);
+	}
+}
+
 static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
 				   struct device_node *np)
 {
-	static int index;
+	struct mv88e6xxx_mdio_bus *mdio_bus;
 	struct mii_bus *bus;
+	static int index;
 	int err;
 
 	if (np)
 		chip->mdio_np = of_get_child_by_name(np, "mdio");
 
-	bus = devm_mdiobus_alloc(chip->dev);
+	bus = devm_mdiobus_alloc_size(chip->dev, sizeof(*bus));
 	if (!bus)
 		return -ENOMEM;
 
-	bus->priv = (void *)chip;
+	mdio_bus = bus->priv;
+	mdio_bus->chip = chip;
+	mdio_bus->external = false;
+
 	if (np) {
 		bus->name = np->full_name;
 		snprintf(bus->id, MII_BUS_ID_SIZE, "%s", np->full_name);
@@ -3085,8 +3154,8 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
 static const struct mv88e6xxx_ops mv88e6123_ops = {
 	/* MV88E6XXX_FAMILY_6165 */
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
-	.phy_read = mv88e6xxx_read,
-	.phy_write = mv88e6xxx_write,
+	.phy_read = mv88e6xxx_read_phy,
+	.phy_write = mv88e6xxx_write_phy,
 	.port_set_link = mv88e6xxx_port_set_link,
 	.port_set_duplex = mv88e6xxx_port_set_duplex,
 	.port_set_speed = mv88e6185_port_set_speed,
@@ -3132,8 +3201,8 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
 static const struct mv88e6xxx_ops mv88e6161_ops = {
 	/* MV88E6XXX_FAMILY_6165 */
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
-	.phy_read = mv88e6xxx_read,
-	.phy_write = mv88e6xxx_write,
+	.phy_read = mv88e6xxx_read_phy,
+	.phy_write = mv88e6xxx_write_phy,
 	.port_set_link = mv88e6xxx_port_set_link,
 	.port_set_duplex = mv88e6xxx_port_set_duplex,
 	.port_set_speed = mv88e6185_port_set_speed,
@@ -3157,8 +3226,8 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
 static const struct mv88e6xxx_ops mv88e6165_ops = {
 	/* MV88E6XXX_FAMILY_6165 */
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
-	.phy_read = mv88e6xxx_read,
-	.phy_write = mv88e6xxx_write,
+	.phy_read = mv88e6xxx_read_phy,
+	.phy_write = mv88e6xxx_write_phy,
 	.port_set_link = mv88e6xxx_port_set_link,
 	.port_set_duplex = mv88e6xxx_port_set_duplex,
 	.port_set_speed = mv88e6185_port_set_speed,
@@ -4367,12 +4436,21 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
 	if (err)
 		goto out_g2_irq;
 
+	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_EXTERNAL_MDIO)) {
+		err = mv88e6xxx_external_mdio_register(chip, np);
+		if (err)
+			goto out_mdio;
+	}
+
 	err = mv88e6xxx_register_switch(chip, np);
 	if (err)
-		goto out_mdio;
+		goto out_mdio_external;
 
 	return 0;
 
+out_mdio_external:
+	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_EXTERNAL_MDIO))
+		mv88e6xxx_external_mdio_unregister(chip);
 out_mdio:
 	mv88e6xxx_mdio_unregister(chip);
 out_g2_irq:
@@ -4395,6 +4473,10 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
 
 	mv88e6xxx_phy_destroy(chip);
 	mv88e6xxx_unregister_switch(chip);
+
+	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_EXTERNAL_MDIO))
+		mv88e6xxx_external_mdio_unregister(chip);
+
 	mv88e6xxx_mdio_unregister(chip);
 
 	if (chip->irq > 0) {
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index ead2e265c9ef..5c9ccb6775ae 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -502,11 +502,14 @@ static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
 }
 
 int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, int addr, int reg,
-			      u16 *val)
+			      u16 *val, bool external)
 {
 	u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_READ_DATA | (addr << 5) | reg;
 	int err;
 
+	if (external)
+		cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL;
+
 	err = mv88e6xxx_g2_smi_phy_wait(chip);
 	if (err)
 		return err;
@@ -519,11 +522,14 @@ int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, int addr, int reg,
 }
 
 int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg,
-			       u16 val)
+			       u16 val, bool external)
 {
 	u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_WRITE_DATA | (addr << 5) | reg;
 	int err;
 
+	if (external)
+		cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL;
+
 	err = mv88e6xxx_g2_smi_phy_wait(chip);
 	if (err)
 		return err;
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h
index 2918f22388f7..080afb50c21d 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -24,9 +24,9 @@ static inline int mv88e6xxx_g2_require(struct mv88e6xxx_chip *chip)
 }
 
 int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, int addr, int reg,
-			      u16 *val);
+			      u16 *val, bool external);
 int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg,
-			       u16 val);
+			       u16 val, bool external);
 int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr);
 
 int mv88e6xxx_g2_get_eeprom8(struct mv88e6xxx_chip *chip,
diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index ce8b43b14e96..b7f60a1bd4dc 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -387,6 +387,8 @@
 #define GLOBAL2_PTP_AVB_DATA	0x17
 #define GLOBAL2_SMI_PHY_CMD			0x18
 #define GLOBAL2_SMI_PHY_CMD_BUSY		BIT(15)
+#define GLOBAL2_SMI_PHY_CMD_INTERNAL		(0x0 << 13)
+#define GLOBAL2_SMI_PHY_CMD_EXTERNAL		(0x1 << 13)
 #define GLOBAL2_SMI_PHY_CMD_MODE_22		BIT(12)
 #define GLOBAL2_SMI_PHY_CMD_OP_22_WRITE_DATA	((0x1 << 10) | \
 						 GLOBAL2_SMI_PHY_CMD_MODE_22 | \
@@ -490,6 +492,7 @@ enum mv88e6xxx_cap {
 	MV88E6XXX_CAP_G2_PVT_ADDR,	/* (0x0b) Cross Chip Port VLAN Addr */
 	MV88E6XXX_CAP_G2_PVT_DATA,	/* (0x0c) Cross Chip Port VLAN Data */
 	MV88E6XXX_CAP_G2_POT,		/* (0x0f) Priority Override Table */
+	MV88E6XXX_CAP_G2_EXTERNAL_MDIO, /* (0x18) SMI PHY Command */
 
 	/* Per VLAN Spanning Tree Unit (STU).
 	 * The Port State database, if present, is accessed through VTU
@@ -525,7 +528,7 @@ enum mv88e6xxx_cap {
 #define MV88E6XXX_FLAG_G2_PVT_ADDR	BIT_ULL(MV88E6XXX_CAP_G2_PVT_ADDR)
 #define MV88E6XXX_FLAG_G2_PVT_DATA	BIT_ULL(MV88E6XXX_CAP_G2_PVT_DATA)
 #define MV88E6XXX_FLAG_G2_POT		BIT_ULL(MV88E6XXX_CAP_G2_POT)
-
+#define MV88E6XXX_FLAG_G2_EXTERNAL_MDIO	BIT_ULL(MV88E6XXX_CAP_G2_EXTERNAL_MDIO)
 #define MV88E6XXX_FLAG_STU		BIT_ULL(MV88E6XXX_CAP_STU)
 #define MV88E6XXX_FLAG_VTU		BIT_ULL(MV88E6XXX_CAP_VTU)
 
@@ -633,13 +636,14 @@ enum mv88e6xxx_cap {
 
 struct mv88e6xxx_ops;
 
-#define MV88E6XXX_FLAGS_FAMILY_6390	\
-	(MV88E6XXX_FLAG_EEE |		\
-	 MV88E6XXX_FLAG_GLOBAL2 |	\
-	 MV88E6XXX_FLAG_STU |		\
-	 MV88E6XXX_FLAG_VTU |		\
-	 MV88E6XXX_FLAGS_IRL |		\
-	 MV88E6XXX_FLAGS_MULTI_CHIP |	\
+#define MV88E6XXX_FLAGS_FAMILY_6390		\
+	(MV88E6XXX_FLAG_EEE |			\
+	 MV88E6XXX_FLAG_GLOBAL2 |		\
+	 MV88E6XXX_FLAG_G2_EXTERNAL_MDIO |	\
+	 MV88E6XXX_FLAG_STU |			\
+	 MV88E6XXX_FLAG_VTU |			\
+	 MV88E6XXX_FLAGS_IRL |			\
+	 MV88E6XXX_FLAGS_MULTI_CHIP |		\
 	 MV88E6XXX_FLAGS_PVT)
 
 struct mv88e6xxx_info {
@@ -743,6 +747,12 @@ struct mv88e6xxx_chip {
 	struct mv88e6xxx_irq g2_irq;
 	int irq;
 	int device_irq;
+
+	/* Device node for the external MDIO bus */
+	struct device_node *external_mdio_np;
+
+	/* And the MDIO bus itself */
+	struct mii_bus *external_mdio_bus;
 };
 
 struct mv88e6xxx_bus_ops {
@@ -750,6 +760,11 @@ struct mv88e6xxx_bus_ops {
 	int (*write)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
 };
 
+struct mv88e6xxx_mdio_bus {
+	bool external;
+	struct mv88e6xxx_chip *chip;
+};
+
 struct mv88e6xxx_ops {
 	int (*get_eeprom)(struct mv88e6xxx_chip *chip,
 			  struct ethtool_eeprom *eeprom, u8 *data);
@@ -759,9 +774,9 @@ struct mv88e6xxx_ops {
 	int (*set_switch_mac)(struct mv88e6xxx_chip *chip, u8 *addr);
 
 	int (*phy_read)(struct mv88e6xxx_chip *chip, int addr, int reg,
-			u16 *val);
+			u16 *val, bool external);
 	int (*phy_write)(struct mv88e6xxx_chip *chip, int addr, int reg,
-			 u16 val);
+			 u16 val, bool external);
 
 	/* PHY Polling Unit (PPU) operations */
 	int (*ppu_enable)(struct mv88e6xxx_chip *chip);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 2/8] net: phy: Add 2000base-x, 2500base-x and rxaui modes
  2017-01-20 23:30 [net-next 0/8] More MV88E6390 patches Andrew Lunn
  2017-01-20 23:30 ` [PATCH net-next 1/8] net: dsa: mv88e6xxx: Implement external MDIO bus on mv88e6390 Andrew Lunn
@ 2017-01-20 23:30 ` Andrew Lunn
  2017-01-21  0:07   ` Florian Fainelli
  2017-01-20 23:30 ` [PATCH net-next 3/8] net: dsa: mv88e6xxx: Fix ATU age timer for MV88E6390 Andrew Lunn
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Andrew Lunn @ 2017-01-20 23:30 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Vivien Didelot, Andrew Lunn

The mv88e6390 ports 9 and 10 supports some additional PHY modes. Add
these modes to the PHY core so they can be used in the binding.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 Documentation/devicetree/bindings/net/ethernet.txt | 3 +++
 include/linux/phy.h                                | 9 +++++++++
 2 files changed, 12 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/ethernet.txt b/Documentation/devicetree/bindings/net/ethernet.txt
index 05150957ecfd..3a6916909d90 100644
--- a/Documentation/devicetree/bindings/net/ethernet.txt
+++ b/Documentation/devicetree/bindings/net/ethernet.txt
@@ -29,6 +29,9 @@ The following properties are common to the Ethernet controllers:
   * "smii"
   * "xgmii"
   * "trgmii"
+  * "2000base-x",
+  * "2500base-x",
+  * "rxaui"
 - phy-connection-type: the same as "phy-mode" property but described in ePAPR;
 - phy-handle: phandle, specifies a reference to a node representing a PHY
   device; this property is described in ePAPR and so preferred;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 5c9d2529685f..2252ce88efdd 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -82,6 +82,9 @@ typedef enum {
 	PHY_INTERFACE_MODE_MOCA,
 	PHY_INTERFACE_MODE_QSGMII,
 	PHY_INTERFACE_MODE_TRGMII,
+	PHY_INTERFACE_MODE_1000BASEX,
+	PHY_INTERFACE_MODE_2500BASEX,
+	PHY_INTERFACE_MODE_RXAUI,
 	PHY_INTERFACE_MODE_MAX,
 } phy_interface_t;
 
@@ -142,6 +145,12 @@ static inline const char *phy_modes(phy_interface_t interface)
 		return "qsgmii";
 	case PHY_INTERFACE_MODE_TRGMII:
 		return "trgmii";
+	case PHY_INTERFACE_MODE_1000BASEX:
+		return "1000base-x";
+	case PHY_INTERFACE_MODE_2500BASEX:
+		return "2500base-x";
+	case PHY_INTERFACE_MODE_RXAUI:
+		return "rxaui";
 	default:
 		return "unknown";
 	}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 3/8] net: dsa: mv88e6xxx: Fix ATU age timer for MV88E6390
  2017-01-20 23:30 [net-next 0/8] More MV88E6390 patches Andrew Lunn
  2017-01-20 23:30 ` [PATCH net-next 1/8] net: dsa: mv88e6xxx: Implement external MDIO bus on mv88e6390 Andrew Lunn
  2017-01-20 23:30 ` [PATCH net-next 2/8] net: phy: Add 2000base-x, 2500base-x and rxaui modes Andrew Lunn
@ 2017-01-20 23:30 ` Andrew Lunn
  2017-01-21  0:10   ` Vivien Didelot
  2017-01-20 23:30 ` [PATCH net-next 4/8] net: dsa: mv88e6xxx: Set the CMODE for mv88e6390 ports 9 & 10 Andrew Lunn
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Andrew Lunn @ 2017-01-20 23:30 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Vivien Didelot, Andrew Lunn

The MV88E6390 family uses a different ATU age timer coefficient.
Fix the the info structures.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx/chip.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 77e960826402..e79c8d09a95f 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -3932,7 +3932,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.port_base_addr = 0x0,
 		.global1_addr = 0x1b,
 		.tag_protocol = DSA_TAG_PROTO_DSA,
-		.age_time_coeff = 15000,
+		.age_time_coeff = 3750,
 		.g1_irqs = 9,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6390,
 		.ops = &mv88e6190_ops,
@@ -3946,7 +3946,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.num_ports = 11,	/* 10 + Z80 */
 		.port_base_addr = 0x0,
 		.global1_addr = 0x1b,
-		.age_time_coeff = 15000,
+		.age_time_coeff = 3750,
 		.g1_irqs = 9,
 		.tag_protocol = DSA_TAG_PROTO_DSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6390,
@@ -3961,7 +3961,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.num_ports = 11,	/* 10 + Z80 */
 		.port_base_addr = 0x0,
 		.global1_addr = 0x1b,
-		.age_time_coeff = 15000,
+		.age_time_coeff = 3750,
 		.g1_irqs = 9,
 		.tag_protocol = DSA_TAG_PROTO_DSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6390,
@@ -3991,7 +3991,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.num_ports = 11,	/* 10 + Z80 */
 		.port_base_addr = 0x0,
 		.global1_addr = 0x1b,
-		.age_time_coeff = 15000,
+		.age_time_coeff = 3750,
 		.g1_irqs = 9,
 		.tag_protocol = DSA_TAG_PROTO_DSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6390,
@@ -4080,7 +4080,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.num_ports = 11,	/* 10 + Z80 */
 		.port_base_addr = 0x0,
 		.global1_addr = 0x1b,
-		.age_time_coeff = 15000,
+		.age_time_coeff = 3750,
 		.g1_irqs = 9,
 		.tag_protocol = DSA_TAG_PROTO_DSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6390,
@@ -4094,7 +4094,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 		.num_ports = 11,	/* 10 + Z80 */
 		.port_base_addr = 0x0,
 		.global1_addr = 0x1b,
-		.age_time_coeff = 15000,
+		.age_time_coeff = 3750,
 		.g1_irqs = 9,
 		.tag_protocol = DSA_TAG_PROTO_DSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6390,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 4/8] net: dsa: mv88e6xxx: Set the CMODE for mv88e6390 ports 9 & 10
  2017-01-20 23:30 [net-next 0/8] More MV88E6390 patches Andrew Lunn
                   ` (2 preceding siblings ...)
  2017-01-20 23:30 ` [PATCH net-next 3/8] net: dsa: mv88e6xxx: Fix ATU age timer for MV88E6390 Andrew Lunn
@ 2017-01-20 23:30 ` Andrew Lunn
  2017-01-21  0:20   ` Vivien Didelot
  2017-01-20 23:30 ` [PATCH net-next 5/8] net: dsa: mv88e6xxx: Workaround missing PHY ID on mv88e6390 Andrew Lunn
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Andrew Lunn @ 2017-01-20 23:30 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Vivien Didelot, Andrew Lunn

Unlike most ports, ports 9 and 10 of the 6390X family have configurable
PHY modes. Set the mode as part of adjust_link().

Ordering is important, because the SERDES interfaces connected to
ports 9 and 10 can be split and assigned to other ports. The CMODE has
to be correctly set before the SERDES interface on another port can be
configured. Such configuration is likely to be performed in
port_enable() and port_disabled(), called on slave_open() and
slave_close().

The simple case is port 9 and 10 are used for 'CPU' or 'DSA'. In this
case, the CMODE is set via a phy-mode in dsa_cpu_dsa_setup(), which is
called early in the switch setup.

When ports 9 or 10 are used as user ports, and have a fixed-phy, when
the fixed fixed-phy is attached, dsa_slave_adjust_link() is called,
which results in the adjust_link function being called, setting the
cmode. The port_enable() will for other ports will be called much
later.

When ports 9 or 10 are used as user ports and have a real phy attached
which does not use all the available SERDES interface, e.g. a 1Gbps
SGMII, there is currently no mechanism in place to set the CMODE of
the port from software. It must be hoped the stripping resistors are
correct.

At the same time, add a function to get the cmode. This will be needed
when configuring the SERDES interfaces.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx/chip.c      |  8 +++++
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h |  9 +++++
 drivers/net/dsa/mv88e6xxx/port.c      | 64 +++++++++++++++++++++++++++++++++++
 drivers/net/dsa/mv88e6xxx/port.h      |  3 ++
 4 files changed, 84 insertions(+)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index e79c8d09a95f..4c53db6ceffc 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -718,6 +718,12 @@ static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
 			goto restore_link;
 	}
 
+	if (chip->info->ops->port_set_cmode) {
+		err = chip->info->ops->port_set_cmode(chip, port, mode);
+		if (err && err != -EOPNOTSUPP)
+			goto restore_link;
+	}
+
 	err = 0;
 restore_link:
 	if (chip->info->ops->port_set_link(chip, port, link))
@@ -3497,6 +3503,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
 	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
 	.port_set_ether_type = mv88e6351_port_set_ether_type,
 	.port_pause_config = mv88e6390_port_pause_config,
+	.port_set_cmode = mv88e6390x_port_set_cmode,
 	.stats_snapshot = mv88e6390_g1_stats_snapshot,
 	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
 	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
@@ -3688,6 +3695,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
 	.port_jumbo_config = mv88e6165_port_jumbo_config,
 	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
 	.port_pause_config = mv88e6390_port_pause_config,
+	.port_set_cmode = mv88e6390x_port_set_cmode,
 	.stats_snapshot = mv88e6390_g1_stats_snapshot,
 	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
 	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index b7f60a1bd4dc..7961467f709e 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -58,6 +58,9 @@
 #define PORT_STATUS_CMODE_100BASE_X	0x8
 #define PORT_STATUS_CMODE_1000BASE_X	0x9
 #define PORT_STATUS_CMODE_SGMII		0xa
+#define PORT_STATUS_CMODE_2500BASEX	0xb
+#define PORT_STATUS_CMODE_XAUI		0xc
+#define PORT_STATUS_CMODE_RXAUI		0xd
 #define PORT_PCS_CTRL		0x01
 #define PORT_PCS_CTRL_RGMII_DELAY_RXCLK	BIT(15)
 #define PORT_PCS_CTRL_RGMII_DELAY_TXCLK	BIT(14)
@@ -833,6 +836,12 @@ struct mv88e6xxx_ops {
 	int (*port_egress_rate_limiting)(struct mv88e6xxx_chip *chip, int port);
 	int (*port_pause_config)(struct mv88e6xxx_chip *chip, int port);
 
+	/* CMODE control what PHY mode the MAC will use, eg. SGMII, RGMII, etc.
+	 * Some chips allow this to be configured on specific ports.
+	 */
+	int (*port_set_cmode)(struct mv88e6xxx_chip *chip, int port,
+			      phy_interface_t mode);
+
 	/* Snapshot the statistics for a port. The statistics can then
 	 * be read back a leisure but still with a consistent view.
 	 */
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 0db7fa0373ae..e253ecb6624b 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -11,6 +11,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/phy.h>
 #include "mv88e6xxx.h"
 #include "port.h"
 
@@ -304,6 +305,69 @@ int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
 	return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
 }
 
+int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
+			      phy_interface_t mode)
+{
+	u16 reg;
+	u16 cmode;
+	int err;
+
+	if (mode == PHY_INTERFACE_MODE_NA)
+		return 0;
+
+	if (port != 9 && port != 10)
+		return -EOPNOTSUPP;
+
+	switch (mode) {
+	case PHY_INTERFACE_MODE_1000BASEX:
+		cmode = PORT_STATUS_CMODE_1000BASE_X;
+		break;
+	case PHY_INTERFACE_MODE_SGMII:
+		cmode = PORT_STATUS_CMODE_SGMII;
+		break;
+	case PHY_INTERFACE_MODE_2500BASEX:
+		cmode = PORT_STATUS_CMODE_2500BASEX;
+		break;
+	case PHY_INTERFACE_MODE_XGMII:
+		cmode = PORT_STATUS_CMODE_XAUI;
+		break;
+	case PHY_INTERFACE_MODE_RXAUI:
+		cmode = PORT_STATUS_CMODE_RXAUI;
+		break;
+	default:
+		cmode = 0;
+	}
+
+	if (cmode) {
+		err = mv88e6xxx_port_read(chip, port, PORT_STATUS, &reg);
+		if (err)
+			return err;
+
+		reg &= ~PORT_STATUS_CMODE_MASK;
+		reg |= cmode;
+
+		err = mv88e6xxx_port_write(chip, port, PORT_STATUS, reg);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
+{
+	int err;
+	u16 reg;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_STATUS, &reg);
+	if (err)
+		return err;
+
+	*cmode = reg & PORT_STATUS_CMODE_MASK;
+
+	return 0;
+}
+
 /* Offset 0x02: Pause Control
  *
  * Do not limit the period of time that this port can be paused for by
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 7b3bacaacbfe..cb871e306f62 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -67,5 +67,8 @@ int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
 int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
 int mv88e6097_port_pause_config(struct mv88e6xxx_chip *chip, int port);
 int mv88e6390_port_pause_config(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
+			      phy_interface_t mode);
+int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
 
 #endif /* _MV88E6XXX_PORT_H */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 5/8] net: dsa: mv88e6xxx: Workaround missing PHY ID on mv88e6390
  2017-01-20 23:30 [net-next 0/8] More MV88E6390 patches Andrew Lunn
                   ` (3 preceding siblings ...)
  2017-01-20 23:30 ` [PATCH net-next 4/8] net: dsa: mv88e6xxx: Set the CMODE for mv88e6390 ports 9 & 10 Andrew Lunn
@ 2017-01-20 23:30 ` Andrew Lunn
  2017-01-21  0:03   ` Florian Fainelli
  2017-01-21  0:26   ` Vivien Didelot
  2017-01-20 23:31 ` [PATCH net-next 6/8] net: phy: Marvell: Add mv88e6390 internal PHY Andrew Lunn
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 22+ messages in thread
From: Andrew Lunn @ 2017-01-20 23:30 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Vivien Didelot, Andrew Lunn

The internal PHYs of the mv88e6390 do not have a model ID. Trap any
calls to the ID register, and if it is zero, return the ID for the
mv88e6390. The Marvell PHY driver can then bind to this ID.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx/global2.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index 5c9ccb6775ae..e2b00d1b0c28 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -518,7 +518,21 @@ int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, int addr, int reg,
 	if (err)
 		return err;
 
-	return mv88e6xxx_g2_read(chip, GLOBAL2_SMI_PHY_DATA, val);
+	err = mv88e6xxx_g2_read(chip, GLOBAL2_SMI_PHY_DATA, val);
+	if (err)
+		return err;
+
+	if (reg == MII_PHYSID2) {
+		/* The mv88e6390 internal PHYS don't have a model number.
+		 * Use the switch family model number instead.
+		 */
+		if (!(*val & 0x1ff)) {
+			if (chip->info->family == MV88E6XXX_FAMILY_6390)
+				*val |= PORT_SWITCH_ID_PROD_NUM_6390;
+		}
+	}
+
+	return 0;
 }
 
 int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 6/8] net: phy: Marvell: Add mv88e6390 internal PHY
  2017-01-20 23:30 [net-next 0/8] More MV88E6390 patches Andrew Lunn
                   ` (4 preceding siblings ...)
  2017-01-20 23:30 ` [PATCH net-next 5/8] net: dsa: mv88e6xxx: Workaround missing PHY ID on mv88e6390 Andrew Lunn
@ 2017-01-20 23:31 ` Andrew Lunn
  2017-01-21  0:04   ` Florian Fainelli
  2017-01-20 23:31 ` [PATCH net-next 7/8] net: dsa: mv88e6xxx: Implement Clause 45 access to SMI devices Andrew Lunn
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Andrew Lunn @ 2017-01-20 23:31 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Vivien Didelot, Andrew Lunn

The mv88e6390 Ethernet switch has internal PHYs. These PHYs don't have
an model ID in the ID2 register. So the MDIO driver in the switch
intercepts reads to this register, and returns the switch family ID.
Extend the Marvell PHY driver by including this ID, and tread the PHY
as a 88E1540.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/phy/marvell.c   | 20 ++++++++++++++++++++
 include/linux/marvell_phy.h |  6 ++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 64229976ace1..d02bb58a8c99 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -2141,6 +2141,25 @@ static struct phy_driver marvell_drivers[] = {
 		.get_strings = marvell_get_strings,
 		.get_stats = marvell_get_stats,
 	},
+	{
+		.phy_id = MARVELL_PHY_ID_88E6390,
+		.phy_id_mask = MARVELL_PHY_ID_MASK,
+		.name = "Marvell 88E6390",
+		.features = PHY_GBIT_FEATURES,
+		.flags = PHY_HAS_INTERRUPT,
+		.probe = marvell_probe,
+		.config_init = &marvell_config_init,
+		.config_aneg = &m88e1510_config_aneg,
+		.read_status = &marvell_read_status,
+		.ack_interrupt = &marvell_ack_interrupt,
+		.config_intr = &marvell_config_intr,
+		.did_interrupt = &m88e1121_did_interrupt,
+		.resume = &genphy_resume,
+		.suspend = &genphy_suspend,
+		.get_sset_count = marvell_get_sset_count,
+		.get_strings = marvell_get_strings,
+		.get_stats = marvell_get_stats,
+	},
 };
 
 module_phy_driver(marvell_drivers);
@@ -2159,6 +2178,7 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = {
 	{ MARVELL_PHY_ID_88E1510, MARVELL_PHY_ID_MASK },
 	{ MARVELL_PHY_ID_88E1540, MARVELL_PHY_ID_MASK },
 	{ MARVELL_PHY_ID_88E3016, MARVELL_PHY_ID_MASK },
+	{ MARVELL_PHY_ID_88E6390, MARVELL_PHY_ID_MASK },
 	{ }
 };
 
diff --git a/include/linux/marvell_phy.h b/include/linux/marvell_phy.h
index a57f0dfb6db7..3d616d7f65bf 100644
--- a/include/linux/marvell_phy.h
+++ b/include/linux/marvell_phy.h
@@ -19,6 +19,12 @@
 #define MARVELL_PHY_ID_88E1540		0x01410eb0
 #define MARVELL_PHY_ID_88E3016		0x01410e60
 
+/* The MV88e6390 Ethernet switch contains embedded PHYs. These PHYs do
+ * not have a model ID. So the switch driver traps reads to the ID2
+ * register and returns the switch family ID
+ */
+#define MARVELL_PHY_ID_88E6390		0x01410f90
+
 /* struct phy_device dev_flags definitions */
 #define MARVELL_PHY_M1145_FLAGS_RESISTANCE	0x00000001
 #define MARVELL_PHY_M1118_DNS323_LEDS		0x00000002
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 7/8] net: dsa: mv88e6xxx: Implement Clause 45 access to SMI devices
  2017-01-20 23:30 [net-next 0/8] More MV88E6390 patches Andrew Lunn
                   ` (5 preceding siblings ...)
  2017-01-20 23:31 ` [PATCH net-next 6/8] net: phy: Marvell: Add mv88e6390 internal PHY Andrew Lunn
@ 2017-01-20 23:31 ` Andrew Lunn
  2017-01-20 23:31 ` [PATCH net-next 8/8] net: dsa: mv88e6xxx: Fix typ0 when configuring 2.5Gbps Andrew Lunn
  2017-01-23 18:06 ` [net-next 0/8] More MV88E6390 patches David Miller
  8 siblings, 0 replies; 22+ messages in thread
From: Andrew Lunn @ 2017-01-20 23:31 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Vivien Didelot, Andrew Lunn

The mv88e6390 SERDES devices need clause 45 MDIO to access them.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx/global2.c   | 108 ++++++++++++++++++++++++++++++++--
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h |   7 +++
 2 files changed, 111 insertions(+), 4 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index e2b00d1b0c28..d1a0b7d3ebb8 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -501,8 +501,60 @@ static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
 	return mv88e6xxx_g2_smi_phy_wait(chip);
 }
 
-int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, int addr, int reg,
-			      u16 *val, bool external)
+static int mv88e6xxx_g2_smi_phy_write_addr(struct mv88e6xxx_chip *chip,
+					   int addr, int device, int reg,
+					   bool external)
+{
+	int cmd = SMI_CMD_OP_45_WRITE_ADDR | (addr << 5) | device;
+	int err;
+
+	if (external)
+		cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL;
+
+	err = mv88e6xxx_g2_smi_phy_wait(chip);
+	if (err)
+		return err;
+
+	err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, reg);
+	if (err)
+		return err;
+
+	return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
+}
+
+int mv88e6xxx_g2_smi_phy_read_c45(struct mv88e6xxx_chip *chip, int addr,
+				  int reg_c45, u16 *val, bool external)
+{
+	int device = (reg_c45 >> 16) & 0x1f;
+	int reg = reg_c45 & 0xffff;
+	int err;
+	u16 cmd;
+
+	err = mv88e6xxx_g2_smi_phy_write_addr(chip, addr, device, reg,
+					      external);
+	if (err)
+		return err;
+
+	cmd = GLOBAL2_SMI_PHY_CMD_OP_45_READ_DATA | (addr << 5) | device;
+
+	if (external)
+		cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL;
+
+	err = mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
+	if (err)
+		return err;
+
+	err = mv88e6xxx_g2_read(chip, GLOBAL2_SMI_PHY_DATA, val);
+	if (err)
+		return err;
+
+	err = *val;
+
+	return 0;
+}
+
+int mv88e6xxx_g2_smi_phy_read_c22(struct mv88e6xxx_chip *chip, int addr,
+				  int reg, u16 *val, bool external)
 {
 	u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_READ_DATA | (addr << 5) | reg;
 	int err;
@@ -535,8 +587,46 @@ int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, int addr, int reg,
 	return 0;
 }
 
-int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg,
-			       u16 val, bool external)
+int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, int addr, int reg,
+			      u16 *val, bool external)
+{
+	if (reg & MII_ADDR_C45)
+		return mv88e6xxx_g2_smi_phy_read_c45(chip, addr, reg, val,
+						     external);
+	return mv88e6xxx_g2_smi_phy_read_c22(chip, addr, reg, val, external);
+}
+
+int mv88e6xxx_g2_smi_phy_write_c45(struct mv88e6xxx_chip *chip, int addr,
+				   int reg_c45, u16 val, bool external)
+{
+	int device = (reg_c45 >> 16) & 0x1f;
+	int reg = reg_c45 & 0xffff;
+	int err;
+	u16 cmd;
+
+	err = mv88e6xxx_g2_smi_phy_write_addr(chip, addr, device, reg,
+					      external);
+	if (err)
+		return err;
+
+	cmd = GLOBAL2_SMI_PHY_CMD_OP_45_WRITE_DATA | (addr << 5) | device;
+
+	if (external)
+		cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL;
+
+	err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, val);
+	if (err)
+		return err;
+
+	err = mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+int mv88e6xxx_g2_smi_phy_write_c22(struct mv88e6xxx_chip *chip, int addr,
+				   int reg, u16 val, bool external)
 {
 	u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_WRITE_DATA | (addr << 5) | reg;
 	int err;
@@ -555,6 +645,16 @@ int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg,
 	return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
 }
 
+int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg,
+			       u16 val, bool external)
+{
+	if (reg & MII_ADDR_C45)
+		return mv88e6xxx_g2_smi_phy_write_c45(chip, addr, reg, val,
+						      external);
+
+	return mv88e6xxx_g2_smi_phy_write_c22(chip, addr, reg, val, external);
+}
+
 static void mv88e6xxx_g2_irq_mask(struct irq_data *d)
 {
 	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index 7961467f709e..6cbde36027f1 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -399,6 +399,13 @@
 #define GLOBAL2_SMI_PHY_CMD_OP_22_READ_DATA	((0x2 << 10) | \
 						 GLOBAL2_SMI_PHY_CMD_MODE_22 | \
 						 GLOBAL2_SMI_PHY_CMD_BUSY)
+#define GLOBAL2_SMI_PHY_CMD_OP_45_WRITE_ADDR	((0x0 << 10) | \
+						 GLOBAL2_SMI_PHY_CMD_BUSY)
+#define GLOBAL2_SMI_PHY_CMD_OP_45_WRITE_DATA	((0x1 << 10) | \
+						 GLOBAL2_SMI_PHY_CMD_BUSY)
+#define GLOBAL2_SMI_PHY_CMD_OP_45_READ_DATA	((0x3 << 10) | \
+						 GLOBAL2_SMI_PHY_CMD_BUSY)
+
 #define GLOBAL2_SMI_PHY_DATA			0x19
 #define GLOBAL2_SCRATCH_MISC	0x1a
 #define GLOBAL2_SCRATCH_BUSY		BIT(15)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH net-next 8/8] net: dsa: mv88e6xxx: Fix typ0 when configuring 2.5Gbps
  2017-01-20 23:30 [net-next 0/8] More MV88E6390 patches Andrew Lunn
                   ` (6 preceding siblings ...)
  2017-01-20 23:31 ` [PATCH net-next 7/8] net: dsa: mv88e6xxx: Implement Clause 45 access to SMI devices Andrew Lunn
@ 2017-01-20 23:31 ` Andrew Lunn
  2017-01-21  0:53   ` Vivien Didelot
  2017-01-23 18:06 ` [net-next 0/8] More MV88E6390 patches David Miller
  8 siblings, 1 reply; 22+ messages in thread
From: Andrew Lunn @ 2017-01-20 23:31 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Vivien Didelot, Andrew Lunn

In order to enable 2.5Gbps mode, we need the base speed of 10G, plus
the Alt bit setting. Fix a typ0 that used 1Gb base speed.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx/port.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index e253ecb6624b..d543a6817d61 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -194,7 +194,7 @@ static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
 		ctrl = PORT_PCS_CTRL_SPEED_1000;
 		break;
 	case 2500:
-		ctrl = PORT_PCS_CTRL_SPEED_1000 | PORT_PCS_CTRL_ALTSPEED;
+		ctrl = PORT_PCS_CTRL_SPEED_10000 | PORT_PCS_CTRL_ALTSPEED;
 		break;
 	case 10000:
 		/* all bits set, fall through... */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 1/8] net: dsa: mv88e6xxx: Implement external MDIO bus on mv88e6390
  2017-01-20 23:30 ` [PATCH net-next 1/8] net: dsa: mv88e6xxx: Implement external MDIO bus on mv88e6390 Andrew Lunn
@ 2017-01-21  0:01   ` Florian Fainelli
  2017-01-21 16:07     ` Andrew Lunn
  2017-01-21  0:04   ` Vivien Didelot
  1 sibling, 1 reply; 22+ messages in thread
From: Florian Fainelli @ 2017-01-21  0:01 UTC (permalink / raw)
  To: Andrew Lunn, David Miller; +Cc: netdev, Vivien Didelot

On 01/20/2017 03:30 PM, Andrew Lunn wrote:
> The mv88e6390 has two MDIO busses. The internal MDIO bus is used for
> the internal PHYs. The external MDIO can be used for external PHYs.
> The external MDIO bus will be instantiated if there is an
> "mdio-external" node in the device tree.

This looks fine, although I am not clear why we cannot utilize a
standard representation of a MDIO bus (with PHY devices as child nodes)
which has a specific compatible string, e.g:
marvell,mv88e6390-external-mdio, and that is a child node of the 6390
Ethernet switch itself, something like:

/* assuming this is, e.g: an independent or CPU EThernet MAC MDIO bus */
&mdio {
	switch@0 {
		compatible = "marvell,mv88e6390";
		reg = <0>;

		ports {
			#address-cells = <1>;
			#size-cells = <0>;
	
			port@0 {
				phy-handle = <phy0>;
				reg = <0>;
			};
		};

		mdio {
			compatible = "marvell,mv88e6390-external-mdio";
			#address-cells = <1>;
			#size-cells = <0>;

			phy0: phy@0 {
				reg = <0>;
			};
		};
	};
};

In both cases (your proposal) and this one, we still have a dependency
on the Ethernet switch driver being probed to create the internal and
external MDIO buses.

Thanks!
-- 
Florian

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 5/8] net: dsa: mv88e6xxx: Workaround missing PHY ID on mv88e6390
  2017-01-20 23:30 ` [PATCH net-next 5/8] net: dsa: mv88e6xxx: Workaround missing PHY ID on mv88e6390 Andrew Lunn
@ 2017-01-21  0:03   ` Florian Fainelli
  2017-01-21  0:26   ` Vivien Didelot
  1 sibling, 0 replies; 22+ messages in thread
From: Florian Fainelli @ 2017-01-21  0:03 UTC (permalink / raw)
  To: Andrew Lunn, David Miller; +Cc: netdev, Vivien Didelot

On 01/20/2017 03:30 PM, Andrew Lunn wrote:
> The internal PHYs of the mv88e6390 do not have a model ID. Trap any
> calls to the ID register, and if it is zero, return the ID for the
> mv88e6390. The Marvell PHY driver can then bind to this ID.
> 
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

Nice and clean!
-- 
Florian

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 6/8] net: phy: Marvell: Add mv88e6390 internal PHY
  2017-01-20 23:31 ` [PATCH net-next 6/8] net: phy: Marvell: Add mv88e6390 internal PHY Andrew Lunn
@ 2017-01-21  0:04   ` Florian Fainelli
  0 siblings, 0 replies; 22+ messages in thread
From: Florian Fainelli @ 2017-01-21  0:04 UTC (permalink / raw)
  To: Andrew Lunn, David Miller; +Cc: netdev, Vivien Didelot

On 01/20/2017 03:31 PM, Andrew Lunn wrote:
> The mv88e6390 Ethernet switch has internal PHYs. These PHYs don't have
> an model ID in the ID2 register. So the MDIO driver in the switch
> intercepts reads to this register, and returns the switch family ID.
> Extend the Marvell PHY driver by including this ID, and tread the PHY
> as a 88E1540.
> 
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 1/8] net: dsa: mv88e6xxx: Implement external MDIO bus on mv88e6390
  2017-01-20 23:30 ` [PATCH net-next 1/8] net: dsa: mv88e6xxx: Implement external MDIO bus on mv88e6390 Andrew Lunn
  2017-01-21  0:01   ` Florian Fainelli
@ 2017-01-21  0:04   ` Vivien Didelot
  2017-01-21 16:15     ` Andrew Lunn
  1 sibling, 1 reply; 22+ messages in thread
From: Vivien Didelot @ 2017-01-21  0:04 UTC (permalink / raw)
  To: Andrew Lunn, David Miller; +Cc: netdev, Andrew Lunn

Hi Andrew,

Andrew Lunn <andrew@lunn.ch> writes:

> The mv88e6390 has two MDIO busses. The internal MDIO bus is used for
> the internal PHYs. The external MDIO can be used for external PHYs.
> The external MDIO bus will be instantiated if there is an
> "mdio-external" node in the device tree.

Thanks for pushing the 88E6390 support. Some comments below.

> +static int mv88e6xxx_read_phy(struct mv88e6xxx_chip *chip, int addr, int reg,
> +static int mv88e6xxx_write_phy(struct mv88e6xxx_chip *chip, int addr, int reg,
>  static int mv88e6xxx_phy_read(struct mv88e6xxx_chip *chip, int phy,
>  static int mv88e6xxx_phy_write(struct mv88e6xxx_chip *chip, int phy,

Adding mv88e6xxx_read/write_phy() in addition to existing
mv88e6xxx_phy_read/write() feels really confusing and hard to
maintain. Can that be done the other way around maybe?

> +static int mv88e6xxx_external_mdio_register(struct mv88e6xxx_chip *chip,
> +					    struct device_node *np)
> +static void mv88e6xxx_external_mdio_unregister(struct mv88e6xxx_chip *chip)
>  static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
>  				   struct device_node *np)

We already have mv88e6xxx_mdio_register/unregister(). Isn't it possible
to tweak them to take a struct mv88e6xxx_mdio_bus instance and use them
twice for both internal and external MDIO busses?

> +	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_EXTERNAL_MDIO)) {
> +		err = mv88e6xxx_external_mdio_register(chip, np);
> +		if (err)
> +			goto out_mdio;
> +	}

We are trying to get rid of the flags and family checks... Please don't
add new ones. If the external MDIO bus is a new feature of switches like
88E6390, isn't it better to add new external_phy_read/write ops and
register the bus if they are provided?

    if (chip->info->ops->external_phy_read) {
        struct mv88e6xxx_mdio_bus *external_mdio_bus;
        ...
        err = mv88e6xxx_mdio_register(external_mdio_bus);
        if (err)
            ...
    }

Thanks,

        Vivien

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 2/8] net: phy: Add 2000base-x, 2500base-x and rxaui modes
  2017-01-20 23:30 ` [PATCH net-next 2/8] net: phy: Add 2000base-x, 2500base-x and rxaui modes Andrew Lunn
@ 2017-01-21  0:07   ` Florian Fainelli
  0 siblings, 0 replies; 22+ messages in thread
From: Florian Fainelli @ 2017-01-21  0:07 UTC (permalink / raw)
  To: Andrew Lunn, David Miller; +Cc: netdev, Vivien Didelot

On 01/20/2017 03:30 PM, Andrew Lunn wrote:
> The mv88e6390 ports 9 and 10 supports some additional PHY modes. Add
> these modes to the PHY core so they can be used in the binding.
> 
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

Can you also send a Device Tree specification patch with these updates?
Thanks!
-- 
Florian

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 3/8] net: dsa: mv88e6xxx: Fix ATU age timer for MV88E6390
  2017-01-20 23:30 ` [PATCH net-next 3/8] net: dsa: mv88e6xxx: Fix ATU age timer for MV88E6390 Andrew Lunn
@ 2017-01-21  0:10   ` Vivien Didelot
  0 siblings, 0 replies; 22+ messages in thread
From: Vivien Didelot @ 2017-01-21  0:10 UTC (permalink / raw)
  To: Andrew Lunn, David Miller; +Cc: netdev, Andrew Lunn

Hi Andrew,

Andrew Lunn <andrew@lunn.ch> writes:

> The MV88E6390 family uses a different ATU age timer coefficient.
> Fix the the info structures.

Redundant "the" here. Otherwise good catch, the minimum age time is 3.75
seconds.

> Signed-off-by: Andrew Lunn <andrew@lunn.ch>

Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>

Thanks,

        Vivien

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 4/8] net: dsa: mv88e6xxx: Set the CMODE for mv88e6390 ports 9 & 10
  2017-01-20 23:30 ` [PATCH net-next 4/8] net: dsa: mv88e6xxx: Set the CMODE for mv88e6390 ports 9 & 10 Andrew Lunn
@ 2017-01-21  0:20   ` Vivien Didelot
  0 siblings, 0 replies; 22+ messages in thread
From: Vivien Didelot @ 2017-01-21  0:20 UTC (permalink / raw)
  To: Andrew Lunn, David Miller; +Cc: netdev, Andrew Lunn

Hi Andrew,

Andrew Lunn <andrew@lunn.ch> writes:

> Unlike most ports, ports 9 and 10 of the 6390X family have configurable
> PHY modes. Set the mode as part of adjust_link().
>
> Ordering is important, because the SERDES interfaces connected to
> ports 9 and 10 can be split and assigned to other ports. The CMODE has
> to be correctly set before the SERDES interface on another port can be
> configured. Such configuration is likely to be performed in
> port_enable() and port_disabled(), called on slave_open() and
> slave_close().
>
> The simple case is port 9 and 10 are used for 'CPU' or 'DSA'. In this
> case, the CMODE is set via a phy-mode in dsa_cpu_dsa_setup(), which is
> called early in the switch setup.
>
> When ports 9 or 10 are used as user ports, and have a fixed-phy, when
> the fixed fixed-phy is attached, dsa_slave_adjust_link() is called,
> which results in the adjust_link function being called, setting the
> cmode. The port_enable() will for other ports will be called much
> later.
>
> When ports 9 or 10 are used as user ports and have a real phy attached
> which does not use all the available SERDES interface, e.g. a 1Gbps
> SGMII, there is currently no mechanism in place to set the CMODE of
> the port from software. It must be hoped the stripping resistors are
> correct.
>
> At the same time, add a function to get the cmode. This will be needed
> when configuring the SERDES interfaces.
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>

Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>

Thanks for the very descriptive message, the patch looks perfect.

        Vivien

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 5/8] net: dsa: mv88e6xxx: Workaround missing PHY ID on mv88e6390
  2017-01-20 23:30 ` [PATCH net-next 5/8] net: dsa: mv88e6xxx: Workaround missing PHY ID on mv88e6390 Andrew Lunn
  2017-01-21  0:03   ` Florian Fainelli
@ 2017-01-21  0:26   ` Vivien Didelot
  2017-01-24 21:00     ` Gregory CLEMENT
  1 sibling, 1 reply; 22+ messages in thread
From: Vivien Didelot @ 2017-01-21  0:26 UTC (permalink / raw)
  To: Andrew Lunn, David Miller; +Cc: netdev, Andrew Lunn

Hi Andrew,

Andrew Lunn <andrew@lunn.ch> writes:

> The internal PHYs of the mv88e6390 do not have a model ID. Trap any
> calls to the ID register, and if it is zero, return the ID for the
> mv88e6390. The Marvell PHY driver can then bind to this ID.

This, in addition to the temperature code not working (despite what the
datasheet says) makes me wonder if this is intentional from Marvell. Do
we have a revision number for the 88E6390X's on the ZII Dev Rev C board?

It would be interesting to ask Gregory maybe about that. This looks not
"production-ready".

Other than that, I have no objection on the patch itself if that is
indeed expected from them...

Thanks,

        Vivien

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 8/8] net: dsa: mv88e6xxx: Fix typ0 when configuring 2.5Gbps
  2017-01-20 23:31 ` [PATCH net-next 8/8] net: dsa: mv88e6xxx: Fix typ0 when configuring 2.5Gbps Andrew Lunn
@ 2017-01-21  0:53   ` Vivien Didelot
  0 siblings, 0 replies; 22+ messages in thread
From: Vivien Didelot @ 2017-01-21  0:53 UTC (permalink / raw)
  To: Andrew Lunn, David Miller; +Cc: netdev, Andrew Lunn

Hi Andrew,

Andrew Lunn <andrew@lunn.ch> writes:

> In order to enable 2.5Gbps mode, we need the base speed of 10G, plus
> the Alt bit setting. Fix a typ0 that used 1Gb base speed.
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>

Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>

Thanks,

        Vivien

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 1/8] net: dsa: mv88e6xxx: Implement external MDIO bus on mv88e6390
  2017-01-21  0:01   ` Florian Fainelli
@ 2017-01-21 16:07     ` Andrew Lunn
  0 siblings, 0 replies; 22+ messages in thread
From: Andrew Lunn @ 2017-01-21 16:07 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: David Miller, netdev, Vivien Didelot

> This looks fine, although I am not clear why we cannot utilize a
> standard representation of a MDIO bus (with PHY devices as child nodes)
> which has a specific compatible string, e.g:
> marvell,mv88e6390-external-mdio, and that is a child node of the 6390
> Ethernet switch itself, something like:

Humm, interesting idea. I did not think of this, because the current
code just looks for an mdio property, and does not care about any
compatible string.

I will think about this.

Thanks

  Andrew

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 1/8] net: dsa: mv88e6xxx: Implement external MDIO bus on mv88e6390
  2017-01-21  0:04   ` Vivien Didelot
@ 2017-01-21 16:15     ` Andrew Lunn
  0 siblings, 0 replies; 22+ messages in thread
From: Andrew Lunn @ 2017-01-21 16:15 UTC (permalink / raw)
  To: Vivien Didelot; +Cc: David Miller, netdev

On Fri, Jan 20, 2017 at 07:04:35PM -0500, Vivien Didelot wrote:
> Hi Andrew,
> 
> Andrew Lunn <andrew@lunn.ch> writes:
> 
> > The mv88e6390 has two MDIO busses. The internal MDIO bus is used for
> > the internal PHYs. The external MDIO can be used for external PHYs.
> > The external MDIO bus will be instantiated if there is an
> > "mdio-external" node in the device tree.
> 
> Thanks for pushing the 88E6390 support. Some comments below.
> 
> > +static int mv88e6xxx_read_phy(struct mv88e6xxx_chip *chip, int addr, int reg,
> > +static int mv88e6xxx_write_phy(struct mv88e6xxx_chip *chip, int addr, int reg,
> >  static int mv88e6xxx_phy_read(struct mv88e6xxx_chip *chip, int phy,
> >  static int mv88e6xxx_phy_write(struct mv88e6xxx_chip *chip, int phy,
> 
> Adding mv88e6xxx_read/write_phy() in addition to existing
> mv88e6xxx_phy_read/write() feels really confusing and hard to
> maintain. Can that be done the other way around maybe?

Yes, i agree. I didn't particularly like it either. What might be
simpler is to pass the struct mii_bus all the way down, where as we
only currently have chip.

     Andrew

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [net-next 0/8] More MV88E6390 patches
  2017-01-20 23:30 [net-next 0/8] More MV88E6390 patches Andrew Lunn
                   ` (7 preceding siblings ...)
  2017-01-20 23:31 ` [PATCH net-next 8/8] net: dsa: mv88e6xxx: Fix typ0 when configuring 2.5Gbps Andrew Lunn
@ 2017-01-23 18:06 ` David Miller
  8 siblings, 0 replies; 22+ messages in thread
From: David Miller @ 2017-01-23 18:06 UTC (permalink / raw)
  To: andrew; +Cc: netdev, vivien.didelot

From: Andrew Lunn <andrew@lunn.ch>
Date: Sat, 21 Jan 2017 00:30:54 +0100

> This is the ongoing work to add support for the Marvell 9390 family of
> switches. There are now two MDIO busses, one for the internal PHYs and
> an external bus for external PHYs. Add support for this external bus.

I am anticipating another respin of this based upon feedback, just
FYI.

Correct me if my expectations are wrong.

Thanks.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH net-next 5/8] net: dsa: mv88e6xxx: Workaround missing PHY ID on mv88e6390
  2017-01-21  0:26   ` Vivien Didelot
@ 2017-01-24 21:00     ` Gregory CLEMENT
  0 siblings, 0 replies; 22+ messages in thread
From: Gregory CLEMENT @ 2017-01-24 21:00 UTC (permalink / raw)
  To: Vivien Didelot; +Cc: Andrew Lunn, David Miller, netdev

Hi Vivien,
 
 On sam., janv. 21 2017, Vivien Didelot <vivien.didelot@savoirfairelinux.com> wrote:

> Hi Andrew,
>
> Andrew Lunn <andrew@lunn.ch> writes:
>
>> The internal PHYs of the mv88e6390 do not have a model ID. Trap any
>> calls to the ID register, and if it is zero, return the ID for the
>> mv88e6390. The Marvell PHY driver can then bind to this ID.
>
> This, in addition to the temperature code not working (despite what the
> datasheet says) makes me wonder if this is intentional from Marvell. Do
> we have a revision number for the 88E6390X's on the ZII Dev Rev C board?
>
> It would be interesting to ask Gregory maybe about that. This looks not
> "production-ready".

What I can say is that with the 88E6341, which seems to have the same
issue (ie incomplete PHY ID), reading the temperature worked.

Gregory

>
> Other than that, I have no objection on the patch itself if that is
> indeed expected from them...
>
> Thanks,
>
>         Vivien

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2017-01-24 21:00 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-20 23:30 [net-next 0/8] More MV88E6390 patches Andrew Lunn
2017-01-20 23:30 ` [PATCH net-next 1/8] net: dsa: mv88e6xxx: Implement external MDIO bus on mv88e6390 Andrew Lunn
2017-01-21  0:01   ` Florian Fainelli
2017-01-21 16:07     ` Andrew Lunn
2017-01-21  0:04   ` Vivien Didelot
2017-01-21 16:15     ` Andrew Lunn
2017-01-20 23:30 ` [PATCH net-next 2/8] net: phy: Add 2000base-x, 2500base-x and rxaui modes Andrew Lunn
2017-01-21  0:07   ` Florian Fainelli
2017-01-20 23:30 ` [PATCH net-next 3/8] net: dsa: mv88e6xxx: Fix ATU age timer for MV88E6390 Andrew Lunn
2017-01-21  0:10   ` Vivien Didelot
2017-01-20 23:30 ` [PATCH net-next 4/8] net: dsa: mv88e6xxx: Set the CMODE for mv88e6390 ports 9 & 10 Andrew Lunn
2017-01-21  0:20   ` Vivien Didelot
2017-01-20 23:30 ` [PATCH net-next 5/8] net: dsa: mv88e6xxx: Workaround missing PHY ID on mv88e6390 Andrew Lunn
2017-01-21  0:03   ` Florian Fainelli
2017-01-21  0:26   ` Vivien Didelot
2017-01-24 21:00     ` Gregory CLEMENT
2017-01-20 23:31 ` [PATCH net-next 6/8] net: phy: Marvell: Add mv88e6390 internal PHY Andrew Lunn
2017-01-21  0:04   ` Florian Fainelli
2017-01-20 23:31 ` [PATCH net-next 7/8] net: dsa: mv88e6xxx: Implement Clause 45 access to SMI devices Andrew Lunn
2017-01-20 23:31 ` [PATCH net-next 8/8] net: dsa: mv88e6xxx: Fix typ0 when configuring 2.5Gbps Andrew Lunn
2017-01-21  0:53   ` Vivien Didelot
2017-01-23 18:06 ` [net-next 0/8] More MV88E6390 patches David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.