linux pl320 mbox控制器驱动分析-(3) pl320驱动代码分析

news2024/12/25 14:44:16

linux pl320 mbox控制器驱动分析-(3)pl320驱动代码分析

  • 1 pl320 mbox控制器宏定义
  • 2 初始化接口
  • 3 ipc_handler mbox中断处理函数
  • 4 数据的收发
    • 4.1 数据发送
    • 4.2 数据接收
    • 4.3 中断发送接收测试代码
  • 5 设置以及清除远端目的core
    • 5.1 设置远端目的core
    • 5.2 清除远端目的core

pl320-ipc.c mbox中断控制器的驱动代码路径为:driver/mailbox/pl320-ipc.c

1 pl320 mbox控制器宏定义

  1. #define IPCMxSOURCE(m) ((m) * 0x40) 每个mbox有0x40byte的控制寄存器用于做ipcm处理。而每个mbox的第一个寄存器用于设置源 core的。
    在这里插入图片描述
  2. #define IPCMxDSET(m) (((m) * 0x40) + 0x004)
    在这里插入图片描述
  3. IPCMxDCLEAR ~ IPCMxDR则依次对应于上面的表格所表示的寄存器。
  4. IPCMMIS和IPCMRIS寄存器用于判断mbox中断源的
    在这里插入图片描述
  5. #define MBOX_MASK(n) (1 << (n)) 用于判断当前的中断来自于哪个mbox
#define IPCMxSOURCE(m)		((m) * 0x40)
#define IPCMxDSET(m)		(((m) * 0x40) + 0x004)
#define IPCMxDCLEAR(m)		(((m) * 0x40) + 0x008)
#define IPCMxDSTATUS(m)		(((m) * 0x40) + 0x00C)
#define IPCMxMODE(m)		(((m) * 0x40) + 0x010)
#define IPCMxMSET(m)		(((m) * 0x40) + 0x014)
#define IPCMxMCLEAR(m)		(((m) * 0x40) + 0x018)
#define IPCMxMSTATUS(m)		(((m) * 0x40) + 0x01C)
#define IPCMxSEND(m)		(((m) * 0x40) + 0x020)
#define IPCMxDR(m, dr)		(((m) * 0x40) + ((dr) * 4) + 0x024)

#define IPCMMIS(irq)		(((irq) * 8) + 0x800)
#define IPCMRIS(irq)		(((irq) * 8) + 0x804)

#define MBOX_MASK(n)		(1 << (n))
#define IPC_TX_MBOX		1
#define IPC_RX_MBOX		2

#define CHAN_MASK(n)		(1 << (n))
#define A9_SOURCE		1   /* core 1 表示为A9 core */
#define M3_SOURCE		0 	/* core 0 表示为m3 core */

2 初始化接口

  1. ipc_base = ioremap(adev->res.start, resource_size(&adev->res));依据在设备树中分配设置的ipcm地址做iomap地址映射,用于对pl320 mbox中断控制器做处理。

  2. writel_relaxed(0, ipc_base + IPCMxSEND(IPC_TX_MBOX)); 将当前IPC_TX_MBOX channel的mbox修改为0,表示当前不做数据发送处理。

  3. ret = request_irq(ipc_irq, ipc_handler, 0, dev_name(&adev->dev), NULL); 注册pl320 mbox的中断处理函数

  4. writel_relaxed(CHAN_MASK(A9_SOURCE), ipc_base + IPCMxSOURCE(IPC_TX_MBOX)); 设置IPC_TX_MBOX channel的mbox的源core 为 A9_SOURCE
    在这里插入图片描述

  5. writel_relaxed(CHAN_MASK(M3_SOURCE), ipc_base + IPCMxDSET(IPC_TX_MBOX));设置IPC_TX_MBOX channel的mbox的目的core 为 M3_SOURCE
    在这里插入图片描述

  6. writel_relaxed(CHAN_MASK(M3_SOURCE) | CHAN_MASK(A9_SOURCE), ipc_base + IPCMxMSET(IPC_TX_MBOX));设置IPC_TX_MBOX的收发core的中断使能
    在这里插入图片描述

static int pl320_probe(struct amba_device *adev, const struct amba_id *id)
{
	int ret;

	ipc_base = ioremap(adev->res.start, resource_size(&adev->res));
	if (ipc_base == NULL)
		return -ENOMEM;

	writel_relaxed(0, ipc_base + IPCMxSEND(IPC_TX_MBOX));

	ipc_irq = adev->irq[0];
	ret = request_irq(ipc_irq, ipc_handler, 0, dev_name(&adev->dev), NULL);
	if (ret < 0)
		goto err;

	/* Init slow mailbox */
	writel_relaxed(CHAN_MASK(A9_SOURCE),
		       ipc_base + IPCMxSOURCE(IPC_TX_MBOX));
	writel_relaxed(CHAN_MASK(M3_SOURCE),
		       ipc_base + IPCMxDSET(IPC_TX_MBOX));
	writel_relaxed(CHAN_MASK(M3_SOURCE) | CHAN_MASK(A9_SOURCE),
		       ipc_base + IPCMxMSET(IPC_TX_MBOX));

	/* Init receive mailbox */
	writel_relaxed(CHAN_MASK(M3_SOURCE),
		       ipc_base + IPCMxSOURCE(IPC_RX_MBOX));
	writel_relaxed(CHAN_MASK(A9_SOURCE),
		       ipc_base + IPCMxDSET(IPC_RX_MBOX));
	writel_relaxed(CHAN_MASK(M3_SOURCE) | CHAN_MASK(A9_SOURCE),
		       ipc_base + IPCMxMSET(IPC_RX_MBOX));

	return 0;
err:
	iounmap(ipc_base);
	return ret;
}

3 ipc_handler mbox中断处理函数

  1. irq_stat = readl_relaxed(ipc_base + IPCMMIS(1)); 读取core 1的中断状态寄存器,以判断中断的来源
Masked Interrupt Status Registers:
The read-only IPCMMISx Registers contain the current mailbox status for every interrupt identified by the address encoding. This enables each core to read a single register to determine which mailbox caused the interrupt. For example, if Core0 is mapped to Channel ID0, it reads IPCMMIS0 to determine which mailboxes require attention.
  1. irq_stat & MBOX_MASK(IPC_TX_MBOX) 判断当前的中断是否来自于IPC_TX_MBOX mbox
  2. writel_relaxed(0, ipc_base + IPCMxSEND(IPC_TX_MBOX));清除中断
  3. irq_stat & MBOX_MASK(IPC_RX_MBOX)判断当前的中断是否来自于IPC_RX_MBOX mbox
  4. __ipc_rcv(IPC_RX_MBOX, data);接收数据
  5. writel_relaxed(2, ipc_base + IPCMxSEND(IPC_RX_MBOX));向源core发送ack中断,通知源core已经处理完成当前的mbox中断。
static irqreturn_t ipc_handler(int irq, void *dev)
{
	u32 irq_stat;
	u32 data[7];

	irq_stat = readl_relaxed(ipc_base + IPCMMIS(1));
	if (irq_stat & MBOX_MASK(IPC_TX_MBOX)) {
		writel_relaxed(0, ipc_base + IPCMxSEND(IPC_TX_MBOX));
		complete(&ipc_completion);
	}
	if (irq_stat & MBOX_MASK(IPC_RX_MBOX)) {
		__ipc_rcv(IPC_RX_MBOX, data);
		atomic_notifier_call_chain(&ipc_notifier, data[0], data + 1);
		writel_relaxed(2, ipc_base + IPCMxSEND(IPC_RX_MBOX));
	}

	return IRQ_HANDLED;
}

4 数据的收发

4.1 数据发送

  1. writel_relaxed(data[i], ipc_base + IPCMxDR(mbox, i));将数据写入到对应mbox channel的数据寄存器中。
  2. writel_relaxed(0x1, ipc_base + IPCMxSEND(mbox));向远端目的core发送中断。
The Mailbox Send Register bits can only be written to after the Mailbox Source Register is defined:
• setting bit 0 generates an interrupt to the destination core(s)
• setting bit 1 generates an interrupt to the source core.
static void __ipc_send(int mbox, u32 *data)
{
	int i;
	for (i = 0; i < 7; i++)
		writel_relaxed(data[i], ipc_base + IPCMxDR(mbox, i));
	writel_relaxed(0x1, ipc_base + IPCMxSEND(mbox));
}

4.2 数据接收

数据接收函数是依次从当前mbox的7个数据寄存器中取出数据。

static u32 __ipc_rcv(int mbox, u32 *data)
{
	int i;
	for (i = 0; i < 7; i++)
		data[i] = readl_relaxed(ipc_base + IPCMxDR(mbox, i));
	return data[1];
}

4.3 中断发送接收测试代码

  1. __ipc_send(IPC_TX_MBOX, data);设置数据寄存器要发送的数据,同时触发发送向远端目的core的中断。
  2. wait_for_completion_timeout(&ipc_completion, msecs_to_jiffies(1000));等待中断处理函数完成数据的处理,然后继续执行后面的处理操作。
  3. ret = __ipc_rcv(IPC_TX_MBOX, data);接收数据
int pl320_ipc_transmit(u32 *data)
{
	int ret;

	mutex_lock(&ipc_m1_lock);

	init_completion(&ipc_completion);
	__ipc_send(IPC_TX_MBOX, data);
	ret = wait_for_completion_timeout(&ipc_completion,
					  msecs_to_jiffies(1000));
	if (ret == 0) {
		ret = -ETIMEDOUT;
		goto out;
	}

	ret = __ipc_rcv(IPC_TX_MBOX, data);
out:
	mutex_unlock(&ipc_m1_lock);
	return ret;
}

5 设置以及清除远端目的core

5.1 设置远端目的core

在这里插入图片描述

static inline void set_destination(int source, int mbox)
{
	writel_relaxed(CHAN_MASK(source), ipc_base + IPCMxDSET(mbox));
	writel_relaxed(CHAN_MASK(source), ipc_base + IPCMxMSET(mbox));
}

5.2 清除远端目的core

在这里插入图片描述

static inline void clear_destination(int source, int mbox)
{
	writel_relaxed(CHAN_MASK(source), ipc_base + IPCMxDCLEAR(mbox));
	writel_relaxed(CHAN_MASK(source), ipc_base + IPCMxMCLEAR(mbox));
}

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

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

相关文章

中东地区DNSpionage安全事件分析

事件摘要 思科Talos公司最近发现了一个以影响.gov域名为攻击手段的安全事件&#xff0c;而此安全事件主要针对黎巴嫩和阿拉伯联合酋长国&#xff08;阿联酋&#xff09;以及一家私营的黎巴嫩航空公司。根据我们的研究&#xff0c;攻击者花费了许多时间来了解受害者的基础网络&…

第九章结构性模式—桥接模式

文章目录 桥接模式解决的问题概念结构 实例使用场景 结构型模式描述如何将类或对象按某种布局组成更大的结构&#xff0c;有以下两种&#xff1a; 类结构型模式&#xff1a;采用继承机制来组织接口和类。对象结构型模式&#xff1a;釆用组合或聚合来组合对象。 由于组合关系或…

【数据科学赛】评估大语言模型 #¥65000

CompHub[1] 实时聚合多平台的数据类(Kaggle、天池…)和OJ类(Leetcode、牛客…&#xff09;比赛。本账号会推送最新的比赛消息&#xff0c;欢迎关注&#xff01; 以下信息由AI辅助创作&#xff0c;仅供参考 比赛名称 大语言模型评估[2] (见文末阅读原文) 大赛背景 本次竞赛希…

OTA实现设备升级方案

引言 空中下载技术&#xff08;Over-the-Air Technology&#xff0c; OTA&#xff09;是通过移动通信的空中接口实现对移动终端设备进行远程管理的技术。 该技术在IOT行业非常的重要&#xff0c;当随着市场上的产品越来越多&#xff0c;保有量也越来越多&#xff0c;随着时间…

MySQL 性能调优及生产实战篇(一)

前言数据建模方案、数据类型优化存储引擎选择合理使用范式、反范式字符集选择主键选择适当数据冗余适当拆分数据类型优化更小更好简单就好尽量避免 NULL具体优化细节整型字符、字符串类型datetime、timestamp枚举代替字符串类型特殊类型 索引优化索引用处索引分类技术名词 总结…

由浅入深RPC通信原理实战

目录 1 背景知识2 RPC概述3 RPC框架实现要点3.1 注册中心3.2 代理技术3.3 序列化技术3.4 RPC通信协议3.5 系统IO3.6 超时重试机制3.7 时间轮算法3.8 负载均衡策略3.9 熔断限流3.10 滑动窗口算法3.11 限流组件 1 背景知识 单体架构 RPC产生解决的问题&#xff1a; 序列化是指…

Ae:图层面板 - 视图选项

从图层面板 Layer Panel的“显示通道和色彩管理设置” Show Channel and Color Manage Settings按钮中可以选择各种视图模式&#xff0c;与 Alpha 通道相关的一些视图可直接通过图层面板左下方的按钮或者使用快捷键进行切换。 其它的视图选项&#xff08;图层面板的最下方一行&…

基于PyQt5的图形化界面开发——PyQt示例_扫雷

基于PyQt5的图形化界面开发——PyQt示例_扫雷 前言1. 效果演示2. minesweeper.py3.图片文件其他文章 前言 今天来学习PyQt5的示例&#xff0c;其中主要涉及到一些触发函数窗口切换函数。 操作系统&#xff1a;Windows10 专业版 开发环境&#xff1a;Pycahrm Comunity 2022.3…

三分钟了解Spring Boot启动原理

大家通常只需要给一个类添加一个SpringBootApplication 注解&#xff0c;然后再加一个main 方法里面固定的写法 SpringApplication.run(Application.class, args); 那么spring boot 到底是如何启动服务的呢。 接下来咱们通过源码解析。 Spring Boot 的启动原理可以概括为以下几…

一篇吃透布隆过滤器(Bloom Filter)及其使用场景

目录 1、什么是布隆过滤器 2、布隆过滤器的原理 2.1 布隆过滤器的数据结构 2.2 布隆过滤器的检索和插入原理 2.3 布隆过滤器元素的修改和删除 3、布隆过滤器的使用场景 3.1 Redis通过布隆过滤器防止缓存穿透 3.2 RocketMQ通过布隆过滤器防止消息重复消费 4、布隆过滤器…

DAPP开发(三)——智能合约开发

智能合约 Remix IDE 是开发以太坊智能合约的在线IDE工具&#xff0c;部署简单的智能合约非常方便。 http://remix.ethereum.org truffle 一个世界级的智能合约开发框架&#xff0c;专为智能合约而生。 管理智能合约的生命周期自动化合约测试可编程&#xff0c;可部署&…

linux安装jupyter notebook

目录 使用miniconda的conda安装 切换conda镜像源有两种方法: 设置密码: 修改配置文件: 启动 关闭进程: 使用miniconda的conda安装 conda install jupyter 如果镜像不好用则切换conda镜像源 切换conda镜像源有两种方法: 1. [shuqiqshuqiq bin]$ ./conda config --add…

MyBatis - 基础使用Ⅰ

这篇文章将讲解MyBatis的基础使用&#xff0c;MyBatis的学习是非常重要的&#xff0c;在前面学习servlet的时候&#xff0c;我们就能感受到将数据持久化存储的重要性&#xff0c;当时在使用JDBC的时候非常繁琐麻烦&#xff0c;但是在Spring里&#xff0c;提供了一种框架可以轻松…

真题详解(传引用)-软件设计(七十五)

真题详解&#xff08;补码转换&#xff09;-软件设计&#xff08;七十四)https://blog.csdn.net/ke1ying/article/details/130674214 分治算法技术设计______。 答案&#xff1a;1、问题划分 2、递归求解 3、合并解 虚拟存储体系_____两级构成。 解析&#xff1a;主存 和 辅…

vue项目打包成桌面应用并修改图标

目录 1. 打包为桌面应用 2.修改图标 1. 打包为桌面应用 1.在vux项目的终端执行打包 npm run build 2.会在项目文件夹里面出现一个dist文件夹 里面有这几个文件组成 3.在这里需要添加一个 package.json 文件 package.json 内容 {"name": "鼠标放图标上面的提…

环形链表解释约瑟夫问题

环形链表解释约瑟夫问题 来自尚硅谷开放课程的迁移学习&#xff0c;致敬尚硅谷的各位老师&#xff0c;受益匪浅&#xff01;&#xff01;&#xff01; 单向链表&#xff0c;双向链表&#xff0c;环形链表对比介绍 单向链表、双向链表和环形链表都是常见的链表数据结构&#…

介绍如何在 MySQL 中创建新用户并授予权限?

MySQL 是一个开源的关系型数据库管理系统&#xff0c;常用于存储和管理大量的结构化数据。在使用 MySQL 进行数据管理时&#xff0c;为了安全和方便管理&#xff0c;通常需要创建新用户并授予相应的权限。本文将介绍如何在 MySQL 中创建新用户并授予权限的方法。 创建新用户 在…

第十一章结构性模式—组合模式

文章目录 组合模式解决的问题概念结构 实例组合模式的分类优点使用场景 结构型模式描述如何将类或对象按某种布局组成更大的结构&#xff0c;有以下两种&#xff1a; 类结构型模式&#xff1a;采用继承机制来组织接口和类。 对象结构型模式&#xff1a;釆用组合或聚合来组合对…

shell脚本之“awk“命令

文章目录 1.awk工作原理2.awk命令演示操作部分2.1 按行输出文本演示操作2.2 BEGIN模式演示操作2.3 按字段输出文本演示操作2.4 通过管道、双引号调用Shell命令2.5 date命令演示操作2.6 getline参数详解2.7 awk命令的数组操作 3. 总结 1.awk工作原理 逐行读取文本&#xff0c;默…

位域和字节对齐

结构体中的位域 位域是一种特殊的结构体成员&#xff0c;它允许将一个字节或多个字节中的每个位作为一个独立的成员来使用。位域的语法形式为&#xff1a; struct {type [member_name] : width; }; 其中&#xff0c;type 表示位域成员的类型&#xff0c;可以是 int、unsigne…