Liam White
TI CPSW hardware lacks soft resets and breaks drivers

In the AM35xx TRM, Table 22-43 on page 2564 documents the field descriptions for the USERACCESS0 register, which is used to kick off a MDIO access operation. For clarity, the table is reproduced as follows:

Bit Field Value Description
31 GO 0-1 Go bit. Writing a 1 to this bit causes the MDIO
state machine to perform an MDIO access when
it is convenient for it to do so; this is not an
instantaneous process. Writing a 0 to this bit has
no effect. This bit is writeable only if the MDIO
state machine is enabled. This bit will self clear
when the requested access has been completed.
Any writes to USERACCESS0 are blocked when
the GO bit is 1.
30 WRITE 0-1 Write enable bit. Setting this bit to 1 causes the
MDIO transaction to be a register write;
otherwise, it is a register read.
29 ACK 0-1 Acknowledge bit. This bit is set if the PHY
acknowledged the read transaction.
28-26 Reserved 0 Reserved
25-21 REGADR 0-1Fh Register address bits. This field specifies the
PHY register to be accessed for this transaction.
20-16 PHYADR 0-1Fh PHY address bits. This field specifies the PHY
to be accessed for this transaction.
15-0 DATA 0-FFFFh User data bits. These bits specify the data
value read from or to be written to the specified
PHY register.

USERACCESS0 is a 32-bit MMIO register. In U-Boot, it is accessed as follows:

static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
			  int dev_addr, int phy_reg)
{
	struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus);
	int data, ret;
	u32 reg;

	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
		return -EINVAL;

	ret = cpsw_mdio_wait_for_user_access(mdio);
	if (ret)
		return ret;
	reg = (USERACCESS_GO | USERACCESS_READ |
	       (phy_reg << USERACCESS_PHY_REG_SHIFT) |
	       (phy_id << USERACCESS_PHY_ADDR_SHIFT));
	writel(reg, &mdio->regs->user[0].access);
	ret = cpsw_mdio_wait_for_user_access(mdio);
	if (ret)
		return ret;

	reg = readl(&mdio->regs->user[0].access);
	data = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -1;
	return data;
}

You might be wondering what happens in cpsw_mdio_wait_for_user_access. Well, it spinwaits for the GO bit to be cleared by the CPSW hardware for up to CPSW_MDIO_TIMEOUT (100) milliseconds. And what happens if that timeout is hit?

Chaos. The CPSW hardware is sensitive to the MDIO pin muxing, so if the pins are not muxed for MDIO by the board file in U-Boot, the GO bit will never be cleared. This will cause to a string of seemingly random errors from the mii and mdio commands. There is no command to soft interrupt the CPSW hardware while a PHY access is pending, either, so the driver enters an invalid state where it is waiting for the GO bit to clear on every user access command.

To get out of this state, the entire switch block has to be turned off and back on again. This could be implemented in the driver, but it is probably not worth it in the context of what the driver is used for.