[PATCH 04/32] leon, greth: new option and change soft-reset logic for EDCL

Daniel Hellstrom daniel at gaisler.com
Thu May 11 14:25:49 UTC 2017


---
 c/src/lib/libbsp/sparc/shared/net/greth.c | 67 ++++++++++++++++++++++---------
 1 file changed, 49 insertions(+), 18 deletions(-)

diff --git a/c/src/lib/libbsp/sparc/shared/net/greth.c b/c/src/lib/libbsp/sparc/shared/net/greth.c
index 2e479ed..5e2ee49 100644
--- a/c/src/lib/libbsp/sparc/shared/net/greth.c
+++ b/c/src/lib/libbsp/sparc/shared/net/greth.c
@@ -155,6 +155,7 @@ struct greth_softc
    int minor;
    int phyaddr;  /* PHY Address configured by user (or -1 to autodetect) */
    unsigned int edcl_dis;
+   int greth_rst;
 
    int acceptBroadcast;
    rtems_id daemonTid;
@@ -353,7 +354,7 @@ greth_initialize_hardware (struct greth_softc *sc)
     int tmp2;
     struct timespec tstart, tnow;
     greth_regs *regs;
-    unsigned int advmodes;
+    unsigned int advmodes, speed;
 
     regs = sc->regs;
 
@@ -361,10 +362,18 @@ greth_initialize_hardware (struct greth_softc *sc)
     sc->rxInterrupts = 0;
     sc->rxPackets = 0;
 
-    regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED; /* Reset ON */
-    for (i = 0; i<100 && (regs->ctrl & GRETH_CTRL_RST); i++)
-        ;
-    regs->ctrl = GRETH_CTRL_DD | GRETH_CTRL_ED; /* Reset OFF. SW do PHY Init */
+    if (sc->greth_rst) {
+        /* Reset ON */
+        regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED;
+        for (i = 0; i<100 && (regs->ctrl & GRETH_CTRL_RST); i++)
+            ;
+        speed = 0; /* probe mode below */
+    } else {
+        /* inherit EDCL mode for now */
+        speed = sc->regs->ctrl & (GRETH_CTRL_GB|GRETH_CTRL_SP|GRETH_CTRL_FULLD);
+    }
+    /* Reset OFF and RX/TX DMA OFF. SW do PHY Init */
+    regs->ctrl = GRETH_CTRL_DD | GRETH_CTRL_ED | speed;
 
     /* Check if mac is gbit capable*/
     sc->gbit_mac = (regs->ctrl >> 27) & 1;
@@ -526,10 +535,15 @@ auto_neg_done:
     }
     while ((read_mii(sc, phyaddr, 0)) & 0x8000) {}
 
-    regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED; /* Reset ON */
-    for (i = 0; i < 100 && (regs->ctrl & GRETH_CTRL_RST); i++)
-        ;
-    regs->ctrl = GRETH_CTRL_DD | sc->edcl_dis; /* Reset OFF. SW do PHY Init */
+    if (sc->greth_rst) {
+        /* Reset ON */
+        regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED;
+        for (i = 0; i < 100 && (regs->ctrl & GRETH_CTRL_RST); i++)
+            ;
+    }
+    /* Reset OFF. Set mode matching PHY settings. */
+    speed = (sc->gb << 8) | (sc->sp << 7) | (sc->fd << 4);
+    regs->ctrl = GRETH_CTRL_DD | sc->edcl_dis | speed;
 
     /* Initialize rx/tx descriptor table pointers. Due to alignment we 
      * always allocate maximum table size.
@@ -616,7 +630,7 @@ auto_neg_done:
     /* install interrupt handler */
     drvmgr_interrupt_register(sc->dev, 0, "greth", greth_interrupt, sc);
 
-    regs->ctrl |= GRETH_CTRL_RXEN | (sc->fd << 4) | GRETH_CTRL_RXIRQ | (sc->sp << 7) | (sc->gb << 8);
+    regs->ctrl |= GRETH_CTRL_RXEN | GRETH_CTRL_RXIRQ;
 
     print_init_info(sc);
 }
@@ -1178,17 +1192,20 @@ greth_stop (struct greth_softc *sc)
 {
     struct ifnet *ifp = &sc->arpcom.ac_if;
     SPIN_IRQFLAGS(flags);
+    unsigned int speed;
 
     SPIN_LOCK_IRQ(&sc->devlock, flags);
     ifp->if_flags &= ~IFF_RUNNING;
 
+    speed = sc->regs->ctrl & (GRETH_CTRL_GB | GRETH_CTRL_SP | GRETH_CTRL_FULLD);
+
     /* RX/TX OFF */
-    sc->regs->ctrl = GRETH_CTRL_DD | GRETH_CTRL_ED;
+    sc->regs->ctrl = GRETH_CTRL_DD | GRETH_CTRL_ED | speed;
     /* Reset ON */
-    sc->regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED;
+    if (sc->greth_rst)
+        sc->regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED | speed;
     /* Reset OFF and restore link settings previously detected if any */
-    sc->regs->ctrl = GRETH_CTRL_DD | sc->edcl_dis |
-                     (sc->gb << 8) | (sc->sp << 7) | (sc->fd << 4);
+    sc->regs->ctrl = GRETH_CTRL_DD | sc->edcl_dis | speed;
     SPIN_UNLOCK_IRQ(&sc->devlock, flags);
 
     sc->next_tx_mbuf = NULL;
@@ -1460,6 +1477,7 @@ int greth_device_init(struct greth_softc *sc)
     pnpinfo = &ambadev->info;
     sc->regs = (greth_regs *)pnpinfo->apb_slv->start;
     sc->minor = sc->dev->minor_drv;
+    sc->greth_rst = 1;
 
     /* Remember EDCL enabled/disable state before reset */
     sc->edcl_dis = sc->regs->ctrl & GRETH_CTRL_ED;
@@ -1468,19 +1486,32 @@ int greth_device_init(struct greth_softc *sc)
     value = drvmgr_dev_key_get(sc->dev, "edclDis", DRVMGR_KT_INT);
     if ( value ) {
         /* Force EDCL mode. Has an effect later when GRETH+PHY is initialized */
-        if (value->i > 0)
+        if (value->i > 0) {
             sc->edcl_dis = GRETH_CTRL_ED;
-        else
+        } else {
+            /* Default to avoid soft-reset the GRETH when EDCL is forced */
             sc->edcl_dis = 0;
+            sc->greth_rst = 0;
+	}
+    }
+
+    /* let user control soft-reset of GRETH (for debug) */
+    value = drvmgr_dev_key_get(sc->dev, "soft-reset", DRVMGR_KT_INT);
+    if ( value) {
+        sc->greth_rst = value->i ? 1 : 0;
     }
 
     /* clear control register and reset NIC and keep current speed modes.
      * This should be done as quick as possible during startup, this is to
      * stop DMA transfers after a reboot.
+     *
+     * When EDCL is forced enabled reset is skipped, disabling RX/TX DMA is
+     * is enough during debug.
      */
     speed = sc->regs->ctrl & (GRETH_CTRL_GB | GRETH_CTRL_SP | GRETH_CTRL_FULLD);
-    sc->regs->ctrl = GRETH_CTRL_DD | GRETH_CTRL_ED;
-    sc->regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED;
+    sc->regs->ctrl = GRETH_CTRL_DD | GRETH_CTRL_ED | speed;
+    if (sc->greth_rst)
+        sc->regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED | speed;
     sc->regs->ctrl = GRETH_CTRL_DD | sc->edcl_dis | speed;
 
     /* Configure driver by overriding default config with the bus resources 
-- 
2.7.4



More information about the devel mailing list