MT7620设置GPIO输入中断

        1. 创建设备节点,设备号,这些不多说了。我们要对操作集中修改。

static const struct
file_operations ralink_gpio_fops =
{
	.owner		= THIS_MODULE,
	.unlocked_ioctl	= ralink_gpio_ioctl,
	.open		= ralink_gpio_open,
	.release	= ralink_gpio_release,
};

int __init ralink_gpio_init(void){
    
    int r = register_chrdev(ralink_gpio_major, RALINK_GPIO_DEVNAME, &ralink_gpio_fops);
    if(r < 0) {
	    printk(KERN_ERR "%s: unable to register character device\n", RALINK_GPIO_NAME);
    	return r;
    }
    //......
    ralink_gpio_init_irq();
}

        2.open函数中对引脚进行寄存器初始化设置


#define GPIO_PIN_NUM	67

volatile unsigned long *GPIO_CTRL_0;   //--- GPIO direction control register  0-input 1-output                                              
volatile unsigned long *GINT_REDGE_0;  //--GPIO rising edge interrupt enable register
volatile unsigned long *GINT_FEDGE_0;  //--GPIO falling edge interrupt enable register
volatile unsigned long *GINT_STAT_0;  //---GPIO interrupt status register 1-


static int
ralink_gpio_open(struct inode *inode, struct file *file)
{
	  try_module_get(THIS_MODULE);

      /* 67 pin set input interrupt */
	  GPIO_CTRL_0=(volatile unsigned long *)ioremap(0x10000674,4);   //--- GPIO40 to GPIO71 direction control register  0-input 1-output
      GINT_REDGE_0=(volatile unsigned long *)ioremap(0x10000668,4);  //--GPIO40 to GPIO71 rising edge interrupt enable register
      GINT_FEDGE_0=(volatile unsigned long *)ioremap(0x1000066C,4);  //--GPIO0-31, falling edge interrupt enable register
      GINT_STAT_0=(volatile unsigned long *)ioremap(0x10000660,4);  //---GPIO0 to GPIO31 interrupt status register 1-int  0 -no int
      //GINT_EDGE_0;  //---GPIO0 to GPIO31 interrupt edge status register 1-rising 0-falling

	  //---------   set GPIO purpose  -----------
      *GPIO_CTRL_0 &=~(0x1<<(GPIO_PIN_NUM-40)); //---bit set 0, input mode
      *GINT_REDGE_0 |=(0x1<<(GPIO_PIN_NUM-40)); //--bit set 1,enable Rising Edge interrupt  
      *GINT_FEDGE_0 &=~(0x1<<(GPIO_PIN_NUM-40)); //--bit set 0,disable Falling Edge interrupt  

	return 0;
}

        3.open函数中对引脚释放寄存器

static int
ralink_gpio_release(struct inode *inode, struct file *file)
{
	module_put(THIS_MODULE);
	
	iounmap(GPIO_CTRL_0);
	iounmap(GINT_REDGE_0);
	iounmap(GINT_FEDGE_0);
	iounmap(GINT_STAT_0);

	return 0;
}

        4.中断初始化

        回过来,我们再来看最开始的__init函数,初始化中断那里。申请了一个中断号为14的中断事件。

static void
ralink_gpio_irq_clear(void)
{
	*(volatile u32 *)(RALINK_REG_PIOINT)     = cpu_to_le32(0x00FFFFFF);
	*(volatile u32 *)(RALINK_REG_PIO3924INT) = cpu_to_le32(0x0000FFFF);
	*(volatile u32 *)(RALINK_REG_PIO7140INT) = cpu_to_le32(0xFFFFFFFF);
	*(volatile u32 *)(RALINK_REG_PIO72INT)   = cpu_to_le32(0x00000001);
}//清除中断

static void
ralink_gpio_init_irq(void)
{
	int err;

	memset(ralink_gpio_irq_data, 0, sizeof(ralink_gpio_irq_data));

	ralink_gpio_irq_clear();

	err = request_irq(SURFBOARDINT_GPIO, ralink_gpio_irq_handler, IRQF_DISABLED|IRQF_TRIGGER_FALLING, "ralink_gpio", NULL);    //注册中断,中断号为14,代码中设置的,中断名称为"ralink_gpio"
}

        5.中断函数

        这个函数不需要了解细节,只需要知道,最后执行一个ralink_gpio_notify_user函数。这个才是重点。

irqreturn_t ralink_gpio_irq_handler(int irq, void *dev_id)
{
	u32 i, rise_edge;

	u32 ralink_gpio_intp     = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIOINT));
	u32 ralink_gpio_edge     = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIOEDGE));
	u32 ralink_gpio3924_intp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIO3924INT));
	u32 ralink_gpio3924_edge = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIO3924EDGE));
	u32 ralink_gpio7140_intp = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIO7140INT));
	u32 ralink_gpio7140_edge = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIO7140EDGE));
	u32 ralink_gpio72_intp   = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIO72INT));
	u32 ralink_gpio72_edge   = le32_to_cpu(*(volatile u32 *)(RALINK_REG_PIO72EDGE));
    
    ralink_gpio_irq_clear();

	for (i = 0; i < 24; i++) {
		if ( !(ralink_gpio_intp & RALINK_GPIO(i)) )
			continue;
		rise_edge = (ralink_gpio_edge & RALINK_GPIO(i)) ? 1 : 0;
		if (ralink_gpio_notify_user(i, rise_edge))
			break;
	}

	for (i = 24; i < 40; i++) {
		if ( !(ralink_gpio3924_intp & RALINK_GPIO((i-24))) )
			continue;
		rise_edge = (ralink_gpio3924_edge & RALINK_GPIO((i-24))) ? 1 : 0;
		if (ralink_gpio_notify_user(i, rise_edge))
			break;
	}
	for (i = 40; i < 72; i++) {
		if ( !(ralink_gpio7140_intp & RALINK_GPIO((i-40))) )
			continue;
		rise_edge = (ralink_gpio7140_edge & RALINK_GPIO((i-40))) ? 1 : 0;
		if (ralink_gpio_notify_user(i, rise_edge))
			break;
	}

	for (i = 72; i < RALINK_GPIO_NUMBER; i++) {
		if ( !(ralink_gpio72_intp & RALINK_GPIO((i-72))) )
			continue;
		rise_edge = (ralink_gpio72_edge & RALINK_GPIO((i-72))) ? 1 : 0;
		if (ralink_gpio_notify_user(i, rise_edge))
			break;
	}
	return IRQ_HANDLED;
}

        6.向用户空间发送信号

        在这个函数里面我们可以做我们想做的事情。最终,在文件系统下使用cat /proc/interrupts命令可以读取到中断的上升沿次数的变化

/*
 * send a signal(SIGUSR2) to the registered user process whenever
 * any gpio interrupt comes (called by interrupt handler)
 */
static int
ralink_gpio_notify_user(u32 irq_gpio, u32 rise_edge)
{
	struct task_struct *p = NULL;
/************************USER DO SOMETHING****************************/
	//printk("irq_gpio = %d , rise_edge = %d\n" , irq_gpio , rise_edge);
	if(irq_gpio == GPIO_PIN_NUM	){

	}	
/****************************************************/
	if (irq_gpio >= RALINK_GPIO_NUMBER)
		return 0;

	// don't send any signal if pid < 1
	if (ralink_gpio_irq_data[irq_gpio].pid < 1)
		return 0;

	if (!(ralink_gpio_irq_data[irq_gpio].rise && rise_edge) &&
	    !(ralink_gpio_irq_data[irq_gpio].fall && !rise_edge))
		return 0;

	p = find_task_by_vpid(ralink_gpio_irq_data[irq_gpio].pid);

	if (!p)
		return 0;

	send_sig(SIGUSR2, p, 0);

	return 1;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值