电源管理之pmu驱动分析

本文详细解析了Linux内核中针对Max77663电源管理单元(PMU)的驱动实现,包括SD和LDO稳压器的初始化配置、电源模式管理、帧频源设置等关键步骤,展示了如何注册和使用regulator以控制电源供应。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


电源管理芯片可以为多设备供电,且这些设备电压电流有所不同。为这些设备提供的稳压器代码模型即为regulator

说白了regulator就是稳压器,它提供电源供给.简单的可以gpio操作,高电平开电,低电平关电.一般的还包括电流值,

电压值等.

一般regulator有两种不同的电源,:ldosd.

Ldo适合电压要求比较稳,但是功率不是很大的设备.

Sd适合功率要求比较大,但可以接受较小的纹波的设备.

除此之外pmu还可能集成,charger,battery,音频功放等等.

 

首先我们分析pmu驱动的平台设备注册部分.

我以max77663这款pmu芯片为分析对象, cpu用的是nvidiategra3

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 =                  \

  {                        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值