ckfwq/linux-3.0.4/arch/mips/loongson/blx-hs3210/soc-irq.c

255 lines
6.8 KiB
C

/*
*
* BRIEF MODULE DESCRIPTION
* SOC32101 SOC SOC interrupt/setup routines.
*
* Copyright 2000,2001 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* Part of this file was derived from Carsten Langgaard's
* arch/mips/ite-boards/generic/init.c.
*
* Carsten Langgaard, carstenl@mips.com
* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel_stat.h>
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/timex.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/serial_reg.h>
#include <asm/bitops.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
#include <asm/mipsregs.h>
#include <asm/system.h>
#include <soc_soc.h>
#include <soc_soc_int.h>
int printf_raw(const char *fmt, ...);
#undef DEBUG_IRQ
#ifdef DEBUG_IRQ
/* note: prints function name for you */
#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
#else
#define DPRINTK(fmt, args...)
#endif
#ifdef CONFIG_REMOTE_DEBUG
extern void breakpoint(void);
#endif
/* revisit */
#define EXT_IRQ0_TO_IP 2 /* IP 2 */
#define EXT_IRQ5_TO_IP 7 /* IP 7 */
#define ALLINTS_NOTIMER (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
void disable_soc_soc_irq(struct irq_data *d);
void enable_soc_soc_irq(struct irq_data *d);
extern void set_debug_traps(void);
extern void mips_timer_interrupt(int irq, struct pt_regs *regs);
extern asmlinkage void soc_soc_IRQ(void);
static struct soc_soc_intc_regs volatile *soc_soc_hw0_icregs
= (struct soc_soc_intc_regs volatile *)(KSEG1ADDR(SOC_SOC_INTC_BASE));
void disable_soc_soc_irq(struct irq_data *d)
{
#if 0
int irq = d->irq;
DPRINTK("disable_soc_soc_irq %d\n", irq);
soc_soc_hw0_icregs->int_en &= ~(1 << irq);
#endif
}
void enable_soc_soc_irq(struct irq_data *d)
{
#if 0
int irq = d->irq;
DPRINTK("enable_soc_soc_irq %d\n", irq);
soc_soc_hw0_icregs->int_en |= (1 << irq);
#endif
}
static unsigned int startup_soc_soc_irq(struct irq_data *d)
{
enable_soc_soc_irq(d);
return 0;
}
#define shutdown_soc_soc_irq disable_soc_soc_irq
#define mask_and_ack_soc_soc_irq disable_soc_soc_irq
static void end_soc_soc_irq(struct irq_data *d)
{
int irq = d->irq;
// if (!(irq_to_desc(irq)->istate & IRQS_PENDING)){
soc_soc_hw0_icregs->int_clr |= 1 << irq;
//if(irq<SOC_SOC_GPIO_FIRST_IRQ)
enable_soc_soc_irq(d);
// }
}
#if 0
struct hw_interrupt_type soc_soc_irq_type = {
.name="GC SOC",
.startup=startup_soc_soc_irq,
.shutdown=shutdown_soc_soc_irq,
.enable=enable_soc_soc_irq,
.disable=disable_soc_soc_irq,
.ack=mask_and_ack_soc_soc_irq,
.end=end_soc_soc_irq,
NULL
};
#else
static struct irq_chip hs3210_soc_irq_controller = {
.name = "soc controller",
.irq_startup = startup_soc_soc_irq,
.irq_shutdown = shutdown_soc_soc_irq,
.irq_enable = enable_soc_soc_irq,
.irq_disable = disable_soc_soc_irq,
.irq_ack = mask_and_ack_soc_soc_irq,
.irq_mask = disable_soc_soc_irq,
.irq_mask_ack = disable_soc_soc_irq,
.irq_unmask = enable_soc_soc_irq,
.irq_eoi = end_soc_soc_irq,
};
#endif
char soc_soc_can0_status, soc_soc_can1_status;
EXPORT_SYMBOL(soc_soc_can0_status);
EXPORT_SYMBOL(soc_soc_can1_status);
void soc_soc_hw0_irqdispatch(void)
{
int irq = MIPS_CPU_IRQ_BASE + 8;
int intstatus = 0;
int status;
/* Fix Me!!*/
#ifdef CONFIG_SIMOS_SOC_SOC
do_IRQ(SOC_SOC_MODEM_IRQ);
return;
#endif
/* Receive interrupt signal, compute the irq */
status = read_c0_cause();
intstatus = soc_soc_hw0_icregs->int_isr;
if (intstatus & INT_LCD) //0
{
irq += SOC_SOC_LCD_IRQ;
}
else if (intstatus & INT_MAC1) //1
{
irq += SOC_SOC_MAC1_IRQ;
}
else if (intstatus & INT_MAC2) //2
{
irq += SOC_SOC_MAC2_IRQ;
}
else if (intstatus & INT_AC97) //3
{
irq += SOC_SOC_AC97_IRQ;
}
else if (intstatus & INT_SPI) //8
{
irq += SOC_SOC_SPI_IRQ;
}
else if (intstatus & INT_UART0) //11
{
irq += SOC_SOC_UART0_IRQ;
}
else if (intstatus & INT_UART1) //12
{
irq += SOC_SOC_UART1_IRQ;
}
else if (intstatus & INT_KBD) //9
{
irq += SOC_SOC_KBD_IRQ;
}
else if (intstatus & INT_MOUSE) //10
{
irq += SOC_SOC_MOUSE_IRQ;
}
//------------------------------------------------------------------------------
else if((soc_soc_hw0_icregs->int_en && (1<<SOC_SOC_CAN0_IRQ))&&((soc_soc_can0_status=*(volatile char *)0xbf004403) & 0x1f))
{
irq += SOC_SOC_CAN0_IRQ;
}
else if((soc_soc_hw0_icregs->int_en&&(1<<SOC_SOC_CAN1_IRQ)) && ((soc_soc_can1_status=*(volatile char *)0xbf004303) & 0x1f))
{
irq += SOC_SOC_CAN1_IRQ;
}
//------------------------------------------------------------------------------
else if (intstatus & INT_PCI_INTA)
irq += SOC_SOC_PCI_INTA_IRQ;
else if (intstatus & INT_PCI_INTB)
irq += SOC_SOC_PCI_INTB_IRQ;
else if (intstatus & INT_PCI_INTC)
irq += SOC_SOC_PCI_INTC_IRQ;
else if (intstatus & INT_PCI_INTD)
irq += SOC_SOC_PCI_INTD_IRQ;
else if (intstatus & INT_GPIO15)
irq += SOC_SOC_GPIO15_IRQ;
else if (intstatus & INT_GPIO14)
irq += SOC_SOC_GPIO14_IRQ;
else if (intstatus & INT_GPIO13)
irq += SOC_SOC_GPIO13_IRQ;
else if (intstatus & INT_GPIO12)
irq += SOC_SOC_GPIO12_IRQ;
else {
printk("Unknow interrupt status %x intstatus %x \n" , status, intstatus);
return;
}
// printf_raw("%s: dispatch interrupt to irq_nr(%d)\n", __FUNCTION__, irq);
do_IRQ(irq);
}
void hs3210_soc_irq_init(int irq_base)
{
u32 i;
for (i = irq_base; i <= irq_base + SOC_SOC_LAST_IRQ; i++) {
irq_set_chip_and_handler(i, &hs3210_soc_irq_controller,
handle_edge_irq);
}
}