Support lbc interrupts:
o Save and clear the LTESR register in the interrupt handler. o In lbc_read_reg(), return the saved LTESR register value if applicable (i.e. when the saved value is not invalid (read: ~0U)). o In lbc_write_reg(), clear the bits in the saved register when when it's written to and when the asved value is not invalid. o Also in lbc_write_reg(), the LTESR register is unlocked (in H/W) when bit 1 of LTEATR is cleared. We use this to invalidate our saved LTESR register value. Subsequent reads and write go to H/W directly. While here: o In lbc_read_reg() & lbc_write_reg(), add some belts and suspenders to catch when register offsets are out of range. o In lbc_attach(), initialize completely and don't leave something left for lbc_banks_enable().
This commit is contained in:
parent
120c7e2eb7
commit
23fbc06bfc
@ -273,13 +273,8 @@ lbc_banks_enable(struct lbc_softc *sc)
|
||||
|
||||
for (i = 0; i < LBC_DEV_MAX; i++) {
|
||||
size = sc->sc_banks[i].size;
|
||||
if (size == 0) {
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh,
|
||||
LBC85XX_BR(i), 0);
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh,
|
||||
LBC85XX_OR(i), 0);
|
||||
if (size == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute and program BR value.
|
||||
@ -331,23 +326,6 @@ lbc_banks_enable(struct lbc_softc *sc)
|
||||
LBC85XX_OR(i), regval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize configuration register:
|
||||
* - enable Local Bus
|
||||
* - set data buffer control signal function
|
||||
* - disable parity byte select
|
||||
* - set ECC parity type
|
||||
* - set bus monitor timing and timer prescale
|
||||
*/
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LBCR, 0);
|
||||
|
||||
/*
|
||||
* Initialize clock ratio register:
|
||||
* - disable PLL bypass mode
|
||||
* - configure LCLK delay cycles for the assertion of LALE
|
||||
* - set system clock divider
|
||||
*/
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LCRR, 0x00030008);
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
@ -426,6 +404,18 @@ out:
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static void
|
||||
lbc_intr(void *arg)
|
||||
{
|
||||
struct lbc_softc *sc = arg;
|
||||
uint32_t ltesr;
|
||||
|
||||
ltesr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR);
|
||||
sc->sc_ltesr = ltesr;
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ltesr);
|
||||
wakeup(sc->sc_dev);
|
||||
}
|
||||
|
||||
static int
|
||||
lbc_probe(device_t dev)
|
||||
{
|
||||
@ -455,14 +445,59 @@ lbc_attach(device_t dev)
|
||||
sc = device_get_softc(dev);
|
||||
sc->sc_dev = dev;
|
||||
|
||||
sc->sc_rid = 0;
|
||||
sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
|
||||
sc->sc_mrid = 0;
|
||||
sc->sc_mres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_mrid,
|
||||
RF_ACTIVE);
|
||||
if (sc->sc_res == NULL)
|
||||
if (sc->sc_mres == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
sc->sc_bst = rman_get_bustag(sc->sc_res);
|
||||
sc->sc_bsh = rman_get_bushandle(sc->sc_res);
|
||||
sc->sc_bst = rman_get_bustag(sc->sc_mres);
|
||||
sc->sc_bsh = rman_get_bushandle(sc->sc_mres);
|
||||
|
||||
for (bank = 0; bank < LBC_DEV_MAX; bank++) {
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_BR(bank), 0);
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_OR(bank), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize configuration register:
|
||||
* - enable Local Bus
|
||||
* - set data buffer control signal function
|
||||
* - disable parity byte select
|
||||
* - set ECC parity type
|
||||
* - set bus monitor timing and timer prescale
|
||||
*/
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LBCR, 0);
|
||||
|
||||
/*
|
||||
* Initialize clock ratio register:
|
||||
* - disable PLL bypass mode
|
||||
* - configure LCLK delay cycles for the assertion of LALE
|
||||
* - set system clock divider
|
||||
*/
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LCRR, 0x00030008);
|
||||
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEDR, 0);
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ~0);
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEIR, 0x64080001);
|
||||
|
||||
sc->sc_irid = 0;
|
||||
sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
|
||||
RF_ACTIVE | RF_SHAREABLE);
|
||||
if (sc->sc_ires != NULL) {
|
||||
error = bus_setup_intr(dev, sc->sc_ires,
|
||||
INTR_TYPE_MISC | INTR_MPSAFE, NULL, lbc_intr, sc,
|
||||
&sc->sc_icookie);
|
||||
if (error) {
|
||||
device_printf(dev, "could not activate interrupt\n");
|
||||
bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
|
||||
sc->sc_ires);
|
||||
sc->sc_ires = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
sc->sc_ltesr = ~0;
|
||||
|
||||
rangesptr = NULL;
|
||||
|
||||
rm = &sc->sc_rman;
|
||||
@ -614,7 +649,7 @@ lbc_attach(device_t dev)
|
||||
|
||||
fail:
|
||||
free(rangesptr, M_OFWPROP);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mrid, sc->sc_mres);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -742,17 +777,49 @@ lbc_get_devinfo(device_t bus, device_t child)
|
||||
void
|
||||
lbc_write_reg(device_t child, u_int off, uint32_t val)
|
||||
{
|
||||
device_t dev;
|
||||
struct lbc_softc *sc;
|
||||
|
||||
sc = device_get_softc(device_get_parent(child));
|
||||
dev = device_get_parent(child);
|
||||
|
||||
if (off >= 0x1000) {
|
||||
device_printf(dev, "%s(%s): invalid offset %#x\n",
|
||||
__func__, device_get_nameunit(child), off);
|
||||
return;
|
||||
}
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (off == LBC85XX_LTESR && sc->sc_ltesr != ~0u) {
|
||||
sc->sc_ltesr ^= (val & sc->sc_ltesr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (off == LBC85XX_LTEATR && (val & 1) == 0)
|
||||
sc->sc_ltesr = ~0u;
|
||||
bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
lbc_read_reg(device_t child, u_int off)
|
||||
{
|
||||
device_t dev;
|
||||
struct lbc_softc *sc;
|
||||
uint32_t val;
|
||||
|
||||
sc = device_get_softc(device_get_parent(child));
|
||||
return (bus_space_read_4(sc->sc_bst, sc->sc_bsh, off));
|
||||
dev = device_get_parent(child);
|
||||
|
||||
if (off >= 0x1000) {
|
||||
device_printf(dev, "%s(%s): invalid offset %#x\n",
|
||||
__func__, device_get_nameunit(child), off);
|
||||
return (~0U);
|
||||
}
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (off == LBC85XX_LTESR && sc->sc_ltesr != ~0U)
|
||||
val = sc->sc_ltesr;
|
||||
else
|
||||
val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, off);
|
||||
return (val);
|
||||
}
|
||||
|
@ -105,10 +105,15 @@ struct lbc_bank {
|
||||
|
||||
struct lbc_softc {
|
||||
device_t sc_dev;
|
||||
struct resource *sc_res;
|
||||
|
||||
struct resource *sc_mres;
|
||||
bus_space_handle_t sc_bsh;
|
||||
bus_space_tag_t sc_bst;
|
||||
int sc_rid;
|
||||
int sc_mrid;
|
||||
|
||||
int sc_irid;
|
||||
struct resource *sc_ires;
|
||||
void *sc_icookie;
|
||||
|
||||
struct rman sc_rman;
|
||||
|
||||
@ -117,6 +122,8 @@ struct lbc_softc {
|
||||
|
||||
struct lbc_memrange sc_range[LBC_DEV_MAX];
|
||||
struct lbc_bank sc_banks[LBC_DEV_MAX];
|
||||
|
||||
uint32_t sc_ltesr;
|
||||
};
|
||||
|
||||
struct lbc_devinfo {
|
||||
|
Loading…
x
Reference in New Issue
Block a user