0%

前不久在高通 SDM450 平台接触了 voter 机制(投票机制)。最近终于得空,结合一个问题简单研究了一下。现将研究流程简单记录一下,由于时间有限,所以是实用为目的,没有做详细的分析,不过结合着这篇分析和源码一起参考,应该能快速地应用 voter 做一些事情。

voter

第一步是找到 voter 的实现代码,然后分析 voter 的机制。voter 的实现代码主要是为各种 voter 提供接口,我提炼了两个最关键的接口,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# kernel/msm-4.9/drivers/power/supply/qcom/pmic-voter.c
/*
** vote 函数主要用来给 votable 添加投票选项
** votable: 投票的对象
** client_str: 投票者
** enabled: 投票者的内容(val)是否参与投票
** val: 投票内容
**/
int vote(struct votable *votable, const char *client_str, bool enabled, int val)
{
...
switch (votable->type) { // type 的值来自于 create_votable()
case VOTE_MIN: // 取投票对象所有内容的最小值
vote_min(votable, client_id, &effective_result, &effective_id);
break;
case VOTE_MAX:
vote_max(votable, client_id, &effective_result, &effective_id);
break;
case VOTE_SET_ANY:
vote_set_any(votable, client_id,
&effective_result, &effective_id);
break;
...
}

/* 投票相关参数,可以在此文件中搜索此结构体的成员找到其值从哪儿来*/
struct votable {
int type;
...
int (*callback)(struct votable *votable,
}
--->

struct votable *create_votable(const char *name,
int votable_type,
int (*callback)(struct votable *votable,..)
{
// 创建 votable, 引入 votable type 和 callback 函数
...
/* 创建 debugfs*/
debug_root = debugfs_create_dir("pmic-votable", NULL);
...
}
eg: 创建流入电池电流的投票对象
chip->fcc_votable = create_votable("FCC", VOTE_MIN,
pl_fcc_vote_callback,
chip);
Read more »

Add node

此方法只为一个示例,有些平台不是使用此文件,如 SDM450(MSM8953)使用的 dwc3-qcom.c 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# kernel/msm-4.9/drivers/usb/phy/phy-msm-usb.c
@@ -51,6 +51,11 @@

#include <linux/msm-bus.h>

+#undef dev_dbg
+#define dev_dbg dev_info
+#undef pr_debug
+#define pr_debug pr_info
+
/**
* Requested USB votes for BUS bandwidth
*
@@ -3601,6 +3606,53 @@ static int msm_otg_setup_devices(struct
return retval;
}

+
+#define DUMP_ENTRIES 152
+
+static ssize_t usbphy_regs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct msm_otg *motg = the_msm_otg;
+ //struct msm_otg_platform_data *pdata = motg->pdata;
+ struct usb_phy *phy = &motg->phy;
+ u32 *dump;
+ unsigned int i, n = 0;
+ //dbg_trace("[%s] %pK\n", __func__, buf);
+ if (attr == NULL || buf == NULL) {
+ dev_err(dev, "[%s] EINVAL\n", __func__);
+ return 0;
+ }
+ if (atomic_read(&motg->in_lpm)){
+ dev_err(dev, "[%s] usb in lpm\n", __func__);
+ return 0;
+ }
+ dump = kmalloc(sizeof(u8) * DUMP_ENTRIES, GFP_KERNEL);
+ if (!dump)
+ return 0;
+
+ for(i = 0; i < DUMP_ENTRIES -1; i++)
+ dump[i] = ulpi_read(phy, i);
+
+ for (i = 0; i < DUMP_ENTRIES -1; i++) {
+ n += scnprintf(buf + n, PAGE_SIZE - n,
+ "reg[0x%04X] = 0x%04X\n",
+ i, dump[i]);
+ }
+ kfree(dump);
+
+ return n;
+}
+
+static ssize_t usbphy_regs_store(struct device *dev,
+ struct device_attribute *attr, const char
+ *buf, size_t size)
+{
+ return size;
+}
+
+static DEVICE_ATTR(usbphy_regs, 0644,
+ usbphy_regs_show, usbphy_regs_store);
+
static ssize_t dpdm_pulldown_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -4426,6 +4478,7 @@ static int msm_otg_probe(struct platform
motg->caps |= ALLOW_HOST_PHY_RETENTION;

device_create_file(&pdev->dev, &dev_attr_dpdm_pulldown_enable);
+ device_create_file(&pdev->dev, &dev_attr_usbphy_regs);

if (motg->pdata->enable_lpm_on_dev_suspend)
motg->caps |= ALLOW_LPM_ON_DEV_SUSPEND;
@@ -4527,6 +4580,7 @@ otg_remove_devices:
remove_cdev:
pm_runtime_disable(&pdev->dev);
device_remove_file(&pdev->dev, &dev_attr_dpdm_pulldown_enable);
+ device_remove_file(&pdev->dev, &dev_attr_usbphy_regs);
msm_otg_debugfs_cleanup();
phy_reg_deinit:
devm_regulator_unregister(motg->phy.dev, motg->dpdm_rdev);
@@ -4619,6 +4673,7 @@ static int msm_otg_remove(struct platfor
usb_remove_phy(phy);

device_remove_file(&pdev->dev, &dev_attr_dpdm_pulldown_enable);
+ device_remove_file(&pdev->dev, &dev_attr_usbphy_regs);

/*
* Put PHY in low power mode.
Read more »

时光总是匆匆,一转眼 18 年都已经 2 月份了,今天是农历新年前倒数第二天上班了。17 年过得不那么顺畅,自己想做的很多事都没做,很遗憾;18 年自己即将 30 岁,想想还是很惶恐,已到而立之年了。这些时间自己的懒散加上工作上的事情,很久没有写东西了,博客也好久没有更新过了,考虑到今年的状态,和明年一些决定,今天来写个小结,列个计划。

遗憾的 17 年

17 年整体来说对自己是有些失望的,生活上遇到了一件让自己痛心的事情,也完成了人生一件最重要的事情,工作上除了薪资的涨幅,自己没有明显的进步,也没有什么成就感。

Read more »

这真的是一篇简析。。。 (╯_╰) 本来准备详细分析整个 sensor 架构的,实在时间紧张,只能先简析了。

Platform information: MTK6797(X20)+ Android 7.0

Android 支持的传感器

现在 Android 支持多达数十种的各种各样的传感器,支持的类型如下:

Sensor_Type

Android Sensor 架构

Read more »

Android 源码分析系列综述博文: Android 系统源码分析综述

前言

Android/Linux 输入设备总类繁杂,常见的有按键、键盘、触摸屏、鼠标、摇杆等,之前其驱动都是采用字符设备、misc 设备处理的,但是如此多的设备就导致驱动混乱,所以 Linux 引入了输入子系统在字符设备等上抽象出一层来统一输入设备的驱动。本文就基于 MTK Android 7.0 源码来分析一下输入子系统。

输入子系统架构

输入子系统的系统架构如下图所示:
input_system_arch

Framework 层以上只是简单跟了一下源码,没有深入查看

Read more »

Android 源码分析系列综述博文: Android 系统源码分析综述

Platform information: MTK6797(X20)+ Android 7.0

之前做高通的时候,对高通此部分做过粗略的分析,不过当时胡乱做的些笔记,只简单整理了几篇博客,感兴趣可以参考如下路径:

高通平台Android源码bootloader分析之sbl1(一)

高通平台Android源码bootloader分析之sbl1(二)

高通平台Android源码bootloader分析之sbl1(三)

Android不带电量计的电量计算

Android 电源管理架构

Android电池监控系统-BMS-之电池系统架构 (有坑未填)

高通电池管理系统(BMS)驱动分析

高通 smb135x charger 驱动分析

高通 PMIC 架构简析

高通 linear charger 驱动分析

充电简析

充电状态机

电池充电过程分为预充、恒流充电(CC模式)、恒压充电(CV模式)、涓流充电四个流程,MTK的状态机如下:

state

Read more »

由于现做的是MTK平台,源码路径基于MTK, 不过高通大同小异

说明

Android 5.0以后完全引入了 SEAndroid/SELinux 安全机制,这样即使拥有 root 权限或 chmod 777 ,仍然无法再JNI以上访问内核节点。

其实在 Android 4.4 就有限制的启用此安全机制了。后面内容都按照 5.0 以后介绍,4.4 会有些许差异。

SELinux Mode

SELinux 分为两种模式,Android 5.0 后所有进程都使用 enforcing mode。

1
2
enforcing mode: 限制访问
permissive mode: 只审查权限,不限制
Read more »

技术发展越来越快,快充技术也一样,那现在怎么样才能算快充,有哪些快充技术呢?

高通方案

高通 Quick Charge 方案

QC 1.0

最高支持 5V/2A 充电功率(目前已经被划分为慢充),基本都是骁龙 600 平台。

Read more »