linux下的powerpc中断注册的方法

下面是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);



原文地址:https://www.cnblogs.com/fishoneseaatblog/p/2340938.html