diff options
author | sam <sam@FreeBSD.org> | 2009-03-10 17:16:16 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2009-03-10 17:16:16 +0000 |
commit | 3d9037abb90273c6befe1cd4af92f4a0a525f68c (patch) | |
tree | b62f317d56f838daf98f4218abab65b905232201 | |
parent | 08492346145fe35af92cabab62c9a05774ccfd98 (diff) | |
download | FreeBSD-src-3d9037abb90273c6befe1cd4af92f4a0a525f68c.zip FreeBSD-src-3d9037abb90273c6befe1cd4af92f4a0a525f68c.tar.gz |
Small cleanup of memory resource allocation from Cambria branch:
o encode need for A4 bus space tag hackery according to the memory
address; checking for "uart" breaks down with the GPS chip support
which is also a uart but does not require the same hackery
o encode the correct memory window instead of carving up all of i/o
space, potentially with a larger window than a device should have;
this likely should be handled in the drivers by using a proper bus
alloc call but since some drivers depend on the bus support to figure
this out we cannot simply mod them
o add optional GPS and RS485 support (conditionally as the support
isn't ready yet)
-rw-r--r-- | sys/arm/xscale/ixp425/ixp425.c | 130 |
1 files changed, 92 insertions, 38 deletions
diff --git a/sys/arm/xscale/ixp425/ixp425.c b/sys/arm/xscale/ixp425/ixp425.c index d8cce84..6b8d1b3 100644 --- a/sys/arm/xscale/ixp425/ixp425.c +++ b/sys/arm/xscale/ixp425/ixp425.c @@ -315,43 +315,82 @@ ixp425_read_ivar(device_t bus, device_t child, int which, u_char *result) } /* - * NB: This table handles P->V translations for regions mapped - * through bus_alloc_resource. Anything done with bus_space_map - * is handled elsewhere and does not require an entry here. + * NB: This table handles P->V translations for regions setup with + * static mappings in initarm. This is used solely for calls to + * bus_alloc_resource_any; anything done with bus_space_map is + * handled elsewhere and does not require an entry here. * - * XXX getvbase is also used by uart_cpu_getdev (hence public) + * XXX this table is also used by uart_cpu_getdev via getvbase + * (hence the public api) */ -static const struct { +struct hwvtrans { uint32_t hwbase; uint32_t size; uint32_t vbase; -} hwvtrans[] = { - { IXP425_IO_HWBASE, IXP425_IO_SIZE, IXP425_IO_VBASE }, - { IXP425_PCI_HWBASE, IXP425_PCI_SIZE, IXP425_PCI_VBASE }, - { IXP425_PCI_MEM_HWBASE,IXP425_PCI_MEM_SIZE, IXP425_PCI_MEM_VBASE }, - { IXP425_EXP_BUS_CS0_HWBASE, IXP425_EXP_BUS_CS0_SIZE, - IXP425_EXP_BUS_CS0_VBASE }, - /* NB: needed only for uart_cpu_getdev */ - { IXP425_UART0_HWBASE, IXP425_REG_SIZE, IXP425_UART0_VBASE }, - { IXP425_UART1_HWBASE, IXP425_REG_SIZE, IXP425_UART1_VBASE }, - /* NB: need for ixp435 ehci controllers */ - { IXP435_USB1_HWBASE, IXP435_USB1_SIZE, IXP435_USB1_VBASE }, - { IXP435_USB2_HWBASE, IXP435_USB2_SIZE, IXP435_USB2_VBASE }, + int isa4x; /* XXX needs special bus space tag */ }; -int -getvbase(uint32_t hwbase, uint32_t size, uint32_t *vbase) +static const struct hwvtrans * +gethwvtrans(uint32_t hwbase, uint32_t size) { + static const struct hwvtrans hwvtrans[] = { + /* NB: needed only for uart_cpu_getdev */ + { .hwbase = IXP425_UART0_HWBASE, + .size = IXP425_REG_SIZE, + .vbase = IXP425_UART0_VBASE, + .isa4x = 1 }, + { .hwbase = IXP425_UART1_HWBASE, + .size = IXP425_REG_SIZE, + .vbase = IXP425_UART1_VBASE, + .isa4x = 1 }, + { .hwbase = IXP425_PCI_HWBASE, + .size = IXP425_PCI_SIZE, + .vbase = IXP425_PCI_VBASE }, + { .hwbase = IXP425_PCI_MEM_HWBASE, + .size = IXP425_PCI_MEM_SIZE, + .vbase = IXP425_PCI_MEM_VBASE }, + { .hwbase = IXP425_EXP_BUS_CS0_HWBASE, + .size = IXP425_EXP_BUS_CS0_SIZE, + .vbase = IXP425_EXP_BUS_CS0_VBASE }, + /* NB: needed for ixp435 ehci controllers */ + { .hwbase = IXP435_USB1_HWBASE, + .size = IXP435_USB1_SIZE, + .vbase = IXP435_USB1_VBASE }, + { .hwbase = IXP435_USB2_HWBASE, + .size = IXP435_USB2_SIZE, + .vbase = IXP435_USB2_VBASE }, +#ifdef CAMBRIA_GPS_VBASE + { .hwbase = CAMBRIA_GPS_HWBASE, + .size = CAMBRIA_GPS_SIZE, + .vbase = CAMBRIA_GPS_VBASE }, +#endif +#ifdef CAMBRIA_RS485_VBASE + { .hwbase = CAMBRIA_RS485_HWBASE, + .size = CAMBRIA_RS485_SIZE, + .vbase = CAMBRIA_RS485_VBASE }, +#endif + }; int i; for (i = 0; i < sizeof hwvtrans / sizeof *hwvtrans; i++) { if (hwbase >= hwvtrans[i].hwbase && - hwbase + size <= hwvtrans[i].hwbase + hwvtrans[i].size) { - *vbase = hwbase - hwvtrans[i].hwbase + hwvtrans[i].vbase; - return (0); - } + hwbase + size <= hwvtrans[i].hwbase + hwvtrans[i].size) + return &hwvtrans[i]; } - return (ENOENT); + return NULL; +} + +/* XXX for uart_cpu_getdev */ +int +getvbase(uint32_t hwbase, uint32_t size, uint32_t *vbase) +{ + const struct hwvtrans *hw; + + hw = gethwvtrans(hwbase, size); + if (hw == NULL) + return (ENOENT); + *vbase = hwbase - hw->hwbase + hw->vbase; + return (0); } static struct resource * @@ -359,9 +398,10 @@ ixp425_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct ixp425_softc *sc = device_get_softc(dev); + const struct hwvtrans *vtrans; struct rman *rmanp; struct resource *rv; - uint32_t vbase, addr; + uint32_t addr; int needactivate = flags & RF_ACTIVE; int irq; @@ -383,16 +423,31 @@ ixp425_alloc_resource(device_t dev, device_t child, int type, int *rid, /* override per hints */ if (BUS_READ_IVAR(dev, child, IXP425_IVAR_ADDR, &addr) == 0) { start = addr; - end = start + 0x1000; /* XXX */ - count = end - start; - } - if (getvbase(start, end - start, &vbase) != 0) { + /* XXX use nominal window to check for mapping */ + vtrans = gethwvtrans(start, 0x1000); + if (vtrans != NULL) { + /* + * Assign the entire mapped region; this may + * not be correct but without more info from + * the caller we cannot tell. + */ + end = start + vtrans->size - + (start - vtrans->hwbase); + if (bootverbose) + device_printf(child, + "%s: assign 0x%lx:0x%lx%s\n", + __func__, start, end - start, + vtrans->isa4x ? " A4X" : ""); + } + } else + vtrans = gethwvtrans(start, end - start); + if (vtrans == NULL) { /* likely means above table needs to be updated */ - device_printf(dev, "%s: no mapping for 0x%lx:0x%lx\n", + device_printf(child, "%s: no mapping for 0x%lx:0x%lx\n", __func__, start, end-start); return NULL; } - rv = rman_reserve_resource(rmanp, start, end, count, + rv = rman_reserve_resource(rmanp, start, end, end - start, flags, child); if (rv != NULL) rman_set_rid(rv, *rid); @@ -415,18 +470,17 @@ ixp425_activate_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { struct ixp425_softc *sc = device_get_softc(dev); - int error; - uint32_t vbase; + const struct hwvtrans *vtrans; if (type == SYS_RES_MEMORY) { - error = getvbase(rman_get_start(r), rman_get_size(r), &vbase); - if (error) - return (error); - if (strcmp(device_get_name(child), "uart") == 0) + vtrans = gethwvtrans(rman_get_start(r), rman_get_size(r)); + if (vtrans == NULL) /* NB: should not happen */ + return (ENOENT); + if (vtrans->isa4x) rman_set_bustag(r, &ixp425_a4x_bs_tag); else rman_set_bustag(r, sc->sc_iot); - rman_set_bushandle(r, vbase); + rman_set_bushandle(r, vtrans->vbase); } return (rman_activate_resource(r)); } |