diff options
author | Jake Burkholder <jake@FreeBSD.org> | 2003-02-19 08:23:38 +0000 |
---|---|---|
committer | Jake Burkholder <jake@FreeBSD.org> | 2003-02-19 08:23:38 +0000 |
commit | 63ec9d57c9f07d0e4e2983fb86f44d371941ffdd (patch) | |
tree | 98cab5c0408be07e217717c1e27231a830e49d80 /sys/sparc64/fhc/fhc.c | |
parent | 9de91598226fb6d6166466d8fc189fff0537e534 (diff) | |
download | src-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
Diffstat (limited to 'sys/sparc64/fhc/fhc.c')
-rw-r--r-- | sys/sparc64/fhc/fhc.c | 104 |
1 files changed, 89 insertions, 15 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; |