本文共 2404 字,大约阅读时间需要 8 分钟。
int irq_set_irq_type(unsigned int irq, unsigned int type)用于设置irq对应的中断的触发类型.其使用的例程如下:static void __init meta_intc_init_cpu(struct meta_intc_priv *priv, int cpu){ unsigned int thread = cpu_2_hwthread_id[cpu]; unsigned int signum = TBID_SIGNUM_TR2(thread); int irq = tbisig_map(signum); /* Register the multiplexed IRQ handler */ irq_set_chained_handler(irq, meta_intc_irq_demux); irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);}这里就通过调用irq_set_irq_type 将中断类型设置为低电平触发.其源码分析如下:int irq_set_irq_type(unsigned int irq, unsigned int type){ unsigned long flags; #通过irq number得到中断描述符,得到并操作中断描述符时需要通过irq_get_desc_buslock和irq_put_desc_busunlock的保护. struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); int ret = 0; #中断描述符为null,则退出 if (!desc) return -EINVAL; #通过中断描述符设置中断触发的类型. ret = __irq_set_trigger(desc, type); irq_put_desc_busunlock(desc, flags); return ret;}int __irq_set_trigger(struct irq_desc *desc, unsigned long flags){ struct irq_chip *chip = desc->irq_data.chip; int ret, unmask = 0; #中断描述符中的chip 或者chip对应的irq_set_type 为null,则退出 #因为这里最终会调用chip->irq_set_type 来设置中断触发类型 if (!chip || !chip->irq_set_type) { /* * IRQF_TRIGGER_* but the PIC does not support multiple * flow-types? */ pr_debug("No set_type function for IRQ %d (%s)\n", irq_desc_get_irq(desc), chip ? (chip->name ? : "unknown") : "unknown"); return 0; } if (chip->flags & IRQCHIP_SET_TYPE_MASKED) { if (!irqd_irq_masked(&desc->irq_data)) mask_irq(desc); if (!irqd_irq_disabled(&desc->irq_data)) unmask = 1; } /* Mask all flags except trigger mode */ flags &= IRQ_TYPE_SENSE_MASK; #核心代码设置irq的中断触发类型 ret = chip->irq_set_type(&desc->irq_data, flags); switch (ret) { #注意这个case 没有break 语句,因此返回值IRQ_SET_MASK_OK/IRQ_SET_MASK_OK_DONE会比IRQ_SET_MASK_OK_NOCOPY 多调用两个函数. case IRQ_SET_MASK_OK: case IRQ_SET_MASK_OK_DONE: irqd_clear(&desc->irq_data, IRQD_TRIGGER_MASK); irqd_set(&desc->irq_data, flags); case IRQ_SET_MASK_OK_NOCOPY: flags = irqd_get_trigger_type(&desc->irq_data); irq_settings_set_trigger_mask(desc, flags); irqd_clear(&desc->irq_data, IRQD_LEVEL); irq_settings_clr_level(desc); if (flags & IRQ_TYPE_LEVEL_MASK) { irq_settings_set_level(desc); irqd_set(&desc->irq_data, IRQD_LEVEL); } ret = 0; break; default: pr_err("Setting trigger mode %lu for irq %u failed (%pF)\n", flags, irq_desc_get_irq(desc), chip->irq_set_type); } if (unmask) unmask_irq(desc); return ret;}
转载地址:http://ygjmi.baihongyu.com/