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.
This commit is contained in:
Jake Burkholder 2003-02-19 08:23:38 +00:00
parent 9de9159822
commit 63ec9d57c9
5 changed files with 111 additions and 16 deletions

View File

@ -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;
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;

View File

@ -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));
}

View File

@ -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));
}

View File

@ -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

View File

@ -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,