RT5350 GPIO中断

一、依赖

sdk版本:MTK_Ralink_ApSoC_SDK_4200_20131106

kernel版本:linux-2.6.21.x

参考:RT5350_datasheet.pdf

二、PIO寄存器

RT5350_datasheet:P56~P61

RT5350总共28路PIO,28路PIO按0~21,22~27分两组寄存器分别控制。

三、ralink_gpio模块主要函数

  1. ralink_gpio_led_do_timer:周期轮询pio,对设定的pio进行on/off/blink操作

  2. ralink_gpio_led_init_timer:初始化pio轮询定时器

  3. ralink_gpio_init:注册ralink_gpio模块,使能pio中断,调用初始化pio轮询定时器

  4. ralink_gpio_exit:注销ralink_gpio模块

  5. ralink_gpio_notify_user:中断通知

  6. ralink_gpio_save_clear_intp:保存清穿中断标识

  7. ralink_gpio_irq_handler:中断处理函数,记录pio触发中断后维持时间,通知用户

  8. ralink_gpio_init_irq:注册中断处理函数

四、添加自定义中断处理函数

  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;
    }





你可能感兴趣的:(RT5350 GPIO中断)