下面是linux下的powerpc中断注册的方法,这个相对来说比较简单。
static int zw_irq_init(void)
{
int ret;
irq4 = irq_create_mapping(NULL,FPGA_IRQ4);
ret = request_irq(irq4,irq4_handler,IRQF_SHARED,DEV_NAME,(void *)dev_id);
if(ret < 0){
printk(KERN_ERR"Request irq4 failed.\n");
free_irq(irq4,(void *)dev_id);
return ret;
}
irq7 = irq_create_mapping(NULL,FPGA_IRQ7);
ret = request_irq(irq7,irq7_handler,IRQF_SHARED,DEV_NAME,(void *)dev_id);
if(ret < 0){
printk(KERN_ERR"Request irq7 failed.\n");
free_irq(irq7,(void *)dev_id);
return ret;
}
/*select irq4 and irq7,set SICRH BIT 20-21 = 00, BIT 26-27 = 00*/
*(volatile unsigned int *)(immr_base_addr + SICRH_ADDR) &= (~0x00000C30);
udelay(10);
/*set irq4 and irq7 edge sensitive*/
*(volatile unsigned int *)(immr_base_addr + SECNR_ADDR) |= (0x00000900);
udelay(10);
/* set irq4 and irq7 mask bit to open the irq */
*(volatile unsigned int *)(immr_base_addr + SEMSR_ADDR) |= (0x09000000);
// *(volatile unsigned int *)(immr_base_addr + SEMSR_ADDR) &= ~(0x09000000);
udelay(10);
/*Clear SEPNR bit */
*(volatile unsigned int *)(immr_base_addr + SEPNR_ADDR) |= (0x09000000);
udelay(10);
return 0;
}
关于里面的宏定义和immr_base_addr,参看这个定义:
immr_base_addr = GetIMMRBaseAddr(); // GetIMMRBaseAddr()这个函数应该是内核中提供的标准函数,可以得到powerpc的基地址。具体在哪定义,确实是个难点。
#define FPGA_IRQ3 19
#define FPGA_IRQ4 20
#define FPGA_IRQ6 22
#define FPGA_IRQ7 23
这些中断定义,是和pwoerpc的中断号挂钩的,感觉这和此时使用交叉编译链有关。
#define SICRL_ADDR (0x114)
#define SICRH_ADDR (0x118)
#define SEPNR_ADDR (0x72C)
#define SECNR_ADDR (0x73C)
#define SEMSR_ADDR (0x738)
#define GPIO1_BASE_ADDR (0xC00)
#define GPIO2_BASE_ADDR (0xD00)
#define GPDIR_ADDR (0x00)
#define GPODR_ADDR (0x04)
#define GPDAT_ADDR (0x08)
#define GPIER_ADDR (0x0C)
#define GPIMR_ADDR (0x10)
#define GPICR_ADDR (0x1C)
这些定义,就是powerpc本身的定义了,如果想操作这些寄存器,就得需要上面的那个immr_base_addr地址了。
如果把这些个中断方法移植到arm下,应该也是这种方法,不过上面这些关键的东西,是些难点。
下面是中断的响应函数
static irqreturn_t irq4_handler(int irq,void *dev_id,struct pt_regs *regs)
{
unsigned int value;
/* clear irq flag */
*(volatile unsigned *)(immr_base_addr + SEPNR_ADDR) |= (0x08000000);
…………………….
return IRQ_HANDLED;
}
卸载函数如下:
static void zw_irq_deinit(void)
{
free_irq(irq4,(void *)dev_id);
free_irq(irq7,(void *)dev_id);
}
当然了,如果对申请的虚拟地址也是要进行释放的,方法如下:
if( fpga_virt_base)
iounmap((void *)fpga_virt_base);