25 设备树里直接提供gpio口的中断号

通常是在设备树的设备节点里通过属性提供所用的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 <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/interrupt.h>

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");
  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值