diff options
-rw-r--r-- | sys/arm/xscale/ixp425/cambria_exp_space.c | 95 | ||||
-rw-r--r-- | sys/arm/xscale/ixp425/files.avila | 3 | ||||
-rw-r--r-- | sys/arm/xscale/ixp425/ixp425.c | 30 | ||||
-rw-r--r-- | sys/arm/xscale/ixp425/ixp425var.h | 3 |
4 files changed, 120 insertions, 11 deletions
diff --git a/sys/arm/xscale/ixp425/cambria_exp_space.c b/sys/arm/xscale/ixp425/cambria_exp_space.c new file mode 100644 index 0000000..cad6c349 --- /dev/null +++ b/sys/arm/xscale/ixp425/cambria_exp_space.c @@ -0,0 +1,95 @@ +/*- + * Copyright (c) 2009 Sam Leffler. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Hack bus space tag for slow devices on the Cambria expansion bus; + * we slow the timing and add a 2us delay between r/w ops. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> + +#include <machine/bus.h> +#include <machine/cpu.h> + +#include <arm/xscale/ixp425/ixp425reg.h> +#include <arm/xscale/ixp425/ixp425var.h> + +/* Prototypes for all the bus_space structure functions */ +bs_protos(exp); +bs_protos(generic); +bs_protos(generic_armv4); + +static uint8_t +cambria_bs_r_1(void *t, bus_space_handle_t h, bus_size_t o) +{ + DELAY(2); + return bus_space_read_1((struct bus_space *)t, h, o); +} + +static void +cambria_bs_w_1(void *t, bus_space_handle_t h, bus_size_t o, u_int8_t v) +{ + DELAY(2); + bus_space_write_1((struct bus_space *)t, h, o, v); +} + +/* NB: we only define what's needed by uart */ +struct bus_space cambria_exp_bs_tag = { + /* mapping/unmapping */ + .bs_map = generic_bs_map, + .bs_unmap = generic_bs_unmap, + + /* barrier */ + .bs_barrier = generic_bs_barrier, + + /* read (single) */ + .bs_r_1 = cambria_bs_r_1, + + /* write (single) */ + .bs_w_1 = cambria_bs_w_1, +}; + +void +cambria_exp_bus_init(struct ixp425_softc *sc) +{ + uint32_t cs3; + + KASSERT(cpu_is_ixp43x(), ("wrong cpu type")); + + cambria_exp_bs_tag.bs_cookie = sc->sc_iot; + + cs3 = EXP_BUS_READ_4(sc, EXP_TIMING_CS3_OFFSET); + /* XXX force slowest possible timings and byte mode */ + EXP_BUS_WRITE_4(sc, EXP_TIMING_CS3_OFFSET, + cs3 | (EXP_T1|EXP_T2|EXP_T3|EXP_T4|EXP_T5) | EXP_BYTE_EN); + + /* XXX force GPIO 3+4 for GPS+RS485 uarts */ + ixp425_set_gpio(sc, 3, GPIO_TYPE_EDG_RISING); + ixp425_set_gpio(sc, 4, GPIO_TYPE_EDG_RISING); +} diff --git a/sys/arm/xscale/ixp425/files.avila b/sys/arm/xscale/ixp425/files.avila index a9b70dc..4739401 100644 --- a/sys/arm/xscale/ixp425/files.avila +++ b/sys/arm/xscale/ixp425/files.avila @@ -2,6 +2,7 @@ arm/xscale/ixp425/avila_machdep.c standard arm/xscale/ixp425/avila_ata.c optional avila_ata arm/xscale/ixp425/avila_led.c optional avila_led -arm/xscale/ixp425/cambria_led.c optional cambria_led +arm/xscale/ixp425/cambria_exp_space.c standard arm/xscale/ixp425/cambria_fled.c optional cambria_fled +arm/xscale/ixp425/cambria_led.c optional cambria_led arm/xscale/ixp425/ixdp425_pci.c optional pci diff --git a/sys/arm/xscale/ixp425/ixp425.c b/sys/arm/xscale/ixp425/ixp425.c index 6fb2aaa..45d0ab8 100644 --- a/sys/arm/xscale/ixp425/ixp425.c +++ b/sys/arm/xscale/ixp425/ixp425.c @@ -313,6 +313,17 @@ ixp425_attach(device_t dev) } arm_post_filter = ixp425_post_filter; + if (bus_space_map(sc->sc_iot, IXP425_GPIO_HWBASE, IXP425_GPIO_SIZE, + 0, &sc->sc_gpio_ioh)) + panic("%s: unable to map GPIO registers", __func__); + if (bus_space_map(sc->sc_iot, IXP425_EXP_HWBASE, IXP425_EXP_SIZE, + 0, &sc->sc_exp_ioh)) + panic("%s: unable to map Expansion Bus registers", __func__); + + /* XXX belongs in platform init */ + if (cpu_is_ixp43x()) + cambria_exp_bus_init(sc); + if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 0xffffffff, 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_dmat)) @@ -339,13 +350,6 @@ ixp425_attach(device_t dev) /* attach wired devices via hints */ bus_enumerate_hinted_children(dev); - if (bus_space_map(sc->sc_iot, IXP425_GPIO_HWBASE, IXP425_GPIO_SIZE, - 0, &sc->sc_gpio_ioh)) - panic("%s: unable to map GPIO registers", __func__); - if (bus_space_map(sc->sc_iot, IXP425_EXP_HWBASE, IXP425_EXP_SIZE, - 0, &sc->sc_exp_ioh)) - panic("%s: unable to map Expansion Bus registers", __func__); - bus_generic_probe(dev); bus_generic_attach(dev); @@ -420,6 +424,7 @@ struct hwvtrans { uint32_t size; uint32_t vbase; int isa4x; /* XXX needs special bus space tag */ + int isslow; /* XXX needs special bus space tag */ }; static const struct hwvtrans * @@ -453,10 +458,12 @@ gethwvtrans(uint32_t hwbase, uint32_t size) .vbase = IXP435_USB2_VBASE }, { .hwbase = CAMBRIA_GPS_HWBASE, .size = CAMBRIA_GPS_SIZE, - .vbase = CAMBRIA_GPS_VBASE }, + .vbase = CAMBRIA_GPS_VBASE, + .isslow = 1 }, { .hwbase = CAMBRIA_RS485_HWBASE, .size = CAMBRIA_RS485_SIZE, - .vbase = CAMBRIA_RS485_VBASE }, + .vbase = CAMBRIA_RS485_VBASE, + .isslow = 1 }, }; int i; @@ -522,7 +529,8 @@ ixp425_alloc_resource(device_t dev, device_t child, int type, int *rid, device_printf(child, "%s: assign 0x%lx:0x%lx%s\n", __func__, start, end - start, - vtrans->isa4x ? " A4X" : ""); + vtrans->isa4x ? " A4X" : + vtrans->isslow ? " SLOW" : ""); } } else vtrans = gethwvtrans(start, end - start); @@ -578,6 +586,8 @@ ixp425_activate_resource(device_t dev, device_t child, int type, int rid, } if (vtrans->isa4x) rman_set_bustag(r, &ixp425_a4x_bs_tag); + else if (vtrans->isslow) + rman_set_bustag(r, &cambria_exp_bs_tag); else rman_set_bustag(r, sc->sc_iot); rman_set_bushandle(r, vtrans->vbase); diff --git a/sys/arm/xscale/ixp425/ixp425var.h b/sys/arm/xscale/ixp425/ixp425var.h index 8149372..0f22b91 100644 --- a/sys/arm/xscale/ixp425/ixp425var.h +++ b/sys/arm/xscale/ixp425/ixp425var.h @@ -97,6 +97,9 @@ struct ixppcib_softc { extern struct bus_space ixp425_bs_tag; extern struct bus_space ixp425_a4x_bs_tag; +extern struct bus_space cambria_exp_bs_tag; +void cambria_exp_bus_init(struct ixp425_softc *); + void ixp425_io_bs_init(bus_space_tag_t, void *); void ixp425_mem_bs_init(bus_space_tag_t, void *); |