summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arm/xscale/ixp425/if_npe.c68
-rw-r--r--sys/arm/xscale/ixp425/ixp425_npe.c104
-rw-r--r--sys/arm/xscale/ixp425/ixp425_npevar.h3
3 files changed, 109 insertions, 66 deletions
diff --git a/sys/arm/xscale/ixp425/if_npe.c b/sys/arm/xscale/ixp425/if_npe.c
index 52bea7657eca..ff8bd09e52ee 100644
--- a/sys/arm/xscale/ixp425/if_npe.c
+++ b/sys/arm/xscale/ixp425/if_npe.c
@@ -157,7 +157,6 @@ struct npe_softc {
* assumptions probably need to be handled through hints.
*/
static const struct {
- uint32_t imageid; /* default fw image */
uint32_t macbase;
uint32_t miibase;
int phy; /* phy id */
@@ -167,7 +166,6 @@ static const struct {
uint8_t tx_doneqid;
} npeconfig[NPE_MAX] = {
[NPE_A] = {
- .imageid = IXP425_NPE_A_IMAGEID,
.macbase = IXP435_MAC_A_HWBASE,
.miibase = IXP425_MAC_C_HWBASE,
.phy = 2,
@@ -177,7 +175,6 @@ static const struct {
.tx_doneqid = 31
},
[NPE_B] = {
- .imageid = IXP425_NPE_B_IMAGEID,
.macbase = IXP425_MAC_B_HWBASE,
.miibase = IXP425_MAC_C_HWBASE,
.phy = 0,
@@ -187,7 +184,6 @@ static const struct {
.tx_doneqid = 31
},
[NPE_C] = {
- .imageid = IXP425_NPE_C_IMAGEID,
.macbase = IXP425_MAC_C_HWBASE,
.miibase = IXP425_MAC_C_HWBASE,
.phy = 1,
@@ -258,7 +254,7 @@ SYSCTL_NODE(_hw, OID_AUTO, npe, CTLFLAG_RD, 0, "IXP4XX NPE driver parameters");
static int npe_debug = 0;
SYSCTL_INT(_hw_npe, OID_AUTO, debug, CTLFLAG_RW, &npe_debug,
0, "IXP4XX NPE network interface debug msgs");
-TUNABLE_INT("hw.npe.npe", &npe_debug);
+TUNABLE_INT("hw.npe.debug", &npe_debug);
#define DPRINTF(sc, fmt, ...) do { \
if (sc->sc_debug) device_printf(sc->sc_dev, fmt, __VA_ARGS__); \
} while (0)
@@ -301,16 +297,21 @@ npe_probe(device_t dev)
[NPE_B] = "IXP NPE-B",
[NPE_C] = "IXP NPE-C"
};
+ int unit = device_get_unit(dev);
int npeid;
+ if (unit > 2 ||
+ (ixp4xx_read_feature_bits() &
+ (unit == 0 ? EXP_FCTRL_ETH0 : EXP_FCTRL_ETH1)) == 0)
+ return EINVAL;
+
npeid = -1;
if (!override_npeid(dev, "npeid", &npeid))
- npeid = unit2npeid(device_get_unit(dev));
+ npeid = unit2npeid(unit);
if (npeid == -1) {
- device_printf(dev, "unit not supported\n");
+ device_printf(dev, "unit %d not supported\n", unit);
return EINVAL;
}
- /* XXX check feature register to see if enabled */
device_set_desc(dev, desc[npeid]);
return 0;
}
@@ -644,22 +645,6 @@ override_unit(device_t dev, const char *resname, int *val, int min, int max)
return 1;
}
-static int
-override_imageid(device_t dev, const char *resname, uint32_t *val)
-{
- int unit = device_get_unit(dev);
- int resval;
-
- if (resource_int_value("npe", unit, resname, &resval) != 0)
- return 0;
- /* XXX validate */
- if (bootverbose)
- device_printf(dev, "using npe.%d.%s=0x%x override\n",
- unit, resname, resval);
- *val = resval;
- return 1;
-}
-
static void
npe_mac_reset(struct npe_softc *sc)
{
@@ -677,7 +662,6 @@ npe_activate(device_t dev)
{
struct npe_softc * sc = device_get_softc(dev);
int error, i, macbase, miibase;
- uint32_t imageid, msg[2];
/*
* Setup NEP ID, MAC, and MII bindings. We allow override
@@ -722,35 +706,12 @@ npe_activate(device_t dev)
sc->sc_miih = sc->sc_ioh;
/*
- * Load NPE firmware and start it running. We assume
- * that minor version bumps remain compatible so probe
- * the firmware image starting with the expected version
- * and then bump the minor version up to the max.
+ * Load NPE firmware and start it running.
*/
- if (!override_imageid(dev, "imageid", &imageid))
- imageid = npeconfig[sc->sc_npeid].imageid;
- for (;;) {
- error = ixpnpe_init(sc->sc_npe, "npe_fw", imageid);
- if (error == 0)
- break;
- /* ESRCH is returned when the requested image is not present */
- if (error != ESRCH) {
- device_printf(dev, "cannot init NPE (error %d)\n",
- error);
- return error;
- }
- /* bump the minor version up to the max possible */
- if (NPEIMAGE_MINOR(imageid) == 0xff) {
- device_printf(dev, "cannot locate firmware "
- "(imageid 0x%08x)\n", imageid);
- return error;
- }
- imageid++;
- }
- /* NB: firmware should respond with a status msg */
- if (ixpnpe_recvmsg_sync(sc->sc_npe, msg) != 0) {
- device_printf(dev, "firmware did not respond as expected\n");
- return EIO;
+ error = ixpnpe_init(sc->sc_npe);
+ if (error != 0) {
+ device_printf(dev, "cannot init NPE (error %d)\n", error);
+ return error;
}
/* probe for PHY */
@@ -984,7 +945,6 @@ npe_setmac(struct npe_softc *sc, u_char *eaddr)
WR4(sc, NPE_MAC_UNI_ADDR_4, eaddr[3]);
WR4(sc, NPE_MAC_UNI_ADDR_5, eaddr[4]);
WR4(sc, NPE_MAC_UNI_ADDR_6, eaddr[5]);
-
}
static void
diff --git a/sys/arm/xscale/ixp425/ixp425_npe.c b/sys/arm/xscale/ixp425/ixp425_npe.c
index ea1928a05e37..0aa162a95c00 100644
--- a/sys/arm/xscale/ixp425/ixp425_npe.c
+++ b/sys/arm/xscale/ixp425/ixp425_npe.c
@@ -112,6 +112,8 @@ struct ixpnpe_softc {
struct mtx sc_mtx; /* mailbox lock */
uint32_t sc_msg[2]; /* reply msg collected in ixpnpe_intr */
int sc_msgwaiting; /* sc_msg holds valid data */
+ int sc_npeid;
+ int sc_nrefs; /* # of references */
int validImage; /* valid ucode image loaded */
int started; /* NPE is started */
@@ -121,6 +123,7 @@ struct ixpnpe_softc {
uint32_t savedExecCount;
uint32_t savedEcsDbgCtxtReg2;
};
+static struct ixpnpe_softc *npes[NPE_MAX];
#define IX_NPEDL_NPEIMAGE_FIELD_MASK 0xff
@@ -287,6 +290,11 @@ ixpnpe_attach(device_t dev, int npeid)
device_printf(dev, "%s: bad npeid %d\n", __func__, npeid);
return NULL;
}
+ sc = npes[npeid];
+ if (sc != NULL) {
+ sc->sc_nrefs++;
+ return sc;
+ }
config = &npeconfigs[npeid];
/* XXX M_BUS */
@@ -294,6 +302,8 @@ ixpnpe_attach(device_t dev, int npeid)
sc->sc_dev = dev;
sc->sc_iot = sa->sc_iot;
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "npe driver", MTX_DEF);
+ sc->sc_npeid = npeid;
+ sc->sc_nrefs = 1;
sc->sc_size = config->size;
sc->insMemSize = config->ins_memsize; /* size of instruction memory */
@@ -320,20 +330,26 @@ ixpnpe_attach(device_t dev, int npeid)
npe_reg_write(sc, IX_NPECTL,
npe_reg_read(sc, IX_NPECTL) | (IX_NPECTL_OFE | IX_NPECTL_OFWE));
+ npes[npeid] = sc;
+
return sc;
}
void
ixpnpe_detach(struct ixpnpe_softc *sc)
{
- /* disable output fifo interrupts */
- npe_reg_write(sc, IX_NPECTL,
- npe_reg_read(sc, IX_NPECTL) &~ (IX_NPECTL_OFE | IX_NPECTL_OFWE));
+ if (--sc->sc_nrefs == 0) {
+ npes[sc->sc_npeid] = NULL;
- bus_teardown_intr(sc->sc_dev, sc->sc_irq, sc->sc_ih);
- bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
- mtx_destroy(&sc->sc_mtx);
- free(sc, M_TEMP);
+ /* disable output fifo interrupts */
+ npe_reg_write(sc, IX_NPECTL,
+ npe_reg_read(sc, IX_NPECTL) &~ (IX_NPECTL_OFE | IX_NPECTL_OFWE));
+
+ bus_teardown_intr(sc->sc_dev, sc->sc_irq, sc->sc_ih);
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
+ mtx_destroy(&sc->sc_mtx);
+ free(sc, M_TEMP);
+ }
}
int
@@ -361,7 +377,7 @@ ixpnpe_start_locked(struct ixpnpe_softc *sc)
if (!sc->started) {
error = npe_cpu_start(sc);
if (error == 0)
- sc->started = 1;
+ sc->started = 1;
} else
error = 0;
@@ -442,8 +458,9 @@ npe_findimage(struct ixpnpe_softc *sc,
return ESRCH;
}
-int
-ixpnpe_init(struct ixpnpe_softc *sc, const char *imageName, uint32_t imageId)
+static int
+ixpnpe_load_firmware(struct ixpnpe_softc *sc, const char *imageName,
+ uint32_t imageId)
{
static const char *devname[4] =
{ "IXP425", "IXP435/IXP465", "DeviceID#2", "DeviceID#3" };
@@ -504,6 +521,73 @@ done:
return error;
}
+static int
+override_imageid(device_t dev, const char *resname, uint32_t *val)
+{
+ int unit = device_get_unit(dev);
+ int resval;
+
+ if (resource_int_value("npe", unit, resname, &resval) != 0)
+ return 0;
+ /* XXX validate */
+ if (bootverbose)
+ device_printf(dev, "using npe.%d.%s=0x%x override\n",
+ unit, resname, resval);
+ *val = resval;
+ return 1;
+}
+
+int
+ixpnpe_init(struct ixpnpe_softc *sc)
+{
+ static const uint32_t npeconfig[NPE_MAX] = {
+ [NPE_A] = IXP425_NPE_A_IMAGEID,
+ [NPE_B] = IXP425_NPE_B_IMAGEID,
+ [NPE_C] = IXP425_NPE_C_IMAGEID,
+ };
+ uint32_t imageid, msg[2];
+ int error;
+
+ if (sc->started)
+ return 0;
+ /*
+ * Load NPE firmware and start it running. We assume
+ * that minor version bumps remain compatible so probe
+ * the firmware image starting with the expected version
+ * and then bump the minor version up to the max.
+ */
+ if (!override_imageid(sc->sc_dev, "imageid", &imageid))
+ imageid = npeconfig[sc->sc_npeid];
+ for (;;) {
+ error = ixpnpe_load_firmware(sc, "npe_fw", imageid);
+ if (error == 0)
+ break;
+ /*
+ * ESRCH is returned when the requested image
+ * is not present
+ */
+ if (error != ESRCH) {
+ device_printf(sc->sc_dev,
+ "cannot init NPE (error %d)\n", error);
+ return error;
+ }
+ /* bump the minor version up to the max possible */
+ if (NPEIMAGE_MINOR(imageid) == 0xff) {
+ device_printf(sc->sc_dev, "cannot locate firmware "
+ "(imageid 0x%08x)\n", imageid);
+ return error;
+ }
+ imageid++;
+ }
+ /* NB: firmware should respond with a status msg */
+ if (ixpnpe_recvmsg_sync(sc, msg) != 0) {
+ device_printf(sc->sc_dev,
+ "firmware did not respond as expected\n");
+ return EIO;
+ }
+ return 0;
+}
+
int
ixpnpe_getfunctionality(struct ixpnpe_softc *sc)
{
diff --git a/sys/arm/xscale/ixp425/ixp425_npevar.h b/sys/arm/xscale/ixp425/ixp425_npevar.h
index 286f2169b248..fdab8bb9ffcd 100644
--- a/sys/arm/xscale/ixp425/ixp425_npevar.h
+++ b/sys/arm/xscale/ixp425/ixp425_npevar.h
@@ -111,8 +111,7 @@ void ixpnpe_detach(struct ixpnpe_softc *);
int ixpnpe_stopandreset(struct ixpnpe_softc *);
int ixpnpe_start(struct ixpnpe_softc *);
int ixpnpe_stop(struct ixpnpe_softc *);
-int ixpnpe_init(struct ixpnpe_softc *,
- const char *imageName, uint32_t imageId);
+int ixpnpe_init(struct ixpnpe_softc *);
int ixpnpe_getfunctionality(struct ixpnpe_softc *sc);
int ixpnpe_sendmsg_async(struct ixpnpe_softc *, const uint32_t msg[2]);