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;
}
中断API之irq_set_irq_type
最新推荐文章于 2024-08-08 15:45:47 发布