nuc972自带的开发板上没有提供按键外部中断实验,以下是我调试通的外部中断1(EINT1)代码和注意点。
注意点1:
arch\arm\mach-nuc970\irq.c中下面的代码注释掉, 因为irq_set_chained_handler会把中断设置成IRQ_NOREQUEST, 后面request_irq的时候就会失败。
// for (irqno = IRQ_EXT0; irqno <= IRQ_EXT7; irqno++) {
// //printk("registering irq %d (extended nuc970 irq)\n", irqno);
// irq_set_chip(irqno, &nuc970_irq_chip);
// irq_set_chained_handler(irqno, nuc970_irq_demux_intgroup2);
// }
注意点2, 为了使用pingctrl,arch\arm\mach-nuc970\dev.c中把下面的注释掉
// &nuc970_device_gpio,
然后自己写的platform_dev的名字起成“nuc970-gpio”, 这样才能在自己的驱动里面调用成功下面这句:
devm_pinctrl_get_select(dev, "eint1-PF")
注意点3, 关于配置中断,需要注意一下:
a) 使能GPIO时钟
b) 配置GPIO引脚复用为终端
c) 设置GPIO引脚为输入模式,配置GPIO中断为下降沿触发
d) 中断处理函数里面还要清一下中断flag
代码如下:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/regs-aic.h>
#include <mach/hardware.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <mach/regs-clock.h>
#include <mach/regs-gcr.h>
#include <mach/regs-clock.h>
#include <linux/io.h>
#define DEVICE_NAME "hello"
static int MYDRIVER_Major = 0;
static struct class *hello_class;
static int hello_open(struct inode *inode, struct file *file)
{
printk("%s enter\n", __func__);
return 0;
}
static int hello_release(struct inode *inode, struct file *file)
{
printk("%s enter\n", __func__);
return 0;
}
static int hello_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
printk("%s enter\n", __func__);
return 0;
}
static int hello_write(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
printk("%s enter\n", __func__);
return 0;
}
static int hello_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
return 0;
}
static struct file_operations hello_fops =
{
.owner = THIS_MODULE,
.open = hello_open,
.release = hello_release,
.read = hello_read,
.write = hello_write,
.unlocked_ioctl = hello_ioctl,
};
irqreturn_t hello_irq(int irq, void *data)
{
unsigned int val;
val = __raw_readl(REG_GPIOF_ISR);
val |= (1<<12);
__raw_writel(val, REG_GPIOF_ISR);
printk("%s enter\n", __func__);
return IRQ_HANDLED;
}
static show_reg_value(const volatile void __iomem *addr, char *reg_name)
{
unsigned int val;
val = __raw_readl(addr);
printk("%s: 0x%x\n", reg_name, val);
}
static void eint_hw_init(struct device *dev)
{
unsigned int val = 0, ret = 0;;
struct pinctrl* p = NULL;
struct clk *clk = NULL;
/* Enable GPIO clock */
clk = clk_get(NULL, "gpio");
if (IS_ERR(clk)) {
printk(KERN_ERR "nuc970-gpio:failed to get gpio clock source\n");
return -1;
}
clk_prepare(clk);
clk_enable(clk);
clk = clk_get(NULL, "gpio_eclk");
if (IS_ERR(clk)) {
printk(KERN_ERR "nuc970-gpio:failed to get egpio clock source\n");
return -1;
}
clk_prepare(clk);
clk_enable(clk);
p = devm_pinctrl_get_select(dev, "eint1-PF");
if (IS_ERR(p)) {
ret = PTR_ERR(p);
dev_err(dev, "Cannot get pinctrl eint1-PF: %d\n", ret);
return ret;
}
/* set gpiof11~14 input */
val = __raw_readl(REG_GPIOF_DIR);
val &= ~(0xf<<11);
__raw_writel(val, REG_GPIOF_DIR);
show_reg_value(REG_GPIOF_DIR, "REG_GPIOF_DIR");
/*falling int enable*/
val = __raw_readl(REG_GPIOF_IFEN);
val |= 0xf<<11;
__raw_writel(val, REG_GPIOF_IFEN);
show_reg_value(REG_GPIOF_IFEN, "REG_GPIOF_IFEN");
}
static int hello_probe(struct platform_device *pdev)
{
int ret = 0;
int i = 0;
printk("%s enter\n", __func__);
eint_hw_init(&pdev->dev);
ret = devm_request_irq(&pdev->dev, IRQ_EXT1, hello_irq, IRQF_TRIGGER_FALLING, "hello_ext_irq", 1);
if (ret) {
printk("request ext1 irq failed, ret=%d\n", ret);
}
printk(DEVICE_NAME " initialized\n");
return 0;
}
static int hello_remove(struct platform_device *pdev)
{
printk("%s enter\n", __func__);
return 0;
}
static struct platform_driver hello_platform_driver = {
.probe = hello_probe,
.remove = hello_remove,
.driver = {
.name = "nuc970-gpio",
.owner = THIS_MODULE,
},
};
module_platform_driver(hello_platform_driver);
MODULE_AUTHOR("zwy");
MODULE_DESCRIPTION("platform driver template");
MODULE_LICENSE("GPL");