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

qcom ucsi probe

ucsi glink 注册一个ucsi 设备,和pmic glink进行通信,ucsi作为pmic glink的一个client。

lkml的patch  https://lkml.org/lkml/2023/1/30/233

dtsi中一般会定义 qcom,ucsi-glink 信息,用于和驱动进行匹配

static const struct of_device_id ucsi_match_table[] = {
    {.compatible = "qcom,ucsi-glink"},
    {},
};

static struct platform_driver ucsi_driver = {
    .driver    = {
        .name = "ucsi_glink",
        .of_match_table = ucsi_match_table,
    },
    .probe    = ucsi_probe,
    .remove    = ucsi_remove,
};

module_platform_driver(ucsi_driver);

MODULE_DESCRIPTION("QTI UCSI Glink driver");
MODULE_LICENSE("GPL v2");
 

ucsi probe都进行了哪些工作呢

ucsi_dev 结构解析

struct ucsi_dev {struct device			*dev;struct ucsi			*ucsi;//用于与 UCSI 核心逻辑进行交互。负责处理相关的连接和协议逻辑struct pmic_glink_client	*client;//指向 PMIC GLink 客户端结构体的指针,用于与 PMIC GLink 通信接口进行交互,实现电源管理和通信struct completion		read_ack;struct completion		write_ack;struct completion		sync_write_ack;struct mutex			read_lock;struct mutex			write_lock;struct mutex			notify_lock;struct mutex			state_lock;struct ucsi_read_buf_resp_msg	rx_buf;//存储从设备接收到的数据缓冲区响应消息unsigned long			flags;atomic_t			rx_valid;unsigned long			cmd_requested_flags;struct list_head		constat_info_list;//head ,node is constat_info_entrystruct work_struct		notify_work;//ucsi_qti_notify_workstruct work_struct		setup_work;//ucsi_qti_setup_workstruct work_struct		unregister_work;atomic_t			state;
};

 

static int ucsi_probe(struct platform_device *pdev)
{struct device *dev = &pdev->dev;struct pmic_glink_client_data client_data;struct ucsi_dev *udev;int rc;udev = devm_kzalloc(dev, sizeof(*udev), GFP_KERNEL);//创建并进行初始化if (!udev)return -ENOMEM;INIT_LIST_HEAD(&udev->constat_info_list);INIT_WORK(&udev->notify_work, ucsi_qti_notify_work);INIT_WORK(&udev->setup_work, ucsi_qti_setup_work);INIT_WORK(&udev->unregister_work, ucsi_qti_unregister_work);//注销?销毁mutex_init(&udev->read_lock);mutex_init(&udev->write_lock);mutex_init(&udev->notify_lock);mutex_init(&udev->state_lock);init_completion(&udev->read_ack);init_completion(&udev->write_ack);init_completion(&udev->sync_write_ack);atomic_set(&udev->rx_valid, 0);atomic_set(&udev->state, PMIC_GLINK_STATE_UP);client_data.id = MSG_OWNER_UC;client_data.name = "ucsi";client_data.msg_cb = ucsi_callback;client_data.priv = udev;client_data.state_cb = ucsi_qti_state_cb;udev->client = pmic_glink_register_client(dev, &client_data);//client data->clientif (IS_ERR(udev->client)) {rc = PTR_ERR(udev->client);if (rc != -EPROBE_DEFER)dev_err(dev, "Error in registering with pmic_glink rc=%d\n",rc);return rc;}platform_set_drvdata(pdev, udev);udev->dev = dev;ucsi_ipc_log = ipc_log_context_create(NUM_LOG_PAGES, "ucsi", 0);if (!ucsi_ipc_log)dev_warn(dev, "Error in creating ipc_log_context\n");rc = ucsi_setup(udev);if (rc) {ipc_log_context_destroy(ucsi_ipc_log);ucsi_ipc_log = NULL;pmic_glink_unregister_client(udev->client);}return rc;
}

ucsi_setup的过程如下

static int ucsi_setup(struct ucsi_dev *udev)
{int rc;if (udev->ucsi) {dev_err(udev->dev, "ucsi is not NULL\n");return -EINVAL;//已经有了,不需要创建了}mutex_lock(&udev->state_lock);udev->ucsi = ucsi_create(udev->dev, &ucsi_qti_ops);//createif (IS_ERR(udev->ucsi)) {rc = PTR_ERR(udev->ucsi);dev_err(udev->dev, "ucsi_create failed rc=%d\n", rc);udev->ucsi = NULL;mutex_unlock(&udev->state_lock);return rc;}ucsi_set_drvdata(udev->ucsi, udev);rc = ucsi_register(udev->ucsi);//then 注册if (rc) {dev_err(udev->dev, "ucsi_register failed rc=%d\n", rc);ucsi_destroy(udev->ucsi);udev->ucsi = NULL;mutex_unlock(&udev->state_lock);return rc;}mutex_unlock(&udev->state_lock);return 0;
}

 其中的static const struct ucsi_operations ucsi_qti_ops = {
    .read = ucsi_qti_read,
    .sync_write = ucsi_qti_sync_write,
    .async_write = ucsi_qti_async_write
};

 

/*** ucsi_create - Allocate UCSI instance* @dev: Device interface to the PPM (Platform Policy Manager)* @ops: I/O routines*/
struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops)
{struct ucsi *ucsi;if (!ops || !ops->read || !ops->sync_write || !ops->async_write)return ERR_PTR(-EINVAL);ucsi = kzalloc(sizeof(*ucsi), GFP_KERNEL);//new ucsiif (!ucsi)return ERR_PTR(-ENOMEM);INIT_WORK(&ucsi->resume_work, ucsi_resume_work);INIT_DELAYED_WORK(&ucsi->work, ucsi_init_work);mutex_init(&ucsi->ppm_lock);ucsi->dev = dev;ucsi->ops = ops;//ucsi_qti_opsreturn ucsi;
}

 

*** ucsi_register - Register UCSI interface* @ucsi: UCSI instance*/
int ucsi_register(struct ucsi *ucsi)
{int ret;ret = ucsi->ops->read(ucsi, UCSI_VERSION, &ucsi->version, //read ucsi版本号sizeof(ucsi->version));//ucsi_qti_readif (ret)return ret;if (!ucsi->version)return -ENODEV;queue_delayed_work(system_long_wq, &ucsi->work, 0);//ucsi_init_workreturn 0;
}
static void ucsi_init_work(struct work_struct *work)
{struct ucsi *ucsi = container_of(work, struct ucsi, work.work);int ret;ret = ucsi_init(ucsi);//initif (ret)dev_err(ucsi->dev, "PPM init failed (%d)\n", ret);if (ret == -EPROBE_DEFER) {if (ucsi->work_count++ > UCSI_ROLE_SWITCH_WAIT_COUNT)return;queue_delayed_work(system_long_wq, &ucsi->work,UCSI_ROLE_SWITCH_INTERVAL);}
}
/*** ucsi_init - Initialize UCSI interface* @ucsi: UCSI to be initialized** Registers all ports @ucsi has and enables all notification events.*/
static int ucsi_init(struct ucsi *ucsi)
{struct ucsi_connector *con, *connector;u64 command, ntfy;int ret;int i;/* Reset the PPM */ret = ucsi_reset_ppm(ucsi);if (ret) {dev_err(ucsi->dev, "failed to reset PPM!\n");goto err;}/* Enable basic notifications */ntfy = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR;command = UCSI_SET_NOTIFICATION_ENABLE | ntfy;ret = ucsi_send_command(ucsi, command, NULL, 0);if (ret < 0)goto err_reset;/* Get PPM capabilities */command = UCSI_GET_CAPABILITY;ret = ucsi_send_command(ucsi, command, &ucsi->cap, sizeof(ucsi->cap));//get cap dataif (ret < 0)goto err_reset;if (!ucsi->cap.num_connectors) {ret = -ENODEV;goto err_reset;}/* Allocate the connectors. Released in ucsi_unregister() */connector = kcalloc(ucsi->cap.num_connectors + 1, sizeof(*connector), GFP_KERNEL);if (!connector) {ret = -ENOMEM;goto err_reset;}//创建connector/* Register all connectors */for (i = 0; i < ucsi->cap.num_connectors; i++) {connector[i].num = i + 1;ret = ucsi_register_port(ucsi, &connector[i]);if (ret)goto err_unregister;}/* Enable all notifications */ntfy = UCSI_ENABLE_NTFY_ALL;command = UCSI_SET_NOTIFICATION_ENABLE | ntfy;ret = ucsi_send_command(ucsi, command, NULL, 0);if (ret < 0)goto err_unregister;ucsi->connector = connector;//connetor数组ucsi->ntfy = ntfy;return 0;err_unregister:for (con = connector; con->port; con++) {ucsi_unregister_partner(con);ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);ucsi_unregister_port_psy(con);if (con->wq)destroy_workqueue(con->wq);typec_unregister_port(con->port);con->port = NULL;}kfree(connector);
err_reset:memset(&ucsi->cap, 0, sizeof(ucsi->cap));ucsi_reset_ppm(ucsi);
err:return ret;
}

 

 ucsi_send_command是一个发送命令返回数据的函数,遵循ucsi协议发送命令后读取状态和数据。ppm执行命令后,opm发送ack确认命令收到并正确进行了处理

  • 功能ucsi_send_command 函数主要负责发送一个 UCSI 命令,并在需要时从设备读取响应数据,然后确认命令完成。
  • 锁机制:使用互斥锁 ppm_lock 确保对 UCSI 设备的操作是线程安全的。
  • 命令执行:首先执行命令,并获取命令的长度或相关信息。
  • 数据读取:如果需要,从设备读取数据。
  • 确认命令:执行完命令后确认命令完成。
  • 错误处理:函数通过 goto out 跳转到错误处理标签,确保在发生错误时能够适当释放锁。
  • 返回值:返回命令的长度或其他相关信息,或在出现错误时返回错误代码。

 

int ucsi_send_command(struct ucsi *ucsi, u64 command,void *data, size_t size)
{u8 length;int ret;mutex_lock(&ucsi->ppm_lock);//互斥锁ret = ucsi_exec_command(ucsi, command);if (ret < 0)goto out;length = ret;if (data) {ret = ucsi->ops->read(ucsi, UCSI_MESSAGE_IN, data, size);if (ret)goto out;}ret = ucsi_acknowledge_command(ucsi);if (ret)goto out;ret = length;
out:mutex_unlock(&ucsi->ppm_lock);return ret;
}

 

 

相关文章:

qcom ucsi probe

ucsi glink 注册一个ucsi 设备&#xff0c;和pmic glink进行通信&#xff0c;ucsi作为pmic glink的一个client。 lkml的patch https://lkml.org/lkml/2023/1/30/233 dtsi中一般会定义 qcom,ucsi-glink 信息&#xff0c;用于和驱动进行匹配 static const struct of_device_id …...

flask和redis配合

对于涉及数据提交的场景&#xff0c;比如更新用户信息&#xff0c;你可能会使用POST或PUT请求。但是&#xff0c;这些操作通常与直接从Redis缓存中检索数据不同&#xff0c;因为它们可能涉及到对后端数据库或其他存储系统的修改。并且可能需要将更新后的数据同步回Redis缓存&am…...

深度学习中的早停法

早停法&#xff08;Early Stopping&#xff09;是一种用于防止模型过拟合的技术&#xff0c;在训练过程中监视验证集&#xff08;或者测试集&#xff09;上的损失值。具体设立早停的限制包括两个主要参数&#xff1a; Patience&#xff08;耐心&#xff09;&#xff1a;这是指验…...

科普文:JUC系列之多线程门闩同步器CountDownLatch的使用和源码

CountDownLatch类位于java.util.concurrent包下&#xff0c;利用它可以实现类似计数器的功能。比如有一个任务A&#xff0c;它要等待其他10个线程的任务执行完毕之后才能执行&#xff0c;此时就可以利用CountDownLatch来实现这种功能了。 CountDownLatch是通过一个计数器来实现…...

foreach循环和for循环在PHP中各有什么优势

在PHP中&#xff0c;foreach循环和for循环都是用来遍历数组的常用结构&#xff0c;但它们各有其优势和使用场景。 foreach循环的优势 简化代码&#xff1a;foreach循环提供了一种更简洁的方式来遍历数组&#xff0c;不需要手动控制索引或指针。易于阅读&#xff1a;对于简单的…...

巧用casaos共享挂载自己的外接硬盘为局域网共享

最近入手了个魔改机顶盒&#xff0c;已经刷好了的armbian&#xff0c;虽然是原生的&#xff0c;但是我觉得挺强大的&#xff0c;内置了很多 常用的docker和应用&#xff0c;只需要armbian-software 安装就行&#xff0c;缺点就是emmc太小了。 买到之后第一时间装上了casaos和1p…...

标题:解码“八股文”:助力、阻力,还是空谈?

标题&#xff1a;解码“八股文”&#xff1a;助力、阻力&#xff0c;还是空谈&#xff1f; 在程序员的面试与职场发展中&#xff0c;“八股文”一直是一个备受争议的话题。它既是求职者展示自己技术功底的途径&#xff0c;也是一些公司筛选人才的标准之一。但“八股文”在实际…...

语言无界,沟通无限:2024年好用在线翻译工具推荐

随着技术的发展现在的翻译在线工具从基础词句翻译到复杂的文章翻译都不在话下。为了防止你被五花八门的工具挑花眼&#xff0c;我给你介绍几款我用过的便捷、高效、准确的翻译工具吧。 1.福晰翻译端 链接直通&#xff1a;https://www.foxitsoftware.cn/fanyi/ 这个软件支持…...

【Golang 面试 - 进阶题】每日 3 题(十八)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…...

二分+dp,CF 1993D - Med-imize

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 D - Med-imize 二、解题报告 1、思路分析 对于n < k的情况直接排序就行 对于n > k的情况 最终的序列长度一定是 (n - 1) % k 1 这个序列是原数组的一个子序列 对于该序列的第一个元素&#xff0…...

三十种未授权访问漏洞复现 合集( 三)

未授权访问漏洞介绍 未授权访问可以理解为需要安全配置或权限认证的地址、授权页面存在缺陷&#xff0c;导致其他用户可以直接访问&#xff0c;从而引发重要权限可被操作、数据库、网站目录等敏感信息泄露。---->目录遍历 目前主要存在未授权访问漏洞的有:NFS服务&a…...

数据湖和数据仓库核心概念与对比

随着近几年数据湖概念的兴起&#xff0c;业界对于数据仓库和数据湖的对比甚至争论就一直不断。有人说数据湖是下一代大数据平台&#xff0c;各大云厂商也在纷纷的提出自己的数据湖解决方案&#xff0c;一些云数仓产品也增加了和数据湖联动的特性。但是数据仓库和数据湖的区别到…...

探索WebKit的奥秘:打造高效、兼容的现代网页应用

1. 简介 1.1. 主要特点 WebKit 是一个开源的浏览器引擎,它允许开发者构建高性能、功能丰富的 web 应用程序。WebKit 与 Mozilla Firefox 等使用的 Gecko 引擎、Internet Explorer 使用的 Trident 引擎以及 EdgeHTML 引擎共同构成了现代 web 浏览器的核心技术。 1.2. 学习资…...

【leetcode】平衡二叉树、对称二叉树、二叉树的层序遍历(广度优先遍历)(详解)

Hi~&#xff01;这里是奋斗的明志&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f331;&#x1f331;个人主页&#xff1a;奋斗的明志 &#x1f331;&#x1f331;所属专栏&#xff1a;数据结构、LeetCode专栏 &#x1f4da;本系…...

最短路径算法:Floyd-Warshall算法

引言 在图论中&#xff0c;Floyd-Warshall算法是一种用于计算任意两点之间最短路径的动态规划算法。它适用于加权有向图和无向图&#xff0c;可以处理带有负权重边的图&#xff0c;但要求图中不能有负权重环。本文将详细介绍Floyd-Warshall算法的定义、步骤及其实现。 Floyd-…...

3DM游戏运行库合集离线安装包2024最新版

3DM游戏运行库合集离线安装包是一款由国内最大的游戏玩家论坛社区3DM推出的集成式游戏运行库合集软件&#xff0c;旨在解决玩家在玩游戏时遇到的运行库缺失或错误问题。该软件包含多种常用的系统运行库组件&#xff0c;支持32位和64位操作系统&#xff0c;能够自动识别系统版本…...

【Bigdata】什么是混合型联机分析处理

这是我父亲 日记里的文字 这是他的生命 留下留下来的散文诗 几十年后 我看着泪流不止 可我的父亲已经 老得像一个影子 &#x1f3b5; 许飞《父亲写的散文诗》 混合型联机分析处理&#xff08;Hybrid OLAP&#xff0c;简称 HOLAP&#xff09;是一种结合了多…...

Java 并发编程:volatile 关键字介绍与使用

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 026 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…...

【Spark计算引擎----第三篇(RDD)---《深入理解 RDD:依赖、Spark 流程、Shuffle 与缓存》】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;本阶段和大家一起分享和探索大数据技术Spark—RDD&#xff0c;本篇文章主要讲述了&#xff1a;RDD的依赖、Spark 流程、Shuffle 与缓存等等。欢迎大家一起探索讨论&#xff01;&#xff0…...

四、日志收集loki+ promtail+grafana

一、简介 Loki是受Prometheus启发由Grafana Labs团队开源的水平可扩展&#xff0c;高度可用的多租户日志聚合系统。 开发语言: Google Go。它的设计具有很高的成本效益&#xff0c;并且易于操作。使用标签来作为索引&#xff0c;而不是对全文进行检索&#xff0c;也就是说&…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...