当前位置: 首页 > news >正文

JJJ-2 init_IRQ

void __init init_IRQ(void)
{int ret;if (IS_ENABLED(CONFIG_OF) && !machine_desc->init_irq)irqchip_init();else // init_irq成员定义为imx6ul_init_irq,会走这个分支machine_desc->init_irq(); if (IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_CACHE_L2X0) &&(machine_desc->l2c_aux_mask || machine_desc->l2c_aux_val)) {if (!outer_cache.write_sec)outer_cache.write_sec = machine_desc->l2c_write_sec;ret = l2x0_of_init(machine_desc->l2c_aux_val,machine_desc->l2c_aux_mask);if (ret)pr_err("L2C: failed to init: %d\n", ret);}
}

看imx6ul_init_irq

static void __init imx6ul_init_irq(void)
{imx_gpc_check_dt();imx_init_revision_from_anatop();imx_src_init();irqchip_init();
}

看imx_gpc_check_dt

void __init imx_gpc_check_dt(void)
{struct device_node *np;// 应该是定义在 imx6ul.dtsinp = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");if (WARN_ON(!np))return;if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) {pr_warn("Outdated DT detected, suspend/resume will NOT work\n");/* map GPC, so that at least CPUidle and WARs keep working */gpc_base = of_iomap(np, 0);}
}设备节点如下:
gpc: gpc@020dc000 {compatible = "fsl,imx6ul-gpc", "fsl,imx6q-gpc";reg = <0x020dc000 0x4000>;interrupt-controller;#interrupt-cells = <3>;interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;interrupt-parent = <&intc>;fsl,mf-mix-wakeup-irq = <0x7c00000 0x7d00 0x0 0x1400640>;};

看 imx_init_revision_from_anatop

void __init imx_init_revision_from_anatop(void)
{struct device_node *np;void __iomem *anatop_base;unsigned int revision;u32 digprog;u16 offset = ANADIG_DIGPROG;np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");anatop_base = of_iomap(np, 0);WARN_ON(!anatop_base);if (of_device_is_compatible(np, "fsl,imx6sl-anatop")) // 不会走这个分支offset = ANADIG_DIGPROG_IMX6SL;if (of_device_is_compatible(np, "fsl,imx7d-anatop")) // 不会走这个分支offset = ANADIG_DIGPROG_IMX7D;根据offset偏移然后去读寄存器的值digprog = readl_relaxed(anatop_base + offset);iounmap(anatop_base);switch (digprog & 0xff) {case 0:if (digprog >> 8 & 0x01)revision = IMX_CHIP_REVISION_2_0;elserevision = IMX_CHIP_REVISION_1_0;break;case 1:revision = IMX_CHIP_REVISION_1_1;break;case 2:revision = IMX_CHIP_REVISION_1_2;break;case 3:revision = IMX_CHIP_REVISION_1_3;break;case 4:revision = IMX_CHIP_REVISION_1_4;break;case 5:/** i.MX6DQ TO1.5 is defined as Rev 1.3 in Data Sheet, marked* as 'D' in Part Number last character.*/revision = IMX_CHIP_REVISION_1_5;break;default:/** Fail back to return raw register value instead of 0xff.* It will be easy know version information in SOC if it* can't recongized by known version. And some chip like* i.MX7D soc digprog value match linux version format,* needn't map again and direct use register value.*/revision = digprog & 0xff;}mxc_set_cpu_type(digprog >> 16 & 0xff);imx_set_soc_revision(revision);
}

看 mxc_set_cpu_type

// 判断 cpu类型,赋值给 soc_id 字串
void mxc_set_cpu_type(unsigned int type)
{__mxc_cpu_type = type;
}

看 mxc_set_arch_type

// 判断arch,似乎没怎么用到
void mxc_set_arch_type(unsigned int type)
{__mxc_arch_type = type;
}

看 imx_src_init

void __init imx_src_init(void)
{struct device_node *np;u32 val;np = of_find_compatible_node(NULL, NULL, "fsl,imx51-src");if (!np)return;src_base = of_iomap(np, 0);WARN_ON(!src_base);//这个if没跑到if (cpu_is_imx7d()) {val = readl_relaxed(src_base + SRC_M4RCR);if (((val & BIT(3)) == BIT(3)) && !(val & BIT(0)))m4_is_enabled = true;elsem4_is_enabled = false;return;}// 详见下imx_reset_controller.of_node = np;if (IS_ENABLED(CONFIG_RESET_CONTROLLER))reset_controller_register(&imx_reset_controller);/** force warm reset sources to generate cold reset* for a more reliable restart*/spin_lock(&src_lock);val = readl_relaxed(src_base + SRC_SCR);/* bit 4 is m4c_non_sclr_rst on i.MX6SX */if (cpu_is_imx6sx() && ((val &(1 << BP_SRC_SCR_SW_OPEN_VG_RST)) == 0))m4_is_enabled = true;elsem4_is_enabled = false;val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE);writel_relaxed(val, src_base + SRC_SCR);spin_unlock(&src_lock);
}

linux reset framework介绍

compatible 为 “fsl,imx51-src” 对应的节点为:

imx6ul.dtsisrc: src@020d8000 {compatible = "fsl,imx6ul-src", "fsl,imx51-src";reg = <0x020d8000 0x4000>;interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,<GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;#reset-cells = <1>;};

看 irqchip_init

void __init irqchip_init(void)
{of_irq_init(__irqchip_of_table);// 空函数acpi_irq_init();
}

/*** of_irq_init - Scan and init matching interrupt controllers in DT* @matches: 0 terminated array of nodes to match and init function to call** This function scans the device tree for matching interrupt controller nodes,* and calls their initialization functions in order with parents first.*/
void __init of_irq_init(const struct of_device_id *matches)
{struct device_node *np, *parent = NULL;struct intc_desc *desc, *temp_desc;struct list_head intc_desc_list, intc_parent_list;INIT_LIST_HEAD(&intc_desc_list);INIT_LIST_HEAD(&intc_parent_list);// 遍历所有的node,寻找定义了interrupt-controller属性的node,如果定义了interrupt-controller属性则说明该node就是一个中断控制器。详细分析见下for_each_matching_node(np, matches) {if (!of_find_property(np, "interrupt-controller", NULL) ||!of_device_is_available(np))continue;/** Here, we allocate and populate an intc_desc with the node* pointer, interrupt-parent device_node etc.*/desc = kzalloc(sizeof(*desc), GFP_KERNEL);if (WARN_ON(!desc))goto err;// 此处会有两个node符合条件,分别为interrupt-controller和gpcdesc->dev = np;desc->interrupt_parent = of_irq_find_parent(np);if (desc->interrupt_parent == np)desc->interrupt_parent = NULL;list_add_tail(&desc->list, &intc_desc_list);}/** The root irq controller is the one without an interrupt-parent.* That one goes first, followed by the controllers that reference it,* followed by the ones that reference the 2nd level controllers, etc.*/while (!list_empty(&intc_desc_list)) {/** Process all controllers with the current 'parent'.* First pass will be looking for NULL as the parent.* The assumption is that NULL parent means a root controller.*/list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {const struct of_device_id *match;int ret;// typedef int (*of_irq_init_cb_t)(struct device_node *, struct device_node *);of_irq_init_cb_t irq_init_cb;if (desc->interrupt_parent != parent)continue;list_del(&desc->list);// 传入一个node设备树节点,让它与给定的一组的matches匹配,返回其中最合适的matchesmatch = of_match_node(matches, desc->dev);if (WARN(!match->data,"of_irq_init: no init function for %s\n",match->compatible)) {kfree(desc);continue;}pr_debug("of_irq_init: init %s @ %p, parent %p\n",match->compatible,desc->dev, desc->interrupt_parent);//jl_test 能走到这儿的也只有两个节点,分别为interrupt-controller和gpcpr_err("irq_test:%s:%d:node_name=%s:compatible=%s\n", __func__, __LINE__, desc->dev->name, match->compatible);irq_init_cb = (of_irq_init_cb_t)match->data;// gic_of_init 和 imx_gpc_init 接下来要重点分析这两个函数了,见3ret = irq_init_cb(desc->dev, desc->interrupt_parent);if (ret) {kfree(desc);continue;}/** This one is now set up; add it to the parent list so* its children can get processed in a subsequent pass.*/list_add_tail(&desc->list, &intc_parent_list);}/* Get the next pending parent that might have children */desc = list_first_entry_or_null(&intc_parent_list,typeof(*desc), list);if (!desc) {pr_err("of_irq_init: children remain, but no parents\n");break;}list_del(&desc->list);parent = desc->dev;kfree(desc);}list_for_each_entry_safe(desc, temp_desc, &intc_parent_list, list) {list_del(&desc->list);kfree(desc);}
err:list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {list_del(&desc->list);kfree(desc);}
}

关于reset framework 详见这篇

关于for_each_matching_node,详见这篇

http://www.lryc.cn/news/59561.html

相关文章:

  • 【NLP实战】基于Bert和双向LSTM的情感分类【下篇】
  • 程序设计方法学
  • Hadoop之Yarn篇
  • Spring Cloud Nacos使用总结
  • 目标检测框架yolov5环境搭建
  • Vulnhub:Digitalworld.local (JOY)靶机
  • STL源码剖析-六大部件, 部件的关系,复杂度, 区间表示
  • 总有一个可用的连接,metaIPC1.2进入智能连接新时代
  • 棋盘问题c
  • 华纳云:Linux系统下怎么创建普通用户并更改用户组
  • 「她时代」背后的欧拉力量
  • kubespray v2.21.0 在线部署 kubernetes v1.24.0 集群【2】
  • 聚焦运营商信创运维,美信时代监控易四大亮点值得一试!
  • [python刷题模板] 博弈入门-记忆化搜索/dp/打表
  • I2C通信
  • 【Linux】man什么都搜不了,No manual entry for xxx的解决方案
  • STM32 库函数 GPIO_SetBits、GPIO_ResetBits、GPIO_WriteBit、GPIO_Write 区别
  • 在 RISC-V Linux 内核中添加模块
  • 利用AOP实现统一功能处理
  • 会话技巧---英文单词
  • VS中解决方案和项目的区别
  • MyBatis的parameterType传入参数类型和resultType返回结果类型
  • 什么是Android FrameWork,请你介绍一下?
  • 【SQL 必知必会】- 第十六课 更新和删除数据
  • 常见哈希算法及其应用
  • PHP快速入门02-PHP语言基础
  • FSCapture - 长截图工具
  • [ 云计算 | Azure ] Chapter 05 | 核心体系结构之管理组、订阅、资源和资源组以及层次关系
  • 【算法LearnNO.1】算法介绍以及算法的时间复杂度和空间复杂度
  • 013:Mapbox GL添加marker