Linux AMBA 驱动:DMA 控制器 PL330 驱动简析

文章目录

  • 1. 前言
  • 2. 背景
  • 3. PL330 简介
  • 4. PL330 驱动加载流程
    • 4.1 PL330 设备注册流程
    • 4.2 PL330 驱动加载流程
  • 5. 小结
  • 6. 参考资料

1. 前言

限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。

2. 背景

本文基于 ARMv8 架构Linux 5.10 进行分析,DMA 控制器(DMAC: DMA Controller)ARM 的 PL330。

3. PL330 简介

PL330ARM 设计的 DMA 控制器(DMAC: DMA Controller),支持 Scatter/Gather 和 LLI(Linked-List Item) 特性。

在这里插入图片描述
上图是 PL330 的接口图,其中:

. AXI master 接口,用于 DMA 传输。
. APB slave 接口,用于配置/控制 DMAC PL330。
. Peripheral request interface [x:0],外设通过它发起 DMA 传输请求。
. Interrupts[x:0] 接口,用于发送中断给 CPU。

PL330 的典型应用框图如下:

在这里插入图片描述

更详细的 PL330 框图如下:

在这里插入图片描述

本文对 PL330 的介绍,就到此为止,更多关于 PL330 的细节,可参考 ARM 官方文档 DDI0424A_dmac_pl330_r0p0_trm.pdf

4. PL330 驱动加载流程

章节 3. 简单的介绍了 PL330 的功能和接口,本节将着重介绍 PL330 驱动的加载过程。首先看一下 PL330DTS 配置:

4.1 PL330 设备注册流程

dmac0: dma-controller@ff2c0000 {compatible = "arm,pl330", "arm,primecell";reg = <0x0 0xff2c0000 0x0 0x4000>;interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,<GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;arm,pl330-periph-burst;clocks = <&cru ACLK_DMAC0>;clock-names = "apb_pclk";#dma-cells = <1>;
};

系统启动过程中,解析 DMAC PL330DTS 配置:

kernel_init()kernel_init_freeable()...do_one_initcall()// arch_initcall_sync(of_platform_default_populate_init);of_platform_default_populate_init()of_platform_default_populate(NULL, NULL, NULL)of_platform_populate(root, of_default_bus_match_table, lookup, parent)rc = of_platform_bus_create(child, matches, lookup, parent, true)/* drivers/of/platform.c */static int of_platform_bus_create(struct device_node *bus,const struct of_device_id *matches, const struct of_dev_auxdata *lookup, struct device *parent, bool strict)
{...if (of_device_is_compatible(bus, "arm,primecell")) {/** Don't return an error here to keep compatibility with older* device tree files.*/of_amba_device_create(bus, bus_id, platform_data, parent);return 0;}...
}#ifdef CONFIG_ARM_AMBA
static struct amba_device *of_amba_device_create(struct device_node *node,const char *bus_id, void *platform_data,struct device *parent)
{struct amba_device *dev;.../* 1. 创建 AMBA 设备: DMA PL330 */dev = amba_device_alloc(NULL, 0, 0);.../* 2. AMBA 设备初始化 *//* AMBA devices only support a single DMA mask */dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);dev->dev.dma_mask = &dev->dev.coherent_dma_mask;/* setup generic device info */dev->dev.of_node = of_node_get(node);dev->dev.fwnode = &node->fwnode;dev->dev.parent = parent ? : &platform_bus;dev->dev.platform_data = platform_data;if (bus_id)dev_set_name(&dev->dev, "%s", bus_id);elseof_device_make_bus_id(&dev->dev);.../* Decode the IRQs and address ranges */for (i = 0; i < AMBA_NR_IRQS; i++)dev->irq[i] = irq_of_parse_and_map(node, i);.../* 3. 注册 AMBA 设备到系统 */ret = amba_device_add(dev, &iomem_resource);...
}
#else /* CONFIG_ARM_AMBA */
static struct amba_device *of_amba_device_create(struct device_node *node,const char *bus_id,void *platform_data,struct device *parent)
{return NULL;
}
#endif /* CONFIG_ARM_AMBA */

上面 amba_device_alloc() 创建设备过程中,绑定设备总线类型为 amba_bustype,是 PL330 驱动匹配加载的重要一环:

amba_device_alloc()struct amba_device *dev;dev = kzalloc(sizeof(*dev), GFP_KERNEL);if (dev) {amba_device_initialize(dev, name);...dev->dev.bus = &amba_bustype; /* 绑定 设备 的 总线类型 为 amba_bustype */......}return dev;

amba_device_add() 在注册设备到系统前,扫描读取 AMBA(Advanced Microcontroller Bus Architecture) 设备的 {periphid, cid},是 PL330 驱动匹配加载的另一重要环节:

amba_device_add()amba_device_try_add()static int amba_device_try_add(struct amba_device *dev, struct resource *parent)
{.../* 扫描读取 AMBA 设备的 {periph_id,cid} */ret = amba_get_enable_pclk(dev);if (ret == 0) {u32 pid, cid;.../** Read pid and cid based on size of resource* they are located at end of region*//* 读取 {periph_id,cid} */for (pid = 0, i = 0; i < 4; i++)pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) << (i * 8);for (cid = 0, i = 0; i < 4; i++)cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) << (i * 8);...amba_put_disable_pclk(dev);/* 记录 {periphid, cid} 到设备对象 */if (cid == AMBA_CID || cid == CORESIGHT_CID) {dev->periphid = pid;dev->cid = cid;}if (!dev->periphid)ret = -ENODEV;}...skip_probe:/* 注册 AMBA 设备到系统 */ret = device_add(&dev->dev);...
}

读取到的 PL330periphid0x00241330cid0xb105f00d

4.2 PL330 驱动加载流程

/* drivers/dma/pl330.c */static const struct amba_id pl330_ids[] = {{.id = 0x00041330,.mask = 0x000fffff,},{ 0, 0 },
};MODULE_DEVICE_TABLE(amba, pl330_ids);static struct amba_driver pl330_driver = {.drv = {.owner = THIS_MODULE,.name = "dma-pl330",.pm = &pl330_pm,},.id_table = pl330_ids,.probe = pl330_probe,.remove = pl330_remove,
};module_amba_driver(pl330_driver);
/* include/linux/amba/bus.h */#define module_amba_driver(__amba_drv) \module_driver(__amba_drv, amba_driver_register, amba_driver_unregister)
/* drivers/amba/bus.c */int amba_driver_register(struct amba_driver *drv)
{if (!drv->probe)return -EINVAL;drv->drv.bus = &amba_bustype; /* 绑定 驱动 的 总线类型 为 amba_bustype */drv->drv.probe = amba_probe;drv->drv.remove = amba_remove;drv->drv.shutdown = amba_shutdown;return driver_register(&drv->drv);
}
driver_register()bus_add_driver()driver_attach()__driver_attach().../* 驱动匹配 */ret = driver_match_device(drv, dev);amba_match()amba_lookup().../* 驱动绑定 */device_driver_attach(drv, dev);driver_probe_device(drv, dev);really_probe(dev, drv);drv->probe(dev); /* pl330_probe() */...static const struct amba_id *
amba_lookup(const struct amba_id *table, struct amba_device *dev)
{while (table->mask) {if (((dev->periphid & table->mask) == table->id) &&((dev->cid != CORESIGHT_CID) ||(amba_cs_uci_id_match(table, dev))))return table;table++;}return NULL;
}

从上面的分析中,可以看到 AMBA 设备 (PL330) 的匹配是通过 {periphid, cid} 进行匹配的。前面读到的 正好匹配到 pl330_ids[0],驱动加载流程进入了 pl330_probe()

pl330_probe().../* 注册 DMA 中断处理接口 */for (i = 0; i < AMBA_NR_IRQS; i++) {irq = adev->irq[i];if (irq) {ret = devm_request_irq(&adev->dev, irq,pl330_irq_handler, 0, dev_name(&adev->dev), pl330);...} else {break;}}.../* 注册 DMA 控制器设备到 DMA 子系统 */ret = dma_async_device_register(pd);...

5. 小结

虽然本文分析的 DMAC(DMA Controller) 设备的设备驱动注册加载,但其主干流程也适用于其它 AMBA(Advanced Microcontroller Bus Architecture) 设备驱动。

6. 参考资料

[1] DDI0424A_dmac_pl330_r0p0_trm.pdf
[2] 102202_0100_01_Introduction_to_AMBA_AXI.pdf

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3281028.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

鸿蒙对接极光推送时候报错1000900010,厂商token获取失败

在AppGallery Connect上配置项目的调试证书&#xff0c;然后手动导入&#xff0c;不要用IDE的自动构建证书&#xff1a; https://developer.huawei.com/consumer/cn/service/josp/agc/index.html#/

探索Python的加速神器:CyToolz,让数据处理快如闪电!

文章目录 探索Python的加速神器&#xff1a;CyToolz&#xff0c;让数据处理快如闪电&#xff01;背景&#xff1a;为何选择CyToolz&#xff1f;CyToolz是什么&#xff1f;如何安装CyToolz&#xff1f;五个简单函数的使用方法1. cytoolz.curry2. cytoolz.map3. cytoolz.reduce4.…

(十)联合概率数据互联原理及应用(JPDA)

目录 前言 一、JPDA原理及算法步骤 &#xff08;一&#xff09;算法步骤 1.确认矩阵计算 2.确认矩阵拆分 3.互联概率计算 4.状态及协方差更新 二、仿真验证 &#xff08;一&#xff09;模型构建 &#xff08;二&#xff09;仿真结果 总结 引用文献 前言 本文主要针…

微软:警惕利用VMware ESXi进行身份验证绕过攻击

微软于7月29日发布警告&#xff0c;称勒索软件团伙正在积极利用 VMware ESXi 身份验证绕过漏洞进行攻击。 该漏洞被追踪为 CVE-2024-37085&#xff0c;由微软安全研究人员 Edan Zwick、Danielle Kuznets Nohi 和 Meitar Pinto 发现&#xff0c;并在 6 月 25 日发布的 ESXi 8.0 …

吴恩达机器学习C1W2Lab05-使用Scikit-Learn进行线性回归

前言 有一个开源的、商业上可用的机器学习工具包&#xff0c;叫做scikit-learn。这个工具包包含了你将在本课程中使用的许多算法的实现。 目标 在本实验中&#xff0c;你将: 利用scikit-learn实现使用梯度下降的线性回归 工具 您将使用scikit-learn中的函数以及matplotli…

c#中使用数据验证器

前言 在很多情况下&#xff0c;用户的输入不一定满足我们的设计要求&#xff0c;需要验证输入是否正确&#xff0c;传统的方案是拿到控件数据进行逻辑判定验证后&#xff0c;给用户弹窗提示。这种方法有点职责延后的感觉&#xff0c;数据视图层应该很好的处理用户的输入。使用…

STM32DMA数据传输

我估计大多数人学这么久连听说都没听说过DMA&#xff0c;更不用提知道它是干嘛的。其实DMA的本质就是一个数据的搬运工。平常的时候当我们没有配置的时候&#xff0c;一直都是CPU在搬运数据&#xff0c;但是这个活又累又没有技术含量&#xff0c;所以DMA的重要性还是有的。 1.…

YOLOv9最新最全代码复现(论文复现)

YOLOv9最新最全代码复现&#xff08;论文复现&#xff09; 本文所涉及所有资源均在传知代码平台可获取 文章目录 YOLOv9最新最全代码复现&#xff08;论文复现&#xff09;引言YOLOv9模型概述模型框架图环境搭建及训练推理环境配置数据集准备训练过程测试和评估实践应用 报错修…

【机器学习西瓜书学习笔记——神经网络】

机器学习西瓜书学习笔记【第四章】 第五章 神经网络5.1神经元模型5.2 感知机与多层网络学习感知机学习率成本/损失函数梯度下降 5.3 BP神经网络&#xff08;误差逆传播&#xff09;5.4 全局最小与局部极小5.5 其他常见神经网络RBF网络RBF 与 BP 最重要的区别 ART网络 第五章 神…

Vue组件库移动端预览实现原理

引言 大家如果使用过移动端组件库&#xff08;比如&#xff1a;Vant&#xff09;&#xff0c;会发现在网站右侧有一个手机端的预览效果。 而且这个手机端预览的内容和外面的组件代码演示是同步的&#xff0c;切换组件的时候&#xff0c;移动端预览的内容也会发生相应的变化。 …

守护线程(Daemon Threads)详解:与非守护线程的区别

守护线程&#xff08;Daemon Threads&#xff09;详解&#xff1a;与非守护线程的区别 1、守护线程是什么&#xff1f;2、守护线程与非守护线程的区别2.1 JVM关闭行为2.2 任务性质2.3 线程设置2.4 示例代码 3、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收…

pytorch 绘制Depth Anything网络结构

pytorch 绘制模型的网络结构有很多中方法&#xff0c;个人比较喜欢 torchview 生成的 Graphviz 风格的图片。 Graphviz介绍 Graphviz是一款开源的图形可视化软件&#xff0c;其名称来源于“Graph Visualization Software”的缩写。它通过使用一种名为DOT的描述语言来定义图形…

不踩雷的护眼大路灯有哪些?五款盲选不踩雷的护眼大路灯推荐

不踩雷的护眼大路灯有哪些&#xff1f;作为一名专业的实测博主温馨提示大家&#xff0c;虽然护眼落地灯是个好东西&#xff0c;它能够提供柔和舒适的环境光&#xff0c;减少对眼睛的伤害&#xff0c;但是千万别乱买跟风&#xff0c;盲目入手踩雷率80%以上。那么如何辨别一盏护眼…

创客项目秀 | 基于 XIAO 开发板的语音向导

背景 柴火创客空间作为大湾区科技创新的窗口&#xff0c;每年到访空间的社区伙伴众多&#xff0c;为了更好的进行空间信息交互&#xff0c;我们希望有一个装置是可以解决&#xff1a;当空间管理员不在现场的时候&#xff0c;到访者可以通过装置获得清晰的介绍与引导。 为了解…

vue2 封装插槽组件

安装 element-ui npm install element-ui --save ---force main.js 导入 import Vue from vue; import ElementUI from element-ui; import element-ui/lib/theme-chalk/index.css; import App from ./App.vue; Vue.use(ElementUI); new Vue({ el: #app, render: h > h(Ap…

全渠道AI数字化商品管理 零售品牌增长“超级引擎”

随着“流量红利”时代的终结 品牌面临增速放缓、利润下滑的双重挑战。 消费者的诉求日益理性和个性化&#xff0c; 国内外品牌角逐市场份额 A1、大数据等先进技术迅猛发展 品牌商品计划管理变得更加复杂而多维。 零售品牌正加速数字化与全渠道融合以应对挑战。 可持续盈利…

对于一家企业来说,电气数字化是否有那么重要?

时代大背景下&#xff0c;尤其是在复杂的国际与社会环境交织之中&#xff0c;全社会的“数字化”转型已成必然之势。对于电子产业而言&#xff0c;“数字化”无疑是重大机遇。 众所周知&#xff0c;在蒸汽机时代&#xff0c;身为机械工程师堪称幸运&#xff0c;彼时涌现出众多…

MySQL 将查询结果导出到文件(select … into Statement)

我们经常会遇到需要将SQL查询结果导出到文件&#xff0c;以便后续的传输或数据分析的场景。为了满足这个需求&#xff0c;MySQL的select语句提供了into子句可以将的查询结果直接导出到文本文件。本文就MySQL中select…into的用法进行演示。 文章目录 一、select…into语句简介…

AWS账号注册:AWS 用借记卡注册是否有风险?

亚马逊云服务&#xff08;Amazon Web Services&#xff0c;简称 AWS&#xff09;作为全球领先的云服务提供商&#xff0c;吸引了众多企业和个人用户。注册 AWS 账户时&#xff0c;提供支付方式是必要的步骤&#xff0c;许多用户会选择使用借记卡来完成注册。那么&#xff0c;使…

idea、webstorm、navicat等2024大佬总结亲测可用

宝藏网址&#xff0c;亲测可用。 关于JetBrains全家桶激活。 扫码关注&#xff1a;JAVA和人工智能。回复 idea 或 webStorm 或 navicat 获取 仅学习使用&#xff0c;不要用于商业用途&#xff01;