OK6410 linux3.0.1 外部中断组1~9无法request_irq的解决方法

来源:互联网 发布:医学数据分析软件 编辑:程序博客网 时间:2024/06/05 11:44

因项目需求远程遥控,准备在OK6410上使用红外线控制板子。由于板子上自带的红外所接引脚GPE1几乎等同于摆设,故需要外加红外头。在写驱动的时候发现中断组1~9无法request_irq成功,咨询官方技术支持和论坛没有任何答复,只好自己改内核了。仔细看源码,飞凌居然没初始化19组的中断,我和我的小伙伴都惊呆了


以下代码加入到irq-eint.c中

static inline void s3c_irq_eint_group_78_mask(struct irq_data *data){    u32 mask;    mask = __raw_readl(S3C64XX_EINT78MASK);    mask |= (u32)data->chip_data;    __raw_writel(mask, S3C64XX_EINT78MASK);}static void s3c_irq_eint_group_78_unmask(struct irq_data *data){    u32 mask;    mask = __raw_readl(S3C64XX_EINT78MASK);    mask &= ~((u32)data->chip_data);    __raw_writel(mask, S3C64XX_EINT78MASK);}static inline void s3c_irq_eint_group_78_ack(struct irq_data *data){    //__raw_writel(__raw_readl(S3C64XX_EINT78PEND)&~((u32)data->chip_data), S3C64XX_EINT78PEND);    __raw_writel((u32)data->chip_data, S3C64XX_EINT78PEND);//此处不知为何}static void s3c_irq_eint_group_78_maskack(struct irq_data *data){    /* compiler should in-line these */    s3c_irq_eint_group_78_mask(data);    s3c_irq_eint_group_78_ack(data);}static int s3c_irq_eint_set_group_78_type(struct irq_data *data, unsigned int type){    int offs = (data->irq - IRQ_EINT_GROUP(7, 0));    int pin, pin_val;    int shift;    u32 ctrl, mask;    u32 newvalue = 0;    void __iomem *reg;    if (offs > 31)    {        printk(KERN_EMERG"offs in s3c_irq_eint_set_group_78_type %d\n", offs);        return -EINVAL;    }    reg = S3C64XX_EINT78CON;    switch (type)    {    case IRQ_TYPE_NONE:        printk(KERN_WARNING "No edge setting!\n");        break;    case IRQ_TYPE_EDGE_RISING:        newvalue = S3C2410_EXTINT_RISEEDGE;        break;    case IRQ_TYPE_EDGE_FALLING:        newvalue = S3C2410_EXTINT_FALLEDGE;        break;    case IRQ_TYPE_EDGE_BOTH:        newvalue = S3C2410_EXTINT_BOTHEDGE;        break;    case IRQ_TYPE_LEVEL_LOW:        newvalue = S3C2410_EXTINT_LOWLEV;        break;    case IRQ_TYPE_LEVEL_HIGH:        newvalue = S3C2410_EXTINT_HILEV;        break;    default:        printk(KERN_ERR "No such irq type %d", type);        return -1;    }    shift = (offs / 4) * 4;    mask = 0x7 << shift;    ctrl = __raw_readl(reg);    ctrl &= ~mask;    ctrl |= newvalue << shift;    __raw_writel(ctrl, reg);    /* set the GPIO pin appropriately */    if (offs <= 15)    {        pin = S3C64XX_GPO(offs);        pin_val = S3C_GPIO_SFN(3);          //GPO口0x11表示外部中断    }    else    {        pin = S3C64XX_GPP(offs - 16);        pin_val = S3C_GPIO_SFN(3);    }    s3c_gpio_cfgpin(pin, pin_val);    return 0;}static struct irq_chip s3c_irq_eint_group78 ={    .name       = "s3c-eintgroup78",    .irq_mask   = s3c_irq_eint_group_78_mask,    .irq_unmask = s3c_irq_eint_group_78_unmask,    .irq_mask_ack   = s3c_irq_eint_group_78_maskack,    .irq_ack    = s3c_irq_eint_group_78_ack,    .irq_set_type   = s3c_irq_eint_set_group_78_type,    .irq_set_wake   = s3c_irqext_wake,};static inline void zc_irq_demux_eint_group78(){    u32 status = __raw_readl(S3C64XX_EINT78PEND);    u32 mask = __raw_readl(S3C64XX_EINT78MASK);    unsigned int irq;    status &= ~mask;    status >>= 0;    status &= (1 << (31 - 0 + 1)) - 1;    for (irq = IRQ_EINT_GROUP(7, 0); irq <= IRQ_EINT_GROUP(8, 14); irq++)    {        if (status & 1)            generic_handle_irq(irq);        else printk("%d status is not 1\n", irq);        status >>= 1;    }}//注册78组外部中断static inline void zc_init_irq_data_chip_group78(){    int i = 0;    for (i = 0; i < 31; i++)    {        if (i <= 15)        {            //设置desc.irq_data.chip函数组和desc->handle_irq默认触发函数            irq_set_chip_and_handler(IRQ_EINT_GROUP(7, i), &s3c_irq_eint_group78, handle_level_irq);            //设置desc.irq_data.chip_data            irq_set_chip_data(IRQ_EINT_GROUP(7, i), (void *)((u32)(1 << (IRQ_EINT_GROUP(7, i) - IRQ_EINT_GROUP(7, 0)))));            set_irq_flags(IRQ_EINT_GROUP(7, i), IRQF_VALID);        }        else        {            irq_set_chip_and_handler(IRQ_EINT_GROUP(8, i - 16), &s3c_irq_eint_group78, handle_level_irq);            irq_set_chip_data(IRQ_EINT_GROUP(8, i - 16), (void *)((u32)(1 << (IRQ_EINT_GROUP(8, i - 16) - IRQ_EINT_GROUP(7, 0)))));            set_irq_flags(IRQ_EINT_GROUP(8, i - 16), IRQF_VALID);        }    }    irq_set_chained_handler(S3C64XX_IRQ_VIC1(21), zc_irq_demux_eint_group78);}


原创粉丝点击