The branch main has been updated by wma:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=89595c17915a11779de050b05ee7a5da09fc7f97

commit 89595c17915a11779de050b05ee7a5da09fc7f97
Author:     Kornel Duleba <[email protected]>
AuthorDate: 2021-11-15 09:00:07 +0000
Commit:     Wojciech Macek <[email protected]>
CommitDate: 2021-11-24 06:40:37 +0000

    vscphy: Add support for PHY interrupts
    
    They're allocated using standard newbus API,
    which means that we rely on miibus to handle the allocation.
    Add VSC8504 to the list of supported PHYs, as it is similar enough
    to the VSC8501 that is already supported by this driver.
    
    Obtained from: Semihalf
    Sponsored by: Alstom Group
    Differential revision: https://reviews.freebsd.org/D32816
---
 sys/dev/mii/miidevs  |  1 +
 sys/dev/mii/vscphy.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs
index b2b446637b2e..0b818c2e6e2b 100644
--- a/sys/dev/mii/miidevs
+++ b/sys/dev/mii/miidevs
@@ -345,6 +345,7 @@ model xxTSC 78Q2121         0x0015 78Q2121 100BASE-TX media 
interface
 
 /* Vitesse Semiconductor (now Microsemi) */
 model xxVITESSE VSC8501                0x0013 Vitesse VSC8501 10/100/1000TX PHY
+model xxVITESSE VSC8504                0x000c Vitesse VSC8504 10/100/1000TX PHY
 model xxVITESSE VSC8641                0x0003 Vitesse VSC8641 10/100/1000TX PHY
 
 /* XaQti Corp. PHYs */
diff --git a/sys/dev/mii/vscphy.c b/sys/dev/mii/vscphy.c
index be90145e6299..b91cb408dae7 100644
--- a/sys/dev/mii/vscphy.c
+++ b/sys/dev/mii/vscphy.c
@@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/module.h>
 #include <sys/bus.h>
 #include <sys/malloc.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
 
 #include <net/if.h>
 #include <net/if_media.h>
@@ -59,12 +61,23 @@ __FBSDID("$FreeBSD$");
 #include <dev/mii/mii_fdt.h>
 #endif
 
+#define        BIT(x)  (1 << (x))
+
 /* Vitesse VSC8501 */
 #define        VSC8501_EXTPAGE_REG             0x001f
 
 #define        VSC8501_EXTCTL1_REG             0x0017
 #define          VSC8501_EXTCTL1_RGMII_MODE      (1u << 12)
 
+#define        VSC8501_INT_MASK                0x19
+#define        VSC8501_INT_MDINT               BIT(15)
+#define        VSC8501_INT_SPD_CHG             BIT(14)
+#define        VSC8501_INT_LINK_CHG            BIT(13)
+#define        VSC8501_INT_FD_CHG              BIT(12)
+#define        VSC8501_INT_AN_CMPL             BIT(10)
+
+#define        VSC8501_INT_STS                 0x1a
+
 #define        VSC8501_RGMII_CTRL_PAGE         0x02
 #define        VSC8501_RGMII_CTRL_REG          0x14
 #define          VSC8501_RGMII_DELAY_MASK        0x07
@@ -83,6 +96,8 @@ struct vscphy_softc {
        int             rxdelay;
        int             txdelay;
        bool            laneswap;
+       struct resource *irq_res;
+       void            *irq_cookie;
 };
 
 static void vscphy_reset(struct mii_softc *);
@@ -90,6 +105,7 @@ static int  vscphy_service(struct mii_softc *, struct 
mii_data *, int);
 
 static const struct mii_phydesc vscphys[] = {
        MII_PHY_DESC(xxVITESSE, VSC8501),
+       MII_PHY_DESC(xxVITESSE, VSC8504),
        MII_PHY_END
 };
 
@@ -235,10 +251,30 @@ vscphy_probe(device_t dev)
        return (mii_phy_dev_probe(dev, vscphys, BUS_PROBE_DEFAULT));
 }
 
+static void
+vscphy_intr(void *arg)
+{
+       struct vscphy_softc *vsc;
+       uint32_t status;
+
+       vsc = (struct vscphy_softc *)arg;
+
+       status = vscphy_read(vsc, VSC8501_INT_STS);
+       status &= vscphy_read(vsc, VSC8501_INT_MASK);
+
+       if (!status)
+               return;
+
+       PHY_STATUS(&vsc->mii_sc);
+       mii_phy_update(&vsc->mii_sc, MII_MEDIACHG);
+}
+
 static int
 vscphy_attach(device_t dev)
 {
        struct vscphy_softc *vsc;
+       uint32_t value;
+       int rid, error;
 
        vsc = device_get_softc(dev);
        vsc->dev = dev;
@@ -250,14 +286,51 @@ vscphy_attach(device_t dev)
        mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &vscphy_funcs, 1);
        mii_phy_setmedia(&vsc->mii_sc);
 
+       rid = 0;
+       vsc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+           RF_ACTIVE | RF_SHAREABLE);
+       if (vsc->irq_res == NULL)
+               goto no_irq;
+
+       error = bus_setup_intr(dev, vsc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
+           NULL, vscphy_intr, vsc, &vsc->irq_cookie);
+       if (error != 0) {
+               bus_release_resource(dev, SYS_RES_IRQ, 0, vsc->irq_res);
+               vsc->irq_res = NULL;
+               goto no_irq;
+       }
+
+       /* Ack and unmask all relevant interrupts. */
+       (void)vscphy_read(vsc, VSC8501_INT_STS);
+       value = VSC8501_INT_MDINT    |
+               VSC8501_INT_SPD_CHG  |
+               VSC8501_INT_LINK_CHG |
+               VSC8501_INT_FD_CHG   |
+               VSC8501_INT_AN_CMPL;
+       vscphy_write(vsc, VSC8501_INT_MASK, value);
+
+no_irq:
        return (0);
 }
 
+static int
+vscphy_detach(device_t dev)
+{
+       struct vscphy_softc *vsc;
+
+       vsc = device_get_softc(dev);
+
+       bus_teardown_intr(dev, vsc->irq_res, vsc->irq_cookie);
+       bus_release_resource(dev, SYS_RES_IRQ, 0, vsc->irq_res);
+
+       return (mii_phy_detach(dev));
+}
+
 static device_method_t vscphy_methods[] = {
        /* device interface */
        DEVMETHOD(device_probe,         vscphy_probe),
        DEVMETHOD(device_attach,        vscphy_attach),
-       DEVMETHOD(device_detach,        mii_phy_detach),
+       DEVMETHOD(device_detach,        vscphy_detach),
        DEVMETHOD(device_shutdown,      bus_generic_shutdown),
        DEVMETHOD_END
 };

Reply via email to