电源管理芯片可以为多设备供电,且这些设备电压电流有所不同。为这些设备提供的稳压器代码模型即为regulator。
说白了regulator就是稳压器,它提供电源供给.简单的可以gpio操作,高电平开电,低电平关电.一般的还包括电流值,
电压值等.
一般regulator有两种不同的电源,即:ldo和sd.
Ldo适合电压要求比较稳,但是功率不是很大的设备.
Sd适合功率要求比较大,但可以接受较小的纹波的设备.
除此之外pmu还可能集成,charger,battery,音频功放等等.
首先我们分析pmu驱动的平台设备注册部分.
我以max77663这款pmu芯片为分析对象, cpu用的是nvidia的tegra3.
Pmu的板级初始化文件:kernel\arch\arm\mach-tegra\board-kai-power.c
主要代码如下:
#define PMC_CTRL 0x0
#define PMC_CTRL_INTR_LOW (1 << 17)
#define REBOOT_FLAG"rebooting"
#define DEVICE_PATH "/dev/block/platform/sdhci-tegra.3/by-name/UDE"
static structregulator_consumer_supply max77663_sd0_supply[] = {
REGULATOR_SUPPLY("vdd_cpu",NULL),
};
static structregulator_consumer_supply max77663_sd1_supply[] = {
REGULATOR_SUPPLY("vdd_core",NULL),
};
static struct regulator_consumer_supplymax77663_sd2_supply[] = {
REGULATOR_SUPPLY("vdd_gen1v8",NULL),
REGULATOR_SUPPLY("avdd_hdmi_pll",NULL),
REGULATOR_SUPPLY("avdd_usb_pll",NULL),
REGULATOR_SUPPLY("avdd_osc",NULL),
REGULATOR_SUPPLY("vddio_sys",NULL),
REGULATOR_SUPPLY("vddio_sdmmc","sdhci-tegra.3"),
REGULATOR_SUPPLY("pwrdet_sdmmc4",NULL),
REGULATOR_SUPPLY("vddio_uart",NULL),
REGULATOR_SUPPLY("pwrdet_uart",NULL),
REGULATOR_SUPPLY("vddio_bb",NULL),
REGULATOR_SUPPLY("pwrdet_bb",NULL),
REGULATOR_SUPPLY("vddio_lcd_pmu",NULL),
REGULATOR_SUPPLY("pwrdet_lcd",NULL),
REGULATOR_SUPPLY("vddio_audio",NULL),
REGULATOR_SUPPLY("pwrdet_audio",NULL),
REGULATOR_SUPPLY("vddio_cam",NULL),
REGULATOR_SUPPLY("pwrdet_cam",NULL),
REGULATOR_SUPPLY("vddio_sdmmc","sdhci-tegra.2"),
REGULATOR_SUPPLY("pwrdet_sdmmc3",NULL),
REGULATOR_SUPPLY("vddio_vi",NULL),
REGULATOR_SUPPLY("pwrdet_vi",NULL),
REGULATOR_SUPPLY("vcore_nand",NULL),
REGULATOR_SUPPLY("pwrdet_nand",NULL),
};
static structregulator_consumer_supply max77663_sd3_supply[] = {
REGULATOR_SUPPLY("vdd_ddr3l_1v35",NULL),
};
static structregulator_consumer_supply max77663_ldo0_supply[] = {
REGULATOR_SUPPLY("vdd_ddr_hs",NULL),
};
static structregulator_consumer_supply max77663_ldo1_supply[] = {
};
static structregulator_consumer_supply max77663_ldo2_supply[] = {
REGULATOR_SUPPLY("vdd_ddr_rx",NULL),
};
static structregulator_consumer_supply max77663_ldo3_supply[] = {
REGULATOR_SUPPLY("vmmc",NULL),
};
static structregulator_consumer_supply max77663_ldo4_supply[] = {
REGULATOR_SUPPLY("vdd_rtc",NULL),
};
static structregulator_consumer_supply max77663_ldo5_supply[] = {
REGULATOR_SUPPLY("vdd_sensor_2v8",NULL),
};
static structregulator_consumer_supply max77663_ldo6_supply[] = {
REGULATOR_SUPPLY("vddio_sdmmc","sdhci-tegra.0"),
REGULATOR_SUPPLY("pwrdet_sdmmc1",NULL),
};
static structregulator_consumer_supply max77663_ldo7_supply[] = {
REGULATOR_SUPPLY("avdd_dsi_csi",NULL),
REGULATOR_SUPPLY("pwrdet_mipi",NULL),
};
static struct regulator_consumer_supplymax77663_ldo8_supply[] = {
REGULATOR_SUPPLY("avdd_plla_p_c_s",NULL),
REGULATOR_SUPPLY("avdd_pllm",NULL),
REGULATOR_SUPPLY("avdd_pllu_d",NULL),
REGULATOR_SUPPLY("avdd_pllu_d2",NULL),
REGULATOR_SUPPLY("avdd_pllx",NULL),
};
static structmax77663_regulator_fps_cfg max77663_fps_cfgs[] = {
{
.src= FPS_SRC_0,
.en_src= FPS_EN_SRC_EN0,
.time_period= FPS_TIME_PERIOD_DEF,
},
{
.src= FPS_SRC_1,
.en_src= FPS_EN_SRC_EN1,
.time_period= FPS_TIME_PERIOD_DEF,
},
{
.src= FPS_SRC_2,
.en_src= FPS_EN_SRC_EN0,
.time_period= FPS_TIME_PERIOD_DEF,
},
};
#define MAX77663_PDATA_INIT(_id,_min_uV, _max_uV, _supply_reg, \
_always_on, _boot_on, _apply_uV, \
_init_apply, _init_enable, _init_uV, \
_fps_src, _fps_pu_period, _fps_pd_period,_flags) \
staticstruct max77663_regulator_platform_data max77663_regulator_pdata_##_id = \
{ \
.init_data= { \
.constraints= { \
.min_uV= _min_uV, \
.max_uV= _max_uV, \
.valid_modes_mask= (REGULATOR_MODE_NORMAL | \
REGULATOR_MODE_STANDBY), \
.valid_ops_mask= (REGULATOR_CHANGE_MODE | \
REGULATOR_CHANGE_STATUS | \
REGULATOR_CHANGE_VOLTAGE), \
.always_on= _always_on, \
.boot_on= _boot_on, \
.apply_uV= _apply_uV, \
}, \
.num_consumer_supplies= \
ARRAY_SIZE(max77663_##_id##_supply), \
.consumer_supplies= max77663_##_id##_supply, \
.supply_regulator= _supply_reg, \
}, \
.init_apply= _init_apply, \
.init_enable= _init_enable, \
.init_uV= _init_uV, \
.fps_src= _fps_src, \
.fps_pu_period= _fps_pu_period, \
.fps_pd_period= _fps_pd_period, \
.fps_cfgs= max77663_fps_cfgs, \
.flags= _flags, \
}
MAX77663_PDATA_INIT(sd0, 600000, 3387500, NULL, 1, 0, 0,0, 0, -1,FPS_SRC_NONE, -1, -1, EN2_CTRL_SD0);
MAX77663_PDATA_INIT(sd1, 800000, 1587500, NULL, 1, 0, 0,1, 1, -1,FPS_SRC_1, FPS_POWER_PERIOD_1, FPS_POWER_PERIOD_6, 0);
MAX77663_PDATA_INIT(sd2, 1800000, 1800000, NULL, 1, 0, 0,1, 1, -1,FPS_SRC_0, -1, -1, 0);
MAX77663_PDATA_INIT(sd3, 600000, 3387500, NULL, 1, 0, 0,1, 1, -1,FPS_SRC_0, -1, -1, 0);
MAX77663_PDATA_INIT(ldo0, 800000,2350000, max77663_rails(sd3), 1, 0, 0,1, 1, -1, FPS_SRC_1, -1, -1, 0);
MAX77663_PDATA_INIT(ldo1, 800000,2350000, max77663_rails(sd3), 0, 0, 0,0, 0, -1, FPS_SRC_NONE, -1, -1, 0);
MAX77663_PDATA_INIT(ldo2, 800000,3950000, NULL, 1, 0, 0,1, 1, -1, FPS_SRC_1, -1, -1, 0);
MAX77663_PDATA_INIT(ldo3, 800000,3950000, NULL, 1, 0, 0,1, 1, -1, FPS_SRC_1, -1, -1, 0);
MAX77663_PDATA_INIT(ldo4, 800000,1587500, NULL, 0, 0, 0,1, 1, 1000000, FPS_SRC_0, -1, -1, LDO4_EN_TRACKING);
MAX77663_PDATA_INIT(ldo5, 800000,2800000, NULL, 0, 0, 0,1, 1, -1, FPS_SRC_NONE, -1, -1, 0);
MAX77663_PDATA_INIT(ldo6, 800000,3950000, NULL, 0, 0, 0,0, 0, -1, FPS_SRC_NONE, -1, -1, 0);
MAX77663_PDATA_INIT(ldo7, 800000,3950000, max77663_rails(sd3), 0, 0, 0,0, 0, -1, FPS_SRC_NONE, -1, -1, 0);
MAX77663_PDATA_INIT(ldo8, 800000,3950000, max77663_rails(sd3), 0, 0, 0,1, 1, -1, FPS_SRC_1, -1, -1, 0);
#define MAX77663_REG(_id, _data) \
{ \
.name= "max77663-regulator", \
.id= MAX77663_REGULATOR_ID_##_id, \
.platform_data= &max77663_regulator_pdata_##_data, \
.pdata_size= sizeof(max77663_regulator_pdata_##_data), \
}
#define MAX77663_RTC() \
{ \
.name= "max77663-rtc", \
.id= 0, \
}
static struct mfd_cellmax77663_subdevs[] = {
MAX77663_REG(SD0,sd0),
MAX77663_REG(SD1,sd1),
MAX77663_REG(SD2,sd2),
MAX77663_REG(SD3,sd3),
MAX77663_REG(LDO0,ldo0),
MAX77663_REG(LDO1,ldo1),
MAX77663_REG(LDO2,ldo2),
MAX77663_REG(LDO3,ldo3),
MAX77663_REG(LDO4,ldo4),
MAX77663_REG(LDO5,ldo5),
MAX77663_REG(LDO6,ldo6),
MAX77663_REG(LDO7,ldo7),
MAX77663_REG(LDO8,ldo8),
MAX77663_RTC(),
};
static structmax77663_gpio_config max77663_gpio_cfgs[] = {
{
.gpio= MAX77663_GPIO0,
.dir= GPIO_DIR_OUT,
.dout= GPIO_DOUT_LOW,
.out_drv= GPIO_OUT_DRV_PUSH_PULL,
.alternate= GPIO_ALT_DISABLE,
},
{
.gpio= MAX77663_GPIO1,
.dir= GPIO_DIR_IN,
.dout= GPIO_DOUT_LOW,
.out_drv= GPIO_OUT_DRV_PUSH_PULL,
.alternate= GPIO_ALT_DISABLE,
},
{
.gpio= MAX77663_GPIO2,
.dir= GPIO_DIR_OUT,
.dout= GPIO_DOUT_HIGH,
.out_drv= GPIO_OUT_DRV_OPEN_DRAIN,
.alternate= GPIO_ALT_DISABLE,
},
{
.gpio= MAX77663_GPIO3,
.dir= GPIO_DIR_OUT,
.dout= GPIO_DOUT_LOW,
.out_drv= GPIO_OUT_DRV_OPEN_DRAIN,
.alternate= GPIO_ALT_ENABLE,
},
{
.gpio= MAX77663_GPIO4,
.dir= GPIO_DIR_OUT,
.dout= GPIO_DOUT_HIGH,
.out_drv= GPIO_OUT_DRV_PUSH_PULL,
.alternate= GPIO_ALT_ENABLE,
},
{
.gpio= MAX77663_GPIO5,
.dir= GPIO_DIR_OUT,
.dout= GPIO_DOUT_LOW,
.out_drv= GPIO_OUT_DRV_PUSH_PULL,
.alternate= GPIO_ALT_DISABLE,
},
{
.gpio= MAX77663_GPIO6,
.dir= GPIO_DIR_IN,
.alternate= GPIO_ALT_DISABLE,
},
{
.gpio= MAX77663_GPIO7,
.dir= GPIO_DIR_OUT,
.dout= GPIO_DOUT_LOW,
.out_drv= GPIO_OUT_DRV_OPEN_DRAIN,
.alternate= GPIO_ALT_DISABLE,
},
};
static structmax77663_platform_data max7763_pdata = {
.irq_base = MAX77663_IRQ_BASE,
.gpio_base = MAX77663_GPIO_BASE,
.flags=SLP_MONITORS_ENABLE|SLP_LPM_ENABLE,
.num_gpio_cfgs = ARRAY_SIZE(max77663_gpio_cfgs),
.gpio_cfgs = max77663_gpio_cfgs,
.num_subdevs = ARRAY_SIZE(max77663_subdevs),
.sub_devices = max77663_subdevs,
.rtc_i2c_addr = 0x68,
.use_power_off = true,
};
static struct i2c_board_info__initdata max77663_regulators[] = {
{
/*The I2C address was determined by OTP factory setting */
I2C_BOARD_INFO("max77663",0x3c),
.irq = INT_EXTERNAL_PMU,
.platform_data = &max7763_pdata,
},
};
static int __initkai_max77663_regulator_init(void)
{
void__iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
u32pmc_ctrl;
/*configure the power management controller to trigger PMU
* interrupts when low */
pmc_ctrl= readl(pmc + PMC_CTRL);
writel(pmc_ctrl| PMC_CTRL_INTR_LOW, pmc + PMC_CTRL);
i2c_register_board_info(4,max77663_regulators,
ARRAY_SIZE(max77663_regulators));
return0;
}
static structregulator_consumer_supply fixed_reg_en_1v8_cam_supply[] = {
REGULATOR_SUPPLY("vdd_1v8_cam1",NULL),
};
static structregulator_consumer_supply fixed_reg_en_cam1_ldo_supply[] = {
REGULATOR_SUPPLY("vdd_cam1",NULL),
};
static structregulator_consumer_supply fixed_reg_en_3v3_sys_a01_supply[] = {
REGULATOR_SUPPLY("vdd_3v3",NULL),
REGULATOR_SUPPLY("vdd_3v3_devices",NULL),
REGULATOR_SUPPLY("debug_cons",NULL),
REGULATOR_SUPPLY("pwrdet_pex_ctl",NULL),
REGULATOR_SUPPLY("vddio_gmi",NULL),
};
static structregulator_consumer_supply fixed_reg_en_avdd_hdmi_usb_a01_supply[] = {
REGULATOR_SUPPLY("avdd_hdmi",NULL),
REGULATOR_SUPPLY("avdd_usb",NULL),
};
static structregulator_consumer_supply fixed_reg_en_vddio_vid_supply[] = {
REGULATOR_SUPPLY("vdd_hdmi_con",NULL),
};
static structregulator_consumer_supply fixed_reg_en_vdd_sdmmc1_supply[] = {
REGULATOR_SUPPLY("vddio_sd_slot","sdhci-tegra.0"),
};
static structregulator_consumer_supply fixed_reg_en_3v3_fuse_supply[] = {
REGULATOR_SUPPLY("vdd_fuse",NULL),
};
/* Macro for defining fixedregulator sub device data */
#define FIXED_SUPPLY(_name)"fixed_reg_"#_name
#define FIXED_REG(_id, _var,_name, _in_supply, _always_on, _boot_on, \
_gpio_nr,_active_high, _boot_state, _millivolts) \
staticstruct regulator_init_data ri_data_##_var = \
{