From 63ec9d57c9f07d0e4e2983fb86f44d371941ffdd Mon Sep 17 00:00:00 2001 From: Jake Burkholder Date: Wed, 19 Feb 2003 08:23:38 +0000 Subject: [PATCH] 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. --- sys/sparc64/fhc/fhc.c | 104 +++++++++++++++++++++++++++++----- sys/sparc64/fhc/fhc_central.c | 7 +++ sys/sparc64/fhc/fhc_nexus.c | 3 + sys/sparc64/fhc/fhcreg.h | 7 +++ sys/sparc64/fhc/fhcvar.h | 6 +- 5 files changed, 111 insertions(+), 16 deletions(-) diff --git a/sys/sparc64/fhc/fhc.c b/sys/sparc64/fhc/fhc.c index 829e21ce5f0..6b7c8139a4c 100644 --- a/sys/sparc64/fhc/fhc.c +++ b/sys/sparc64/fhc/fhc.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -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; - return (bus_generic_setup_intr(bus, child, r, flags, intr, arg, - cookiep)); + 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); + + 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 a1daee9bbe4..3f6a31a3d58 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 **)®); 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 e989b5c6419..d62e189dba5 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 f8801e2e7d5..46cda1fc9c5 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 b8662dfcf7b..ad4a72dc64b 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,