rk3399 gpio interrupt


原文链接: rk3399 gpio interrupt

本文链接:https://blog.csdn.net/jklinux/article/details/78707537
通常是在设备树的设备节点里通过属性提供所用的gpio口,再在设备驱动代码里根据gpiod_to_irq(…)找到gpio口对应的中断号来使用.但有些场合下并不完全适用.如在描述i2c设备/spi设备时, 它们可以直接提供中断号:

struct i2c_client {
    unsigned short flags;       
    unsigned short addr;        
    ...
    char name[I2C_NAME_SIZE];
    struct i2c_adapter *adapter;    
    struct device dev;      
    int irq;      //中断号     
    ...
};

struct spi_device {
    struct device       dev;
    struct spi_master   *master;
    u32         max_speed_hz;
    u8          chip_select;
    u8          bits_per_word;
    u16         mode;
    int         irq; //中断号
    ...
};

在设备树里直接提供gpio口中断号的方法:

1 先确认设备树里的gpio控制器具有中断的功能:

    pio: pinctrl@01c20800 {
    ...
        gpio-controller; //这表示是一个gpio控制器
        #gpio-cells = <3>; //表示使用此gpio控制器时需要用3个参数来指定
         // 如用PA17的led:  leds-gpios = <&pio 0  17  GPIO_ACTIVIE_HIGH>
        interrupt-controller; //表示此设备还是一个中断控制器
        #interrupt-cells = <3>; //表示使用此中断控制器的中断号时由3个参数来指定.
                    // <gpio组  组内io口序号  中断触发标志>
    ... 
};  

2 在使用gpio口的spi设备节点里(使用PA12下降沿):

myspidev {
    ...
    interrupt-parent = <&pio>; //指定使用哪一个中断控制器
    interrupts = <0 12 IRQ_TYPE_EDGE_FALLING>;
};

3 设备驱动代码里直接访问spi_device的irq成员即可获取中断号.

gpio口的中断触发标志定义在:include/dt-bindings/interrupt-controller/irq.h

#define IRQ_TYPE_NONE       0
#define IRQ_TYPE_EDGE_RISING    1
#define IRQ_TYPE_EDGE_FALLING   2
#define IRQ_TYPE_EDGE_BOTH  (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
#define IRQ_TYPE_LEVEL_HIGH 4
#define IRQ_TYPE_LEVEL_LOW  8

如实现一个提供gpio口中断的spi设备,此设备使用一个PA12 gpio口.
设备树里的描述:

&spi1 {

#address-cells = <1>;
#size-cells = <0>;

status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins &spi1_cs_pins>;
cs-gpios = <&pio 0 13 GPIO_ACTIVE_HIGH>;

myspidev {
    compatible = "myspidev";
    reg = <0>;
    status = "okay";
    spi-max-frequency = <100000>;
    interrupt-parent = <&pio>;
    interrupts = <0  12  IRQ_TYPE_EDGE_BOTH>;
};  

};
设备驱动代码里中断号的使用:

/* mydrv.c */

#include
#include
#include
#include

irqreturn_t irq_func(int irqno, void *arg)
{

printk("irq ...\n");
return IRQ_HANDLED;

}

int myprobe(struct spi_device *spi)
{

int ret;

printk("in myprobe ...\n");
ret = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, irq_func, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING|IRQF_ONESHOT, spi->modalias , spi);

return ret;

}

int myremove(struct spi_device *spi)
{

devm_free_irq(&spi->dev, spi->irq, spi);
printk("in myremove ...\n");
return 0;

}

struct of_device_id ids[] = {

{.compatible = "myspidev"},
{},

};

struct spi_driver mydrv = {

    .probe = myprobe,
    .remove = myremove,

    .driver = {
        .owner = THIS_MODULE,
        .name = "myspidrv",
        .of_match_table = ids,
    },

};

module_spi_driver(mydrv);
MODULE_LICENSE("GPL");
————————————————
版权声明:本文为CSDN博主「jklinux」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jklinux/article/details/78707537

`