RT5350 GPIO中斷

1、依賴

sdk版本:MTK_Ralink_ApSoC_SDK_4200_20131106linux

kernel版本:linux-2.6.21.x數組

參考:RT5350_datasheet.pdf函數

2、PIO寄存器

RT5350_datasheet:P56~P61spa

RT5350總共28路PIO,28路PIO按0~21,22~27分兩組寄存器分別控制。input

3、ralink_gpio模塊主要函數

  1. ralink_gpio_led_do_timer:週期輪詢pio,對設定的pio進行on/off/blink操做
    it

  2. ralink_gpio_led_init_timer:初始化pio輪詢定時器io

  3. ralink_gpio_init:註冊ralink_gpio模塊,使能pio中斷,調用初始化pio輪詢定時器pdf

  4. ralink_gpio_exit:註銷ralink_gpio模塊cli

  5. ralink_gpio_notify_user:中斷通知sdk

  6. ralink_gpio_save_clear_intp:保存清穿中斷標識

  7. ralink_gpio_irq_handler:中斷處理函數,記錄pio觸發中斷後維持時間,通知用戶

  8. ralink_gpio_init_irq:註冊中斷處理函數

4、添加自定義中斷處理函數

  1. 添加自定義中斷處理函數數組

typedef void(*pio_irq_hdlr)(void*);
typedef struct __cstm_pio_hdlr{
    pio_irq_hdlr irq_hdlr;
    unsigned char rising;
}cstm_pio_hdlr_t,*cstm_pio_hdlr_p;
cstm_pio_hdlr_t cstm_pio_irq_hdlr[RALINK_GPIO_NUMBER] = {0};

    2. 添加自定義中斷處理函數綁定

    unsigned long tmp;
    unsigned long reg_pio_dir = (irq_num<22)? RALINK_REG_PIODIR:RALINK_REG_PIO2722DIR;
    unsigned char bitoffset = (irq_num<22)? irq_num:(irq_num-22);
    unsigned long reg_irq_ena = 0;
      unsigned long gpiomode = irq_num==0 ? 0 : \
        (irq_num<=2 ? RALINK_GPIOMODE_I2C : \
        (irq_num<=6 ? RALINK_GPIOMODE_SPI : \
        (irq_num<=14 ? RALINK_GPIOMODE_UARTF : \
        (irq_num<=16 ? RALINK_GPIOMODE_UARTL : \
        (irq_num<=21 ? RALINK_GPIOMODE_JTAG : \
        (irq_num<=26 ? RALINK_GPIOMODE_EPHY : \
        (irq_num<=27 ? RALINK_GPIOMODE_SPI_CS1 : 0)))))));


    /*set pio as gpio*/
    *(volatile u32 *)(RALINK_REG_GPIOMODE) = cpu_to_le32(gpiomode);
    
    /* set pio direction as input */
    tmp = le32_to_cpu(*(volatile u32 *)(reg_pio_dir));
    tmp &= ~cpu_to_le32(1<<bitoffset);
    *(volatile u32 *)(RALINK_REG_PIODIR) = tmp;    

    /* enable gpio interrupt*/
    *(volatile u32 *)(RALINK_REG_INTENA) = cpu_to_le32(RALINK_INTCTL_PIO);
    
    /* set irq edge trigger*/
    if(rising)
    {
        reg_irq_ena = (irq_num<22)? RALINK_REG_PIORENA:RALINK_REG_PIO2722RENA;
    }
    else
    {
        reg_irq_ena = (irq_num<22)? RALINK_REG_PIOFENA:RALINK_REG_PIO2722FENA;
    }
    *(volatile u32 *)(reg_irq_ena) = bitoffset;

EXPORT_SYMBOL(ralink_gpio_cstm_irq_bind);

    3. 添加中斷跳轉捕獲

修改ralink_gpio_irq_handler,

#if defined (RALINK_GPIO_HAS_2722)
    for (i = 0; i < 22; i++) {
        if (! (ralink_gpio_intp & (1 << i)))
            continue;
        ralink_gpio_irqnum = i;
        if (ralink_gpio_edge & (1 << i)) { //rising edge
            if( NULL != cstm_pio_irq_hdlr[i].cstm_pio_irq_hdlr && cstm_pio_irq_hdlr[i].rising)
            {
                cstm_pio_irq_hdlr[i].irq_hdlr(NULL);
                continue;
            }  
     
            if (record[i].rising != 0 && time_before_eq(now,
                        record[i].rising + 40L)) {
                /*
                 * If the interrupt comes in a short period,
                 * it might be floating. We ignore it.
                 */
            }
            else {
                record[i].rising = now;
                if (time_before(now, record[i].falling + 200L)) {
                    //one click
                    ralink_gpio_notify_user(1);
                }
                else {
                    //press for several seconds
                    ralink_gpio_notify_user(2);
                }
            }
        }
        else { //falling edge
            if( NULL != cstm_pio_irq_hdlr[i].cstm_pio_irq_hdlr && !cstm_pio_irq_hdlr[i].rising)            {                cstm_pio_irq_hdlr[i].irq_hdlr(NULL);                continue;            }                            record[i].falling = now;        }        break;    }    for (i = 22; i < 28; i++) {        if (! (ralink_gpio2722_intp & (1 << (i - 22))))            continue;        ralink_gpio_irqnum = i;        if (ralink_gpio2722_edge & (1 << (i - 22))) {            if( NULL != cstm_pio_irq_hdlr[i].cstm_pio_irq_hdlr && cstm_pio_irq_hdlr[i].rising)            {                cstm_pio_irq_hdlr[i].irq_hdlr(NULL);                continue;            }                                if (record[i].rising != 0 && time_before_eq(now,                        record[i].rising + 40L)) {            }            else {                record[i].rising = now;                if (time_before(now, record[i].falling + 200L)) {                    ralink_gpio_notify_user(1);                }                else {                    ralink_gpio_notify_user(2);                }            }        }        else {            if( NULL != cstm_pio_irq_hdlr[i].cstm_pio_irq_hdlr && !cstm_pio_irq_hdlr[i].rising)            {                cstm_pio_irq_hdlr[i].irq_hdlr(NULL);                continue;            }                                record[i].falling = now;        }        break;    }

相關文章
相關標籤/搜索