qpnp-regulator: Add support for pm6125 regulators
Add support for HFSMPS, FTSMPS and other LDOs supported on PM6125. Change-Id: I2c9062876417915adeb9e739625adbbc58da8ff4 Signed-off-by: Kavya Nunna <knunna@codeaurora.org>
This commit is contained in:
parent
20fbe1a9a1
commit
5bcb9da72b
@ -53,6 +53,9 @@ enum qpnp_regulator_logical_type {
|
||||
QPNP_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS,
|
||||
QPNP_REGULATOR_LOGICAL_TYPE_ULT_LDO,
|
||||
QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS2,
|
||||
QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3,
|
||||
QPNP_REGULATOR_LOGICAL_TYPE_LDO_510,
|
||||
QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS,
|
||||
};
|
||||
|
||||
enum qpnp_regulator_type {
|
||||
@ -103,6 +106,17 @@ enum qpnp_regulator_subtype {
|
||||
QPNP_REGULATOR_SUBTYPE_ULT_HF_CTL2 = 0x0E,
|
||||
QPNP_REGULATOR_SUBTYPE_ULT_HF_CTL3 = 0x0F,
|
||||
QPNP_REGULATOR_SUBTYPE_ULT_HF_CTL4 = 0x10,
|
||||
QPNP_REGULATOR_SUBTYPE_HFSMPS_510 = 0x0A,
|
||||
QPNP_REGULATOR_SUBTYPE_FTSMPS_510 = 0x0B,
|
||||
QPNP_REGULATOR_SUBTYPE_LV_P150_510 = 0x71,
|
||||
QPNP_REGULATOR_SUBTYPE_LV_P300_510 = 0x72,
|
||||
QPNP_REGULATOR_SUBTYPE_LV_P600_510 = 0x73,
|
||||
QPNP_REGULATOR_SUBTYPE_N300_510 = 0x6A,
|
||||
QPNP_REGULATOR_SUBTYPE_N600_510 = 0x6B,
|
||||
QPNP_REGULATOR_SUBTYPE_N1200_510 = 0x6C,
|
||||
QPNP_REGULATOR_SUBTYPE_MV_P50_510 = 0x7A,
|
||||
QPNP_REGULATOR_SUBTYPE_MV_P150_510 = 0x7B,
|
||||
QPNP_REGULATOR_SUBTYPE_MV_P600_510 = 0x7D,
|
||||
};
|
||||
|
||||
/* First common register layout used by older devices */
|
||||
@ -130,6 +144,11 @@ enum qpnp_common2_regulator_registers {
|
||||
QPNP_COMMON2_REG_STEP_CTRL = 0x61,
|
||||
};
|
||||
|
||||
enum qpnp_common3_regulator_registers {
|
||||
QPNP_COMMON3_REG_STEP_CTRL = 0x3C,
|
||||
};
|
||||
|
||||
|
||||
enum qpnp_ldo_registers {
|
||||
QPNP_LDO_REG_SOFT_START = 0x4C,
|
||||
};
|
||||
@ -191,6 +210,15 @@ enum qpnp_common2_control_register_index {
|
||||
|
||||
#define QPNP_COMMON2_MODE_MASK 0x07
|
||||
|
||||
/* Third common regulator mode register values */
|
||||
#define QPNP_COMMON3_MODE_BYPASS 2
|
||||
#define QPNP_COMMON3_MODE_RETENTION 3
|
||||
#define QPNP_COMMON3_MODE_LPM 4
|
||||
#define QPNP_COMMON3_MODE_AUTO 6
|
||||
#define QPNP_COMMON3_MODE_HPM 7
|
||||
|
||||
#define QPNP_COMMON3_MODE_MASK 0x07
|
||||
|
||||
/* Common regulator pull down control register layout */
|
||||
#define QPNP_COMMON_PULL_DOWN_ENABLE_MASK 0x80
|
||||
|
||||
@ -251,6 +279,9 @@ enum qpnp_common2_control_register_index {
|
||||
#define QPNP_FTSMPS2_STEP_MARGIN_NUM 10
|
||||
#define QPNP_FTSMPS2_STEP_MARGIN_DEN 11
|
||||
|
||||
/* slew_rate has units of uV/us. */
|
||||
#define QPNP_COMMON3_FTSMPS3_SLEW_RATE_38p4 38400
|
||||
|
||||
/*
|
||||
* This voltage in uV is returned by get_voltage functions when there is no way
|
||||
* to determine the current voltage level. It is needed because the regulator
|
||||
@ -451,6 +482,26 @@ static struct qpnp_voltage_range ftsmps426_ranges[] = {
|
||||
VOLTAGE_RANGE(0, 0, 320000, 1352000, 1352000, 4000),
|
||||
};
|
||||
|
||||
static struct qpnp_voltage_range pldo_510_ranges[] = {
|
||||
VOLTAGE_RANGE(0, 1504000, 1504000, 2000000, 2000000, 8000),
|
||||
};
|
||||
|
||||
static struct qpnp_voltage_range mv_pldo_510_ranges[] = {
|
||||
VOLTAGE_RANGE(0, 1504000, 1504000, 3544000, 3544000, 8000),
|
||||
};
|
||||
|
||||
static struct qpnp_voltage_range nldo_510_ranges[] = {
|
||||
VOLTAGE_RANGE(0, 320000, 320000, 1304000, 1304000, 8000),
|
||||
};
|
||||
|
||||
static struct qpnp_voltage_range hfsmps510_ranges[] = {
|
||||
VOLTAGE_RANGE(0, 320000, 320000, 2040000, 2040000, 8000),
|
||||
};
|
||||
|
||||
static struct qpnp_voltage_range ftsmps510_ranges[] = {
|
||||
VOLTAGE_RANGE(0, 300000, 300000, 1372000, 1372000, 4000),
|
||||
};
|
||||
|
||||
static struct qpnp_voltage_set_points pldo_set_points = SET_POINTS(pldo_ranges);
|
||||
static struct qpnp_voltage_set_points nldo1_set_points
|
||||
= SET_POINTS(nldo1_ranges);
|
||||
@ -479,6 +530,16 @@ static struct qpnp_voltage_set_points ult_pldo_set_points
|
||||
= SET_POINTS(ult_pldo_ranges);
|
||||
static struct qpnp_voltage_set_points ftsmps426_set_points
|
||||
= SET_POINTS(ftsmps426_ranges);
|
||||
static struct qpnp_voltage_set_points pldo_510_set_points
|
||||
= SET_POINTS(pldo_510_ranges);
|
||||
static struct qpnp_voltage_set_points mv_pldo_510_set_points
|
||||
= SET_POINTS(mv_pldo_510_ranges);
|
||||
static struct qpnp_voltage_set_points nldo_510_set_points
|
||||
= SET_POINTS(nldo_510_ranges);
|
||||
static struct qpnp_voltage_set_points hfsmps510_set_points
|
||||
= SET_POINTS(hfsmps510_ranges);
|
||||
static struct qpnp_voltage_set_points ftsmps510_set_points
|
||||
= SET_POINTS(ftsmps510_ranges);
|
||||
static struct qpnp_voltage_set_points none_set_points;
|
||||
|
||||
static struct qpnp_voltage_set_points *all_set_points[] = {
|
||||
@ -497,6 +558,11 @@ static struct qpnp_voltage_set_points *all_set_points[] = {
|
||||
&ult_nldo_set_points,
|
||||
&ult_pldo_set_points,
|
||||
&ftsmps426_set_points,
|
||||
&pldo_510_set_points,
|
||||
&mv_pldo_510_set_points,
|
||||
&nldo_510_set_points,
|
||||
&hfsmps510_set_points,
|
||||
&ftsmps510_set_points,
|
||||
};
|
||||
|
||||
/* Determines which label to add to a debug print statement. */
|
||||
@ -1212,12 +1278,27 @@ static int qpnp_regulator_common2_set_mode(struct regulator_dev *rdev,
|
||||
* ensures that AUTO mode is re-asserted after switching away from
|
||||
* forced HPM if it was configured initially.
|
||||
*/
|
||||
if (mode == REGULATOR_MODE_NORMAL)
|
||||
val = QPNP_COMMON2_MODE_HPM;
|
||||
else if (vreg->init_mode == QPNP_COMMON2_MODE_HPM)
|
||||
val = QPNP_COMMON2_MODE_LPM;
|
||||
else
|
||||
val = vreg->init_mode;
|
||||
if ((vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) ||
|
||||
(vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS) ||
|
||||
(vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_LDO_510)) {
|
||||
if (mode == REGULATOR_MODE_NORMAL)
|
||||
val = QPNP_COMMON3_MODE_HPM;
|
||||
else if (vreg->init_mode == QPNP_COMMON3_MODE_HPM &&
|
||||
vreg->logical_type !=
|
||||
QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3)
|
||||
val = QPNP_COMMON3_MODE_LPM;
|
||||
else if (vreg->init_mode == QPNP_COMMON3_MODE_HPM)
|
||||
val = QPNP_COMMON3_MODE_RETENTION;
|
||||
else
|
||||
val = vreg->init_mode;
|
||||
} else {
|
||||
if (mode == REGULATOR_MODE_NORMAL)
|
||||
val = QPNP_COMMON2_MODE_HPM;
|
||||
else if (vreg->init_mode == QPNP_COMMON2_MODE_HPM)
|
||||
val = QPNP_COMMON2_MODE_LPM;
|
||||
else
|
||||
val = vreg->init_mode;
|
||||
}
|
||||
|
||||
rc = qpnp_vreg_write_optimized(vreg, QPNP_COMMON2_REG_MODE, &val,
|
||||
&vreg->ctrl_reg[QPNP_COMMON2_IDX_MODE], 1);
|
||||
@ -1335,6 +1416,18 @@ static const char * const qpnp_common2_mode_label[] = {
|
||||
[QPNP_COMMON2_MODE_HPM] = "HPM",
|
||||
};
|
||||
|
||||
static const char * const qpnp_common3_mode_label[] = {
|
||||
[0] = "RSV",
|
||||
[1] = "RSV",
|
||||
[2] = "RSV",
|
||||
[QPNP_COMMON3_MODE_BYPASS] = "BYP",
|
||||
[QPNP_COMMON3_MODE_RETENTION] = "RET",
|
||||
[QPNP_COMMON3_MODE_LPM] = "LPM",
|
||||
[QPNP_COMMON3_MODE_AUTO] = "AUTO",
|
||||
[QPNP_COMMON3_MODE_HPM] = "HPM",
|
||||
};
|
||||
|
||||
|
||||
static void qpnp_vreg_show_state(struct regulator_dev *rdev,
|
||||
enum qpnp_regulator_action action)
|
||||
{
|
||||
@ -1495,6 +1588,16 @@ static void qpnp_vreg_show_state(struct regulator_dev *rdev,
|
||||
action_label, vreg->rdesc.name, enable_label, uV,
|
||||
mode_label);
|
||||
break;
|
||||
case QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS:
|
||||
case QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3:
|
||||
case QPNP_REGULATOR_LOGICAL_TYPE_LDO_510:
|
||||
mode_reg = vreg->ctrl_reg[QPNP_COMMON_IDX_MODE];
|
||||
mode_label = qpnp_common3_mode_label[mode_reg
|
||||
& QPNP_COMMON3_MODE_MASK];
|
||||
pr_info("%s %-11s: %s, v=%7d uV, mode=%s\n",
|
||||
action_label, vreg->rdesc.name, enable_label, uV,
|
||||
mode_label);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1618,6 +1721,45 @@ static struct regulator_ops qpnp_ftsmps426_ops = {
|
||||
.enable_time = qpnp_regulator_common_enable_time,
|
||||
};
|
||||
|
||||
static struct regulator_ops qpnp_hfsmps510_ops = {
|
||||
.enable = qpnp_regulator_common_enable,
|
||||
.disable = qpnp_regulator_common_disable,
|
||||
.is_enabled = qpnp_regulator_common_is_enabled,
|
||||
.set_voltage = qpnp_regulator_common2_set_voltage,
|
||||
.get_voltage = qpnp_regulator_common2_get_voltage,
|
||||
.list_voltage = qpnp_regulator_common_list_voltage,
|
||||
.set_mode = qpnp_regulator_common2_set_mode,
|
||||
.get_mode = qpnp_regulator_common2_get_mode,
|
||||
.get_optimum_mode = qpnp_regulator_common_get_optimum_mode,
|
||||
.enable_time = qpnp_regulator_common_enable_time,
|
||||
};
|
||||
|
||||
static struct regulator_ops qpnp_ftsmps510_ops = {
|
||||
.enable = qpnp_regulator_common_enable,
|
||||
.disable = qpnp_regulator_common_disable,
|
||||
.is_enabled = qpnp_regulator_common_is_enabled,
|
||||
.set_voltage = qpnp_regulator_common2_set_voltage,
|
||||
.get_voltage = qpnp_regulator_common2_get_voltage,
|
||||
.list_voltage = qpnp_regulator_common_list_voltage,
|
||||
.set_mode = qpnp_regulator_common2_set_mode,
|
||||
.get_mode = qpnp_regulator_common2_get_mode,
|
||||
.get_optimum_mode = qpnp_regulator_common_get_optimum_mode,
|
||||
.enable_time = qpnp_regulator_common_enable_time,
|
||||
};
|
||||
|
||||
static struct regulator_ops qpnp_ldo_510_ops = {
|
||||
.enable = qpnp_regulator_common_enable,
|
||||
.disable = qpnp_regulator_common_disable,
|
||||
.is_enabled = qpnp_regulator_common_is_enabled,
|
||||
.set_voltage = qpnp_regulator_common2_set_voltage,
|
||||
.get_voltage = qpnp_regulator_common2_get_voltage,
|
||||
.list_voltage = qpnp_regulator_common_list_voltage,
|
||||
.set_mode = qpnp_regulator_common2_set_mode,
|
||||
.get_mode = qpnp_regulator_common2_get_mode,
|
||||
.get_optimum_mode = qpnp_regulator_common_get_optimum_mode,
|
||||
.enable_time = qpnp_regulator_common_enable_time,
|
||||
};
|
||||
|
||||
/* Maximum possible digital major revision value */
|
||||
#define INF 0xFF
|
||||
|
||||
@ -1679,8 +1821,27 @@ static const struct qpnp_regulator_mapping supported_regulators[] = {
|
||||
10000),
|
||||
QPNP_VREG_MAP(ULT_LDO, P50, 0, INF, ULT_LDO, ult_ldo, ult_pldo,
|
||||
5000),
|
||||
QPNP_VREG_MAP(FTS, FTS426, 0, INF, FTSMPS2, ftsmps426, ftsmps426,
|
||||
QPNP_VREG_MAP(FTS, FTS426, 0, INF, FTSMPS2, ftsmps426, ftsmps426,
|
||||
100000),
|
||||
QPNP_VREG_MAP(LDO, LV_P150_510, 0, INF, LDO_510, ldo_510, pldo_510,
|
||||
10000),
|
||||
QPNP_VREG_MAP(LDO, LV_P300_510, 0, INF, LDO_510, ldo_510, pldo_510,
|
||||
10000),
|
||||
QPNP_VREG_MAP(LDO, LV_P600_510, 0, INF, LDO_510, ldo_510, pldo_510,
|
||||
10000),
|
||||
QPNP_VREG_MAP(LDO, MV_P50_510, 0, INF, LDO_510, ldo_510, mv_pldo_510,
|
||||
10000),
|
||||
QPNP_VREG_MAP(LDO, MV_P150_510, 0, INF, LDO_510, ldo_510, mv_pldo_510,
|
||||
10000),
|
||||
QPNP_VREG_MAP(LDO, MV_P600_510, 0, INF, LDO_510, ldo_510, mv_pldo_510,
|
||||
10000),
|
||||
QPNP_VREG_MAP(LDO, N300_510, 0, INF, LDO_510, ldo_510, nldo_510, 10000),
|
||||
QPNP_VREG_MAP(LDO, N600_510, 0, INF, LDO_510, ldo_510, nldo_510, 10000),
|
||||
QPNP_VREG_MAP(LDO, N1200_510, 0, INF, LDO_510, ldo_510, nldo_510, 10000),
|
||||
QPNP_VREG_MAP(BUCK, HFSMPS_510, 0, INF, HFSMPS, hfsmps510, hfsmps510,
|
||||
100000),
|
||||
QPNP_VREG_MAP(FTS, FTSMPS_510, 0, INF, FTSMPS3, ftsmps510, ftsmps510,
|
||||
100000),
|
||||
};
|
||||
|
||||
static int qpnp_regulator_match(struct qpnp_regulator *vreg)
|
||||
@ -1792,10 +1953,18 @@ static int qpnp_regulator_ftsmps2_init_slew_rate(struct qpnp_regulator *vreg)
|
||||
int i, rc, delay;
|
||||
u8 reg = 0;
|
||||
|
||||
rc = qpnp_vreg_read(vreg, QPNP_COMMON2_REG_STEP_CTRL, ®, 1);
|
||||
if (rc) {
|
||||
vreg_err(vreg, "spmi read failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
if (vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) {
|
||||
rc = qpnp_vreg_read(vreg, QPNP_COMMON3_REG_STEP_CTRL, ®, 1);
|
||||
if (rc) {
|
||||
vreg_err(vreg, "spmi read failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
rc = qpnp_vreg_read(vreg, QPNP_COMMON2_REG_STEP_CTRL, ®, 1);
|
||||
if (rc) {
|
||||
vreg_err(vreg, "spmi read failed, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1817,14 +1986,18 @@ static int qpnp_regulator_ftsmps2_init_slew_rate(struct qpnp_regulator *vreg)
|
||||
delay = (reg & QPNP_FTSMPS2_STEP_CTRL_DELAY_MASK)
|
||||
>> QPNP_FTSMPS2_STEP_CTRL_DELAY_SHIFT;
|
||||
|
||||
/* slew_rate has units of uV/us. */
|
||||
vreg->slew_rate = QPNP_FTSMPS2_CLOCK_RATE * range->step_uV;
|
||||
vreg->slew_rate /= 1000 * (QPNP_FTSMPS2_STEP_DELAY << delay);
|
||||
vreg->slew_rate = vreg->slew_rate * QPNP_FTSMPS2_STEP_MARGIN_NUM
|
||||
/ QPNP_FTSMPS2_STEP_MARGIN_DEN;
|
||||
if (vreg->logical_type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) {
|
||||
vreg->slew_rate = QPNP_COMMON3_FTSMPS3_SLEW_RATE_38p4 >> delay;
|
||||
} else {
|
||||
/* slew_rate has units of uV/us. */
|
||||
vreg->slew_rate = QPNP_FTSMPS2_CLOCK_RATE * range->step_uV;
|
||||
vreg->slew_rate /= 1000 * (QPNP_FTSMPS2_STEP_DELAY << delay);
|
||||
vreg->slew_rate = vreg->slew_rate * QPNP_FTSMPS2_STEP_MARGIN_NUM
|
||||
/ QPNP_FTSMPS2_STEP_MARGIN_DEN;
|
||||
|
||||
/* Ensure that the slew rate is greater than 0. */
|
||||
vreg->slew_rate = max(vreg->slew_rate, 1);
|
||||
/* Ensure that the slew rate is greater than 0. */
|
||||
vreg->slew_rate = max(vreg->slew_rate, 1);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -1905,6 +2078,35 @@ static int qpnp_regulator_init_registers(struct qpnp_regulator *vreg,
|
||||
= QPNP_COMMON2_MODE_LPM;
|
||||
}
|
||||
|
||||
if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3 ||
|
||||
type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS ||
|
||||
type == QPNP_REGULATOR_LOGICAL_TYPE_LDO_510) {
|
||||
if (pdata->hpm_enable == QPNP_REGULATOR_ENABLE)
|
||||
ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
= QPNP_COMMON3_MODE_HPM;
|
||||
else if (pdata->auto_mode_enable == QPNP_REGULATOR_ENABLE
|
||||
&& type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS)
|
||||
ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
= QPNP_COMMON3_MODE_AUTO;
|
||||
else if (pdata->hpm_enable == QPNP_REGULATOR_DISABLE
|
||||
&& ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
== QPNP_COMMON3_MODE_HPM &&
|
||||
type != QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3)
|
||||
ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
= QPNP_COMMON3_MODE_LPM;
|
||||
else if (pdata->hpm_enable == QPNP_REGULATOR_DISABLE
|
||||
&& ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
== QPNP_COMMON3_MODE_HPM)
|
||||
ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
= QPNP_COMMON3_MODE_RETENTION;
|
||||
else if (pdata->auto_mode_enable == QPNP_REGULATOR_DISABLE
|
||||
&& ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
== QPNP_COMMON2_MODE_AUTO &&
|
||||
type == QPNP_REGULATOR_LOGICAL_TYPE_HFSMPS)
|
||||
ctrl_reg[QPNP_COMMON2_IDX_MODE]
|
||||
= QPNP_COMMON2_MODE_LPM;
|
||||
}
|
||||
|
||||
/* Set up mode pin control. */
|
||||
if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS
|
||||
|| type == QPNP_REGULATOR_LOGICAL_TYPE_LDO)
|
||||
@ -2068,8 +2270,9 @@ static int qpnp_regulator_init_registers(struct qpnp_regulator *vreg,
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the slew rate for FTSMPS2 regulators. */
|
||||
if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS2) {
|
||||
/* Calculate the slew rate for FTSMPS2 and FTSMPS3 regulators. */
|
||||
if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS2 ||
|
||||
type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS3) {
|
||||
rc = qpnp_regulator_ftsmps2_init_slew_rate(vreg);
|
||||
if (rc) {
|
||||
vreg_err(vreg, "failed to initialize step rate, rc=%d\n",
|
||||
|
Loading…
Reference in New Issue
Block a user