255 lines
6.8 KiB
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);
|
|
}
|
|
|
|
}
|
|
|