/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Cliff Neighbors
*
* 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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.
*/
/*
* RMI Peripherals IO Bus support
* - interface to NOR, NAND, PCMCIA Memory controllers, &etc.
* - manages the 10 Chip Selects
* - manages the "Flash" interrupts
* - manages the "Flash" errors
*/
/*
* iobus control registers are accessed as 32 bits.
* ALEn and CLEn NAND control registers are defined as 8 bits wide
* but that seems to be a documentation error.
*
* iobus data access may be as 1 or 2 or 4 bytes, even if device is 1 byte wide;
* the controller will sequence the bytes, in big-endian order.
*/
typedef struct {
bool cs_allocated;
uint32_t cs_addr; /* base address on the Peripherals I/O Bus */
uint32_t cs_mask; /* address mask on the Peripherals I/O Bus */
uint32_t cs_dev_parm;
} rmixl_iobus_csconfig_t;
for (intr=0; intr <= RMIXL_UB_INTERRUPT_MAX; intr++) {
if (ih == &sc->sc_dispatch[intr]) {
uint32_t r;
/* disable this interrupt in the usb interface */
r = bus_space_read_4(sc->sc_obio_bst, sc->sc_obio_bsh,
RMIXL_USB_INTERRUPT_ENABLE);
r &= 1 << intr;
bus_space_write_4(sc->sc_obio_bst, sc->sc_obio_bsh,
RMIXL_USB_INTERRUPT_ENABLE, r);
sc->sc_dispatch[intr].func = func;
sc->sc_dispatch[intr].arg = arg;
ih = &sc->sc_dispatch[intr];
/* enable this interrupt in the usb interface */
r = bus_space_read_4(sc->sc_obio_bst, sc->sc_obio_bsh,
RMIXL_USB_INTERRUPT_ENABLE);
r |= 1 << intr;
bus_space_write_4(sc->sc_obio_bst, sc->sc_obio_bsh,
RMIXL_USB_INTERRUPT_ENABLE, r);
out:
splx(s);
return ih;
}
static int
rmixl_iobus_intr(void *arg)
{
rmixl_iobus_softc_t *sc = arg;
uint32_t r;
int intr;
int rv = 0;
r = bus_space_read_4(sc->sc_obio_bst, sc->sc_obio_bsh,
RMIXL_USB_INTERRUPT_STATUS);
if (r != 0) {
for (intr=0; intr <= RMIXL_UB_INTERRUPT_MAX; intr++) {
uint32_t bit = 1 << intr;
if ((r & bit) != 0) {
int (*f)(void *) = sc->sc_dispatch[intr].func;
void *a = sc->sc_dispatch[intr].arg;
if (f != NULL) {
(void)(*f)(a);
sc->sc_dispatch[intr].count.ev_count++;
rv = 1;
}
}
}
}