博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
慢慢欣赏linux 中断学习之外部中断 arm glcv3虚实中断映射
阅读量:4070 次
发布时间:2019-05-25

本文共 8939 字,大约阅读时间需要 29 分钟。

对于linux开发者来说,单板上设备如果有中断,主要的工作有3步.

第一步: 添加设备树的描述, 定义实中断号;
第二步: 进行虚实中断映射;
第三步: 申请中断

通过下面的例子进行说明

int bcm_sf2_sw_probe(struct platform_device *pdev){	/* 虚实中断映射 */	priv->irq0 = irq_of_parse_and_map(dn, 0);	priv->irq1 = irq_of_parse_and_map(dn, 1);		/* 通过虚中断挂接中断处理例程 */	/* Disable all interrupts and request them */	bcm_sf2_intr_disable(priv);	ret = devm_request_irq(&pdev->dev, priv->irq0, bcm_sf2_switch_0_isr, 0, "switch_0", priv);	ret = devm_request_irq(&pdev->dev, priv->irq1, bcm_sf2_switch_1_isr, 0, "switch_1", priv);}

先来看一下虚实中断映射

unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data){	struct irq_fwspec fwspec;	of_phandle_args_to_fwspec(irq_data, &fwspec);	return irq_create_fwspec_mapping(&fwspec);	=>unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)	{		struct irq_domain *domain;		struct irq_data *irq_data;		irq_hw_number_t hwirq;		unsigned int type = IRQ_TYPE_NONE;		int virq;		if (fwspec->fwnode) {			domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_WIRED);			if (!domain)				domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_ANY);		} else {			domain = irq_default_domain;		}		if (irq_domain_translate(domain, fwspec, &hwirq, &type))			return 0;		=>int irq_domain_translate(struct irq_domain *d,				struct irq_fwspec *fwspec,				irq_hw_number_t *hwirq, unsigned int *type)		{		#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY			if (d->ops->translate)				return d->ops->translate(d, fwspec, hwirq, type);				==>.translate = gic_irq_domain_translate				=>int gic_irq_domain_translate(struct irq_domain *d,				    struct irq_fwspec *fwspec,				    unsigned long *hwirq,				    unsigned int *type)				{					if (is_of_node(fwspec->fwnode)) {						if (fwspec->param_count < 3)							return -EINVAL;						switch (fwspec->param[0]) {						case 0:			/* SPI */							*hwirq = fwspec->param[1] + 32;							break;						case 1:			/* PPI */							*hwirq = fwspec->param[1] + 16;							break;						case GIC_IRQ_TYPE_LPI:	/* LPI */							*hwirq = fwspec->param[1];							break;						default:							return -EINVAL;						}						*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;						return 0;					}					if (is_fwnode_irqchip(fwspec->fwnode)) {						if(fwspec->param_count != 2)							return -EINVAL;						*hwirq = fwspec->param[0];						*type = fwspec->param[1];						return 0;					}					return -EINVAL;				}						#endif			if (d->ops->xlate)				return d->ops->xlate(d, to_of_node(fwspec->fwnode),							 fwspec->param, fwspec->param_count,							 hwirq, type);			/* If domain has no translation, then we assume interrupt line */			*hwirq = fwspec->param[0];			return 0;		}		/*		 * WARN if the irqchip returns a type with bits		 * outside the sense mask set and clear these bits.		 */		if (WARN_ON(type & ~IRQ_TYPE_SENSE_MASK))			type &= IRQ_TYPE_SENSE_MASK;		/*		 * If we've already configured this interrupt,		 * don't do it again, or hell will break loose.		 */		virq = irq_find_mapping(domain, hwirq);		if (virq) {			/*			 * If the trigger type is not specified or matches the			 * current trigger type then we are done so return the			 * interrupt number.			 */			if (type == IRQ_TYPE_NONE || type == irq_get_trigger_type(virq))				return virq;			/*			 * If the trigger type has not been set yet, then set			 * it now and return the interrupt number.			 */			if (irq_get_trigger_type(virq) == IRQ_TYPE_NONE) {				irq_data = irq_get_irq_data(virq);				if (!irq_data)					return 0;				irqd_set_trigger_type(irq_data, type);				return virq;			}			pr_warn("type mismatch, failed to map hwirq-%lu for %s!\n",				hwirq, of_node_full_name(to_of_node(fwspec->fwnode)));			return 0;		}		if (irq_domain_is_hierarchy(domain)) {			virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);			=>int irq_domain_alloc_irqs(struct irq_domain *domain,			unsigned int nr_irqs, int node, void *arg)			{				return __irq_domain_alloc_irqs(domain, -1, nr_irqs, node, arg, false, NULL);				=>int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,			    unsigned int nr_irqs, int node, void *arg,			    bool realloc, const struct cpumask *affinity)				{					int i, ret, virq;					if (domain == NULL) {						domain = irq_default_domain;						if (WARN(!domain, "domain is NULL; cannot allocate IRQ\n"))							return -EINVAL;					}					if (realloc && irq_base >= 0) {						virq = irq_base;					} else {						virq = irq_domain_alloc_descs(irq_base, nr_irqs, 0, node, affinity);					}					irq_domain_alloc_irq_data(domain, virq, nr_irqs)					mutex_lock(&irq_domain_mutex);					ret = irq_domain_alloc_irqs_hierarchy(domain, virq, nr_irqs, arg);					=>int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain,										unsigned int irq_base,										unsigned int nr_irqs, void *arg)					{						return domain->ops->alloc(domain, irq_base, nr_irqs, arg);						=>int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,										unsigned int nr_irqs, void *arg)						{							int i, ret;							irq_hw_number_t hwirq;							unsigned int type = IRQ_TYPE_NONE;							struct irq_fwspec *fwspec = arg;							ret = gic_irq_domain_translate(domain, fwspec, &hwirq, &type);							for (i = 0; i < nr_irqs; i++) {								ret = gic_irq_domain_map(domain, virq + i, hwirq + i);								=>int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)								{									struct irq_chip *chip = &gic_chip;									==>static struct irq_chip gic_chip = {										.name			= "GICv3",										.irq_mask		= gic_mask_irq,										.irq_unmask		= gic_unmask_irq,										.irq_eoi		= gic_eoi_irq,										.irq_set_type		= gic_set_type,										.irq_set_affinity	= gic_set_affinity,										.irq_get_irqchip_state	= gic_irq_get_irqchip_state,										.irq_set_irqchip_state	= gic_irq_set_irqchip_state,										.flags			= IRQCHIP_SET_TYPE_MASKED,									};									if (static_key_true(&supports_deactivate))										chip = &gic_eoimode1_chip;									/* SGIs are private to the core kernel */									if (hw < 16)										return -EPERM;									/* Nothing here */									if (hw >= gic_data.irq_nr && hw < 8192)										return -EPERM;									/* Off limits */									if (hw >= GIC_ID_NR)										return -EPERM;									/* PPIs */									if (hw < 32) {										irq_set_percpu_devid(irq);										irq_domain_set_info(d, irq, hw, chip, d->host_data, handle_percpu_devid_irq, NULL, NULL);										irq_set_status_flags(irq, IRQ_NOAUTOEN);									}									/* SPIs */									if (hw >= 32 && hw < gic_data.irq_nr) {										irq_domain_set_info(d, irq, hw, chip, d->host_data, handle_fasteoi_irq, NULL, NULL);										=>void irq_domain_set_info(struct irq_domain *domain, unsigned int virq,													 irq_hw_number_t hwirq, struct irq_chip *chip,													 void *chip_data, irq_flow_handler_t handler,													 void *handler_data, const char *handler_name)										{											irq_domain_set_hwirq_and_chip(domain, virq, hwirq, chip, chip_data);											=>int irq_domain_set_hwirq_and_chip(struct irq_domain *domain, unsigned int virq,															  irq_hw_number_t hwirq, struct irq_chip *chip,															  void *chip_data)											{												struct irq_data *irq_data = irq_domain_get_irq_data(domain, virq);												irq_data->hwirq = hwirq;												irq_data->chip = chip ? chip : &no_irq_chip;												irq_data->chip_data = chip_data;												return 0;											}											__irq_set_handler(virq, handler, 0, handler_name);											=>void __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, const char *name)											{												unsigned long flags;												struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0);												__irq_do_set_handler(desc, handle, is_chained, name);												irq_put_desc_busunlock(desc, flags);											}											irq_set_handler_data(virq, handler_data);											=>int irq_set_handler_data(unsigned int irq, void *data)											{												unsigned long flags;												struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);												desc->irq_common_data.handler_data = data;												irq_put_desc_unlock(desc, flags);												return 0;											}										}																				irq_set_probe(irq);										irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));									}									/* LPIs */									if (hw >= 8192 && hw < GIC_ID_NR) {										if (!gic_dist_supports_lpis())											return -EPERM;										irq_domain_set_info(d, irq, hw, chip, d->host_data, handle_fasteoi_irq, NULL, NULL);									}									return 0;								}							}							return 0;						}					}										for (i = 0; i < nr_irqs; i++)						irq_domain_insert_irq(virq + i);					mutex_unlock(&irq_domain_mutex);					return virq;				}			}			if (virq <= 0)				return 0;		} else {			/* Create mapping */			virq = irq_create_mapping(domain, hwirq);			if (!virq)				return virq;		}		irq_data = irq_get_irq_data(virq);		/* Store trigger type */		irqd_set_trigger_type(irq_data, type);		return virq;	}}

 

转载地址:http://vdlji.baihongyu.com/

你可能感兴趣的文章
PostgreSQL查询优化器详解之逻辑优化篇
查看>>
STM32中assert_param的使用
查看>>
C语言中的 (void*)0 与 (void)0
查看>>
vu 是什么
查看>>
io口的作用
查看>>
IO口的作用
查看>>
UIView的使用setNeedsDisplay
查看>>
归档与解归档
查看>>
Window
查看>>
为什么button在设置标题时要用一个方法,而不像lable一样直接用一个属性
查看>>
字符串的截取
查看>>
2. Add Two Numbers
查看>>
17. Letter Combinations of a Phone Number (DFS, String)
查看>>
93. Restore IP Addresses (DFS, String)
查看>>
19. Remove Nth Node From End of List (双指针)
查看>>
49. Group Anagrams (String, Map)
查看>>
139. Word Break (DP)
查看>>
23. Merge k Sorted Lists (Divide and conquer, Linked List) 以及java匿名内部类
查看>>
Tensorflow入门资料
查看>>
剑指_用两个栈实现队列
查看>>