* drivers/regulator/max77663-regulator.c
* Maxim LDO and Buck regulators driver
*
- * Copyright 2011 Maxim Integrated Products, Inc.
- * Copyright (C) 2011 NVIDIA Corporation
+ * Copyright 2011-2012 Maxim Integrated Products, Inc.
+ * Copyright (C) 2011-2012 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
/* Regulator types */
#define REGULATOR_TYPE_SD 0
-#define REGULATOR_TYPE_LDO 1
+#define REGULATOR_TYPE_LDO_N 1
+#define REGULATOR_TYPE_LDO_P 2
/* SD and LDO Registers */
#define MAX77663_REG_SD0 0x16
#define MAX77663_REG_LDO7_CFG2 0x32
#define MAX77663_REG_LDO8_CFG 0x33
#define MAX77663_REG_LDO8_CFG2 0x34
+#define MAX77663_REG_LDO_CFG3 0x35
/* Power Mode */
#define POWER_MODE_NORMAL 3
#define SD_FSRADE_MASK 0x01
#define SD_FSRADE_SHIFT 0
+/* LDO Configuration 3 */
+#define TRACK4_MASK 0x20
+#define TRACK4_SHIFT 5
+
/* Voltage */
#define SDX_VOLT_MASK 0xFF
#define SD1_VOLT_MASK 0x3F
u8 val;
};
-struct max77663_regulator {
- struct regulator_dev *rdev;
- struct device *dev;
- struct max77663_regulator_platform_data *pdata;
-
+struct max77663_regulator_info {
u8 id;
u8 type;
u32 min_uV;
u32 max_uV;
u32 step_uV;
- int safe_down_uV; /* for stable down scaling */
- u32 regulator_mode;
struct max77663_register regs[3]; /* volt, cfg, fps */
- enum max77663_regulator_fps_src fps_src;
+
+ struct regulator_desc desc;
u8 volt_mask;
- u8 power_mode;
u8 power_mode_mask;
u8 power_mode_shift;
};
+struct max77663_regulator {
+ struct max77663_regulator_info *rinfo;
+ struct regulator_dev *rdev;
+ struct device *dev;
+ struct max77663_regulator_platform_data *pdata;
+ u32 regulator_mode;
+ u8 power_mode;
+ enum max77663_regulator_fps_src fps_src;
+ u8 val[3]; /* volt, cfg, fps */
+ int safe_down_uV; /* for stable down scaling */
+};
+
#define fps_src_name(fps_src) \
(fps_src == FPS_SRC_0 ? "FPS_SRC_0" : \
fps_src == FPS_SRC_1 ? "FPS_SRC_1" : \
enum max77663_regulator_fps_src fps_src)
{
int ret;
+ struct max77663_regulator_info *rinfo = reg->rinfo;
- if ((reg->regs[FPS_REG].addr == MAX77663_REG_FPS_NONE) ||
+ if ((rinfo->regs[FPS_REG].addr == MAX77663_REG_FPS_NONE) ||
(reg->fps_src == fps_src))
return 0;
return -EINVAL;
}
- ret = max77663_regulator_cache_write(reg, reg->regs[FPS_REG].addr,
+ ret = max77663_regulator_cache_write(reg, rinfo->regs[FPS_REG].addr,
FPS_SRC_MASK, fps_src << FPS_SRC_SHIFT,
- ®->regs[FPS_REG].val);
+ ®->val[FPS_REG]);
if (ret < 0)
return ret;
static int max77663_regulator_set_fps(struct max77663_regulator *reg)
{
struct max77663_regulator_platform_data *pdata = _to_pdata(reg);
+ struct max77663_regulator_info *rinfo = reg->rinfo;
u8 fps_val = 0, fps_mask = 0;
int ret = 0;
- if (reg->regs[FPS_REG].addr == MAX77663_REG_FPS_NONE)
+ if (reg->rinfo->regs[FPS_REG].addr == MAX77663_REG_FPS_NONE)
return 0;
if (reg->fps_src == FPS_SRC_NONE)
fps_mask |= FPS_PD_PERIOD_MASK;
}
- if (fps_val)
+ if (fps_val || fps_mask)
ret = max77663_regulator_cache_write(reg,
- reg->regs[FPS_REG].addr, fps_mask,
- fps_val, ®->regs[FPS_REG].val);
+ rinfo->regs[FPS_REG].addr, fps_mask,
+ fps_val, ®->val[FPS_REG]);
return ret;
}
static int
max77663_regulator_set_power_mode(struct max77663_regulator *reg, u8 power_mode)
{
- u8 mask = reg->power_mode_mask;
- u8 shift = reg->power_mode_shift;
+ struct max77663_regulator_info *rinfo = reg->rinfo;
+ u8 mask = rinfo->power_mode_mask;
+ u8 shift = rinfo->power_mode_shift;
int ret;
- if (reg->type == REGULATOR_TYPE_SD)
+ if (rinfo->type == REGULATOR_TYPE_SD)
ret = max77663_regulator_cache_write(reg,
- reg->regs[CFG_REG].addr,
+ rinfo->regs[CFG_REG].addr,
mask, power_mode << shift,
- ®->regs[CFG_REG].val);
+ ®->val[CFG_REG]);
else
ret = max77663_regulator_cache_write(reg,
- reg->regs[VOLT_REG].addr,
+ rinfo->regs[VOLT_REG].addr,
mask, power_mode << shift,
- ®->regs[VOLT_REG].val);
+ ®->val[VOLT_REG]);
if (ret < 0)
return ret;
static u8 max77663_regulator_get_power_mode(struct max77663_regulator *reg)
{
- u8 mask = reg->power_mode_mask;
- u8 shift = reg->power_mode_shift;
+ struct max77663_regulator_info *rinfo = reg->rinfo;
+ u8 mask = rinfo->power_mode_mask;
+ u8 shift = rinfo->power_mode_shift;
- if (reg->type == REGULATOR_TYPE_SD)
- reg->power_mode = (reg->regs[CFG_REG].val & mask) >> shift;
+ if (rinfo->type == REGULATOR_TYPE_SD)
+ reg->power_mode = (reg->val[CFG_REG] & mask) >> shift;
else
- reg->power_mode = (reg->regs[VOLT_REG].val & mask) >> shift;
+ reg->power_mode = (reg->val[VOLT_REG] & mask) >> shift;
return reg->power_mode;
}
static int max77663_regulator_do_set_voltage(struct max77663_regulator *reg,
int min_uV, int max_uV)
{
- u8 addr = reg->regs[VOLT_REG].addr;
- u8 mask = reg->volt_mask;
- u8 *cache = ®->regs[VOLT_REG].val;
+ struct max77663_regulator_info *rinfo = reg->rinfo;
+ u8 addr = rinfo->regs[VOLT_REG].addr;
+ u8 mask = rinfo->volt_mask;
+ u8 *cache = ®->val[VOLT_REG];
u8 val;
int old_uV, new_uV, safe_uV;
int i, steps = 1;
int ret = 0;
- if (min_uV < reg->min_uV || max_uV > reg->max_uV)
+ if (min_uV < rinfo->min_uV || max_uV > rinfo->max_uV)
return -EDOM;
- old_uV = (*cache & mask) * reg->step_uV + reg->min_uV;
+ old_uV = (*cache & mask) * rinfo->step_uV + rinfo->min_uV;
- if ((old_uV > min_uV) && (reg->safe_down_uV >= reg->step_uV)) {
+ if ((old_uV > min_uV) && (reg->safe_down_uV >= rinfo->step_uV)) {
steps = DIV_ROUND_UP(old_uV - min_uV, reg->safe_down_uV);
safe_uV = -reg->safe_down_uV;
}
if (steps == 1) {
- val = (min_uV - reg->min_uV) / reg->step_uV;
+ val = (min_uV - rinfo->min_uV) / rinfo->step_uV;
ret = max77663_regulator_cache_write(reg, addr, mask, val,
cache);
} else {
reg->rdev->desc->name, i + 1, steps, old_uV,
new_uV);
- val = (new_uV - reg->min_uV) / reg->step_uV;
+ val = (new_uV - rinfo->min_uV) / rinfo->step_uV;
ret = max77663_regulator_cache_write(reg, addr, mask,
val, cache);
if (ret < 0)
static int max77663_regulator_get_voltage(struct regulator_dev *rdev)
{
struct max77663_regulator *reg = rdev_get_drvdata(rdev);
+ struct max77663_regulator_info *rinfo = reg->rinfo;
int volt;
- volt = (reg->regs[VOLT_REG].val & reg->volt_mask)
- * reg->step_uV + reg->min_uV;
+ volt = (reg->val[VOLT_REG] & rinfo->volt_mask)
+ * rinfo->step_uV + rinfo->min_uV;
dev_dbg(&rdev->dev, "get_voltage: name=%s, volt=%d, val=0x%02x\n",
- rdev->desc->name, volt, reg->regs[VOLT_REG].val);
+ rdev->desc->name, volt, reg->val[VOLT_REG]);
return volt;
}
static int max77663_regulator_enable(struct regulator_dev *rdev)
{
struct max77663_regulator *reg = rdev_get_drvdata(rdev);
+ struct max77663_regulator_info *rinfo = reg->rinfo;
struct max77663_regulator_platform_data *pdata = _to_pdata(reg);
int power_mode = (pdata->flags & GLPM_ENABLE) ?
POWER_MODE_GLPM : POWER_MODE_NORMAL;
return 0;
}
- if ((reg->id == MAX77663_REGULATOR_ID_SD0)
+ if ((rinfo->id == MAX77663_REGULATOR_ID_SD0)
&& (pdata->flags & EN2_CTRL_SD0)) {
dev_dbg(&rdev->dev,
"enable: Regulator %s is controlled by EN2\n",
return 0;
}
- if (reg->regulator_mode == REGULATOR_MODE_STANDBY)
+ /* N-Channel LDOs don't support Low-Power mode. */
+ if ((rinfo->type != REGULATOR_TYPE_LDO_N) &&
+ (reg->regulator_mode == REGULATOR_MODE_STANDBY))
power_mode = POWER_MODE_LPM;
return max77663_regulator_set_power_mode(reg, power_mode);
{
struct max77663_regulator *reg = rdev_get_drvdata(rdev);
struct max77663_regulator_platform_data *pdata = _to_pdata(reg);
+ struct max77663_regulator_info *rinfo = reg->rinfo;
int power_mode = POWER_MODE_DISABLE;
if (reg->fps_src != FPS_SRC_NONE) {
return 0;
}
- if ((reg->id == MAX77663_REGULATOR_ID_SD0)
+ if ((rinfo->id == MAX77663_REGULATOR_ID_SD0)
&& (pdata->flags & EN2_CTRL_SD0)) {
dev_dbg(&rdev->dev,
"disable: Regulator %s is controlled by EN2\n",
{
struct max77663_regulator *reg = rdev_get_drvdata(rdev);
struct max77663_regulator_platform_data *pdata = _to_pdata(reg);
+ struct max77663_regulator_info *rinfo = reg->rinfo;
int ret = 1;
if (reg->fps_src != FPS_SRC_NONE) {
return 1;
}
- if ((reg->id == MAX77663_REGULATOR_ID_SD0)
+ if ((rinfo->id == MAX77663_REGULATOR_ID_SD0)
&& (pdata->flags & EN2_CTRL_SD0)) {
dev_dbg(&rdev->dev,
"is_enable: Regulator %s is controlled by EN2\n",
{
struct max77663_regulator *reg = rdev_get_drvdata(rdev);
struct max77663_regulator_platform_data *pdata = _to_pdata(reg);
+ struct max77663_regulator_info *rinfo = reg->rinfo;
u8 power_mode;
int ret;
if (mode == REGULATOR_MODE_NORMAL)
power_mode = (pdata->flags & GLPM_ENABLE) ?
POWER_MODE_GLPM : POWER_MODE_NORMAL;
- else if (mode == REGULATOR_MODE_STANDBY)
- power_mode = POWER_MODE_LPM;
- else
+ else if (mode == REGULATOR_MODE_STANDBY) {
+ /* N-Channel LDOs don't support Low-Power mode. */
+ power_mode = (rinfo->type != REGULATOR_TYPE_LDO_N) ?
+ POWER_MODE_LPM : POWER_MODE_NORMAL;
+ } else
return -EINVAL;
ret = max77663_regulator_set_power_mode(reg, power_mode);
static int max77663_regulator_preinit(struct max77663_regulator *reg)
{
struct max77663_regulator_platform_data *pdata = _to_pdata(reg);
+ struct max77663_regulator_info *rinfo = reg->rinfo;
struct device *parent = _to_parent(reg);
int i;
u8 val, mask;
/* Update registers */
for (i = 0; i <= FPS_REG; i++) {
- ret = max77663_read(parent, reg->regs[i].addr,
- ®->regs[i].val, 1, 0);
+ ret = max77663_read(parent, rinfo->regs[i].addr,
+ ®->val[i], 1, 0);
if (ret < 0) {
dev_err(reg->dev,
"preinit: Failed to get register 0x%x\n",
- reg->regs[i].addr);
+ rinfo->regs[i].addr);
return ret;
}
}
/* Update FPS source */
- if (reg->regs[FPS_REG].addr == MAX77663_REG_FPS_NONE)
+ if (rinfo->regs[FPS_REG].addr == MAX77663_REG_FPS_NONE)
reg->fps_src = FPS_SRC_NONE;
else
- reg->fps_src = (reg->regs[FPS_REG].val & FPS_SRC_MASK)
+ reg->fps_src = (reg->val[FPS_REG] & FPS_SRC_MASK)
>> FPS_SRC_SHIFT;
dev_dbg(reg->dev, "preinit: initial fps_src=%s\n",
/* If metal revision is less than rev.3,
* set safe_down_uV for stable down scaling. */
- if ((reg->type == REGULATOR_TYPE_SD) &&
+ if ((rinfo->type == REGULATOR_TYPE_SD) &&
((val & CID_DIDM_MASK) >> CID_DIDM_SHIFT) <= 2)
reg->safe_down_uV = SD_SAFE_DOWN_UV;
else
return ret;
}
+ /* N-Channel LDOs don't support Low-Power mode. */
+ if ((rinfo->type == REGULATOR_TYPE_LDO_N) &&
+ (pdata->flags & GLPM_ENABLE))
+ pdata->flags &= ~GLPM_ENABLE;
+
/* To prevent power rail turn-off when change FPS source,
* it must set power mode to NORMAL before change FPS source to NONE
* from SRC_0, SRC_1 and SRC_2. */
return ret;
}
- /* Set initial state */
- if (!pdata->init_apply)
- goto skip_init_apply;
-
- if (pdata->init_uV >= 0) {
- ret = max77663_regulator_do_set_voltage(reg, pdata->init_uV,
- pdata->init_uV);
- if (ret < 0) {
- dev_err(reg->dev, "preinit: Failed to set voltage to "
- "%d\n", pdata->init_uV);
- return ret;
- }
- }
-
- if (pdata->init_enable)
- val = (pdata->flags & GLPM_ENABLE) ?
- POWER_MODE_GLPM : POWER_MODE_NORMAL;
- else
- val = POWER_MODE_DISABLE;
-
- ret = max77663_regulator_set_power_mode(reg, val);
- if (ret < 0) {
- dev_err(reg->dev,
- "preinit: Failed to set power mode to %d\n", val);
- return ret;
- }
-
-skip_init_apply:
- if (reg->type == REGULATOR_TYPE_SD) {
+ if (rinfo->type == REGULATOR_TYPE_SD) {
val = 0;
mask = 0;
val |= (SD_SR_100 << SD_SR_SHIFT);
}
- if (pdata->flags & SD_FORCED_PWM_MODE) {
- mask |= SD_FPWM_MASK;
+ mask |= SD_FPWM_MASK;
+ if (pdata->flags & SD_FORCED_PWM_MODE)
val |= SD_FPWM_MASK;
- }
- if (pdata->flags & SD_FSRADE_DISABLE) {
- mask |= SD_FSRADE_MASK;
+ mask |= SD_FSRADE_MASK;
+ if (pdata->flags & SD_FSRADE_DISABLE)
val |= SD_FSRADE_MASK;
- }
ret = max77663_regulator_cache_write(reg,
- reg->regs[CFG_REG].addr, mask, val,
- ®->regs[CFG_REG].val);
+ rinfo->regs[CFG_REG].addr, mask, val,
+ ®->val[CFG_REG]);
if (ret < 0) {
dev_err(reg->dev, "preinit: "
"Failed to set register 0x%x\n",
- reg->regs[CFG_REG].addr);
+ rinfo->regs[CFG_REG].addr);
return ret;
}
- if ((reg->id == MAX77663_REGULATOR_ID_SD0)
+ if ((rinfo->id == MAX77663_REGULATOR_ID_SD0)
&& (pdata->flags & EN2_CTRL_SD0)) {
val = POWER_MODE_DISABLE;
ret = max77663_regulator_set_power_mode(reg, val);
}
}
+ if ((rinfo->id == MAX77663_REGULATOR_ID_LDO4)
+ && (pdata->flags & LDO4_EN_TRACKING)) {
+ val = TRACK4_MASK;
+ ret = max77663_write(parent, MAX77663_REG_LDO_CFG3, &val, 1, 0);
+ if (ret < 0) {
+ dev_err(reg->dev, "preinit: "
+ "Failed to set register 0x%x\n",
+ MAX77663_REG_LDO_CFG3);
+ return ret;
+ }
+ }
+
return 0;
}
.min_uV = _min_uV, \
.max_uV = _max_uV, \
.step_uV = _step_uV, \
- .regulator_mode = REGULATOR_MODE_NORMAL, \
- .power_mode = POWER_MODE_NORMAL, \
.power_mode_mask = SD_POWER_MODE_MASK, \
.power_mode_shift = SD_POWER_MODE_SHIFT, \
+ .desc = { \
+ .name = max77663_rails(_id), \
+ .id = MAX77663_REGULATOR_ID_##_id, \
+ .ops = &max77663_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ }, \
}
-#define REGULATOR_LDO(_id, _min_uV, _max_uV, _step_uV) \
+#define REGULATOR_LDO(_id, _type, _min_uV, _max_uV, _step_uV) \
[MAX77663_REGULATOR_ID_##_id] = { \
.id = MAX77663_REGULATOR_ID_##_id, \
- .type = REGULATOR_TYPE_LDO, \
+ .type = REGULATOR_TYPE_LDO_##_type, \
.volt_mask = LDO_VOLT_MASK, \
.regs = { \
[VOLT_REG] = { \
.min_uV = _min_uV, \
.max_uV = _max_uV, \
.step_uV = _step_uV, \
- .regulator_mode = REGULATOR_MODE_NORMAL, \
- .power_mode = POWER_MODE_NORMAL, \
.power_mode_mask = LDO_POWER_MODE_MASK, \
.power_mode_shift = LDO_POWER_MODE_SHIFT, \
+ .desc = { \
+ .name = max77663_rails(_id), \
+ .id = MAX77663_REGULATOR_ID_##_id, \
+ .ops = &max77663_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ }, \
}
-static struct max77663_regulator max77663_regs[MAX77663_REGULATOR_ID_NR] = {
+static struct max77663_regulator_info max77663_regs_info[MAX77663_REGULATOR_ID_NR] = {
REGULATOR_SD(SD0, SDX, SD0, 600000, 3387500, 12500),
REGULATOR_SD(DVSSD0, SDX, NONE, 600000, 3387500, 12500),
REGULATOR_SD(SD1, SD1, SD1, 800000, 1587500, 12500),
REGULATOR_SD(SD3, SDX, SD3, 600000, 3387500, 12500),
REGULATOR_SD(SD4, SDX, SD4, 600000, 3387500, 12500),
- REGULATOR_LDO(LDO0, 800000, 2350000, 25000),
- REGULATOR_LDO(LDO1, 800000, 2350000, 25000),
- REGULATOR_LDO(LDO2, 800000, 3950000, 50000),
- REGULATOR_LDO(LDO3, 800000, 3950000, 50000),
- REGULATOR_LDO(LDO4, 800000, 1587500, 12500),
- REGULATOR_LDO(LDO5, 800000, 3950000, 50000),
- REGULATOR_LDO(LDO6, 800000, 3950000, 50000),
- REGULATOR_LDO(LDO7, 800000, 3950000, 50000),
- REGULATOR_LDO(LDO8, 800000, 3950000, 50000),
-};
-
-#define REGULATOR_DESC(_id, _name) \
- [MAX77663_REGULATOR_ID_##_id] = { \
- .name = max77663_rails(_name), \
- .id = MAX77663_REGULATOR_ID_##_id, \
- .ops = &max77663_ldo_ops, \
- .type = REGULATOR_VOLTAGE, \
- .owner = THIS_MODULE, \
- }
-
-static struct regulator_desc max77663_rdesc[MAX77663_REGULATOR_ID_NR] = {
- REGULATOR_DESC(SD0, sd0),
- REGULATOR_DESC(DVSSD0, dvssd0),
- REGULATOR_DESC(SD1, sd1),
- REGULATOR_DESC(DVSSD1, dvssd1),
- REGULATOR_DESC(SD2, sd2),
- REGULATOR_DESC(SD3, sd3),
- REGULATOR_DESC(SD4, sd4),
- REGULATOR_DESC(LDO0, ldo0),
- REGULATOR_DESC(LDO1, ldo1),
- REGULATOR_DESC(LDO2, ldo2),
- REGULATOR_DESC(LDO3, ldo3),
- REGULATOR_DESC(LDO4, ldo4),
- REGULATOR_DESC(LDO5, ldo5),
- REGULATOR_DESC(LDO6, ldo6),
- REGULATOR_DESC(LDO7, ldo7),
- REGULATOR_DESC(LDO8, ldo8),
+ REGULATOR_LDO(LDO0, N, 800000, 2350000, 25000),
+ REGULATOR_LDO(LDO1, N, 800000, 2350000, 25000),
+ REGULATOR_LDO(LDO2, P, 800000, 3950000, 50000),
+ REGULATOR_LDO(LDO3, P, 800000, 3950000, 50000),
+ REGULATOR_LDO(LDO4, P, 800000, 1587500, 12500),
+ REGULATOR_LDO(LDO5, P, 800000, 3950000, 50000),
+ REGULATOR_LDO(LDO6, P, 800000, 3950000, 50000),
+ REGULATOR_LDO(LDO7, N, 800000, 3950000, 50000),
+ REGULATOR_LDO(LDO8, N, 800000, 3950000, 50000),
};
static int max77663_regulator_probe(struct platform_device *pdev)
{
+ struct max77663_platform_data *pdata =
+ dev_get_platdata(pdev->dev.parent);
struct regulator_desc *rdesc;
struct max77663_regulator *reg;
+ struct max77663_regulator *max_regs;
+ struct max77663_regulator_platform_data *reg_pdata;
int ret = 0;
+ int id;
+ int reg_id;
+ int reg_count;
- if ((pdev->id < 0) || (pdev->id >= MAX77663_REGULATOR_ID_NR)) {
- dev_err(&pdev->dev, "Invalid device id %d\n", pdev->id);
+ if (!pdata) {
+ dev_err(&pdev->dev, "No Platform data\n");
return -ENODEV;
}
- rdesc = &max77663_rdesc[pdev->id];
- reg = &max77663_regs[pdev->id];
- reg->dev = &pdev->dev;
- reg->pdata = dev_get_platdata(&pdev->dev);
+ reg_count = pdata->num_regulator_pdata;
+ max_regs = devm_kzalloc(&pdev->dev,
+ reg_count * sizeof(*max_regs), GFP_KERNEL);
+ if (!max_regs) {
+ dev_err(&pdev->dev, "mem alloc for reg failed\n");
+ return -ENOMEM;
+ }
- dev_dbg(&pdev->dev, "probe: name=%s\n", rdesc->name);
+ for (id = 0; id < reg_count; ++id) {
+ reg_pdata = pdata->regulator_pdata[id];
+ if (!reg_pdata) {
+ dev_err(&pdev->dev,
+ "Regulator pltform data not there\n");
+ goto clean_exit;
+ }
- ret = max77663_regulator_preinit(reg);
- if (ret) {
- dev_err(&pdev->dev, "probe: Failed to preinit regulator %s\n",
- rdesc->name);
- return ret;
- }
+ reg_id = reg_pdata->id;
+ reg = &max_regs[id];
+ rdesc = &max77663_regs_info[reg_id].desc;
+ reg->rinfo = &max77663_regs_info[reg_id];
+ reg->dev = &pdev->dev;
+ reg->pdata = reg_pdata;
+ reg->regulator_mode = REGULATOR_MODE_NORMAL;
+ reg->power_mode = POWER_MODE_NORMAL;
+
+ dev_dbg(&pdev->dev, "probe: name=%s\n", rdesc->name);
+
+ ret = max77663_regulator_preinit(reg);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to preinit regulator %s\n",
+ rdesc->name);
+ goto clean_exit;
+ }
- reg->rdev = regulator_register(rdesc, &pdev->dev,
- ®->pdata->init_data, reg);
- if (IS_ERR(reg->rdev)) {
- dev_err(&pdev->dev, "probe: Failed to register regulator %s\n",
+ reg->rdev = regulator_register(rdesc, &pdev->dev,
+ reg->pdata->reg_init_data, reg, NULL);
+ if (IS_ERR(reg->rdev)) {
+ dev_err(&pdev->dev, "Failed to register regulator %s\n",
rdesc->name);
- return PTR_ERR(reg->rdev);
+ ret = PTR_ERR(reg->rdev);
+ goto clean_exit;
+ }
}
+ platform_set_drvdata(pdev, max_regs);
return 0;
+
+clean_exit:
+ while (--id >= 0) {
+ reg = &max_regs[id];
+ regulator_unregister(reg->rdev);
+ }
+ return ret;
}
static int max77663_regulator_remove(struct platform_device *pdev)
{
- struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ struct max77663_regulator *max_regs = platform_get_drvdata(pdev);
+ struct max77663_regulator *reg;
+ struct max77663_platform_data *pdata =
+ dev_get_platdata(pdev->dev.parent);
+ int reg_count;
+
+ if (!pdata)
+ return 0;
+
+ reg_count = pdata->num_regulator_pdata;
+ while (--reg_count >= 0) {
+ reg = &max_regs[reg_count];
+ regulator_unregister(reg->rdev);
+ }
- regulator_unregister(rdev);
return 0;
}
.probe = max77663_regulator_probe,
.remove = __devexit_p(max77663_regulator_remove),
.driver = {
- .name = "max77663-regulator",
+ .name = "max77663-pmic",
.owner = THIS_MODULE,
},
};