o add a bus space tag that forces a 2usec delay between r/w ops; this is

used for the optional GPS+RS485 uarts on the Gateworks Cambria boards
  which otherwise are unreliable
o setup the hack bus space tag for the GPS+RS485 uarts
o program the gpio interrupts for the uarts to be edge-rising
o force timing on the expansion bus for the uarts to be "slow"

Thanks to Chris Lang of Gateworks for these tips.
This commit is contained in:
sam 2009-06-22 22:54:13 +00:00
parent 2fddb9e2cc
commit 0d93c7da52
4 changed files with 120 additions and 11 deletions

View File

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

View File

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

View File

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

View File

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