This patch looks much better to me. Only one comment. On Wed, Oct 26, 2022 at 09:28:58AM -0700, Tim Harvey wrote: > +static int mv88e6xxx_port_enable(struct udevice *dev, int port, struct > phy_device *phy) > +{ > + struct mv88e6xxx_priv *priv = dev_get_priv(dev); > + int val, ret; > + > + dev_dbg(dev, "%s P%d phy:0x%08x %s\n", __func__, port, > + phy->phy_id, phy_string_for_interface(phy->interface)); > + > + if (phy->phy_id == PHY_FIXED_ID) { > + /* Physical Control register: Table 62 */ > + val = mv88e6xxx_port_read(dev, port, PORT_REG_PHYS_CTRL); > + > + /* configure RGMII delays for fixed link */ > + switch (phy->interface) { > + case PHY_INTERFACE_MODE_RGMII: > + case PHY_INTERFACE_MODE_RGMII_ID: > + case PHY_INTERFACE_MODE_RGMII_RXID: > + case PHY_INTERFACE_MODE_RGMII_TXID: > + dev_dbg(dev, "configure internal RGMII delays\n"); > + > + /* RGMII delays */ > + val &= ~(PORT_REG_PHYS_CTRL_RGMII_DELAY_RXCLK || > + PORT_REG_PHYS_CTRL_RGMII_DELAY_TXCLK); > + if (phy->interface == PHY_INTERFACE_MODE_RGMII_ID || > + phy->interface == PHY_INTERFACE_MODE_RGMII_RXID) > + val |= PORT_REG_PHYS_CTRL_RGMII_DELAY_RXCLK; > + if (phy->interface == PHY_INTERFACE_MODE_RGMII_ID || > + phy->interface == PHY_INTERFACE_MODE_RGMII_TXID) > + val |= PORT_REG_PHYS_CTRL_RGMII_DELAY_TXCLK; > + break; > + default: > + break; > + } > + > + /* Force Link */ > + val |= PORT_REG_PHYS_CTRL_LINK_VALUE | > + PORT_REG_PHYS_CTRL_LINK_FORCE; > + > + ret = mv88e6xxx_port_write(dev, port, PORT_REG_PHYS_CTRL, val); > + if (ret < 0) > + return ret; > + > + if (mv88e6xxx_6352_family(dev)) { > + /* validate interface type */ > + dev_dbg(dev, "validate interface type\n"); > + val = mv88e6xxx_get_cmode(dev, port); > + if (val < 0) > + return val; > + switch (phy->interface) { > + case PHY_INTERFACE_MODE_RGMII: > + case PHY_INTERFACE_MODE_RGMII_RXID: > + case PHY_INTERFACE_MODE_RGMII_TXID: > + case PHY_INTERFACE_MODE_RGMII_ID: > + if (val != PORT_REG_STATUS_CMODE_RGMII) > + goto mismatch; > + break; > + case PHY_INTERFACE_MODE_1000BASEX: > + if (val != PORT_REG_STATUS_CMODE_1000BASE_X) > + goto mismatch; > + break; > +mismatch: > + default: > + dev_err(dev, "Mismatched PHY mode %s on port > %d!\n", > + > phy_string_for_interface(phy->interface), port); > + break; > + } > + } > + } else {
What I was saying was here. The phy_id is not PHY_FIXED_ID, okay, but that doesn't necessarily imply this is an internal PHY port, as the code below goes on to assume. Maybe this is the case for your setup, but I would like to see some guarding in a generic driver such that internal PHY configuration only gets done for ports where that PHY exists. Which actually brings me to another, more important point. This PHY_REG_CTRL1 access is the only PHY access that the DSA driver performs. But we also have a driver for the internal PHY. Why doesn't the Marvell PHY driver do this write? Also, what is the utility of enabling energy-detect sense? > + /* Enable energy-detect sensing on PHY */ > + dev_dbg(dev, "enabling energy-detect sense on PHY\n"); > + val = mv88e6xxx_phy_read(dev, port, PHY_REG_CTRL1); > + if (val < 0) > + return val; > + switch (priv->id) { > + case PORT_SWITCH_ID_6096: > + case PORT_SWITCH_ID_6097: > + case PORT_SWITCH_ID_6172: > + case PORT_SWITCH_ID_6176: > + case PORT_SWITCH_ID_6240: > + case PORT_SWITCH_ID_6352: > + val &= ~GENMASK(8, 2); > + val |= (PHY_REG_CTRL1_ENERGY_DET_SENSE_XMIT << 8); > + break; > + default: > + val &= ~GENMASK(14, 1); > + val |= (PHY_REG_CTRL1_ENERGY_DET_SENSE_PULSE << 14); > + break; > + } > + val = mv88e6xxx_phy_write(dev, port, PHY_REG_CTRL1, val); > + if (val < 0) > + return val; > + } > + > + /* enable port */ > + val = mv88e6xxx_port_read(dev, port, PORT_REG_CTRL); > + if (val < 0) > + return val; > + val &= ~(PORT_REG_CTRL_PSTATE_MASK << PORT_REG_CTRL_PSTATE_SHIFT); > + val |= (PORT_REG_CTRL_PSTATE_FORWARD << PORT_REG_CTRL_PSTATE_SHIFT); > + val = mv88e6xxx_port_write(dev, port, PORT_REG_CTRL, val); > + if (val < 0) > + return val; > + > + return phy_startup(phy); > +}