diff options
-rw-r--r-- | sys/sparc64/fhc/fhc.c | 104 | ||||
-rw-r--r-- | sys/sparc64/fhc/fhc_central.c | 7 | ||||
-rw-r--r-- | sys/sparc64/fhc/fhc_nexus.c | 3 | ||||
-rw-r--r-- | sys/sparc64/fhc/fhcreg.h | 7 | ||||
-rw-r--r-- | 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 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 **)®); 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, |