229 lines
6.2 KiB
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);
|
|
}
|
|
}
|