aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/sparc64/fhc/fhc.c104
-rw-r--r--sys/sparc64/fhc/fhc_central.c7
-rw-r--r--sys/sparc64/fhc/fhc_nexus.c3
-rw-r--r--sys/sparc64/fhc/fhcreg.h7
-rw-r--r--sys/sparc64/fhc/fhcvar.h6
5 files changed, 111 insertions, 16 deletions
diff --git a/sys/sparc64/fhc/fhc.c b/sys/sparc64/fhc/fhc.c
index 829e21ce5f00..6b7c8139a4c2 100644
--- a/sys/sparc64/fhc/fhc.c
+++ b/sys/sparc64/fhc/fhc.c
@@ -31,6 +31,7 @@
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#include <sys/pcpu.h>
#include <dev/ofw/openfirm.h>
@@ -46,6 +47,14 @@
#define INTIGN(map) (((map) & INTMAP_IGN_MASK) >> INTMAP_IGN_SHIFT)
+struct fhc_clr {
+ driver_intr_t *fc_func;
+ void *fc_arg;
+ void *fc_cookie;
+ bus_space_tag_t fc_bt;
+ bus_space_handle_t fc_bh;
+};
+
struct fhc_devinfo {
char *fdi_name;
char *fdi_type;
@@ -53,6 +62,8 @@ struct fhc_devinfo {
struct resource_list fdi_rl;
};
+static void fhc_intr_stub(void *);
+
int
fhc_probe(device_t dev)
{
@@ -71,7 +82,7 @@ fhc_attach(device_t dev)
bus_addr_t size;
bus_addr_t off;
device_t cdev;
- uint64_t map;
+ uint32_t ctrl;
char *name;
int nreg;
int i;
@@ -79,18 +90,27 @@ fhc_attach(device_t dev)
sc = device_get_softc(dev);
node = sc->sc_node;
- sc->sc_ign = bus_space_read_4(sc->sc_bt[FHC_IGN],
- sc->sc_bh[FHC_IGN], 0x0);
for (i = FHC_FANFAIL; i <= FHC_TOD; i++) {
bus_space_write_4(sc->sc_bt[i], sc->sc_bh[i], FHC_ICLR, 0x0);
- map = bus_space_read_4(sc->sc_bt[i], sc->sc_bh[i], FHC_IMAP);
- bus_space_write_4(sc->sc_bt[i], sc->sc_bh[i], FHC_IMAP,
- map & ~INTMAP_V);
- if (INTIGN(map) != sc->sc_ign)
- panic("fhc_attach: map has wrong ign %#lx != %#x",
- INTIGN(map), sc->sc_ign);
+ bus_space_read_4(sc->sc_bt[i], sc->sc_bh[i], FHC_ICLR);
}
+ sc->sc_ign = sc->sc_board << 1;
+ bus_space_write_4(sc->sc_bt[FHC_IGN], sc->sc_bh[FHC_IGN], 0x0,
+ sc->sc_ign);
+ sc->sc_ign = bus_space_read_4(sc->sc_bt[FHC_IGN],
+ sc->sc_bh[FHC_IGN], 0x0);
+
+ ctrl = bus_space_read_4(sc->sc_bt[FHC_INTERNAL],
+ sc->sc_bh[FHC_INTERNAL], FHC_CTRL);
+ if ((sc->sc_flags & FHC_CENTRAL) == 0)
+ ctrl |= FHC_CTRL_IXIST;
+ ctrl &= ~(FHC_CTRL_AOFF | FHC_CTRL_BOFF | FHC_CTRL_SLINE);
+ bus_space_write_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
+ FHC_CTRL, ctrl);
+ ctrl = bus_space_read_4(sc->sc_bt[FHC_INTERNAL],
+ sc->sc_bh[FHC_INTERNAL], FHC_CTRL);
+
sc->sc_nrange = OF_getprop_alloc(node, "ranges",
sizeof(*sc->sc_ranges), (void **)&sc->sc_ranges);
if (sc->sc_nrange == -1) {
@@ -198,19 +218,66 @@ fhc_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
int
fhc_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
- driver_intr_t intr, void *arg, void **cookiep)
+ driver_intr_t *func, void *arg, void **cookiep)
{
+ struct fhc_softc *sc;
+ struct fhc_clr *fc;
+ int error;
+ int rid;
+
+ sc = device_get_softc(bus);
+ rid = rman_get_rid(r);
+
+ fc = malloc(sizeof(*fc), M_DEVBUF, M_ZERO);
+ fc->fc_func = func;
+ fc->fc_arg = arg;
+ fc->fc_bt = sc->sc_bt[rid];
+ fc->fc_bh = sc->sc_bh[rid];
+
+ bus_space_write_4(sc->sc_bt[rid], sc->sc_bh[rid], FHC_IMAP,
+ r->r_start);
+ bus_space_read_4(sc->sc_bt[rid], sc->sc_bh[rid], FHC_IMAP);
- return (bus_generic_setup_intr(bus, child, r, flags, intr, arg,
- cookiep));
+ error = bus_generic_setup_intr(bus, child, r, flags, fhc_intr_stub,
+ fc, cookiep);
+ if (error != 0) {
+ free(fc, M_DEVBUF);
+ return (error);
+ }
+ fc->fc_cookie = *cookiep;
+ *cookiep = fc;
+
+ bus_space_write_4(sc->sc_bt[rid], sc->sc_bh[rid], FHC_ICLR, 0x0);
+ bus_space_write_4(sc->sc_bt[rid], sc->sc_bh[rid], FHC_IMAP,
+ INTMAP_ENABLE(r->r_start, PCPU_GET(mid)));
+ bus_space_read_4(sc->sc_bt[rid], sc->sc_bh[rid], FHC_IMAP);
+
+ return (error);
}
int
fhc_teardown_intr(device_t bus, device_t child, struct resource *r,
void *cookie)
{
+ struct fhc_clr *fc;
+ int error;
- return (bus_generic_teardown_intr(bus, child, r, cookie));
+ fc = cookie;
+ error = bus_generic_teardown_intr(bus, child, r, fc->fc_cookie);
+ if (error != 0)
+ free(fc, M_DEVBUF);
+ return (error);
+}
+
+static void
+fhc_intr_stub(void *arg)
+{
+ struct fhc_clr *fc = arg;
+
+ fc->fc_func(fc->fc_arg);
+
+ bus_space_write_4(fc->fc_bt, fc->fc_bh, FHC_ICLR, 0x0);
+ bus_space_read_4(fc->fc_bt, fc->fc_bh, FHC_ICLR);
}
struct resource *
@@ -225,7 +292,8 @@ fhc_alloc_resource(device_t bus, device_t child, int type, int *rid,
bus_addr_t cend;
bus_addr_t phys;
int isdefault;
- uint64_t map;
+ uint32_t map;
+ uint32_t vec;
int i;
isdefault = (start == 0UL && end == ~0UL);
@@ -236,10 +304,16 @@ fhc_alloc_resource(device_t bus, device_t child, int type, int *rid,
if (!isdefault || count != 1 || *rid < FHC_FANFAIL ||
*rid > FHC_TOD)
break;
+
map = bus_space_read_4(sc->sc_bt[*rid], sc->sc_bh[*rid],
FHC_IMAP);
+ vec = INTINO(map) | (sc->sc_ign << INTMAP_IGN_SHIFT);
+ bus_space_write_4(sc->sc_bt[*rid], sc->sc_bh[*rid],
+ FHC_IMAP, vec);
+ bus_space_read_4(sc->sc_bt[*rid], sc->sc_bh[*rid], FHC_IMAP);
+
res = bus_generic_alloc_resource(bus, child, type, rid,
- INTVEC(map), INTVEC(map), 1, flags);
+ vec, vec, 1, flags);
if (res != NULL)
rman_set_rid(res, *rid);
break;
diff --git a/sys/sparc64/fhc/fhc_central.c b/sys/sparc64/fhc/fhc_central.c
index a1daee9bbe49..3f6a31a3d589 100644
--- a/sys/sparc64/fhc/fhc_central.c
+++ b/sys/sparc64/fhc/fhc_central.c
@@ -96,6 +96,7 @@ fhc_central_attach(device_t dev)
bus_addr_t size;
bus_addr_t off;
phandle_t node;
+ int board;
int nreg;
int rid;
int i;
@@ -103,6 +104,7 @@ fhc_central_attach(device_t dev)
sc = device_get_softc(dev);
node = central_get_node(dev);
sc->sc_node = node;
+ sc->sc_flags |= FHC_CENTRAL;
nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
if (nreg != FHC_NREG) {
@@ -121,5 +123,10 @@ fhc_central_attach(device_t dev)
sc->sc_bh[i] = rman_get_bushandle(sc->sc_memres[i]);
}
free(reg, M_OFWPROP);
+
+ board = bus_space_read_4(sc->sc_bt[FHC_INTERNAL],
+ sc->sc_bh[FHC_INTERNAL], FHC_BSR);
+ sc->sc_board = ((board >> 16) & 0x1) | ((board >> 12) & 0xe);
+
return (fhc_attach(dev));
}
diff --git a/sys/sparc64/fhc/fhc_nexus.c b/sys/sparc64/fhc/fhc_nexus.c
index e989b5c6419d..d62e189dba58 100644
--- a/sys/sparc64/fhc/fhc_nexus.c
+++ b/sys/sparc64/fhc/fhc_nexus.c
@@ -121,5 +121,8 @@ fhc_nexus_attach(device_t dev)
sc->sc_bt[i] = rman_get_bustag(sc->sc_memres[i]);
sc->sc_bh[i] = rman_get_bushandle(sc->sc_memres[i]);
}
+
+ OF_getprop(node, "board#", &sc->sc_board, sizeof(sc->sc_board));
+
return (fhc_attach(dev));
}
diff --git a/sys/sparc64/fhc/fhcreg.h b/sys/sparc64/fhc/fhcreg.h
index f8801e2e7d5c..46cda1fc9c5b 100644
--- a/sys/sparc64/fhc/fhcreg.h
+++ b/sys/sparc64/fhc/fhcreg.h
@@ -41,4 +41,11 @@
#define FHC_IMAP 0x0
#define FHC_ICLR 0x10
+#define FHC_CTRL (0x20)
+#define FHC_CTRL_SLINE (0x00010000)
+#define FHC_CTRL_AOFF (0x00001000)
+#define FHC_CTRL_BOFF (0x00000800)
+#define FHC_CTRL_IXIST (0x00000200)
+#define FHC_BSR (0x30)
+
#endif
diff --git a/sys/sparc64/fhc/fhcvar.h b/sys/sparc64/fhc/fhcvar.h
index b8662dfcf7b4..ad4a72dc64bd 100644
--- a/sys/sparc64/fhc/fhcvar.h
+++ b/sys/sparc64/fhc/fhcvar.h
@@ -35,6 +35,8 @@ enum fhc_device_ivars {
FHC_IVAR_TYPE
};
+#define FHC_CENTRAL (1<<0)
+
struct fhc_softc {
phandle_t sc_node;
struct resource * sc_memres[FHC_NREG];
@@ -42,7 +44,9 @@ struct fhc_softc {
bus_space_tag_t sc_bt[FHC_NREG];
int sc_nrange;
struct sbus_ranges *sc_ranges;
+ int sc_board;
int sc_ign;
+ int sc_flags;
};
int fhc_probe(device_t dev);
@@ -52,7 +56,7 @@ int fhc_print_child(device_t dev, device_t child);
void fhc_probe_nomatch(device_t dev, device_t child);
int fhc_read_ivar(device_t, device_t, int, uintptr_t *);
int fhc_write_ivar(device_t, device_t, int, uintptr_t);
-int fhc_setup_intr(device_t, device_t, struct resource *, int, driver_intr_t,
+int fhc_setup_intr(device_t, device_t, struct resource *, int, driver_intr_t *,
void *, void **);
int fhc_teardown_intr(device_t, device_t, struct resource *, void *);
struct resource *fhc_alloc_resource(device_t, device_t, int, int *, u_long,