aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJake Burkholder <jake@FreeBSD.org>2003-02-19 08:23:38 +0000
committerJake Burkholder <jake@FreeBSD.org>2003-02-19 08:23:38 +0000
commit63ec9d57c9f07d0e4e2983fb86f44d371941ffdd (patch)
tree98cab5c0408be07e217717c1e27231a830e49d80
parent9de91598226fb6d6166466d8fc189fff0537e534 (diff)
downloadsrc-63ec9d57c9f07d0e4e2983fb86f44d371941ffdd.tar.gz
src-63ec9d57c9f07d0e4e2983fb86f44d371941ffdd.zip
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.
Notes
Notes: svn path=/head/; revision=111123
-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,