summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/conf/files.powerpc2
-rw-r--r--sys/dev/tsec/if_tsec.c38
-rw-r--r--sys/dev/tsec/if_tsec.h11
-rw-r--r--sys/dev/tsec/if_tsec_fdt.c21
-rw-r--r--sys/dev/tsec/if_tsecreg.h13
-rw-r--r--sys/powerpc/aim/machdep.c5
-rw-r--r--sys/powerpc/include/ofw_machdep.h1
-rw-r--r--sys/powerpc/ofw/ofw_machdep.c77
8 files changed, 133 insertions, 35 deletions
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index aa55d0a..e0f8ee8 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -140,7 +140,7 @@ powerpc/mpc85xx/mpc85xx.c optional mpc85xx
powerpc/mpc85xx/nexus.c optional mpc85xx
powerpc/mpc85xx/pci_fdt.c optional pci mpc85xx
powerpc/ofw/ofw_cpu.c optional aim
-powerpc/ofw/ofw_machdep.c optional aim
+powerpc/ofw/ofw_machdep.c standard
powerpc/ofw/ofw_pci.c optional pci aim
powerpc/ofw/ofw_pcibus.c optional pci aim
powerpc/ofw/ofw_pcib_pci.c optional pci aim
diff --git a/sys/dev/tsec/if_tsec.c b/sys/dev/tsec/if_tsec.c
index 8041776..242df3e 100644
--- a/sys/dev/tsec/if_tsec.c
+++ b/sys/dev/tsec/if_tsec.c
@@ -111,6 +111,8 @@ DRIVER_MODULE(miibus, tsec, miibus_driver, miibus_devclass, 0, 0);
MODULE_DEPEND(tsec, ether, 1, 1, 1);
MODULE_DEPEND(tsec, miibus, 1, 1, 1);
+struct mtx tsec_phy_mtx;
+
int
tsec_attach(struct tsec_softc *sc)
{
@@ -121,6 +123,10 @@ tsec_attach(struct tsec_softc *sc)
int error = 0;
int i;
+ /* Initialize global (because potentially shared) MII lock */
+ if (!mtx_initialized(&tsec_phy_mtx))
+ mtx_init(&tsec_phy_mtx, "tsec mii", NULL, MTX_DEF);
+
/* Reset all TSEC counters */
TSEC_TX_RX_COUNTERS_INIT(sc);
@@ -406,21 +412,24 @@ tsec_init_locked(struct tsec_softc *sc)
*/
TSEC_WRITE(sc, TSEC_REG_TBIPA, 5);
+ TSEC_PHY_LOCK(sc);
+
/* Step 6: Reset the management interface */
- TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_RESETMGMT);
+ TSEC_PHY_WRITE(sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_RESETMGMT);
/* Step 7: Setup the MII Mgmt clock speed */
- TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_CLKDIV28);
+ TSEC_PHY_WRITE(sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_CLKDIV28);
/* Step 8: Read MII Mgmt indicator register and check for Busy = 0 */
timeout = TSEC_READ_RETRY;
- while (--timeout && (TSEC_READ(sc->phy_sc, TSEC_REG_MIIMIND) &
+ while (--timeout && (TSEC_PHY_READ(sc, TSEC_REG_MIIMIND) &
TSEC_MIIMIND_BUSY))
DELAY(TSEC_READ_DELAY);
if (timeout == 0) {
if_printf(ifp, "tsec_init_locked(): Mgmt busy timeout\n");
return;
}
+ TSEC_PHY_UNLOCK(sc);
/* Step 9: Setup the MII Mgmt */
mii_mediachg(sc->tsec_mii);
@@ -1561,22 +1570,27 @@ tsec_miibus_readreg(device_t dev, int phy, int reg)
{
struct tsec_softc *sc;
uint32_t timeout;
+ int rv;
sc = device_get_softc(dev);
- TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
- TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCOM, 0);
- TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCOM, TSEC_MIIMCOM_READCYCLE);
+ TSEC_PHY_LOCK();
+ TSEC_PHY_WRITE(sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
+ TSEC_PHY_WRITE(sc, TSEC_REG_MIIMCOM, 0);
+ TSEC_PHY_WRITE(sc, TSEC_REG_MIIMCOM, TSEC_MIIMCOM_READCYCLE);
timeout = TSEC_READ_RETRY;
- while (--timeout && TSEC_READ(sc->phy_sc, TSEC_REG_MIIMIND) &
+ while (--timeout && TSEC_PHY_READ(sc, TSEC_REG_MIIMIND) &
(TSEC_MIIMIND_NOTVALID | TSEC_MIIMIND_BUSY))
DELAY(TSEC_READ_DELAY);
if (timeout == 0)
device_printf(dev, "Timeout while reading from PHY!\n");
- return (TSEC_READ(sc->phy_sc, TSEC_REG_MIIMSTAT));
+ rv = TSEC_PHY_READ(sc, TSEC_REG_MIIMSTAT);
+ TSEC_PHY_UNLOCK();
+
+ return (rv);
}
int
@@ -1587,13 +1601,15 @@ tsec_miibus_writereg(device_t dev, int phy, int reg, int value)
sc = device_get_softc(dev);
- TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
- TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCON, value);
+ TSEC_PHY_LOCK();
+ TSEC_PHY_WRITE(sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
+ TSEC_PHY_WRITE(sc, TSEC_REG_MIIMCON, value);
timeout = TSEC_READ_RETRY;
- while (--timeout && (TSEC_READ(sc->phy_sc, TSEC_REG_MIIMIND) &
+ while (--timeout && (TSEC_READ(sc, TSEC_REG_MIIMIND) &
TSEC_MIIMIND_BUSY))
DELAY(TSEC_READ_DELAY);
+ TSEC_PHY_UNLOCK();
if (timeout == 0)
device_printf(dev, "Timeout while writing to PHY!\n");
diff --git a/sys/dev/tsec/if_tsec.h b/sys/dev/tsec/if_tsec.h
index cfba3f6..7c6bc30 100644
--- a/sys/dev/tsec/if_tsec.h
+++ b/sys/dev/tsec/if_tsec.h
@@ -133,7 +133,8 @@ struct tsec_softc {
struct mbuf *frame;
int phyaddr;
- struct tsec_softc *phy_sc;
+ bus_space_tag_t phy_bst;
+ bus_space_handle_t phy_bsh;
};
/* interface to get/put generic objects */
@@ -253,6 +254,14 @@ struct tsec_softc {
#define TSEC_WRITE(sc, reg, val) \
bus_space_write_4((sc)->sc_bas.bst, (sc)->sc_bas.bsh, (reg), (val))
+extern struct mtx tsec_phy_mtx;
+#define TSEC_PHY_LOCK(sc) mtx_lock(&tsec_phy_mtx)
+#define TSEC_PHY_UNLOCK(sc) mtx_unlock(&tsec_phy_mtx)
+#define TSEC_PHY_READ(sc, reg) \
+ bus_space_read_4((sc)->phy_bst, (sc)->phy_bsh, (reg))
+#define TSEC_PHY_WRITE(sc, reg, val) \
+ bus_space_write_4((sc)->phy_bst, (sc)->phy_bsh, (reg), (val))
+
/* Lock for transmitter */
#define TSEC_TRANSMIT_LOCK(sc) do { \
mtx_assert(&(sc)->receive_lock, MA_NOTOWNED); \
diff --git a/sys/dev/tsec/if_tsec_fdt.c b/sys/dev/tsec/if_tsec_fdt.c
index 7f6f414..8836851 100644
--- a/sys/dev/tsec/if_tsec_fdt.c
+++ b/sys/dev/tsec/if_tsec_fdt.c
@@ -110,6 +110,10 @@ tsec_fdt_probe(device_t dev)
struct tsec_softc *sc;
uint32_t id;
+ if (ofw_bus_get_type(dev) == NULL ||
+ strcmp(ofw_bus_get_type(dev), "network") != 0)
+ return (ENXIO);
+
if (!ofw_bus_is_compatible(dev, "gianfar"))
return (ENXIO);
@@ -148,6 +152,7 @@ static int
tsec_fdt_attach(device_t dev)
{
struct tsec_softc *sc;
+ phandle_t phy;
int error = 0;
sc = device_get_softc(dev);
@@ -155,9 +160,14 @@ tsec_fdt_attach(device_t dev)
sc->node = ofw_bus_get_node(dev);
/* Get phy address from fdt */
- if (fdt_get_phyaddr(sc->node, sc->dev, &sc->phyaddr,
- (void **)&sc->phy_sc) != 0)
+ if (OF_getencprop(sc->node, "phy-handle", &phy, sizeof(phy)) <= 0) {
+ device_printf(dev, "PHY not found in device tree");
return (ENXIO);
+ }
+
+ phy = OF_xref_phandle(phy);
+ OF_decode_addr(OF_parent(phy), 0, &sc->phy_bst, &sc->phy_bsh);
+ OF_getencprop(phy, "reg", &sc->phyaddr, sizeof(sc->phyaddr));
/* Init timer */
callout_init(&sc->tsec_callout, 1);
@@ -324,6 +334,13 @@ tsec_get_hwaddr(struct tsec_softc *sc, uint8_t *addr)
return;
}
+ /* Also try the mac-address property, which is second-best */
+ i = OF_getprop(sc->node, "mac-address", (void *)hw.addr, 6);
+ if (i == 6 && (hw.reg[0] != 0 || hw.reg[1] != 0)) {
+ bcopy(hw.addr, addr, 6);
+ return;
+ }
+
/*
* Fall back -- use the currently programmed address in the hope that
* it was set be firmware...
diff --git a/sys/dev/tsec/if_tsecreg.h b/sys/dev/tsec/if_tsecreg.h
index 4ba1997..1994298 100644
--- a/sys/dev/tsec/if_tsecreg.h
+++ b/sys/dev/tsec/if_tsecreg.h
@@ -77,12 +77,13 @@
* register */
#define TSEC_REG_HAFDUP 0x50c /* Half-duplex register */
#define TSEC_REG_MAXFRM 0x510 /* Maximum frame length register */
-#define TSEC_REG_MIIMCFG 0x520 /* MII Management configuration register */
-#define TSEC_REG_MIIMCOM 0x524 /* MII Management command register */
-#define TSEC_REG_MIIMADD 0x528 /* MII Management address register */
-#define TSEC_REG_MIIMCON 0x52c /* MII Management control register */
-#define TSEC_REG_MIIMSTAT 0x530 /* MII Management status register */
-#define TSEC_REG_MIIMIND 0x534 /* MII Management indicator register */
+#define TSEC_REG_MIIBASE 0x520 /* MII Management base, rest offsets */
+#define TSEC_REG_MIIMCFG 0x0 /* MII Management configuration register */
+#define TSEC_REG_MIIMCOM 0x4 /* MII Management command register */
+#define TSEC_REG_MIIMADD 0x8 /* MII Management address register */
+#define TSEC_REG_MIIMCON 0xc /* MII Management control register */
+#define TSEC_REG_MIIMSTAT 0x10 /* MII Management status register */
+#define TSEC_REG_MIIMIND 0x14 /* MII Management indicator register */
#define TSEC_REG_IFSTAT 0x53c /* Interface status register */
#define TSEC_REG_MACSTNADDR1 0x540 /* Station address register, part 1 */
#define TSEC_REG_MACSTNADDR2 0x544 /* Station address register, part 2 */
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index 5ae42bd..4b211fa 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -123,6 +123,7 @@ __FBSDID("$FreeBSD$");
#include <machine/spr.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
+#include <machine/ofw_machdep.h>
#include <ddb/ddb.h>
@@ -249,6 +250,7 @@ extern void *dblow, *dbsize;
extern void *imisstrap, *imisssize;
extern void *dlmisstrap, *dlmisssize;
extern void *dsmisstrap, *dsmisssize;
+char save_trap_init[0x2f00]; /* EXC_LAST */
uintptr_t
powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
@@ -273,6 +275,9 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
trap_offset = 0;
cacheline_warn = 0;
+ /* Save trap vectors. */
+ ofw_save_trap_vec(save_trap_init);
+
#ifdef WII
/*
* The Wii loader doesn't pass us any environment so, mdp
diff --git a/sys/powerpc/include/ofw_machdep.h b/sys/powerpc/include/ofw_machdep.h
index b85ebe1..023fa4c 100644
--- a/sys/powerpc/include/ofw_machdep.h
+++ b/sys/powerpc/include/ofw_machdep.h
@@ -47,5 +47,6 @@ void OF_reboot(void);
void ofw_mem_regions(struct mem_region **, int *, struct mem_region **, int *);
void ofw_quiesce(void); /* Must be called before VM is up! */
+void ofw_save_trap_vec(char *);
#endif /* _MACHINE_OFW_MACHDEP_H_ */
diff --git a/sys/powerpc/ofw/ofw_machdep.c b/sys/powerpc/ofw/ofw_machdep.c
index 8165515..4969ec0 100644
--- a/sys/powerpc/ofw/ofw_machdep.c
+++ b/sys/powerpc/ofw/ofw_machdep.c
@@ -59,18 +59,43 @@ __FBSDID("$FreeBSD$");
#include <machine/md_var.h>
#include <machine/platform.h>
#include <machine/ofw_machdep.h>
+#include <machine/trap.h>
static struct mem_region OFmem[PHYS_AVAIL_SZ], OFavail[PHYS_AVAIL_SZ];
static struct mem_region OFfree[PHYS_AVAIL_SZ];
+static int apple_hacks;
+
+#ifdef AIM
extern register_t ofmsr[5];
extern void *openfirmware_entry;
static void *fdt;
int ofw_real_mode;
+extern char save_trap_init[0x2f00]; /* EXC_LAST */
+char save_trap_of[0x2f00]; /* EXC_LAST */
int ofwcall(void *);
static int openfirmware(void *args);
+__inline void
+ofw_save_trap_vec(char *save_trap_vec)
+{
+ if (apple_hacks)
+ return;
+
+ bcopy((void *)EXC_RST, save_trap_vec, EXC_LAST - EXC_RST);
+}
+
+static __inline void
+ofw_restore_trap_vec(char *restore_trap_vec)
+{
+ if (apple_hacks)
+ return;
+
+ bcopy(restore_trap_vec, (void *)EXC_RST, EXC_LAST - EXC_RST);
+ __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD);
+}
+
/*
* Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback.
*/
@@ -79,6 +104,9 @@ register_t ofw_sprg0_save;
static __inline void
ofw_sprg_prepare(void)
{
+ if (!apple_hacks)
+ return;
+
/*
* Assume that interrupt are disabled at this point, or
* SPRG1-3 could be trashed
@@ -98,6 +126,9 @@ ofw_sprg_prepare(void)
static __inline void
ofw_sprg_restore(void)
{
+ if (!apple_hacks)
+ return;
+
/*
* Note that SPRG1-3 contents are irrelevant. They are scratch
* registers used in the early portion of trap handling when
@@ -107,6 +138,7 @@ ofw_sprg_restore(void)
*/
__asm __volatile("mtsprg0 %0" :: "r"(ofw_sprg0_save));
}
+#endif
/*
* Memory region utilities: determine if two regions overlap,
@@ -178,15 +210,10 @@ parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
/*
* On Apple hardware, address_cells is always 1 for "available",
- * even when it is explicitly set to 2. Then all memory above 4 GB
- * should be added by hand to the available list. Detect Apple hardware
- * by seeing if ofw_real_mode is set -- only Apple seems to use
- * virtual-mode OF.
+ * even when it is explicitly set to 2. All memory above 4 GB
+ * also needs to be added by hand to the available list.
*/
- if (strcmp(prop, "available") == 0 && !ofw_real_mode)
- apple_hack_mode = 1;
-
- if (apple_hack_mode)
+ if (strcmp(prop, "available") == 0 && apple_hacks)
address_cells = 1;
/*
@@ -241,7 +268,7 @@ parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
sz = j*sizeof(output[0]);
#ifdef __powerpc64__
- if (apple_hack_mode) {
+ if (strcmp(prop, "available") == 0 && apple_hacks) {
/* Add in regions above 4 GB to the available list */
struct mem_region himem[16];
int hisz;
@@ -435,6 +462,7 @@ ofw_mem_regions(struct mem_region **memp, int *memsz,
*availsz = fsz;
}
+#ifdef AIM
void
OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *))
{
@@ -481,6 +509,9 @@ OF_bootstrap()
OF_init(fdt);
}
+ /* Apple firmware has some bugs. Check for a "mac-io" alias. */
+ apple_hacks = (OF_finddevice("mac-io") != -1) ? 1 : 0;
+
return (status);
}
@@ -516,6 +547,12 @@ openfirmware_core(void *args)
ofw_sprg_prepare();
+ /* Save trap vectors */
+ ofw_save_trap_vec(save_trap_of);
+
+ /* Restore initially saved trap vectors */
+ ofw_restore_trap_vec(save_trap_init);
+
#if defined(AIM) && !defined(__powerpc64__)
/*
* Clear battable[] translations
@@ -527,6 +564,10 @@ openfirmware_core(void *args)
#endif
result = ofwcall(args);
+
+ /* Restore trap vecotrs */
+ ofw_restore_trap_vec(save_trap_of);
+
ofw_sprg_restore();
intr_restore(oldmsr);
@@ -603,6 +644,8 @@ OF_reboot()
for (;;); /* just in case */
}
+#endif /* AIM */
+
void
OF_getetheraddr(device_t dev, u_char *addr)
{
@@ -623,7 +666,7 @@ OF_getetheraddr(device_t dev, u_char *addr)
static void
OF_get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep, int *pcip)
{
- char name[16];
+ char type[64];
uint32_t addr, size;
int pci, res;
@@ -635,10 +678,10 @@ OF_get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep, int *pcip)
size = 1;
pci = 0;
if (addr == 3 && size == 2) {
- res = OF_getprop(node, "name", name, sizeof(name));
+ res = OF_getprop(node, "device_type", type, sizeof(type));
if (res != -1) {
- name[sizeof(name) - 1] = '\0';
- pci = (strcmp(name, "pci") == 0) ? 1 : 0;
+ type[sizeof(type) - 1] = '\0';
+ pci = (strcmp(type, "pci") == 0) ? 1 : 0;
}
}
if (addrp != NULL)
@@ -672,8 +715,13 @@ OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
if (tag == NULL || handle == NULL)
return (EINVAL);
+ /* Assume big-endian unless we find a PCI device */
+ *tag = &bs_be_tag;
+
/* Get the requested register. */
OF_get_addr_props(bridge, &naddr, &nsize, &pci);
+ if (pci)
+ *tag = &bs_le_tag;
res = OF_getprop(dev, (pci) ? "assigned-addresses" : "reg",
cell, sizeof(cell));
if (res == -1)
@@ -701,6 +749,8 @@ OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
parent = OF_parent(bridge);
while (parent != 0) {
OF_get_addr_props(parent, &nbridge, NULL, &pcib);
+ if (pcib)
+ *tag = &bs_le_tag;
res = OF_getprop(bridge, "ranges", cell, sizeof(cell));
if (res == -1)
goto next;
@@ -741,7 +791,6 @@ OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
OF_get_addr_props(bridge, &naddr, &nsize, &pci);
}
- *tag = &bs_le_tag;
return (bus_space_map(*tag, addr, size,
prefetch ? BUS_SPACE_MAP_PREFETCHABLE : 0, handle));
}
OpenPOWER on IntegriCloud