summaryrefslogtreecommitdiffstats
path: root/sys/sparc64/fhc
diff options
context:
space:
mode:
authorjake <jake@FreeBSD.org>2003-02-19 08:23:38 +0000
committerjake <jake@FreeBSD.org>2003-02-19 08:23:38 +0000
commit677f252b3cd2b8923d91bf6702179cefe3c41f72 (patch)
tree98cab5c0408be07e217717c1e27231a830e49d80 /sys/sparc64/fhc
parentc83bbdf4e7449171620953a348f2c7f91693ae96 (diff)
downloadFreeBSD-src-677f252b3cd2b8923d91bf6702179cefe3c41f72.zip
FreeBSD-src-677f252b3cd2b8923d91bf6702179cefe3c41f72.tar.gz
Implement interrupt resource allocation and setup. Set the interrupt
group number properly based on the board id. Perform dummy reads of registers after writing to flush the hardware write buffers. This gets the soon to be committed zs attachment working.
Diffstat (limited to 'sys/sparc64/fhc')
-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 829e21c..6b7c813 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 a1daee9..3f6a31a 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 e989b5c..d62e189 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 f8801e2..46cda1f 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 b8662df..ad4a72d 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,
OpenPOWER on IntegriCloud