youleqq 发表于 2019-9-3 11:15:29

Linux芯片级移植与底层驱动(基于3.7.4内核)

与local_irq_disable()和local_irq_enable()不同,disable_irq()、enable_irq()针对的则是外部的中断控制器。在内核中,透过irq_chip结构体来描述中断控制器。该结构体内部封装了中断mask、unmask、ack等成员函数,其定义于include/linux/irq.h:

view plain copy



303structirq_chip { 304       const char      *name; 305       unsigned int    (*irq_startup)(structirq_data *data); 306       void         (*irq_shutdown)(struct irq_data *data); 307       void         (*irq_enable)(struct irq_data *data); 308       void         (*irq_disable)(struct irq_data *data); 309 310       void            (*irq_ack)(struct irq_data *data); 311       void            (*irq_mask)(structirq_data *data); 312       void         (*irq_mask_ack)(struct irq_data *data); 313       void         (*irq_unmask)(struct irq_data *data); 314       void            (*irq_eoi)(struct irq_data *data); 315 316       int            (*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest,bool force); 317       int            (*irq_retrigger)(struct irq_data *data); 318       int             (*irq_set_type)(struct irq_data *data,unsigned int flow_type); 319       int            (*irq_set_wake)(struct irq_data *data, unsigned int on); 334};各个芯片公司会将芯片内部的中断控制器实现为irq_chip驱动的形式。受限于中断控制器硬件的能力,这些成员函数并不一定需要全部实现,有时候只需要实现其中的部分函数即可。譬如drivers/pinctrl/pinctrl-sirf.c驱动中的

view plain copy



1438staticstruct irq_chip sirfsoc_irq_chip = {1439      .name = "sirf-gpio-irq",1440      .irq_ack = sirfsoc_gpio_irq_ack,1441       .irq_mask = sirfsoc_gpio_irq_mask,1442      .irq_unmask = sirfsoc_gpio_irq_unmask,1443      .irq_set_type = sirfsoc_gpio_irq_type,1444};我们只实现了其中的ack、mask、unmask和set_type成员函数,ack函数用于清中断,mask、unmask用于中断屏蔽和取消中断屏蔽、set_type则用于配置中断的触发方式,如高电平、低电平、上升沿、下降沿等。至于enable_irq()的时候,虽然没有实现irq_enable成员函数,但是内核会间接调用到irq_unmask成员函数,这点从kernel/irq/chip.c可以看出:

view plain copy



192voidirq_enable(struct irq_desc *desc) 193{ 194       irq_state_clr_disabled(desc); 195       if (desc->irq_data.chip->irq_enable) 196                desc->irq_data.chip->irq_enable(&desc->irq_data); 197       else 198               desc->irq_data.chip->irq_unmask(&desc->irq_data); 199       irq_state_clr_masked(desc); 200}在芯片内部,中断控制器可能不止1个,多个中断控制器之间还很可能是级联的。举个例子,假设芯片内部有一个中断控制器,支持32个中断源,其中有4个来源于GPIO控制器外围的4组GPIO,每组GPIO上又有32个中断(许多芯片的GPIO控制器也同时是一个中断控制器),其关系如下图:

https://img-my.csdn.net/uploads/201301/26/1359197467_9265.PNG

那么,一般来讲,在实际操作中,gpio0_0——gpio0_31这些引脚本身在第1级会使用中断号28,而这些引脚本身的中断号在实现GPIO控制器对应的irq_chip驱动时,我们又会把它映射到Linux系统的32——63号中断。同理,gpio1_0——gpio1_31这些引脚本身在第1级会使用中断号29,而这些引脚本身的中断号在实现GPIO控制器对应的irq_chip驱动时,我们又会把它映射到Linux系统的64——95号中断,以此类推。对于中断号的使用者而言,无需看到这种2级映射关系。如果某设备想申请gpio1_0这个引脚对应的中断,它只需要申请64号中断即可。这个关系图看起来如下:

https://img-my.csdn.net/uploads/201301/26/1359197487_5776.PNG

mj8abcd 发表于 2019-9-3 11:50:54

sun5304 发表于 2019-9-4 07:42:31

cityhu 发表于 2019-9-10 08:26:07

页: [1]
查看完整版本: Linux芯片级移植与底层驱动(基于3.7.4内核)