/*-
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* 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.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``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 ITRONIX INC. 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.
*/
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* 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.
*/
/*
* Interrupt support for the Alchemy Semiconductor Au1x00 CPUs.
*
* The Alchemy Semiconductor Au1x00's interrupts are wired to two internal
* interrupt controllers.
*/
/*
* First, link it into the tables.
* XXX do we want a separate list (really, should only be one item, not
* a list anyway) per irq, not per CPU interrupt?
*/
cpu_int = (irq < 32 ? 0 : 2) + req;
LIST_INSERT_HEAD(&au_cpuintrs[cpu_int].cintr_list, ih, ih_q);
/*
* Now enable it.
*/
if (au_icu_intrtab[irq].intr_refcnt++ == 0) {
icu_base = (irq < 32) ? ic0_base : ic1_base;
irq &= 31; /* throw away high bit if set */
irq = 1 << irq; /* only used as a mask from here on */
/* XXX Only level interrupts for now */
switch (type) {
case IST_NONE:
case IST_PULSE:
case IST_EDGE:
panic("unsupported irq type %d", type);
/* NOTREACHED */
case IST_LEVEL:
case IST_LEVEL_HIGH:
REGVAL(icu_base + IC_CONFIG2_SET) = irq;
REGVAL(icu_base + IC_CONFIG1_CLEAR) = irq;
REGVAL(icu_base + IC_CONFIG0_SET) = irq;
break;
case IST_LEVEL_LOW:
REGVAL(icu_base + IC_CONFIG2_SET) = irq;
REGVAL(icu_base + IC_CONFIG1_SET) = irq;
REGVAL(icu_base + IC_CONFIG0_CLEAR) = irq;
break;
}
wbflush();
/* XXX handle GPIO interrupts - not done at all yet */
if (cpu_int & 0x1)
REGVAL(icu_base + IC_ASSIGN_REQUEST_CLEAR) = irq;
else
REGVAL(icu_base + IC_ASSIGN_REQUEST_SET) = irq;
/*
* First, remove it from the table.
*/
LIST_REMOVE(ih, ih_q);
/*
* Now, disable it, if there is nothing remaining on the
* list.
*/
if (au_icu_intrtab[irq].intr_refcnt-- == 1) {
icu_base = (irq < 32) ? ic0_base : ic1_base;
irq &= 31; /* throw away high bit if set */
irq = 1 << irq; /* only used as a mask from here on */
/*
* Some devices (e.g. PCMCIA) want to be able to mask interrupts at
* the ICU, and leave them masked off until some later time
* (e.g. reenabled by a soft interrupt).
*/
void
au_intr_enable(int irq)
{
int s;
uint32_t icu_base, mask;
if (irq >= NIRQS)
panic("au_intr_enable: bogus IRQ %d", irq);
s = splhigh();
/* only enable the interrupt if we have a handler */
if (au_icu_intrtab[irq].intr_refcnt) {
REGVAL(icu_base + IC_MASK_SET) = mask;
REGVAL(icu_base + IC_WAKEUP_SET) = mask;
wbflush();
}
splx(s);
}
void
au_intr_disable(int irq)
{
int s;
uint32_t icu_base, mask;
if (irq >= NIRQS)
panic("au_intr_disable: bogus IRQ %d", irq);