summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2008-03-22 16:53:28 +0000
committersam <sam@FreeBSD.org>2008-03-22 16:53:28 +0000
commit85a6e3f5ef643fa3f5e78623182c28b37c8992c9 (patch)
tree8fd0256262dfac5a587637bf77b3999d928a72fa
parent16045945a98164861ef57d6224517a95f4c2ca0c (diff)
downloadFreeBSD-src-85a6e3f5ef643fa3f5e78623182c28b37c8992c9.zip
FreeBSD-src-85a6e3f5ef643fa3f5e78623182c28b37c8992c9.tar.gz
Improve mac+phy configuration so that hints can be used to describe
layouts different than the defaults: o hint.npe.0.mac="A", "B", etc. specifies the window for MAC register accesses o hint.npe.0.mii="A", "B", etc. specifies PHY registers o hint.npe.1.phy=%d specifies the PHY to map to a port This allows devices like NSLU to be setup w/o code changes and will also be used for forthcoming support for more Avila boards. Reviewed by: imp MFC after 1 week
-rw-r--r--sys/arm/xscale/ixp425/if_npe.c96
1 files changed, 80 insertions, 16 deletions
diff --git a/sys/arm/xscale/ixp425/if_npe.c b/sys/arm/xscale/ixp425/if_npe.c
index 730f10a..44954f9 100644
--- a/sys/arm/xscale/ixp425/if_npe.c
+++ b/sys/arm/xscale/ixp425/if_npe.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2006 Sam Leffler. All rights reserved.
+ * Copyright (c) 2006-2008 Sam Leffler. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -134,6 +134,7 @@ struct npe_softc {
int rx_freeqid; /* rx free buffers qid */
int tx_qid; /* tx qid */
int tx_doneqid; /* tx completed qid */
+ int sc_phy; /* PHY id */
struct ifmib_iso_8802_3 mibdata;
bus_dma_tag_t sc_stats_tag; /* bus dma tag for stats block */
struct npestats *sc_stats;
@@ -160,6 +161,7 @@ static const struct {
int regsize;
uint32_t miibase;
int miisize;
+ int phy; /* phy id */
uint8_t rx_qid;
uint8_t rx_freeqid;
uint8_t tx_qid;
@@ -172,6 +174,7 @@ static const struct {
.regsize = IXP425_MAC_A_SIZE,
.miibase = IXP425_MAC_A_HWBASE,
.miisize = IXP425_MAC_A_SIZE,
+ .phy = 0,
.rx_qid = 4,
.rx_freeqid = 27,
.tx_qid = 24,
@@ -184,6 +187,7 @@ static const struct {
.regsize = IXP425_MAC_B_SIZE,
.miibase = IXP425_MAC_A_HWBASE,
.miisize = IXP425_MAC_A_SIZE,
+ .phy = 1,
.rx_qid = 12,
.rx_freeqid = 28,
.tx_qid = 25,
@@ -544,11 +548,61 @@ npe_dma_destroy(struct npe_softc *sc, struct npedma *dma)
}
static int
+override_addr(device_t dev, const char *resname, int *base, int *size)
+{
+ int unit = device_get_unit(dev);
+ const char *resval;
+
+ /* XXX warn for wrong hint type */
+ if (resource_string_value("npe", unit, resname, &resval) != 0)
+ return 0;
+ switch (resval[0]) {
+ case 'A':
+ *base = IXP425_MAC_A_HWBASE;
+ *size = IXP425_MAC_A_SIZE;
+ break;
+ case 'B':
+ *base = IXP425_MAC_B_HWBASE;
+ *size = IXP425_MAC_B_SIZE;
+ break;
+ default:
+ device_printf(dev, "Warning, bad value %s for "
+ "npe.%d.%s ignored\n", resval, unit, resname);
+ return 0;
+ }
+ if (bootverbose)
+ device_printf(dev, "using npe.%d.%s=%s override\n",
+ unit, resname, resval);
+ return 1;
+}
+
+static int
+override_unit(device_t dev, const char *resname, int *val, int min, int max)
+{
+ int unit = device_get_unit(dev);
+ int resval;
+
+ if (resource_int_value("npe", unit, resname, &resval) != 0)
+ return 0;
+ if (!(min <= resval && resval <= max)) {
+ device_printf(dev, "Warning, bad value %d for npe.%d.%s "
+ "ignored (value must be [%d-%d])\n", resval, unit,
+ resname, min, max);
+ return 0;
+ }
+ if (bootverbose)
+ device_printf(dev, "using npe.%d.%s=%d override\n",
+ unit, resname, resval);
+ *val = resval;
+ return 1;
+}
+
+static int
npe_activate(device_t dev)
{
struct npe_softc * sc = device_get_softc(dev);
int unit = device_get_unit(dev);
- int error, i;
+ int error, i, regbase, regsize, miibase, miisize;
uint32_t imageid;
/*
@@ -571,24 +625,29 @@ npe_activate(device_t dev)
imageid++;
}
- if (bus_space_map(sc->sc_iot, npeconfig[unit].regbase,
- npeconfig[unit].regsize, 0, &sc->sc_ioh)) {
+ if (!override_addr(dev, "mac", &regbase, &regsize)) {
+ regbase = npeconfig[unit].regbase;
+ regbase = npeconfig[unit].regsize;
+ }
+ if (bus_space_map(sc->sc_iot, regbase, regsize, 0, &sc->sc_ioh)) {
device_printf(dev, "Cannot map registers 0x%x:0x%x\n",
- npeconfig[unit].regbase, npeconfig[unit].regsize);
+ regbase, regsize);
return ENOMEM;
}
- if (npeconfig[unit].miibase != npeconfig[unit].regbase) {
+ if (!override_addr(dev, "mii", &miibase, &miisize)) {
+ miibase = npeconfig[unit].miibase;
+ miisize = npeconfig[unit].miisize;
+ }
+ if (miibase != regbase) {
/*
- * The PHY's are only accessible from one MAC (it appears)
- * so for other MAC's setup an additional mapping for
- * frobbing the PHY registers.
+ * PHY is mapped through a different MAC, setup an
+ * additional mapping for frobbing the PHY registers.
*/
- if (bus_space_map(sc->sc_iot, npeconfig[unit].miibase,
- npeconfig[unit].miisize, 0, &sc->sc_miih)) {
+ if (bus_space_map(sc->sc_iot, miibase, miisize, 0, &sc->sc_miih)) {
device_printf(dev,
"Cannot map MII registers 0x%x:0x%x\n",
- npeconfig[unit].miibase, npeconfig[unit].miisize);
+ miibase, miisize);
return ENOMEM;
}
} else
@@ -667,6 +726,13 @@ device_printf(sc->sc_dev, "remember to fix rx q setup\n");
tx_doneqid = sc->tx_doneqid;
}
+ /*
+ * Setup phy port number. We allow override via hints
+ * to handle different board configs.
+ */
+ if (!override_unit(dev, "phy", &sc->sc_phy, 0, MII_NPHY-1))
+ sc->sc_phy = npeconfig[unit].phy;
+
KASSERT(npes[npeconfig[unit].npeid] == NULL,
("npe %u already setup", npeconfig[unit].npeid));
npes[npeconfig[unit].npeid] = sc;
@@ -1478,8 +1544,6 @@ npe_child_detached(device_t dev, device_t child)
/*
* MII bus support routines.
- *
- * NB: ixp425 has one PHY per NPE
*/
static uint32_t
npe_mii_mdio_read(struct npe_softc *sc, int reg)
@@ -1532,7 +1596,7 @@ npe_miibus_readreg(device_t dev, int phy, int reg)
struct npe_softc *sc = device_get_softc(dev);
uint32_t v;
- if (phy != device_get_unit(dev)) /* XXX */
+ if (phy != sc->sc_phy) /* XXX no auto-detect */
return 0xffff;
v = (phy << NPE_MII_ADDR_SHL) | (reg << NPE_MII_REG_SHL)
| NPE_MII_GO;
@@ -1551,7 +1615,7 @@ npe_miibus_writereg(device_t dev, int phy, int reg, int data)
struct npe_softc *sc = device_get_softc(dev);
uint32_t v;
- if (phy != device_get_unit(dev)) /* XXX */
+ if (phy != sc->sc_phy) /* XXX */
return;
v = (phy << NPE_MII_ADDR_SHL) | (reg << NPE_MII_REG_SHL)
| data | NPE_MII_WRITE
OpenPOWER on IntegriCloud