summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/arm/xscale/ixp425/cambria_exp_space.c95
-rw-r--r--sys/arm/xscale/ixp425/files.avila3
-rw-r--r--sys/arm/xscale/ixp425/ixp425.c30
-rw-r--r--sys/arm/xscale/ixp425/ixp425var.h3
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 *);
OpenPOWER on IntegriCloud