regulator: da9121: Add DA914x support

Add the DA9141 and DA9142 regulators device recognition data and
operational parameters.

Signed-off-by: Adam Ward <Adam.Ward.opensource@diasemi.com>
Link: https://lore.kernel.org/r/5f5b9b02f07578cd36c6bc266349a56efc9b08d1.1638223185.git.Adam.Ward.opensource@diasemi.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Adam Ward 2021-11-29 22:10:13 +00:00 committed by Mark Brown
parent 24f0853228
commit c5187a245e
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
2 changed files with 124 additions and 5 deletions

View File

@ -86,6 +86,22 @@ static struct da9121_range da9121_3A_1phase_current = {
.reg_max = 6,
};
static struct da9121_range da914x_40A_4phase_current = {
.val_min = 14000000,
.val_max = 80000000,
.val_stp = 2000000,
.reg_min = 1,
.reg_max = 14,
};
static struct da9121_range da914x_20A_2phase_current = {
.val_min = 7000000,
.val_max = 40000000,
.val_stp = 2000000,
.reg_min = 1,
.reg_max = 14,
};
struct da9121_variant_info {
int num_bucks;
int num_phases;
@ -97,6 +113,8 @@ static const struct da9121_variant_info variant_parameters[] = {
{ 2, 1, &da9121_3A_1phase_current }, //DA9121_TYPE_DA9220_DA9132
{ 2, 1, &da9121_5A_1phase_current }, //DA9121_TYPE_DA9122_DA9131
{ 1, 2, &da9121_6A_2phase_current }, //DA9121_TYPE_DA9217
{ 1, 4, &da914x_40A_4phase_current }, //DA9121_TYPE_DA9141
{ 1, 2, &da914x_20A_2phase_current }, //DA9121_TYPE_DA9142
};
struct da9121_field {
@ -542,11 +560,65 @@ static const struct regulator_desc da9217_reg = {
.vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT,
};
#define DA914X_MIN_MV 500
#define DA914X_MAX_MV 1000
#define DA914X_STEP_MV 10
#define DA914X_MIN_SEL (DA914X_MIN_MV / DA914X_STEP_MV)
#define DA914X_N_VOLTAGES (((DA914X_MAX_MV - DA914X_MIN_MV) / DA914X_STEP_MV) \
+ 1 + DA914X_MIN_SEL)
static const struct regulator_desc da9141_reg = {
.id = DA9121_IDX_BUCK1,
.name = "DA9141",
.of_match = "buck1",
.of_parse_cb = da9121_of_parse_cb,
.owner = THIS_MODULE,
.regulators_node = of_match_ptr("regulators"),
.of_map_mode = da9121_map_mode,
.ops = &da9121_buck_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = DA914X_N_VOLTAGES,
.min_uV = DA914X_MIN_MV * 1000,
.uV_step = DA914X_STEP_MV * 1000,
.linear_min_sel = DA914X_MIN_SEL,
.vsel_reg = DA9121_REG_BUCK_BUCK1_5,
.vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT,
.enable_reg = DA9121_REG_BUCK_BUCK1_0,
.enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN,
/* Default value of BUCK_BUCK1_0.CH1_SRC_DVC_UP */
.ramp_delay = 20000,
/* tBUCK_EN */
.enable_time = 20,
};
static const struct regulator_desc da9142_reg = {
.id = DA9121_IDX_BUCK1,
.name = "DA9142 BUCK1",
.of_match = "buck1",
.of_parse_cb = da9121_of_parse_cb,
.owner = THIS_MODULE,
.regulators_node = of_match_ptr("regulators"),
.of_map_mode = da9121_map_mode,
.ops = &da9121_buck_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = DA914X_N_VOLTAGES,
.min_uV = DA914X_MIN_MV * 1000,
.uV_step = DA914X_STEP_MV * 1000,
.linear_min_sel = DA914X_MIN_SEL,
.enable_reg = DA9121_REG_BUCK_BUCK1_0,
.enable_mask = DA9121_MASK_BUCK_BUCKx_0_CHx_EN,
.vsel_reg = DA9121_REG_BUCK_BUCK1_5,
.vsel_mask = DA9121_MASK_BUCK_BUCKx_5_CHx_A_VOUT,
};
static const struct regulator_desc *local_da9121_regulators[][DA9121_IDX_MAX] = {
[DA9121_TYPE_DA9121_DA9130] = { &da9121_reg, NULL },
[DA9121_TYPE_DA9220_DA9132] = { &da9220_reg[0], &da9220_reg[1] },
[DA9121_TYPE_DA9122_DA9131] = { &da9122_reg[0], &da9122_reg[1] },
[DA9121_TYPE_DA9217] = { &da9217_reg, NULL },
[DA9121_TYPE_DA9141] = { &da9141_reg, NULL },
[DA9121_TYPE_DA9142] = { &da9142_reg, NULL },
};
static void da9121_status_poll_on(struct work_struct *work)
@ -840,7 +912,7 @@ static int da9121_check_device_type(struct i2c_client *i2c, struct da9121 *chip)
goto error;
}
if (device_id != DA9121_DEVICE_ID) {
if ((device_id != DA9121_DEVICE_ID) && (device_id != DA914x_DEVICE_ID)) {
dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id);
ret = -ENODEV;
goto error;
@ -882,6 +954,22 @@ static int da9121_check_device_type(struct i2c_client *i2c, struct da9121 *chip)
break;
}
if (device_id == DA914x_DEVICE_ID) {
switch (chip->subvariant_id) {
case DA9121_SUBTYPE_DA9141:
type = "DA9141";
config_match = (variant_vrc == DA9141_VARIANT_VRC);
break;
case DA9121_SUBTYPE_DA9142:
type = "DA9142";
config_match = (variant_vrc == DA9142_VARIANT_VRC);
break;
default:
type = "Unknown";
break;
}
}
dev_info(chip->dev,
"Device detected (device-ID: 0x%02X, var-ID: 0x%02X, %s)\n",
device_id, variant_id, type);
@ -895,8 +983,10 @@ static int da9121_check_device_type(struct i2c_client *i2c, struct da9121 *chip)
variant_mrc = (variant_id & DA9121_MASK_OTP_VARIANT_ID_MRC)
>> DA9121_SHIFT_OTP_VARIANT_ID_MRC;
if ((device_id == DA9121_DEVICE_ID) &&
(variant_mrc < DA9121_VARIANT_MRC_BASE)) {
if (((device_id == DA9121_DEVICE_ID) &&
(variant_mrc < DA9121_VARIANT_MRC_BASE)) ||
((device_id == DA914x_DEVICE_ID) &&
(variant_mrc != DA914x_VARIANT_MRC_BASE))) {
dev_err(chip->dev,
"Cannot support variant MRC: 0x%02X\n", variant_mrc);
ret = -EINVAL;
@ -936,6 +1026,14 @@ static int da9121_assign_chip_model(struct i2c_client *i2c,
chip->variant_id = DA9121_TYPE_DA9220_DA9132;
regmap = &da9121_2ch_regmap_config;
break;
case DA9121_SUBTYPE_DA9141:
chip->variant_id = DA9121_TYPE_DA9141;
regmap = &da9121_1ch_regmap_config;
break;
case DA9121_SUBTYPE_DA9142:
chip->variant_id = DA9121_TYPE_DA9142;
regmap = &da9121_2ch_regmap_config;
break;
}
/* Set these up for of_regulator_match call which may want .of_map_modes */
@ -1015,6 +1113,8 @@ static const struct of_device_id da9121_dt_ids[] = {
{ .compatible = "dlg,da9131", .data = (void *) DA9121_SUBTYPE_DA9131 },
{ .compatible = "dlg,da9220", .data = (void *) DA9121_SUBTYPE_DA9220 },
{ .compatible = "dlg,da9132", .data = (void *) DA9121_SUBTYPE_DA9132 },
{ .compatible = "dlg,da9141", .data = (void *) DA9121_SUBTYPE_DA9141 },
{ .compatible = "dlg,da9142", .data = (void *) DA9121_SUBTYPE_DA9142 },
{ }
};
MODULE_DEVICE_TABLE(of, da9121_dt_ids);
@ -1089,6 +1189,8 @@ static const struct i2c_device_id da9121_i2c_id[] = {
{"da9131", DA9121_TYPE_DA9122_DA9131},
{"da9220", DA9121_TYPE_DA9220_DA9132},
{"da9132", DA9121_TYPE_DA9220_DA9132},
{"da9141", DA9121_TYPE_DA9141},
{"da9142", DA9121_TYPE_DA9142},
{},
};
MODULE_DEVICE_TABLE(i2c, da9121_i2c_id);

View File

@ -26,7 +26,9 @@ enum da9121_variant {
DA9121_TYPE_DA9121_DA9130,
DA9121_TYPE_DA9220_DA9132,
DA9121_TYPE_DA9122_DA9131,
DA9121_TYPE_DA9217
DA9121_TYPE_DA9217,
DA9121_TYPE_DA9141,
DA9121_TYPE_DA9142
};
enum da9121_subvariant {
@ -36,7 +38,9 @@ enum da9121_subvariant {
DA9121_SUBTYPE_DA9132,
DA9121_SUBTYPE_DA9122,
DA9121_SUBTYPE_DA9131,
DA9121_SUBTYPE_DA9217
DA9121_SUBTYPE_DA9217,
DA9121_SUBTYPE_DA9141,
DA9121_SUBTYPE_DA9142
};
/* Minimum, maximum and default polling millisecond periods are provided
@ -70,6 +74,14 @@ enum da9121_subvariant {
#define DA9121_REG_SYS_GPIO1_1 0x13
#define DA9121_REG_SYS_GPIO2_0 0x14
#define DA9121_REG_SYS_GPIO2_1 0x15
#define DA914x_REG_SYS_GPIO3_0 0x16
#define DA914x_REG_SYS_GPIO3_1 0x17
#define DA914x_REG_SYS_GPIO4_0 0x18
#define DA914x_REG_SYS_GPIO4_1 0x19
#define DA914x_REG_SYS_ADMUX1_0 0x1A
#define DA914x_REG_SYS_ADMUX1_1 0x1B
#define DA914x_REG_SYS_ADMUX2_0 0x1C
#define DA914x_REG_SYS_ADMUX2_1 0x1D
#define DA9121_REG_BUCK_BUCK1_0 0x20
#define DA9121_REG_BUCK_BUCK1_1 0x21
#define DA9121_REG_BUCK_BUCK1_2 0x22
@ -276,6 +288,7 @@ enum da9121_subvariant {
#define DA9121_MASK_OTP_DEVICE_ID_DEV_ID 0xFF
#define DA9121_DEVICE_ID 0x05
#define DA914x_DEVICE_ID 0x26
/* DA9121_REG_OTP_VARIANT_ID */
@ -293,6 +306,10 @@ enum da9121_subvariant {
#define DA9131_VARIANT_VRC 0x1
#define DA9132_VARIANT_VRC 0x2
#define DA914x_VARIANT_MRC_BASE 0x0
#define DA9141_VARIANT_VRC 0x1
#define DA9142_VARIANT_VRC 0x2
/* DA9121_REG_OTP_CUSTOMER_ID */
#define DA9121_MASK_OTP_CUSTOMER_ID_CUST_ID 0xFF