ckfwq/linux-3.0.4/arch/mips/loongson/gsc3280/gsc3280-irq.c

229 lines
6.2 KiB
C

/*
*
* BRIEF MODULE DESCRIPTION
* gsc3280 interrupt/setup routines.
*
*
*/
#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 <gsc3280/gsc3280_int.h>
#include <gsc3280/gsc3280_regs.h>
#include <gsc3280/sysctl.h>
#define IRQ_REG_INTEN_L 0x00//IRQ interrupt source enable register (low)
#define IRQ_REG_INTEN_H 0x04//IRQ interrupt source enable register (high)
#define IRQ_REG_INTMASK_L 0x08//IRQ interrupt source mask register (low).
#define IRQ_REG_INTMASK_H 0x0c//IRQ interrupt source mask register (high).
#define IRQ_REG_INTFORCE_L 0x10//IRQ interrupt force register
#define IRQ_REG_INTFORCE_H 0x14//
#define IRQ_REG_RAWSTATUS_L 0x18//IRQ raw status register
#define IRQ_REG_RAWSTATUS_H 0x1c//
#define IRQ_REG_STATUS_L 0x20//IRQ status register
#define IRQ_REG_STATUS_H 0x24//
#define IRQ_REG_MASKSTATUS_L 0x28//IRQ interrupt mask status register
#define IRQ_REG_MASKSTATUS_H 0x2c//
#define IRQ_REG_FINALSTATUS_L 0x30//IRQ interrupt final status
#define IRQ_REG_FINALSTATUS_H 0x34
#define FIQ_REG_INTEN 0xc0//Fast interrupt enable register
#define FIQ_REG_INTMASK 0xc4//Fast interrupt mask register
#define FIQ_REG_INTFORCE 0xc8//Fast interrupt force register
#define FIQ_REG_RAWSTATUS 0xcc//Fast interrupt source raw status register
#define FIQ_REG_STATUS 0xd0//Fast interrupt status register
#define FIQ_REG_FINALSTATUS 0xd4//Fast interrupt final status register
#define IRQ_REG_PLEVEL 0xd8//IRQ System Priority Level Register
#ifdef CONFIG_ANDROID_RAM_CONSOLE
extern uint8_t * ram_console_data_buf;
#endif
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
/* revisit */
#define EXT_IRQ0_TO_IP 2 /* IP 2 */
#define EXT_IRQ5_TO_IP 7 /* IP 7 */
#define which_irq_l(irq) (0x01u << (irq))
#define which_irq_h(irq) (0x01u << ((irq) & 0x1f))
#define write_irq_reg(addr, val) __raw_writel(val, (__force unsigned *)(addr+(GSC3280_ICTL_BASEADDR)))
#define read_irq_reg(addr) __raw_readl((__force unsigned *)(addr+(GSC3280_ICTL_BASEADDR)))
#define set_irq_reg(addr, val) write_irq_reg(addr, ((val) | read_irq_reg(addr)))
#define clear_irq_reg(addr, val) write_irq_reg(addr, (~(val) & read_irq_reg(addr)))
void gsc3280_disable_irq(struct irq_data *d);
void gsc3280_enable_irq(struct irq_data *d);
void gsc3280_disable_irq(struct irq_data *d)
{
int irq_base = MIPS_CPU_IRQ_BASE + 8;
int irq = d->irq - irq_base;
if (irq >= 32)
{
set_irq_reg(IRQ_REG_INTMASK_H, which_irq_h(irq));
}
else
{
set_irq_reg(IRQ_REG_INTMASK_L, which_irq_l(irq));
}
}
void gsc3280_enable_irq(struct irq_data *d)
{
int irq_base = MIPS_CPU_IRQ_BASE + 8;
int irq = d->irq - irq_base;
if (irq >= 32)
{
clear_irq_reg(IRQ_REG_INTMASK_H, which_irq_h(irq));
}
else
{
clear_irq_reg(IRQ_REG_INTMASK_L, which_irq_l(irq));
}
}
/*
static unsigned int gsc3280_startup_irq(struct irq_data *d)
{
gsc3280_enable_irq(d);
return 0;
}
*/
static void gsc3280_end_irq(struct irq_data *d)
{
gsc3280_enable_irq(d);
}
static struct irq_chip gsc3280_irq_controller = {
.name = "gsc3280 irq",
.irq_enable = gsc3280_enable_irq,
.irq_disable = gsc3280_disable_irq,
.irq_mask = gsc3280_disable_irq,
.irq_mask_ack = gsc3280_disable_irq,
.irq_unmask = gsc3280_enable_irq,
.irq_eoi = gsc3280_end_irq,
};
/*0 DMA
1 NFC
2 SD/MMC/SDIO
3 MAC
4 LCDC
5 USB
6 SPI0/TS
7 SPI1
8 SCI0
9 SCI1
10 PS2-0
11 PS2-1
12 UART-0
13 UART-1
14 UART-2
15 UART-3
16 UART-4
17 UART-5
18 UART-6
19 UART-7
20 I2S
21 I2C
22 CAN
23 KEYPAD
24 KEYPAD_WAKE
25 PWM
26 TIMER
27 WATCHDOG
28 GPIO
29 ADC
30 BUSERR
*/
//#define UART0 (1<<12)
void soc_soc_hw0_irqdispatch(void)
{
int i;
int irq = MIPS_CPU_IRQ_BASE + 8;
int ictl ;
int irqpending;
ictl = read_irq_reg(IRQ_REG_MASKSTATUS_L);
for (i = 0 ; i < 31; i++)
{
if (ictl & (1<<i))
{
irqpending = irq + i ;
#ifdef CONFIG_ANDROID_RAM_CONSOLE
if (ram_console_data_buf != NULL) {
unsigned int count;
count = read_c0_count();
(((unsigned int *)ram_console_data_buf)[(i+1)<<2])++;
if ((count-(((unsigned int *)ram_console_data_buf)[((i+1)<<2)+1])) < (((unsigned int *)ram_console_data_buf)[((i+1)<<2)+2]))
(((unsigned int *)ram_console_data_buf)[((i+1)<<2)+2]) = count-(((unsigned int *)ram_console_data_buf)[((i+1)<<2)+1]);
(((unsigned int *)ram_console_data_buf)[((i+1)<<2)+1]) = count;
((unsigned int *)ram_console_data_buf)[0] = i;
if (count-((unsigned int *)ram_console_data_buf)[1] < ((unsigned int *)ram_console_data_buf)[2])
((unsigned int *)ram_console_data_buf)[2] = count-((unsigned int *)ram_console_data_buf)[1];
((unsigned int *)ram_console_data_buf)[1] = count;
}
#endif
do_IRQ(irqpending);
}
}
}
void gsc3280_soc_irq_init(int irq_base)
{
u32 i;
sysctl_mod_enable(SYSCTL_MOD_ICTL);
write_irq_reg(IRQ_REG_INTEN_L, 0xffffffff);//enable irq interrupt
// write_irq_reg(IRQ_REG_INTEN_H, 0xffffffff);
write_irq_reg(IRQ_REG_INTMASK_L, 0xffffffff); //mask all irq interrupt
// write_irq_reg(IRQ_REG_INTMASK_H, 0xffffffff);
write_irq_reg(IRQ_REG_INTFORCE_L, 0);
// write_irq_reg(IRQ_REG_INTFORCE_H, 0);
// write_irq_reg(FIQ_REG_INTEN, 0x03); //enable fiq interrupt
// write_irq_reg(FIQ_REG_INTMASK, 0x03); //mask fiq interrupt
// write_irq_reg(IRQ_REG_PLEVEL, 0);
for (i = irq_base; i <= irq_base + GSC3280_LAST_IRQ; i++) {
irq_set_chip_and_handler(i, &gsc3280_irq_controller,
handle_level_irq);
}
}