OK6410A 开发板 (八) 12 linux-5.11 OK6410A start_kernel 打印角度 第一阶段 irq

irq 涉及的概念
1. 硬件A : 异常向量表
2. 硬件A : irq硬件流程及建议的软件流程
3. 硬件B : 芯片实现的中断控制器
	数据手册 12 VECTORED INTERRUPT CONTROLLERS P409
4. 软件A : linux中断处理的软件流程(irq部分)
5. 软件B : linux中断处理的软件流程(中断控制器部分)
6. 软件C : linux中断处理的软件流程(irq_desc部分)
硬件
	2VIC(Vectored Interrupt Controller, ARM PrimeCell
PL192)
	2TZIC(TrustZone Interrupt Controller, SP890)
	1个VIC支持32个中断源
	可编程的  interrupt priority levels 和 可编程的 interrupt priority level masking
	可产生 FIQ IRQ 和 SWI 异常
	可查询的 Raw interrupt status/Interrupt request status
start_kernel
	local_irq_disable
		// include/linux/irqflags.h
		// 224 #define local_irq_disable() do { raw_local_irq_disable(); } while (0)
		
		// 155 #define raw_local_irq_disable()     arch_local_irq_disable()
		
		// arch/arm/include/asm/irqflags.h
		// 46 #define arch_local_irq_disable arch_local_irq_disable
		// 47 static inline void arch_local_irq_disable(void)                                  
		// 48 {                                                                                
		// 49     asm volatile(                                                                
		// 50         "   cpsid i         @ arch_local_irq_disable"                            
		// 51         :                                                                        
		// 52         :                                                                        
		// 53         : "memory", "cc");                                                       
		// 54 } 
	early_boot_irqs_disabled = true;
		// init/main.c
		// 124 bool early_boot_irqs_disabled __read_mostly;
		
	early_irq_init
		// kernel/irq/irqdesc.c
		// 521 int __init early_irq_init(void)
		
		// 打印信息
		// NR_IRQS: 16, nr_irqs: 229, preallocated irqs: 229

		
		// 流程: 
		// 1. 计算 NR_IRQS nr_irqs initcnt
		// 2. 根据 initcnt 的数量(229),创建(229个) irq_desc ,并插入数据结构(radix_tree) 变量 irq_desc_tree 中
		// 注意 : 之后用到的软件中断号就是 irq_desc 数组的下标
		
	init_IRQ
		// arch/arm/kernel/irq.c
		// 78 void __init init_IRQ(void)
		
		// 打印信息
		/*
		S3C6410 clocks: apll = 532000000, mpll = 532000000
		        epll = 96000000, arm_clk = 532000000
		VIC @(ptrval): id 0x00041192, vendor 0x41
		irq: Cannot allocate irq_descs @ IRQ32, assuming pre-allocated
		VIC @(ptrval): id 0x00041192, vendor 0x41
		irq: Cannot allocate irq_descs @ IRQ64, assuming pre-allocated
		*/
		
		// 流程:
		// 1. 调用 machine_desc->init_irq/即s3c6410_init_irq 做 芯片的 irq 初始化(vic)
			

s3c6410_init_irq
	s3c64xx_init_irq(~0 & ~(1 << 7), ~0);
		s3c64xx_clk_init(NULL, xtal_f, xusbxti_f, soc_is_s3c6400(), S3C_VA_SYS);
		// void __init vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
		
		/*
		// map.pfn:71200,map.virtual:f6000000,map.length:4000,map.type:0 // S3C64XX_PA_VIC0
		// map.pfn:71300,map.virtual:f6010000,map.length:4000,map.type:0 // S3C64XX_PA_VIC1
		*/
		/* VIC0 is missing IRQ7, VIC1 is fully populated. */
				// 0xf6000000,0x20,0xffffff7f,0x4
				// hwirq_max 编号  < 0x20 , 不等于 0x20
		vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, IRQ_VIC0_RESUME);
				// 0xf6010000,0x40,0xffffffff,0x53020000
				// hwirq_max 为0x40
		vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, IRQ_VIC1_RESUME);
			__vic_init
				vic_disable(base);
				vic_clear_interrupts(base);
				vic_init2(base);
				vic_register(base, NULL, irq_start, vic_sources, resume_sources, NULL);
					填充vic_devices[0,1]
					set_handle_irq(vic_handle_irq);
						handle_arch_irq = vic_handle_irq;
					v->irq = IRQ_VICx_BASE;

					
					// 建立 硬件中断号与软件中断号的映射
					

					// 1.向系统注册一个irq domain 
					// 因为 一个硬件系统可能有多个 中断控制器
					//  A中断控制器的硬件中断号 无法与 B中断控制器的硬件中断号区分
					// 所以加了一层 irq domain
					// 目前 是 软件中断号 <-> domain <-> 硬件中断号
					
					v->domain = irq_domain_add_simple(node, fls(valid_sources), irq, &vic_irqdomain_ops, v);
					
					// 2. 建立 该 domain 内的硬件中断号与软件中断号的映射
					// 建立HW interrupt ID和IRQ number的映射关系。
					// 该接口函数以irq domain和HW interrupt ID为参数,返回IRQ number(这个IRQ number是动态分配的)
					针对每一个 irq source ,irq_create_mapping(v->domain, i);
					
// vic_sources : 有效的中断源, bit 为 1 ,表示 有效
// resume_sources : 可以resume唤醒的中断源 , bit 为 1 , 表示 有效

其他

硬件中断号 <-> domain <-> 软件中断号 是 通过 什么结构体 关系到一起的

irq_create_mapping -> irq_create_mapping_affinity -> irq_domain_associate(domain, virq, hwirq)
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); 
		struct irq_desc *desc = irq_to_desc(irq); // 通过 irq 找到 irq_desc  , 这个关系被封印在了 数据结构 radix_tree 中 
			radix_tree_lookup(&irq_desc_tree, irq);
		return desc ? &desc->irq_data : NULL;
	irq_data->hwirq = hwirq; // irq_desc 中存在着 irq_data->hwirq 
	irq_data->domain = domain; // irq_desc 中存在着 irq_data->domain 



相关代码
$ ls kernel/irq
autoprobe.c  debug.h   dummychip.c     handle.c     irqdesc.c    Kconfig   manage.c  proc.c    settings.h
chip.c       devres.c  generic-chip.c  internals.h  irqdomain.c  Makefile  pm.c      resend.c  spurious.c
$ ls drivers/irqchip/
irqchip.c  irq-vic.c  Kconfig  Makefile

# cat /proc/interrupts 
           CPU0      
软件中断号 	次数  中断控制器 硬件中断号(有的是vic0上的,有的是vic1上的) 中断触发 中断名称 
 58:          0       VIC  26 Edge      s3c2410-wdt
 59:     757035       VIC  27 Edge      samsung_time_irq
 62:     478966       VIC  30 Edge      s3c-lcd
 69:        183       VIC   5 Edge      s3c6400-uart
 79:         25       VIC  15 Edge      ohci_hcd:usb1
 88:         35       VIC  24 Edge      mmc0
108:      87366  s3c-eint     Level     eth0
Err:          0
--------------------
驱动如何使用 中断
1. 根据 硬件中断号
	

2. 做硬件中断号 和 软件中断号的映射
	irq_of_parse_and_map / of_irq_get // 返回了软件中断号
		irq_create_of_mapping
			irq_create_fwspec_mapping
				irq_domain_alloc_irqs
					1. 从allocated_irqs 位图里分配一个空间的比特位
						// 获取软件中断号 XXX , 即 从低到高 bit XXX 是 第一个为 0的
					2. 分配一个 strct irq_desc 数据结构 // 填充 软件中断号与硬件中断号的映射及其相关的数据结构
						2.1 irq_desc[XXX].irq_data.irq = XXX; // 软件中断号体现在 数组下标,还体现在 irq_desc[XXX].irq_data.irq
						2.2 irq_desc[XXX].irq_data.hwirq = 硬件中断号;
						2.3 设置 desc[XXX].handle_irq = 中断处理函数
3. 根据 软件中断号 申请 handler
	request_threaded_irq/request_irq // 里面的irq成员是 软件中断号

1.直接找到软件中断号
	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);2. 根据 软件中断号 申请 handler
	request_threaded_irq/request_irq // 里面的irq成员是 软件中断号
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值