sdk版本:MTK_Ralink_ApSoC_SDK_4200_20131106linux
kernel版本:linux-2.6.21.x數組
參考:RT5350_datasheet.pdf函數
RT5350_datasheet:P56~P61spa
RT5350總共28路PIO,28路PIO按0~21,22~27分兩組寄存器分別控制。input
ralink_gpio_led_do_timer:週期輪詢pio,對設定的pio進行on/off/blink操做
it
ralink_gpio_led_init_timer:初始化pio輪詢定時器io
ralink_gpio_init:註冊ralink_gpio模塊,使能pio中斷,調用初始化pio輪詢定時器pdf
ralink_gpio_exit:註銷ralink_gpio模塊cli
ralink_gpio_notify_user:中斷通知sdk
ralink_gpio_save_clear_intp:保存清穿中斷標識
ralink_gpio_irq_handler:中斷處理函數,記錄pio觸發中斷後維持時間,通知用戶
ralink_gpio_init_irq:註冊中斷處理函數
添加自定義中斷處理函數數組
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; }