Linux 中斷(irq)控制器以及device tree設定
阿新 • • 發佈:2019-01-22
GPIO相關中斷(高通平臺為例)
- 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