nobody cared (try booting with the irqpoll option)笔记调试全记录

最近接手维护芯唐平台项目, 遇到了irqpoll的问题.查下来是SD卡出问题.
记录下整个调试流程.
irq 3: nobody cared (try booting with the "irqpoll" option)
Backtrace: 
[] (dump_backtrace+0x0/0x104) from [] (dump_stack+0x18/0x1c)
 r6:00000003 r5:00000003 r4:c04da0b0 r3:00000000
[] (dump_stack+0x0/0x1c) from [] (__report_bad_irq.isra.1+0x3c/0x94)
[] (__report_bad_irq.isra.1+0x0/0x94) from [] (note_interrupt+0x130/0x1e4)
 r4:c04da090 r3:0001863c
[] (note_interrupt+0x0/0x1e4) from [] (handle_level_irq+0x104/0x18c)
 r9:c04d2000 r8:00000001 r7:c3e7a2a0 r6:c04d2010 r5:00000003
r4:c04da090
[] (handle_level_irq+0x0/0x18c) from [] (asm_do_IRQ+0x70/0x8c)
 r7:00000002 r6:00000000 r5:c04e68a0 r4:00000003
[] (asm_do_IRQ+0x0/0x8c) from [] (__irq_svc+0x44/0x88)
Exception stack(0xc04d3f50 to 0xc04d3f98)
3f40:                                     c04d4ed8 c04d4ed8 c04d3f88 60000013
3f60: c04d2000 c04d2018 c1117080 c04d5b58 0001f964 41069265 0001f930 c04d3fac
3f80: c04d3f98 c04d3f98 c0136010 c0136010 60000013 ffffffff
 r6:c1117080 r5:f0000000 r4:ffffffff r3:60000013
[] (cpu_idle+0x0/0xc0) from [] (rest_init+0xdc/0x100)
 r5:c00d1ed8 r4:c04d2000
[] (rest_init+0x0/0x100) from [] (start_kernel+0x294/0x2f4)
 r4:c050e454 r3:00000000
[] (start_kernel+0x0/0x2f4) from [<00008034>] (0x8034)
 r6:c00d1ed4 r5:c04faf24 r4:00053175
handlers:
[] (nvt_sd0_card_detect_irq+0x0/0x5c)
Disabling IRQ #3

这个导致启动流程慢10s左右
查看芯片手册,irq:3
5.17.3 Interrupt Sources
The following table lists all interrupts from various peripheral interface modules or external devices.

Channel Name Mode Source
1 WDT_INT Positive Level Watch Dog Timer Interrupt
2 GPIO_INT0 Positive Level GPIO Interrupt 0
3 GPIO_INT1 Positive Level GPIO Interrupt 1
4 GPIO_INT2 Positive Level GPIO Interrupt 2
5 GPIO_INT3 Positive Level GPIO Interrupt 3
6 IPSEC_INT Positive Level AES Interrupt
7 SPU_INT Positive Level SPU Interrupt
判断下来应该是GPIO中断.
nvt_sd0_card_detect_irq
并且应该在SD卡驱动里,
初步推测是SD卡识别脚一直触发,当前开发板共用一套内核,但不需要支持SD卡,SD卡识别脚误触发了?

跟踪code
./w55fa92_sd.c:1721:static irqreturn_t nvt_sd0_card_detect_irq(int irq, void *devid)
./w55fa92_sd.c:1730:        // nvt_sd_debug("--> nvt_sd0_card_detect_irq() GPE10 interrupt happened !\n");
./w55fa92_sd.c:1747:        // nvt_sd_debug("--> nvt_sd0_card_detect_irq() GPD6 interrupt happened !\n");
./w55fa92_sd.c:2156:    ret = request_irq(IRQ_GPIO1, nvt_sd0_card_detect_irq, IRQF_SHARED, mmc_hostname(mmc), host);
网上查下来就是误触发了中断 使用的是GPIO中断3.

刚开始怀疑是硬件接线问题,因为当前项目是二合一版本,该硬件不需要SD卡,经测试不是硬件是兼容的.
不是GPIO的初值问题,或者上电上升下降沿的问题.

版本回退后,发现没有问题了.
最大的疑点是修改的是触摸屏引入的问题.
进入code分析:
#define TOUCH_IRQ_NUM             W55FA92_IRQ(4)  // nIRQ2
使用的是中断四,理论上也没影响才对.
屏蔽触摸屏驱动后, irqpoll的问题没有了,确实是触摸屏导致的.
//---N32926的设�?--//

#define GTP_INT_PORT    0x21//GPB1
#define GPIO_IRQ_FLAG_CLEAR() (writel(readl(REG_IRQTGSRC0)|(1<<((GTP_INT_PORT%0X20)+16)), REG_IRQTGSRC0))//清INT中断标志GPB2
#define GPIO_IRQ_FLAG_READ() (readl(REG_IRQTGSRC0)& (1<<((GTP_INT_PORT%0X20)+16)))//读INT中断标志GPB


//外部中断2  --- IRQSRCGPD 设置中断向量,使其指向中�?
#define GPIO_SET_VECTOR() do{\
writel(readl(REG_IRQSRCGPB)& ~((3 << (GTP_INT_PORT%0X20)*2)), REG_IRQSRCGPB);\
writel(readl(REG_IRQSRCGPB)|((2 << (GTP_INT_PORT%0X20)*2)), REG_IRQSRCGPB);\
}while(0)

//设置GPE1中断类型为下降沿
#define GPIO_SET_IRQ_ENABLE() do{\
writel((readl(REG_IRQENGPB)&~((1<<((GTP_INT_PORT%0X20)+16)) | (1<<(GTP_INT_PORT%0X20)))),REG_IRQENGPB);\
writel((readl(REG_IRQENGPB)| (1<<((GTP_INT_PORT%0X20)+16))), REG_IRQENGPB);\
}while(0)

//设置GPE1中断类型为下降沿
#define GPIO_SET_IRQ_DISABLE() do{\
writel((readl(REG_IRQENGPB)&~(1<<((GTP_INT_PORT%0X20)+16))),REG_IRQENGPB);\
writel((readl(REG_IRQENGPB)&~(1<<(GTP_INT_PORT%0X20))), REG_IRQENGPB);\
}while(0)



检查该部分配置,确实没有发现问题. 使用的是GPB1 的中断4.理论上也不会影响它. 
由于其他事情耽搁,暂时没有跟踪......

以上是之前的笔记:

现在继续笔记:这次直接从irqpoll分析,正向入手到底哪里的问题,哪里产生了中断,为什么会进入SD卡.
#if defined (CONFIG_SD1_CD_GPA3) || defined (CONFIG_SD1_CD_GPD6)
2247     // Allocate the GPIO1 interrupt handler. SD1 card detect GPxx bind to GPIO1 interrupt.
2248     ret = request_irq(IRQ_GPIO1, nvt_sd1_card_detect_irq, IRQF_SHARED, mmc_hostname(mmc1), host1);
2249     if (ret) {
2250         dev_dbg(&pdev->dev, "Error: request GPIO1 interrupt failed!\n");
2251         goto fail10;
2252     }
2253   #endif
使用的是GPD6

通过进一步跟踪,
进入SD插拔检测后,读取中断寄存器发现并不是自己的中断, 返回return 0,
正常应该return IRQ_HANDLED;,

IRQF_SHARED是共享的, 继续看看整个平台有没有其他地方用到中断3的.
排查下来也没有.那么只能是确实进到了中断3,但是却是无效中断.

    src = nvt_sd_read(REG_IRQTGSRC1);
    if (src & BIT22) // This interrupt is trigger by GPD6
    {
        // nvt_sd_debug("--> nvt_sd0_card_detect_irq() GPD6 interrupt happened !\n");
        if (nvt_sd_read(REG_GPIOD_PIN) & BIT6)
            host->present = 1;  // card removed
        else
            host->present = 0;  // card inserted
        /* 0.5s needed because of early card detect switch firing */
        mmc_detect_change(host->mmc, msecs_to_jiffies(500));
        nvt_sd_write(REG_IRQTGSRC1, BIT22); // clear GPD6 interrupt status
        return IRQ_HANDLED;
    }
    else
        return IRQ_NONE;    // interrupt was not from this device 走到了这里
#endif

printk src发现也没有问题
src0 = nvt_sd_read(REG_IRQTGSRC0);
src1 = nvt_sd_read(REG_IRQTGSRC1);
src2 = nvt_sd_read(REG_IRQTGSRC2);
src3 = nvt_sd_read(REG_IRQTGSRC3);
全部打印发现问题了
IRQ_NONE 20000  0  0  0 
跟踪datesheet

中断源选择器的配置. 如

Register ddress R/W Description Reset Value
IRQSRCGPB GP_BA+0x84 R/W GPIO Port B IRQ Source Grouping 0x0000000
31 30 29 28 27 26 25 24
GPB15SEL GPB14SEL GPB13SEL GPB12SEL
23 22 21 20 19 18 17 16
GPB11SEL GPB10SEL GPB9SEL GPB8SEL
15 14 13 12 11 10 9 8
GPB7SEL GPB6SEL GPB5SEL GPB4SEL
7 6 5 4 3 2 1 0
GPB3SEL GPB2SEL GPB1SEL GPB0SEL

Bits Descriptions Default
[2x+1:2x] GPBxSEL
Selection for GPBx as one of input Pins to IRQ0, IRQ1, IRQ2, or IR

出问题的寄存器配置.

IRQ Interrupt Trigger Source 0 (IRQTGSRC0)

Register Address R/W Description Reset Value
IRQTGSRC0 GP_BA+0xF0 R/C IRQ0~3 Interrupt Trigger Source GPIO A and B 0x00000000
# # # # # # # #
31 30 29 28 27 26 25 24
PB15TG PB14TG PB13TG PB12TG PB11TG PB10TG PB9TG PB8TG
23 22 21 20 19 18 17 16
PB7TG PB6TG PB5TG PB4TG PB3TG PB2TG PB1TG PB0TG
15 14 13 12 11 10 9 8
PA15TG PA14TG PA13TG PA12TG PA11TG PA10TG PA9TG PA8TG
7 6 5 4 3 2 1 0
PA7TG PA6TG PA5TG PA4TG PA3TG PA2TG PA1TG PA0TG
0x20000 对应着GPIOB_1 的中断, 确实是触摸屏的中断问题. 

为什么GPIO中断4会进入GPIO中断3呢
查阅很多资料表明,必须有对应的中断号,才会进入中断函数
那么只能是触摸屏配置了中断3
*跟踪触摸屏代码发现只有在设备打开的时候,才会配置GPIO中断为中断4,意味着在应用没
打开时,中断配置寄存器为默认值,上电过程,会有边沿信号,误触发,而且不会被清0,导致SD卡return 0
的次数达到上限99999次(不确认)而报错irqpoll***

IRQSRCGPB GP_BA+0x84 R/W GPIO Port B IRQ Source Grouping 0x55555555

Where x=0~15.
GPBxSEL = 0, GPBx pin is grouped as one of interrupt sources to IRQ0.
1, GPBx pin is grouped as one of interrupt sources to IRQ1.
2, GPBx pin is grouped as one of interrupt sources to IRQ2.
3, GPBx pin is grouped as one of interrupt sources to IRQ3.就是默认中断3.

最终原因:触摸屏程序逻辑错误,没open设备之前,虽然没有配置中断源选择,确开启了中断
导致一直使用默认复位值中断源3再触发,而且刚好SD卡使用的share选项.也是中断源3

触摸屏GPB1默认没配置中断源4,那么默认中断源是3,和SD卡同源.
触摸屏设置边沿触发, 上电过程会有中断误触发一次.
驱动优化该部分后,问题解决.

你可能感兴趣的:(Linux-内核驱动)