diff mbox series

[net-next,v2,7/8] net: phy: meson-gxl: add interrupt support

Message ID 20171207142715.32578-8-jbrunet@baylibre.com
State New
Headers show
Series phy: net: meson-gxl: clean-up and improvements | expand

Commit Message

Jerome Brunet Dec. 7, 2017, 2:27 p.m. UTC
Enable interrupt support in meson-gxl PHY driver

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

---
 drivers/net/phy/meson-gxl.c | 37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

-- 
2.14.3

Comments

Andrew Lunn Dec. 7, 2017, 3:54 p.m. UTC | #1
On Thu, Dec 07, 2017 at 03:27:14PM +0100, Jerome Brunet wrote:
> Enable interrupt support in meson-gxl PHY driver


Hi Jerome

Is it possible to implement did_interrupt()? That allows for shared
interrupts. It does however work fine without it, so long as the
interrupt is not shared.

	  Thanks
		Andrew
Jerome Brunet Dec. 7, 2017, 4:04 p.m. UTC | #2
On Thu, 2017-12-07 at 16:54 +0100, Andrew Lunn wrote:
> On Thu, Dec 07, 2017 at 03:27:14PM +0100, Jerome Brunet wrote:

> > Enable interrupt support in meson-gxl PHY driver

> 

> Hi Jerome

> 

> Is it possible to implement did_interrupt()? That allows for shared

> interrupts. It does however work fine without it, so long as the

> interrupt is not shared.


Hi Andrew,

It is always possible ;). The irq status registers gets reset on read.

In such case, ack_interrupt() and did_interrupt() would be more or less the same
function, except for the returned value, I guess ?

The phy being internal, I think it is unlikely to ever share its interrupt
though. If you prefer I implement this callback, I can certainly re-spin with it
?

Thanks for the lightning fast review by the way !

> 

> 	  Thanks

> 		Andrew
Andrew Lunn Dec. 7, 2017, 4:07 p.m. UTC | #3
> The phy being internal, I think it is unlikely to ever share its interrupt

> though.


O.K, don't bother.
 
> Thanks for the lightning fast review by the way !


You are welcome.

    Andrew
diff mbox series

Patch

diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c
index 5325940fe899..861b021b9758 100644
--- a/drivers/net/phy/meson-gxl.c
+++ b/drivers/net/phy/meson-gxl.c
@@ -33,6 +33,14 @@ 
 #define  TSTCNTL_WRITE_ADDRESS	GENMASK(4, 0)
 #define TSTREAD1	21
 #define TSTWRITE	23
+#define INTSRC_FLAG	29
+#define  INTSRC_ANEG_PR		BIT(1)
+#define  INTSRC_PARALLEL_FAULT	BIT(2)
+#define  INTSRC_ANEG_LP_ACK	BIT(3)
+#define  INTSRC_LINK_DOWN	BIT(4)
+#define  INTSRC_REMOTE_FAULT	BIT(5)
+#define  INTSRC_ANEG_COMPLETE	BIT(6)
+#define INTSRC_MASK	30
 
 #define BANK_ANALOG_DSP		0
 #define BANK_WOL		1
@@ -193,17 +201,44 @@  int meson_gxl_read_status(struct phy_device *phydev)
 	return genphy_read_status(phydev);
 }
 
+static int meson_gxl_ack_interrupt(struct phy_device *phydev)
+{
+	int ret = phy_read(phydev, INTSRC_FLAG);
+
+	return ret < 0 ? ret : 0;
+}
+
+static int meson_gxl_config_intr(struct phy_device *phydev)
+{
+	u16 val;
+
+	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+		val = INTSRC_ANEG_PR
+			| INTSRC_PARALLEL_FAULT
+			| INTSRC_ANEG_LP_ACK
+			| INTSRC_LINK_DOWN
+			| INTSRC_REMOTE_FAULT
+			| INTSRC_ANEG_COMPLETE;
+	} else {
+		val = 0;
+	}
+
+	return phy_write(phydev, INTSRC_MASK, val);
+}
+
 static struct phy_driver meson_gxl_phy[] = {
 	{
 		.phy_id		= 0x01814400,
 		.phy_id_mask	= 0xfffffff0,
 		.name		= "Meson GXL Internal PHY",
 		.features	= PHY_BASIC_FEATURES,
-		.flags		= PHY_IS_INTERNAL,
+		.flags		= PHY_IS_INTERNAL | PHY_HAS_INTERRUPT,
 		.config_init	= meson_gxl_config_init,
 		.config_aneg	= genphy_config_aneg,
 		.aneg_done      = genphy_aneg_done,
 		.read_status	= meson_gxl_read_status,
+		.ack_interrupt	= meson_gxl_ack_interrupt,
+		.config_intr	= meson_gxl_config_intr,
 		.suspend        = genphy_suspend,
 		.resume         = genphy_resume,
 	},