前言
硬件设计,把sim1的pin脚作为gpio使用,vddsim1是这三个pin的电源域,要想拉高gpio,首先要把电源域拉高。
GPIO160 | SIMCLK1 | VIO_SIM1 |
GPIO161 | SIMDAT1 | VIO_SIM1 |
GPIO162 | SIMRST1 | VIO_SIM1 |
概述
驱动通过regulator_desc结构描述一个regulator
内核中
\include\linux\regulator\driver.h
struct regulator_desc {
const char *name;
const char *supply_name;
const char *of_match;
bool of_match_full_name;
const char *regulators_node;
int (*of_parse_cb)(struct device_node *,
const struct regulator_desc *,
struct regulator_config *);
int id;
unsigned int continuous_voltage_range:1;
unsigned n_voltages;
unsigned int n_current_limits;
const struct regulator_ops *ops;
int irq;
enum regulator_type type;
struct module *owner;
unsigned int min_uV;
unsigned int uV_step;
unsigned int linear_min_sel;
int fixed_uV;
unsigned int ramp_delay;
int min_dropout_uV;
const struct linear_range *linear_ranges;
const unsigned int *linear_range_selectors;
int n_linear_ranges;
const unsigned int *volt_table;
const unsigned int *curr_table;
unsigned int vsel_range_reg;
unsigned int vsel_range_mask;
unsigned int vsel_reg;
unsigned int vsel_mask;
unsigned int vsel_step;
unsigned int csel_reg;
unsigned int csel_mask;
unsigned int apply_reg;
unsigned int apply_bit;
unsigned int enable_reg;
unsigned int enable_mask;
unsigned int enable_val;
unsigned int disable_val;
bool enable_is_inverted;
unsigned int bypass_reg;
unsigned int bypass_mask;
unsigned int bypass_val_on;
unsigned int bypass_val_off;
unsigned int active_discharge_on;
unsigned int active_discharge_off;
unsigned int active_discharge_mask;
unsigned int active_discharge_reg;
unsigned int soft_start_reg;
unsigned int soft_start_mask;
unsigned int soft_start_val_on;
unsigned int pull_down_reg;
unsigned int pull_down_mask;
unsigned int pull_down_val_on;
unsigned int enable_time;
unsigned int off_on_delay;
unsigned int poll_enabled_time;
unsigned int (*of_map_mode)(unsigned int mode);
ANDROID_KABI_RESERVE(1);
};
u-boot中不同的ic有不同的定义,以sc2730为例
u-boot15/drivers/power/regulator/sc2730-regulator.c
struct regulator_desc {
const char *name;
int type; /*BIT4: default on/off(0:off, 1:on); BIT0~3: dcdc/ldo type(0:ldo;2:dcdc)*/
unsigned long pd_set;
u32 pd_set_bit;
unsigned long vol_trm;
u32 vol_trm_bits;
u32 vol_def;
u32 vol_sel_cnt;
u32 vol_sel[2];
};
kernel添加方法
dts添加 节点
arch/arm64/boot/dts/sprd/sc2730.dtsi
+ vddsim1: LDO_VDDSIM1 {
+ regulator-name = "vddsim1";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-ramp-delay = <25000>;
+ regulator-always-on;
+ };
驱动添加regulator_desc
drivers/regulator/sc2730-regulator.c
+#define SC2730_LDO_VDDSIM1_PD (SC2730_REGULATOR_BASE + 0x188)
+#define SC2730_LDO_VDDSIM1_PD_MASK BIT(0)
+#define SC2730_LDO_VDDSIM1_VOL (SC2730_REGULATOR_BASE + 0x18c)
+#define SC2730_LDO_VDDSIM1_VOL_MASK GENMASK(7, 0)
static struct regulator_desc regulators[]中添加
+ SC2730_REGU_LINEAR(LDO_VDDSIM1, SC2730_LDO_VDDSIM1_PD,
+ SC2730_LDO_VDDSIM1_PD_MASK, SC2730_LDO_VDDSIM1_VOL,
+ SC2730_LDO_VDDSIM1_VOL_MASK, 10000, 1200000, 3750000,
+ 0),
宏SC2730_LDO_VDDSIM1_PD和SC2730_LDO_VDDSIM1_VOL的定义要参考芯片的datasheet,也可以在代码中找找偏置的值,我是在bootloader中找到的
u-boot15/include/power/sprd_pmic/__regs_ana_sc2730_glb.h
#define ANA_REG_GLB_LDO_VDDSIM0_REG0 (CTL_BASE_ANA_GLB + 0x017C)
#define ANA_REG_GLB_LDO_VDDSIM0_REG1 (CTL_BASE_ANA_GLB + 0x0180)
#define ANA_REG_GLB_LDO_VDDSIM0_REG2 (CTL_BASE_ANA_GLB + 0x0184)
#define ANA_REG_GLB_LDO_VDDSIM1_REG0 (CTL_BASE_ANA_GLB + 0x0188)
#define ANA_REG_GLB_LDO_VDDSIM1_REG1 (CTL_BASE_ANA_GLB + 0x018C)
#define ANA_REG_GLB_LDO_VDDSIM1_REG2 (CTL_BASE_ANA_GLB + 0x0190)
#define ANA_REG_GLB_LDO_VDDSIM2_REG0 (CTL_BASE_ANA_GLB + 0x0194)
#define ANA_REG_GLB_LDO_VDDSIM2_REG1 (CTL_BASE_ANA_GLB + 0x0198)
#define ANA_REG_GLB_LDO_VDDSIM2_REG2 (CTL_BASE_ANA_GLB + 0x019C)
添加成功后就可以通过adb看到相应的文件,向enable写1,就可以打开regular
kfb# ls d/LDO_VDDSIM1
enable voltage
kfb# cat d/LDO_VDDSIM1/enable
0
kfb# cat d/LDO_VDDSIM1/voltage
1800
kfb# echo 1 > d/LDO_VDDSIM1/enable
u-boot添加方法
driver/power/regulator/sc2730-regulator.c
在static struct regulator_desc sc2730_regs_desc[] 中添加
driver/power/regulator/__sc2730_regulator_map.h
添加宏初始化SCI_REGU_REG