1. 程式人生 > >Linux 中斷(irq)控制器以及device tree設定

Linux 中斷(irq)控制器以及device tree設定

GPIO相關中斷(高通平臺為例)

  1. gpio相關的中斷控制器(msm_tlmm_irq) 初始化
(1) IRQCHIP_DECLARE定義irq chip

#define IRQCHIP_DECLARE(name,compstr,fn)                \
    static const struct of_device_id irqchip_of_match_##name    \
    __used __section(__irqchip_of_table)                \
    = { .compatible = compstr, .data = fn }

IRQCHIP_DECLARE(tlmmv3_irq, "qcom,msm-tlmm-gp"
, irq_msm_gpio_init); //定義IRQCHIP_DECLARE之後,相應的內容會儲存到__irqchip_of_table裡邊。 //__irqchip_of_table在vmlinux.lds檔案裡邊被放到了__irqchip_begin和__irqchip_of_end之間 #ifdef CONFIG_IRQCHIP #define IRQCHIP_OF_MATCH_TABLE() \ . = ALIGN(8); \ VMLINUX_SYMBOL(__irqchip_begin) = .; \ *(__irqchip_of_table) \ *(__irqchip_of_end) #endif
__irqchip_begin和__irqchip_of_end的內容被drivers/irqchip/irqchip.c檔案讀出並根據其在device tree裡邊的內容進行初始化。

3.設定中斷喚醒!!
以gpio-key的為例:以下是gpio-key的device tree設定

    gpio_keys {
        compatible = "gpio-keys";
        input-name = "gpio-keys";
        pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend"
; pinctrl-0 = <&gpio_key_active>; pinctrl-1 = <&gpio_key_suspend>; home_key { label = "home_key"; gpios = <&msm_gpio 109 0x1>; linux,input-type = <1>; linux,code = <172>; gpio-key,wakeup; debounce-interval = <15>; }; vol_up { label = "volume_up"; gpios = <&msm_gpio 107 0x1>; linux,input-type = <1>; linux,code = <115>; debounce-interval = <15>; }; };

可以看到home_key裡邊有gpio-key,wakeup;
這個在gpio_keys相關的驅動力,在suspend的時候需要使用enable_irq_wake來進行設定才能通過home_key中斷喚醒系統。

static int gpio_keys_suspend(void){
    ...
    if (device_may_wakeup(global_dev)) {
        for (i = 0; i < ddata->pdata->nbuttons; i++) {
            struct gpio_button_data *bdata = &ddata->data[i];
            if (bdata->button->wakeup)//buttong->wakeup就是通過讀device tree的gpio-key,wakeup設定的
                enable_irq_wake(bdata->irq);//設定該中斷可喚醒系統!!具體設定看上面的中斷控制器內容
        }
    } else {
        mutex_lock(&input->mutex);
        if (input->users)
            gpio_keys_close(input);
        mutex_unlock(&input->mutex);
    }
    ...
}

當然在resume的時候也要對應地取消中斷函式的喚醒。
enable_irq_wake()和disable_irq_wake()函式中可以看到,irq_desc的wake_depth會記錄enable或者disable的次數。
所以需要對應地enable和disable每個irq的中斷喚醒功能。

static void gpio_keys_resume(void)
{
    ...
    if (device_may_wakeup(global_dev)) {
        for (i = 0; i < ddata->pdata->nbuttons; i++) {
            struct gpio_button_data *bdata = &ddata->data[i];
            if (bdata->button->wakeup)
                disable_irq_wake(bdata->irq);
        }
    } else {
        mutex_lock(&input->mutex);
        if (input->users)
            error = gpio_keys_open(input);
        mutex_unlock(&input->mutex);
    }

    ...
}

上面device_may_wakeup()檢查power.can_wakeup,power.wakeup

static inline bool device_may_wakeup(struct device *dev)
{
    return dev->power.can_wakeup && !!dev->power.wakeup;
}

這裡的power.can_wakeup在gpio_keys_probe()函式的device_init_wakeup()函式裡設定。

################################################
IRQ相關的巨集

CONFIG_ARM_GIC //GIC中斷控制器
CONFIG_SPARSE_IRQ
CONFIG_MSM_SHOW_RESUME_IRQ
CONFIG_HAVE_IRQ_TIME_ACCOUNTING
CONFIG_USE_PINCTRL_IRQ
CONFIG_OF_IRQ
CONFIG_IRQ_WORK
CONFIG_SPARSE_IRQ
CONFIG_TRACE_IRQFLAGS_SUPPORT
CONFIG_HARDIRQS_SW_RESEND
CONFIG_SEC_DEBUG_IRQ_EXIT_LOG
CONFIG_GENERIC_IRQ_PROBE
CONFIG_MAY_HAVE_SPARSE_IRQ
CONFIG_GENERIC_IRQ_SHOW 
CONFIG_IRQ_DOMAIN
CONFIG_MULTI_IRQ_HANDLER
CONFIG_IRQCHIP
CONFIG_MSM_IRQ

###############################################
#cat /proc/interrupts 列印的內容

cat interrupts
           CPU0       CPU1       CPU2       CPU3
 20:    1086204     465271     219385     125476       GIC  arch_timer
 35:          0          0          0          0       GIC  apps_wdog_bark
 39:    1274816     928934     431484     252063       GIC  arch_mem_timer
 47:         45          0          0          0       GIC  cpr
 56:          0          0          0          0       GIC  modem
 57:       6678          0          0          0       GIC  qcom,smd-modem
 58:          2          0          0          0       GIC  qcom,smsm-modem
 59:          5          0          0          0       GIC  smp2p
 65:      10820          0          0          0       GIC  kgsl-3d0
 75:          0          0          0          0       GIC  msm_iommu_global_cfg_irq, msm_iommu_global_cfg_irq
 76:        503          0          0          0       GIC  msm_vidc
 82:          9          0          0          0       GIC  cci
 83:          2          0          0          0       GIC  csid
 84:          0          0          0          0       GIC  csid
 89:          2          0          0          0       GIC
102:          0          0          0          0       GIC  msm_iommu_nonsecure_irq, msm_iommu_nonsecure_irq, msm_iommu_nonsecure_irq, msm_iommu_nonsecure_irq, msm_iommu_nonsecure_irq, msm_iommu_nonsecure_irq, msm_iommu_nonsecure_irq, msm_iommu_nonsecure_irq, msm_iommu_secure_irq, msm_iommu_secure_irq, msm_iommu_secure_irq, msm_iommu_secure_irq, msm_iommu_secure_irq, msm_iommu_secure_irq, msm_iommu_nonsecure_irq, msm_iommu_nonsecure_irq, msm_iommu_nonsecure_irq, msm_iommu_nonsecure_irq, msm_iommu_nonsecure_irq, msm_iommu_nonsecure_irq
104:       3821          0          0          0       GIC  MDSS
110:          0          0          0          0       GIC  csiphy
111:          0          0          0          0       GIC  csiphy
127:          0          0          0          0       GIC  i2c-msm-v2-irq
128:       7893          0          0          0       GIC  i2c-msm-v2-irq
130:          0          0          0          0       GIC  i2c-msm-v2-irq
131:          0          0          0          0       GIC  i2c-msm-v2-irq
132:          0          0          0          0       GIC  i2c-msm-v2-irq
140:        576          0          0          0       GIC  msm_serial_hsl0
155:     132532          0          0          0       GIC  mmc0
157:          0          0          0          0       GIC  mmc1
166:        511          0          0          0       GIC  msm_otg, msm_hsusb
170:        663          0          0          0       GIC  7824900.sdhci
172:          0          0          0          0       GIC  msm_otg
174:       1127          0          0          0       GIC  qcom,smd-wcnss
175:          5          0          0          0       GIC  smp2p
176:          0          0          0          0       GIC  qcom,smsm-wcnss
177:       1769          0          0          0       GIC  wcnss_wlan
178:        630          0          0          0       GIC  wcnss_wlan
181:          0          0          0          0       GIC  wcnss
200:     244890     133756      49164      25615       GIC  qcom,smd-rpm
203:     427701     370801     115006      64144       GIC  601d0.qcom,mpm
216:          0          0          0          0       GIC  tsens_interrupt
222:        677          0          0          0       GIC  200f000.qcom,spmi
239:          0          0          0          0       GIC  sps
240:        575          0          0          0       GIC  1000000.pinctrl
253:          2          0          0          0       GIC  7864900.sdhci
273:          0          0          0          0       GIC  msm_iommu_nonsecure_irq
274:          0          0          0          0       GIC  msm_iommu_nonsecure_irq
280:          2          0          0          0       GIC  mobicore
288:          0          0          0          0  msm_tlmm_irq  sm5703
290:          0          0          0          0  msm_tlmm_irq  7864900.sdhci cd
291:          7          0          0          0  qpnp-int  qpnp_kpdpwr_status
292:          2          0          0          0  qpnp-int  qpnp_resin_status
294:          2          0          0          0  qpnp-int  qpnp_kpdpwr_resin_bark
295:        334          0          0          0  qpnp-int  qpnp_rtc_alarm
297:          0          0          0          0  qpnp-int  pm8916_tz
299:          1          0          0          0  qpnp-int  qpnp_adc_tm_high_interrupt
300:          0          0          0          0  qpnp-int  qpnp_adc_tm_low_interrupt
330:          0          0          0          0  msm_tlmm_irq  k2hh_accel
331:          0          0          0          0  msm_tlmm_irq  bcm2079x-i2c
338:          0          0          0          0    sm5703  otffail
348:          0          0          0          0    sm5703  topoff
349:          0          0          0          0    sm5703  done
357:          6          0          0          0  msm_tlmm_irq  sm5703 muic micro USB
454:        569          0          0          0  msm_tlmm_irq  zt7554_ts
455:          0          0          0          0  msm_tlmm_irq  fuelgauge-irq
456:          0          0          0          0  msm_tlmm_irq  sx9500_wifi_irq
457:          0          0          0          0  smp2p_gpio  modem
458:          1          0          0          0  smp2p_gpio  error_ready_interrupt
459:          1          0          0          0  smp2p_gpio  modem
460:          0          0          0          0  smp2p_gpio  modem
489:          0          0          0          0  smp2p_gpio  wcnss
490:          1          0          0          0  smp2p_gpio  error_ready_interrupt
491:          1          0          0          0  smp2p_gpio  wcnss
492:          0          0          0          0  smp2p_gpio  wcnss
521:          0          0          0          0  msm_tlmm_irq  home_key
522:          0          0          0          0  msm_tlmm_irq  volume_up
523:          0          0          0          0  msm_tlmm_irq  sec_headset_detect
IPI0:          0        335        335        335  CPU wakeup interrupts
IPI1:      22678      22996      17470      15718  Timer broadcast interrupts
IPI2:     481360     374947     186478     142656  Rescheduling interrupts
IPI3:      84655     100015     156993     161249  Function call interrupts
IPI4:       1204       6730       6209       7108  Single function call interrupts
IPI5:          0          0          0          0  CPU stop interrupts
IPI6:          0          0          0          0  CPU backtrace
Err:          0