慢慢欣赏linux 中断学习之外部中断 arm实现
2021/5/3 7:25:23
本文主要是介绍慢慢欣赏linux 中断学习之外部中断 arm实现,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
void __init init_IRQ(void) { if (IS_ENABLED(CONFIG_OF) && !machine_desc->init_irq) irqchip_init(); else machine_desc->init_irq(); ==>{ DT_MACHINE_START(CNS3XXX_DT, "Cavium Networks CNS3xxx") .dt_compat = cns3xxx_dt_compat, .map_io = cns3xxx_map_io, .init_irq = cns3xxx_init_irq, =>/* used by entry-macro.S */ void __init cns3xxx_init_irq(void) { gic_init(0, 29, IOMEM(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT), IOMEM(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT)); =>void __init gic_init(unsigned int gic_nr, int irq_start, void __iomem *dist_base, void __iomem *cpu_base) { struct gic_chip_data *gic = &gic_data[gic_nr]; gic->raw_dist_base = dist_base; gic->raw_cpu_base = cpu_base; __gic_init_bases(gic, irq_start, NULL); =>int __init __gic_init_bases(struct gic_chip_data *gic, int irq_start, struct fwnode_handle *handle) { if (gic == &gic_data[0]) { /* * Initialize the CPU interface map to all CPUs. * It will be refined as each CPU probes its ID. * This is only necessary for the primary GIC. */ for (i = 0; i < NR_GIC_CPU_IF; i++) gic_cpu_map[i] = 0xff; set_smp_cross_call(gic_raise_softirq); cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING, "irqchip/arm/gic:starting", gic_starting_cpu, NULL); set_handle_irq(gic_handle_irq); } if (static_key_true(&supports_deactivate) && gic == &gic_data[0]) { name = kasprintf(GFP_KERNEL, "GICv2"); gic_init_chip(gic, NULL, name, true); } else { name = kasprintf(GFP_KERNEL, "GIC-%d", (int)(gic-&gic_data[0])); gic_init_chip(gic, NULL, name, false); } ret = gic_init_bases(gic, irq_start, handle); =>int gic_init_bases(struct gic_chip_data *gic, int irq_start, struct fwnode_handle *handle) { irq_hw_number_t hwirq_base; int gic_irqs, irq_base, ret; if (IS_ENABLED(CONFIG_GIC_NON_BANKED) && gic->percpu_offset) { /* Frankein-GIC without banked registers... */ unsigned int cpu; gic->dist_base.percpu_base = alloc_percpu(void __iomem *); gic->cpu_base.percpu_base = alloc_percpu(void __iomem *); for_each_possible_cpu(cpu) { u32 mpidr = cpu_logical_map(cpu); u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); unsigned long offset = gic->percpu_offset * core_id; *per_cpu_ptr(gic->dist_base.percpu_base, cpu) = gic->raw_dist_base + offset; *per_cpu_ptr(gic->cpu_base.percpu_base, cpu) = gic->raw_cpu_base + offset; } gic_set_base_accessor(gic, gic_get_percpu_base); } else { /* Normal, sane GIC... */ WARN(gic->percpu_offset, "GIC_NON_BANKED not enabled, ignoring %08x offset!", gic->percpu_offset); gic->dist_base.common_base = gic->raw_dist_base; gic->cpu_base.common_base = gic->raw_cpu_base; gic_set_base_accessor(gic, gic_get_common_base); } /* * Find out how many interrupts are supported. * The GIC only supports up to 1020 interrupt sources. */ gic_irqs = readl_relaxed(gic_data_dist_base(gic) + GIC_DIST_CTR) & 0x1f; gic_irqs = (gic_irqs + 1) * 32; if (gic_irqs > 1020) gic_irqs = 1020; gic->gic_irqs = gic_irqs; if (handle) { /* DT/ACPI */ gic->domain = irq_domain_create_linear(handle, gic_irqs, &gic_irq_domain_hierarchy_ops, gic); } else { /* Legacy support */ /* * For primary GICs, skip over SGIs. * For secondary GICs, skip over PPIs, too. */ if (gic == &gic_data[0] && (irq_start & 31) > 0) { hwirq_base = 16; if (irq_start != -1) irq_start = (irq_start & ~31) + 16; } else { hwirq_base = 32; } gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */ irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, numa_node_id()); if (irq_base < 0) { WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", irq_start); irq_base = irq_start; } gic->domain = irq_domain_add_legacy(NULL, gic_irqs, irq_base, hwirq_base, &gic_irq_domain_ops, gic); =>struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, unsigned int size, unsigned int first_irq, irq_hw_number_t first_hwirq, const struct irq_domain_ops *ops, void *host_data) { struct irq_domain *domain; domain = __irq_domain_add(of_node_to_fwnode(of_node), first_hwirq + size, first_hwirq + size, 0, ops, host_data); if (domain) irq_domain_associate_many(domain, first_irq, first_hwirq, size); =>void irq_domain_associate_many(struct irq_domain *domain, unsigned int irq_base, irq_hw_number_t hwirq_base, int count) { struct device_node *of_node; int i; of_node = irq_domain_get_of_node(domain); for (i = 0; i < count; i++) { irq_domain_associate(domain, irq_base + i, hwirq_base + i); =>int irq_domain_associate(struct irq_domain *domain, unsigned int virq, irq_hw_number_t hwirq) { struct irq_data *irq_data = irq_get_irq_data(virq); int ret; irq_data->hwirq = hwirq; irq_data->domain = domain; if (domain->ops->map) { ret = domain->ops->map(domain, virq, hwirq); /* If not already assigned, give the domain the chip's name */ if (!domain->name && irq_data->chip) domain->name = irq_data->chip->name; } domain->mapcount++; irq_domain_set_mapping(domain, hwirq, irq_data); =>void irq_domain_set_mapping(struct irq_domain *domain, irq_hw_number_t hwirq, struct irq_data *irq_data) { if (hwirq < domain->revmap_size) { domain->linear_revmap[hwirq] = irq_data->irq; } else { mutex_lock(&domain->revmap_tree_mutex); radix_tree_insert(&domain->revmap_tree, hwirq, irq_data); mutex_unlock(&domain->revmap_tree_mutex); } } irq_clear_status_flags(virq, IRQ_NOREQUEST); return 0; } } } return domain; } } gic_dist_init(gic); ret = gic_cpu_init(gic); ret = gic_pm_init(gic); return 0; return ret; } return ret; } } } MACHINE_END } ]
这篇关于慢慢欣赏linux 中断学习之外部中断 arm实现的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-18git仓库有更新,jenkins 自动触发拉代码怎么配置的?-icode9专业技术文章分享
- 2024-12-18Jenkins webhook 方式怎么配置指定的分支?-icode9专业技术文章分享
- 2024-12-13Linux C++项目实战入门教程
- 2024-12-13Linux C++编程项目实战入门教程
- 2024-12-11Linux部署Scrapy教程:新手入门指南
- 2024-12-11怎么将在本地创建的 Maven 仓库迁移到 Linux 服务器上?-icode9专业技术文章分享
- 2024-12-10Linux常用命令
- 2024-12-06谁看谁服! Linux 创始人对于进程和线程的理解是…
- 2024-12-04操作系统教程:新手入门及初级技巧详解
- 2024-12-04操作系统入门:新手必学指南