本文共 3734 字,大约阅读时间需要 12 分钟。
int __init gic_of_init(struct device_node *node, struct device_node *parent){ gic_init_bases(dist_base, rdist_regs, nr_redist_regions, redist_stride, &node->fwnode); =>int __init gic_init_bases(void __iomem *dist_base, struct redist_region *rdist_regs, u32 nr_redist_regions, u64 redist_stride, struct fwnode_handle *handle) { gic_data.fwnode = handle; gic_data.dist_base = dist_base; gic_data.redist_regions = rdist_regs; gic_data.nr_redist_regions = nr_redist_regions; gic_data.redist_stride = redist_stride; ==>static struct gic_chip_data gic_data __read_mostly; /* 下面是读硬件, 获取支持中断的个数 */ /* * Find out how many interrupts are supported. * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI) */ typer = readl_relaxed(gic_data.dist_base + GICD_TYPER); gic_data.rdists.id_bits = GICD_TYPER_ID_BITS(typer); gic_irqs = GICD_TYPER_IRQS(typer); if (gic_irqs > 1020) gic_irqs = 1020; gic_data.irq_nr = gic_irqs; /* 创建中断控制器对应的域 */ gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops, &gic_data); ==>static const struct irq_domain_ops gic_irq_domain_ops = { .translate = gic_irq_domain_translate, .alloc = gic_irq_domain_alloc, .free = gic_irq_domain_free, .select = gic_irq_domain_select, }; =>struct irq_domain *irq_domain_create_tree(struct fwnode_handle *fwnode, const struct irq_domain_ops *ops, void *host_data) { return __irq_domain_add(fwnode, 0, ~0, 0, ops, host_data); =>struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size, irq_hw_number_t hwirq_max, int direct_max, const struct irq_domain_ops *ops, void *host_data) { struct device_node *of_node = to_of_node(fwnode); struct irqchip_fwid *fwid; struct irq_domain *domain; static atomic_t unknown_domains; domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size), GFP_KERNEL, of_node_to_nid(of_node)); if (fwnode && is_fwnode_irqchip(fwnode)) { fwid = container_of(fwnode, struct irqchip_fwid, fwnode); switch (fwid->type) { case IRQCHIP_FWNODE_NAMED: case IRQCHIP_FWNODE_NAMED_ID: domain->name = kstrdup(fwid->name, GFP_KERNEL); if (!domain->name) { kfree(domain); return NULL; } domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; break; default: domain->fwnode = fwnode; domain->name = fwid->name; break; } } else if (of_node) { char *name; /* * DT paths contain '/', which debugfs is legitimately * unhappy about. Replace them with ':', which does * the trick and is not as offensive as '\'... */ name = kstrdup(of_node_full_name(of_node), GFP_KERNEL); if (!name) { kfree(domain); return NULL; } strreplace(name, '/', ':'); domain->name = name; domain->fwnode = fwnode; domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; } of_node_get(of_node); /* Fill structure */ INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL); mutex_init(&domain->revmap_tree_mutex); domain->ops = ops; domain->host_data = host_data; domain->hwirq_max = hwirq_max; domain->revmap_size = size; domain->revmap_direct_max_irq = direct_max; irq_domain_check_hierarchy(domain); mutex_lock(&irq_domain_mutex); debugfs_add_domain_dir(domain); list_add(&domain->link, &irq_domain_list); mutex_unlock(&irq_domain_mutex); pr_debug("Added domain %s\n", domain->name); return domain; } } set_handle_irq(gic_handle_irq); void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) { if (handle_arch_irq) return; handle_arch_irq = handle_irq; } }}
中断子系统 ---博客不错
https://blog.csdn.net/yhb1047818384/category_9762456.html