Skip to content

Commit 4ffea5e

Browse files
xc-racer99broonie
authored andcommitted
regulator: max8998: Add charger regulator
The max8998 has a current regulator for charging control. The charger driver in drivers/power/supply/max8998_charger.c has a comment in it stating that 'charger control is done by a current regulator "CHARGER"', but this regulator was never added until now. The current values have been extracted from a downstream driver for the SGH-T959V. Signed-off-by: Jonathan Bakker <[email protected]> Link: https://lore.kernel.org/r/BN6PR04MB0660E1F4A3D5A348BE88311CA3BA0@BN6PR04MB0660.namprd04.prod.outlook.com Signed-off-by: Mark Brown <[email protected]>
1 parent a24490e commit 4ffea5e

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

drivers/regulator/max8998.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ struct max8998_data {
3333
unsigned int buck2_idx;
3434
};
3535

36+
static const unsigned int charger_current_table[] = {
37+
90000, 380000, 475000, 550000, 570000, 600000, 700000, 800000,
38+
};
39+
3640
static int max8998_get_enable_register(struct regulator_dev *rdev,
3741
int *reg, int *shift)
3842
{
@@ -63,6 +67,10 @@ static int max8998_get_enable_register(struct regulator_dev *rdev,
6367
*reg = MAX8998_REG_CHGR2;
6468
*shift = 7 - (ldo - MAX8998_ESAFEOUT1);
6569
break;
70+
case MAX8998_CHARGER:
71+
*reg = MAX8998_REG_CHGR2;
72+
*shift = 0;
73+
break;
6674
default:
6775
return -EINVAL;
6876
}
@@ -88,6 +96,11 @@ static int max8998_ldo_is_enabled(struct regulator_dev *rdev)
8896
return val & (1 << shift);
8997
}
9098

99+
static int max8998_ldo_is_enabled_inverted(struct regulator_dev *rdev)
100+
{
101+
return (!max8998_ldo_is_enabled(rdev));
102+
}
103+
91104
static int max8998_ldo_enable(struct regulator_dev *rdev)
92105
{
93106
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
@@ -358,6 +371,74 @@ static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev,
358371
return 0;
359372
}
360373

374+
int max8998_set_current_limit(struct regulator_dev *rdev,
375+
int min_uA, int max_uA)
376+
{
377+
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
378+
struct i2c_client *i2c = max8998->iodev->i2c;
379+
unsigned int n_currents = rdev->desc->n_current_limits;
380+
int i, sel = -1;
381+
382+
if (n_currents == 0)
383+
return -EINVAL;
384+
385+
if (rdev->desc->curr_table) {
386+
const unsigned int *curr_table = rdev->desc->curr_table;
387+
bool ascend = curr_table[n_currents - 1] > curr_table[0];
388+
389+
/* search for closest to maximum */
390+
if (ascend) {
391+
for (i = n_currents - 1; i >= 0; i--) {
392+
if (min_uA <= curr_table[i] &&
393+
curr_table[i] <= max_uA) {
394+
sel = i;
395+
break;
396+
}
397+
}
398+
} else {
399+
for (i = 0; i < n_currents; i++) {
400+
if (min_uA <= curr_table[i] &&
401+
curr_table[i] <= max_uA) {
402+
sel = i;
403+
break;
404+
}
405+
}
406+
}
407+
}
408+
409+
if (sel < 0)
410+
return -EINVAL;
411+
412+
sel <<= ffs(rdev->desc->csel_mask) - 1;
413+
414+
return max8998_update_reg(i2c, rdev->desc->csel_reg,
415+
sel, rdev->desc->csel_mask);
416+
}
417+
418+
int max8998_get_current_limit(struct regulator_dev *rdev)
419+
{
420+
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
421+
struct i2c_client *i2c = max8998->iodev->i2c;
422+
u8 val;
423+
int ret;
424+
425+
ret = max8998_read_reg(i2c, rdev->desc->csel_reg, &val);
426+
if (ret != 0)
427+
return ret;
428+
429+
val &= rdev->desc->csel_mask;
430+
val >>= ffs(rdev->desc->csel_mask) - 1;
431+
432+
if (rdev->desc->curr_table) {
433+
if (val >= rdev->desc->n_current_limits)
434+
return -EINVAL;
435+
436+
return rdev->desc->curr_table[val];
437+
}
438+
439+
return -EINVAL;
440+
}
441+
361442
static const struct regulator_ops max8998_ldo_ops = {
362443
.list_voltage = regulator_list_voltage_linear,
363444
.map_voltage = regulator_map_voltage_linear,
@@ -379,6 +460,15 @@ static const struct regulator_ops max8998_buck_ops = {
379460
.set_voltage_time_sel = max8998_set_voltage_buck_time_sel,
380461
};
381462

463+
static const struct regulator_ops max8998_charger_ops = {
464+
.set_current_limit = max8998_set_current_limit,
465+
.get_current_limit = max8998_get_current_limit,
466+
.is_enabled = max8998_ldo_is_enabled_inverted,
467+
/* Swapped as register is inverted */
468+
.enable = max8998_ldo_disable,
469+
.disable = max8998_ldo_enable,
470+
};
471+
382472
static const struct regulator_ops max8998_others_ops = {
383473
.is_enabled = max8998_ldo_is_enabled,
384474
.enable = max8998_ldo_enable,
@@ -397,6 +487,19 @@ static const struct regulator_ops max8998_others_ops = {
397487
.owner = THIS_MODULE, \
398488
}
399489

490+
#define MAX8998_CURRENT_REG(_name, _ops, _table, _reg, _mask) \
491+
{ \
492+
.name = #_name, \
493+
.id = MAX8998_##_name, \
494+
.ops = _ops, \
495+
.curr_table = _table, \
496+
.n_current_limits = ARRAY_SIZE(_table), \
497+
.csel_reg = _reg, \
498+
.csel_mask = _mask, \
499+
.type = REGULATOR_CURRENT, \
500+
.owner = THIS_MODULE, \
501+
}
502+
400503
#define MAX8998_OTHERS_REG(_name, _id) \
401504
{ \
402505
.name = #_name, \
@@ -432,6 +535,8 @@ static const struct regulator_desc regulators[] = {
432535
MAX8998_OTHERS_REG(ENVICHG, MAX8998_ENVICHG),
433536
MAX8998_OTHERS_REG(ESAFEOUT1, MAX8998_ESAFEOUT1),
434537
MAX8998_OTHERS_REG(ESAFEOUT2, MAX8998_ESAFEOUT2),
538+
MAX8998_CURRENT_REG(CHARGER, &max8998_charger_ops,
539+
charger_current_table, MAX8998_REG_CHGR1, 0x7),
435540
};
436541

437542
static int max8998_pmic_dt_parse_dvs_gpio(struct max8998_dev *iodev,

include/linux/mfd/max8998.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ enum {
3939
MAX8998_ENVICHG,
4040
MAX8998_ESAFEOUT1,
4141
MAX8998_ESAFEOUT2,
42+
MAX8998_CHARGER,
4243
};
4344

4445
/**

0 commit comments

Comments
 (0)