[RK3288][Android6.0] PMIC之RK818驱动小结
2016-11-28 10:47
197 查看
Platform: RK3288
OS: Android 6.0
Kernel: 3.10.92
Uboot: v2014.10
uboot部分:
pmic_init -> power_rockchip.c
pmic_rk818_init -> pmic_rk818.c
rk818_parse_dt ->
fdt_get_i2c_info
rk818_i2c_probe ->
i2c_set_bus_num
i2c_init -> //RK818_I2C_SPEED是200K
rk_i2c_init -> //设置复用功能以及clock
rk_i2c_iomux
rk_i2c_set_clk
i2c_probe //探测chip
fdt_for_each_subnode
fdt_regulator_match //依次匹配regulator下的各个电源节点,值存到rk818_reg_matches中
rk818_set_regulator_init -> //当最大和最小电压相同并且设置了regulator-boot-on的话就enable电压.
rk818_regulator_set_voltage //先set再enable
rk818_regulator_enable
rk818_pre_init //enable lcd power以及其他ldo
fg_rk818_init //battery相关,暂时未用.
所以说如果想在uboot中就enable相应的dc/dc或者ldo, 那么在dts要设置成regulator-boot-on以及
regulator-min-microvolt和regulator-max-microvolt要一致.
kernel部分:
rk818_module_init -> rk818.c
rk818_i2c_probe ->
rk818_pre_init
rk818_parse_dt -> //解析和uboot类似,只是最后存放的结构体有些变化和差异.
of_regulator_match -> of_regulator.c
of_get_regulator_init_data ->
of_get_regulation_constraints //获取各个电源下的各项属性.
regulator_register -> core.c//注册所有的regulator
device_register //以名字为regulator.x的方式注册,可以在/sys/class/regulator看到注册的各个regulators.
set_machine_constraints ->
_regulator_do_enable //如果是always_on或者是boot_on就enable起来.
list_add //添加到regulator_list链表中.
rk818_irq_init ->
irq_domain_add_linear //创建一个线性映射的domain, rk818的rtc和battery驱动会用它(用irq_create_mapping()定义).
//相关知识: 中断code用IRQ number(虚拟值)标示,而中断controller用HW ID表示,两者需要转换,当一个模块的
//中断数比较多时,可以通过创建一个映射(IRQ Domain)实现(也就是这里的irq_domain_add_linear()),
//具体的IRQ number如何和HW id对应,就通过irq_create_mapping()定义了,这样就得到对应的IRQ number后
//就可以同样方法用request_threaded_irq()注册中断了.
request_threaded_irq //之前有说过,INT脚会发送过流,过压,RTC等给cpu,中断函数就是这个,注意里面还有中断嵌套会调用对应小模块的中断函数,比如rtc-rk818.c的alarm中断.
mfd_add_devices //添加rtc和battery的platform_device, 接下来就会匹配各自的驱动了,后面再小结对应的驱动.
register_syscore_ops //注册系统关机函数是rk818_shutdown(), 关机跑syscore_shutdown()会调到它.
电压操作:
核心的部分是两个ops, rk818_dcdc_ops和rk818_dcdc_ops,
static struct regulator_ops rk818_ldo_ops = {
.set_voltage = rk818_ldo_set_voltage,
.get_voltage = rk818_ldo_get_voltage,
.list_voltage = rk818_ldo_list_voltage,
.is_enabled = rk818_ldo_is_enabled,
.enable = rk818_ldo_enable,
.disable = rk818_ldo_disable,
.set_suspend_enable =rk818_ldo_suspend_enable,
.set_suspend_disable =rk818_ldo_suspend_disable,
.set_suspend_voltage = rk818_ldo_set_sleep_voltage,
};
static struct regulator_ops rk818_dcdc_ops = {
.set_voltage = rk818_dcdc_set_voltage,
.get_voltage = rk818_dcdc_get_voltage,
.list_voltage= rk818_dcdc_list_voltage,
.is_enabled = rk818_dcdc_is_enabled,
.enable = rk818_dcdc_enable,
.disable = rk818_dcdc_disable,
.get_mode = rk818_dcdc_get_mode,
.set_mode = rk818_dcdc_set_mode,
.set_suspend_enable =rk818_dcdc_suspend_enable,
.set_suspend_disable =rk818_dcdc_suspend_disable,
.set_suspend_mode = rk818_dcdc_set_suspend_mode,
.set_suspend_voltage = rk818_dcdc_set_sleep_voltage,
.set_voltage_time_sel = rk818_dcdc_set_voltage_time_sel,
};
它们按照标准的linux regulator架构注册进系统, 关键的两个函数是set_voltage()以及get_voltage(),
也就是说,系统的电压控制最终全部会调用到这两个函数指针,完成电压设置.
比如rk_camera.c就有用到:
sensor_power_default_cb -> regulator_set_voltage -> rdev->desc->ops->set_voltage -> rk818_ldo_set_voltage
中断部分:
rk818_irq -> rk818-irq.c
rk818_i2c_read //读取中断状态寄存器
irq_find_mapping //找到当前触发的中断
handle_nested_irq -> //处理嵌套中断
action->thread_fn -> chip.c //调用对应中断处理函数,比如触发的是alarm中断.
rk818_alm_irq rtc-rk818.c
中断的所有事件如下:
SYR827:
由于RK818提供的DCDC数量不够使用,系统又另外接了一颗电源输出IC: SYR827, 它用来输出VDD_ARM.
对应的驱动文件: kernel/drivers/regulator/syr82x.c
驱动的原理和rk818一模一样,有兴趣看研究下,这里就不再赘述.
参考:
rk3288/kernel/Documentation/IRQ-domain.txt
http://www.wowotech.net/irq_subsystem/irq-domain.html
OS: Android 6.0
Kernel: 3.10.92
Uboot: v2014.10
uboot部分:
pmic_init -> power_rockchip.c
pmic_rk818_init -> pmic_rk818.c
rk818_parse_dt ->
fdt_get_i2c_info
rk818_i2c_probe ->
i2c_set_bus_num
i2c_init -> //RK818_I2C_SPEED是200K
rk_i2c_init -> //设置复用功能以及clock
rk_i2c_iomux
rk_i2c_set_clk
i2c_probe //探测chip
fdt_for_each_subnode
fdt_regulator_match //依次匹配regulator下的各个电源节点,值存到rk818_reg_matches中
rk818_set_regulator_init -> //当最大和最小电压相同并且设置了regulator-boot-on的话就enable电压.
rk818_regulator_set_voltage //先set再enable
rk818_regulator_enable
rk818_pre_init //enable lcd power以及其他ldo
fg_rk818_init //battery相关,暂时未用.
所以说如果想在uboot中就enable相应的dc/dc或者ldo, 那么在dts要设置成regulator-boot-on以及
regulator-min-microvolt和regulator-max-microvolt要一致.
kernel部分:
rk818_module_init -> rk818.c
rk818_i2c_probe ->
rk818_pre_init
rk818_parse_dt -> //解析和uboot类似,只是最后存放的结构体有些变化和差异.
of_regulator_match -> of_regulator.c
of_get_regulator_init_data ->
of_get_regulation_constraints //获取各个电源下的各项属性.
regulator_register -> core.c//注册所有的regulator
device_register //以名字为regulator.x的方式注册,可以在/sys/class/regulator看到注册的各个regulators.
set_machine_constraints ->
_regulator_do_enable //如果是always_on或者是boot_on就enable起来.
list_add //添加到regulator_list链表中.
rk818_irq_init ->
irq_domain_add_linear //创建一个线性映射的domain, rk818的rtc和battery驱动会用它(用irq_create_mapping()定义).
//相关知识: 中断code用IRQ number(虚拟值)标示,而中断controller用HW ID表示,两者需要转换,当一个模块的
//中断数比较多时,可以通过创建一个映射(IRQ Domain)实现(也就是这里的irq_domain_add_linear()),
//具体的IRQ number如何和HW id对应,就通过irq_create_mapping()定义了,这样就得到对应的IRQ number后
//就可以同样方法用request_threaded_irq()注册中断了.
request_threaded_irq //之前有说过,INT脚会发送过流,过压,RTC等给cpu,中断函数就是这个,注意里面还有中断嵌套会调用对应小模块的中断函数,比如rtc-rk818.c的alarm中断.
mfd_add_devices //添加rtc和battery的platform_device, 接下来就会匹配各自的驱动了,后面再小结对应的驱动.
register_syscore_ops //注册系统关机函数是rk818_shutdown(), 关机跑syscore_shutdown()会调到它.
电压操作:
核心的部分是两个ops, rk818_dcdc_ops和rk818_dcdc_ops,
static struct regulator_ops rk818_ldo_ops = {
.set_voltage = rk818_ldo_set_voltage,
.get_voltage = rk818_ldo_get_voltage,
.list_voltage = rk818_ldo_list_voltage,
.is_enabled = rk818_ldo_is_enabled,
.enable = rk818_ldo_enable,
.disable = rk818_ldo_disable,
.set_suspend_enable =rk818_ldo_suspend_enable,
.set_suspend_disable =rk818_ldo_suspend_disable,
.set_suspend_voltage = rk818_ldo_set_sleep_voltage,
};
static struct regulator_ops rk818_dcdc_ops = {
.set_voltage = rk818_dcdc_set_voltage,
.get_voltage = rk818_dcdc_get_voltage,
.list_voltage= rk818_dcdc_list_voltage,
.is_enabled = rk818_dcdc_is_enabled,
.enable = rk818_dcdc_enable,
.disable = rk818_dcdc_disable,
.get_mode = rk818_dcdc_get_mode,
.set_mode = rk818_dcdc_set_mode,
.set_suspend_enable =rk818_dcdc_suspend_enable,
.set_suspend_disable =rk818_dcdc_suspend_disable,
.set_suspend_mode = rk818_dcdc_set_suspend_mode,
.set_suspend_voltage = rk818_dcdc_set_sleep_voltage,
.set_voltage_time_sel = rk818_dcdc_set_voltage_time_sel,
};
它们按照标准的linux regulator架构注册进系统, 关键的两个函数是set_voltage()以及get_voltage(),
也就是说,系统的电压控制最终全部会调用到这两个函数指针,完成电压设置.
比如rk_camera.c就有用到:
sensor_power_default_cb -> regulator_set_voltage -> rdev->desc->ops->set_voltage -> rk818_ldo_set_voltage
中断部分:
rk818_irq -> rk818-irq.c
rk818_i2c_read //读取中断状态寄存器
irq_find_mapping //找到当前触发的中断
handle_nested_irq -> //处理嵌套中断
action->thread_fn -> chip.c //调用对应中断处理函数,比如触发的是alarm中断.
rk818_alm_irq rtc-rk818.c
中断的所有事件如下:
SYR827:
由于RK818提供的DCDC数量不够使用,系统又另外接了一颗电源输出IC: SYR827, 它用来输出VDD_ARM.
对应的驱动文件: kernel/drivers/regulator/syr82x.c
驱动的原理和rk818一模一样,有兴趣看研究下,这里就不再赘述.
参考:
rk3288/kernel/Documentation/IRQ-domain.txt
http://www.wowotech.net/irq_subsystem/irq-domain.html
相关文章推荐
- [RK3288][Android6.0] PMIC之RK818硬件部分小结
- [RK3288][Android6.0] PMIC之RK818配置说明
- [RK3288][Android6.0] 移植笔记 --- RK818配置不正确导致无法开机调试
- [RK3288][Android6.0] 调试笔记 --- 系统识别不同硬件版本方法
- [RK3288][Android6.0] WIFI接入过程的加密和认证方式小结
- [RK3288][Android6.0] Audio录音HAL层的初始化流程分析
- [RK3288][Android6.0] ALSA的DMA buffer读写位置更新
- [RK3288][Android6.0] Audio的音量计算过程小结
- [RK3288][Android6.0] Audio中的混音过程小结
- [RK3288][Android6.0] WiFi的wifi_bt_common.mk文件说明
- [RK3288][Android6.0] 调试笔记 --- 开机设置默认出厂时间方法
- [RK3288][Android6.0] WiFi之priority计算及使用
- [RK3288][Android6.0] 调试笔记 --- UVC Camera jpg和yuv数据帧dump
- [RK3288][Android6.0] MIPI DSI显示屏移植调试总结
- [RK3288][Android6.0] 关于uboot中logo相关知识点小结
- [RK3288][Android6.0] 调试笔记 --- 低电压引起的关机问题
- [RK3288][Android6.0] 调试笔记 --- pmu(rk818)寄存器读写
- [RK3288][Android6.0] Android中的Properties
- [RK3288][Android6.0] 系统按键驱动流程分析
- [RK3288][Android6.0] 调试笔记 --- 开机动画画面偏移