中断映射的大体过程如下:
先来看一个比较典型的例子,linux驱动开源源码
static int bcm2835_mbox_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int ret = 0;
struct resource *iomem;
struct bcm2835_mbox *mbox;
mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
if (mbox == NULL)
return -ENOMEM;
spin_lock_init(&mbox->lock);
ret = devm_request_irq(dev, irq_of_parse_and_map(dev->of_node, 0),
bcm2835_mbox_irq, 0, dev_name(dev), mbox);
if (ret) {
dev_err(dev, "Failed to register a mailbox IRQ handler: %d\n",
ret);
return -ENODEV;
}
irq_of_parse_and_map(dev->of_node, 0)这是我们比较常用的方法。 dev->of_node这是dts解析生成的结构体数据,0 这是中断数组下标表示你要映射的第几个中断。现在来看源码
1.irq_of_parse_and_map
unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
{
struct of_phandle_args oirq;
//解析一个irq,读取其配置值
if (of_irq_parse_one(dev, index, &oirq))
return 0;
//获取映射后的irq
return irq_create_of_mapping(&oirq);
}
2.of_irq_parse_one
int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq)
{
struct device_node *p;
const __be32 *intspec, *tmp, *addr;
u32 intsize, intlen;
int i, res;
pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index);
/* OldWorld mac stuff is "special", handle out of line */
if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
return of_irq_parse_oldworld(device, index, out_irq);
/* Get the reg property (if any) */
addr = of_get_property(device, "reg", NULL);
/* Try the new-style interrupts-extended first */
res = of_parse_phandle_with_args(device, "interrupts-extended",
"#interrupt-cells", index