[RK3288][Android6.0] PMIC之RK818驱动小结

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
中断的所有事件如下:

[RK3288][Android6.0] PMIC之RK818驱动小结_第1张图片

[RK3288][Android6.0] PMIC之RK818驱动小结_第2张图片


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

你可能感兴趣的:(子类__PMU)