项目情况:
pmic 的 vcamio_pmu ,vcama2_pmu,vcamd_pmu 这几个供电引脚默认情况下并未打开,项目中一些外设的电源由这几个引脚提供需要系统启动时默认打开
这里有两种方法打开这些供电引脚,第一种在kernel阶段pmic regulator驱动初始化时打开,另外一种在preloader阶段pmic初始化时打开
一.系统启动后在kernel阶段通过 pmic的 regulator 驱动的初始化阶段打开这些引脚的电源
驱动源码路径:
/kernel-4.14/drivers/regulator/mt6358-regulator.c
mt6358_regulator_probe
{
→ for (i = 0; i < regulator_init_data->size; i++)
rdev = devm_regulator_register(&pdev->dev,
&(mt_regulators + i)->desc, &config);
//通过devm_regulator_register 注册 regulator
}
regulator_register(struct device *dev,
const struct regulator_desc *regulator_desc,
const struct regulator_config *config)
{
→ rdev = regulator_register(regulator_desc, config);
→ init_data = regulator_of_get_init_data(dev, regulator_desc, config
&rdev->dev.of_node);
→ for_each_available_child_of_node(search, child) {
....
init_data = of_get_regulator_init_data(dev, child, desc);
//获取设备树信息进行初始化配置regulator
}
→ ret = set_machine_constraints(rdev, constraints);
→ if (rdev->constraints->always_on || rdev->constraints->boot_on)
ret = _regulator_do_enable(rdev);
//根据 boot_on参数调用 _regulator_do_enable使能regulator从而使对应引
//脚输出电压
}
boot_on参数的初始化:
of_get_regulator_init_data(dev, child, desc);
{
→ of_get_regulation_constraints(node, &init_data, desc);
→ constraints->boot_on = of_property_read_bool(np, "regulator-boot-on");
//根据设备树节点regulator-boot-on 初始化boot_on属性
}
即在对应的vcamio ,vcamd或者vcama2的设备树节点加入 regulator-boot-on 属性即可在kernel阶段pmic初始化regulators时让其供电
例:
mt_pmic_vcamd_ldo_reg: ldo_vcamd {
regulator-name = "vcamd";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1800000>;
regulator-enable-ramp-delay = <270>;
regulator-boot-on; //加入此属性即可
};
二.preloader阶段 pmic初始化时打开 vcamio, vcamd, vcama2
目录:/vendor/mediatek/proprietary/bootable/bootloader/preloader
preloader目录下涉及的文件:
platform/mt6768/src/drivers/inc/mt6358.h
platform/mt6768/src/drivers/mt6358.c
platform/mt6768/src/drivers/pmic_initial_setting.c
此处以打开vcamio为例,vcamd 以及vcama2打开的步骤与之相同
1./platform/mt6768/src/drivers/inc/mt6358.h
1.1.添加对应的id:
enum {
MTK_REGULATOR_VDRAM2,
MTK_REGULATOR_LDO_SUPPORT = MTK_REGULATOR_VDRAM2,
MTK_REGULATOR_VIO18,
+ MTK_REGULATOR_VCAMIO, //添加id
.......
};
1.2 添加寄存器,电压参数:
+ #define vcamio_vol_reg PMIC_RG_VCAMIO_VOCAL_ADDR
+ #define vcamio_vol_mask 0
+ #define vcamio_vol_shift 0
+ #define vcamio_da_vol_reg 0
+ #define vcamio_da_vol_mask 0
+ #define vcamio_da_vol_shift 0
+ #define vcamio_enable_reg PMIC_RG_LDO_VCAMIO_EN_ADDR
+ #define vcamio_enable_shift PMIC_RG_LDO_VCAMIO_EN_SHIFT
+ #define vcamio_mode_reg 0
+ #define vcamio_mode_shift 0
+ #define vcamio_trim_reg PMIC_RG_VCAMIO_VOTRIM_ADDR
+ #define vcamio_trim_mask PMIC_RG_VCAMIO_VOTRIM_MASK
+ #define vcamio_trim_shift PMIC_RG_VCAMIO_VOTRIM_SHIFT
+ #define vcamio_min_uV 1800000
+ #define vcamio_max_uV 1800000
+ #define vcamio_step_uV 0
+ #define vcamio_volt_type FIXED_REGULAR_VOLTAGE
+ #define vcamio_stb 270
preloader下的platform/mt6768/src/drivers/inc/upmu_hw.h文件定义了
PMIC_RG_VCAMIO_VOCAL_ADDR ,PMIC_RG_LDO_VCAMIO_EN_ADDR 这些寄存器
按照具体需求进行修改对应的寄存器
vcamio_min_uV ,vcamio_max_uV,vcamio_stb 这三参数的数值可以按照pmic的dtsi文件去填写
例:
.kernel-4.14/arch/arm64/boot/dts/mediatek/mt6358.dtsi
vcamio的节点信息:
mt_pmic_vcamio_ldo_reg: ldo_vcamio {
compatible = "regulator-fixed";
regulator-name = "vcamio";
regulator-min-microvolt = <1800000>; //vcamio_min_uV
regulator-max-microvolt = <1800000>; //vcamio_max_uV
regulator-enable-ramp-delay = <270>; //vcamio_stb
};
vcamio_volt_type 可以依据kernel阶段vcamio regulator的定义类型进行赋值
例:
/drivers/regulator/mt6358-regulator.c
MT_REG_FIXED("ldo_vcamio", VCAMIO, PMIC_RG_LDO_VCAMIO_EN_ADDR,
PMIC_DA_VCAMIO_EN_ADDR,
1800000, MT_LDO_EN),
MT_REG_FIXED接口定义的是fixed这种类型的所以:
#define vcamio_volt_type FIXED_REGULAR_VOLTAGE
2. /platform/mt6768/src/drivers/mt6358.c
2.1 添加电压配置:
+static const unsigned int vcamio_volts[] = {
+ 1800000,
+};
+static const int vcamio_idxs[] = {
+ 0,
+};
static struct mt6358_ldo_info ldo_ext_info[] = {
mt6358_ldo_decl(vdram2_volts, vdram2_idxs),
mt6358_ldo_decl(vio18_volts, fix_idxs),
+ mt6358_ldo_decl(vcamio_volts, vcamio_idxs),
};
static struct mt6358_regulator_info mt6358_regu_info[] = {
#ifdef LDO_SUPPORT
mt6358_decl(vdram2),
mt6358_decl(vio18),
+ mt6358_decl(vcamio),
#endif /*--LDO_SUPPORT--*/
#endif /*--CFG_MTK_TINYSYS_SSPM_SUPPORT--*/
};
static struct mtk_regulator mt6358_regulator[] = {
.id = MTK_REGULATOR_VIO18,
.reg_ops = &mt6358_regulator_ctrl,
},
+ {
+ .name = "vcamio",
+ .id = MTK_REGULATOR_VCAMIO,
+ .reg_ops = &mt6358_regulator_ctrl,
+ },
#endif /*--LDO_SUPPORT--*/
#endif /*--CFG_MTK_TINYSYS_SSPM_SUPPORT--*/
};
vcamio_volts,以及vcamio_idxs 可以依据kernel阶段vcamio regulator的定义类型进行定义
例:
/drivers/regulator/mt6358-regulator.c
static const u32 vcamio_voltages[] = {
1800000,
};
vcamio_volts 与vcamio_voltages定义一致即可,1800000是vcamio_voltages中的第一个元素
index:0所以vcamio_idxs一个元素初始化为0
3./platform/mt6768/src/drivers/pmic_initial_setting.c
3.1 pmic初始化阶段添加vcamio enable操作打开vcamio
void pmic_default_voltage(void)
{
struct mtk_regulator reg_vproc12 = empty_regulator;
struct mtk_regulator reg_vgpu = empty_regulator;
struct mtk_regulator reg_vmodem = empty_regulator;
+
+#ifdef LDO_SUPPORT
+ struct mtk_regulator reg_vcamio = empty_regulator;
+#endif
int vmodem_vol = 750000, vproc11_vol = 962500, vproc12_vol = 962500,
vsram_proc11_vol = 1062500, vsram_proc12_vol = 1062500;
.............
if (mtk_regulator_get("vmodem", ®_vmodem))
ret |= (1 << MTK_REGULATOR_VMODEM);
-
+#ifdef LDO_SUPPORT
+ if (mtk_regulator_get("vcamio", ®_vcamio))
+ ret |= (1 << MTK_REGULATOR_VCAMIO);
+
+#endif
if (ret) {
pal_log_err("mtk_regulator_get failed.(0x%x)\n", ret);
return;
..............
pal_log_info("vproc12 = %d uV\n",mtk_regulator_get_voltage(®_vproc12));
pal_log_info("vgpu = %d uV\n", mtk_regulator_get_voltage(®_vgpu));
pal_log_info("vmodem = %d uV\n", mtk_regulator_get_voltage(®_vmodem));
+#ifdef LDO_SUPPORT
+ if (mtk_regulator_enable(®_vcamio, 1))
+ ret |= (1 << MTK_REGULATOR_VCAMIO); //打开vcamio
+#endif
}