Thread (13 messages) 13 messages, 5 authors, 2020-12-01

Re: [PATCH net-next v4 4/4] net: phy: dp83td510: Add support for the DP83TD510 Ethernet PHY

From: Ioana Ciornei <hidden>
Date: 2020-11-17 20:57:26
Also in: linux-devicetree, lkml

On Tue, Nov 17, 2020 at 02:15:55PM -0600, Dan Murphy wrote:
The DP83TD510E is an ultra-low power Ethernet physical layer transceiver
that supports 10M single pair cable.

The device supports both 2.4-V p2p and 1-V p2p output voltage as defined
by IEEE 802.3cg 10Base-T1L specfications. These modes can be forced via
the device tree or the device is defaulted to auto negotiation to
determine the proper p2p voltage.

Signed-off-by: Dan Murphy <redacted>
---

v4 - Considerable rework of the code after secondary test setup was created.
This version also uses the handle_interrupt call back and reduces the
configuration arrays as it was determined that 80% of the array was the same.

 drivers/net/phy/Kconfig     |   6 +
 drivers/net/phy/Makefile    |   1 +
 drivers/net/phy/dp83td510.c | 505 ++++++++++++++++++++++++++++++++++++
 3 files changed, 512 insertions(+)
 create mode 100644 drivers/net/phy/dp83td510.c
[snip]
+static int dp83td510_ack_interrupt(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = phy_read(phydev, DP83TD510_INT_REG1);
+	if (ret < 0)
+		return ret;
+
+	ret = phy_read(phydev, DP83TD510_INT_REG2);
+	if (ret < 0)
+		return ret;
+
+	phy_trigger_machine(phydev);
+
+	return 0;
+}
+
+static irqreturn_t dp83td510_handle_interrupt(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = dp83td510_ack_interrupt(phydev);
+	if (ret)
+		return IRQ_NONE;
+
+	return IRQ_HANDLED;
+}
From what I can see in the datasheet, the INT_REG1 and INT_REG2 are used
for both interrupt configuration and interrupt status.

If this is the case, the state machine should only be triggered if the
interrupt was triggered (eg DP83TD510_INT1_LINK is set), not if _any_
bit from the register is set. This is broken since anytime you have
interrupts enabled, the lower half of the register will be non-zero
since that contains you interrupt enabled bits.

The .handle_interrupt() should look something like:

	ret = phy_read(phydev, DP83TD510_INT_REG1);
	if (ret < 0)
		return ret;
	
	if (!(ret & (DP83TD510_INT1_ESD | DP83TD510_INT1_LINK | DP83TD510_INT1_RHF)))
		return IRQ_NONE;

	ret = phy_read(phydev, DP83TD510_INT_REG2);
	if (ret < 0)
		return ret;
	
	if (!(ret & (DP83TD510_INT2_POR | DP83TD510_INT2_POL | DP83TD510_INT2_PAGE)))
		return IRQ_NONE;

	phy_trigger_machine(phydev);

	return IRQ_HANDLED;
+
+static int dp83td510_config_intr(struct phy_device *phydev)
+{
+	int int_status;
+	int gen_cfg_val;
+	int ret;
+
+	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+		int_status = phy_read(phydev, DP83TD510_INT_REG1);
+		if (int_status < 0)
+			return int_status;
+
+		int_status = (DP83TD510_INT1_ESD_EN | DP83TD510_INT1_LINK_EN |
+			      DP83TD510_INT1_RHF_EN);
+
+		ret = phy_write(phydev, DP83TD510_INT_REG1, int_status);
+		if (ret)
+			return ret;
+
+		int_status = phy_read(phydev, DP83TD510_INT_REG2);
+		if (int_status < 0)
+			return int_status;
+
+		int_status = (DP83TD510_INT2_POR | DP83TD510_INT2_POL |
+				DP83TD510_INT2_PAGE);
+
Shouldn't you use DP83TD510_INT2_POR_EN, DP83TD510_INT2_POL_EN etc here?
It seems that you are setting up the bits corresponding with the
interrupt status and not the interrupt enable.

Ioana
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help