mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-05 05:54:25 +00:00
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 <xc-racer2@live.ca> Link: https://lore.kernel.org/r/BN6PR04MB0660E1F4A3D5A348BE88311CA3BA0@BN6PR04MB0660.namprd04.prod.outlook.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
a24490e017
commit
4ffea5e083
2 changed files with 106 additions and 0 deletions
|
@ -33,6 +33,10 @@ struct max8998_data {
|
||||||
unsigned int buck2_idx;
|
unsigned int buck2_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const unsigned int charger_current_table[] = {
|
||||||
|
90000, 380000, 475000, 550000, 570000, 600000, 700000, 800000,
|
||||||
|
};
|
||||||
|
|
||||||
static int max8998_get_enable_register(struct regulator_dev *rdev,
|
static int max8998_get_enable_register(struct regulator_dev *rdev,
|
||||||
int *reg, int *shift)
|
int *reg, int *shift)
|
||||||
{
|
{
|
||||||
|
@ -63,6 +67,10 @@ static int max8998_get_enable_register(struct regulator_dev *rdev,
|
||||||
*reg = MAX8998_REG_CHGR2;
|
*reg = MAX8998_REG_CHGR2;
|
||||||
*shift = 7 - (ldo - MAX8998_ESAFEOUT1);
|
*shift = 7 - (ldo - MAX8998_ESAFEOUT1);
|
||||||
break;
|
break;
|
||||||
|
case MAX8998_CHARGER:
|
||||||
|
*reg = MAX8998_REG_CHGR2;
|
||||||
|
*shift = 0;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -88,6 +96,11 @@ static int max8998_ldo_is_enabled(struct regulator_dev *rdev)
|
||||||
return val & (1 << shift);
|
return val & (1 << shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int max8998_ldo_is_enabled_inverted(struct regulator_dev *rdev)
|
||||||
|
{
|
||||||
|
return (!max8998_ldo_is_enabled(rdev));
|
||||||
|
}
|
||||||
|
|
||||||
static int max8998_ldo_enable(struct regulator_dev *rdev)
|
static int max8998_ldo_enable(struct regulator_dev *rdev)
|
||||||
{
|
{
|
||||||
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
|
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
|
||||||
|
@ -358,6 +371,74 @@ static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int max8998_set_current_limit(struct regulator_dev *rdev,
|
||||||
|
int min_uA, int max_uA)
|
||||||
|
{
|
||||||
|
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
|
||||||
|
struct i2c_client *i2c = max8998->iodev->i2c;
|
||||||
|
unsigned int n_currents = rdev->desc->n_current_limits;
|
||||||
|
int i, sel = -1;
|
||||||
|
|
||||||
|
if (n_currents == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (rdev->desc->curr_table) {
|
||||||
|
const unsigned int *curr_table = rdev->desc->curr_table;
|
||||||
|
bool ascend = curr_table[n_currents - 1] > curr_table[0];
|
||||||
|
|
||||||
|
/* search for closest to maximum */
|
||||||
|
if (ascend) {
|
||||||
|
for (i = n_currents - 1; i >= 0; i--) {
|
||||||
|
if (min_uA <= curr_table[i] &&
|
||||||
|
curr_table[i] <= max_uA) {
|
||||||
|
sel = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < n_currents; i++) {
|
||||||
|
if (min_uA <= curr_table[i] &&
|
||||||
|
curr_table[i] <= max_uA) {
|
||||||
|
sel = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sel < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
sel <<= ffs(rdev->desc->csel_mask) - 1;
|
||||||
|
|
||||||
|
return max8998_update_reg(i2c, rdev->desc->csel_reg,
|
||||||
|
sel, rdev->desc->csel_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
int max8998_get_current_limit(struct regulator_dev *rdev)
|
||||||
|
{
|
||||||
|
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
|
||||||
|
struct i2c_client *i2c = max8998->iodev->i2c;
|
||||||
|
u8 val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = max8998_read_reg(i2c, rdev->desc->csel_reg, &val);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
val &= rdev->desc->csel_mask;
|
||||||
|
val >>= ffs(rdev->desc->csel_mask) - 1;
|
||||||
|
|
||||||
|
if (rdev->desc->curr_table) {
|
||||||
|
if (val >= rdev->desc->n_current_limits)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return rdev->desc->curr_table[val];
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct regulator_ops max8998_ldo_ops = {
|
static const struct regulator_ops max8998_ldo_ops = {
|
||||||
.list_voltage = regulator_list_voltage_linear,
|
.list_voltage = regulator_list_voltage_linear,
|
||||||
.map_voltage = regulator_map_voltage_linear,
|
.map_voltage = regulator_map_voltage_linear,
|
||||||
|
@ -379,6 +460,15 @@ static const struct regulator_ops max8998_buck_ops = {
|
||||||
.set_voltage_time_sel = max8998_set_voltage_buck_time_sel,
|
.set_voltage_time_sel = max8998_set_voltage_buck_time_sel,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct regulator_ops max8998_charger_ops = {
|
||||||
|
.set_current_limit = max8998_set_current_limit,
|
||||||
|
.get_current_limit = max8998_get_current_limit,
|
||||||
|
.is_enabled = max8998_ldo_is_enabled_inverted,
|
||||||
|
/* Swapped as register is inverted */
|
||||||
|
.enable = max8998_ldo_disable,
|
||||||
|
.disable = max8998_ldo_enable,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct regulator_ops max8998_others_ops = {
|
static const struct regulator_ops max8998_others_ops = {
|
||||||
.is_enabled = max8998_ldo_is_enabled,
|
.is_enabled = max8998_ldo_is_enabled,
|
||||||
.enable = max8998_ldo_enable,
|
.enable = max8998_ldo_enable,
|
||||||
|
@ -397,6 +487,19 @@ static const struct regulator_ops max8998_others_ops = {
|
||||||
.owner = THIS_MODULE, \
|
.owner = THIS_MODULE, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MAX8998_CURRENT_REG(_name, _ops, _table, _reg, _mask) \
|
||||||
|
{ \
|
||||||
|
.name = #_name, \
|
||||||
|
.id = MAX8998_##_name, \
|
||||||
|
.ops = _ops, \
|
||||||
|
.curr_table = _table, \
|
||||||
|
.n_current_limits = ARRAY_SIZE(_table), \
|
||||||
|
.csel_reg = _reg, \
|
||||||
|
.csel_mask = _mask, \
|
||||||
|
.type = REGULATOR_CURRENT, \
|
||||||
|
.owner = THIS_MODULE, \
|
||||||
|
}
|
||||||
|
|
||||||
#define MAX8998_OTHERS_REG(_name, _id) \
|
#define MAX8998_OTHERS_REG(_name, _id) \
|
||||||
{ \
|
{ \
|
||||||
.name = #_name, \
|
.name = #_name, \
|
||||||
|
@ -432,6 +535,8 @@ static const struct regulator_desc regulators[] = {
|
||||||
MAX8998_OTHERS_REG(ENVICHG, MAX8998_ENVICHG),
|
MAX8998_OTHERS_REG(ENVICHG, MAX8998_ENVICHG),
|
||||||
MAX8998_OTHERS_REG(ESAFEOUT1, MAX8998_ESAFEOUT1),
|
MAX8998_OTHERS_REG(ESAFEOUT1, MAX8998_ESAFEOUT1),
|
||||||
MAX8998_OTHERS_REG(ESAFEOUT2, MAX8998_ESAFEOUT2),
|
MAX8998_OTHERS_REG(ESAFEOUT2, MAX8998_ESAFEOUT2),
|
||||||
|
MAX8998_CURRENT_REG(CHARGER, &max8998_charger_ops,
|
||||||
|
charger_current_table, MAX8998_REG_CHGR1, 0x7),
|
||||||
};
|
};
|
||||||
|
|
||||||
static int max8998_pmic_dt_parse_dvs_gpio(struct max8998_dev *iodev,
|
static int max8998_pmic_dt_parse_dvs_gpio(struct max8998_dev *iodev,
|
||||||
|
|
|
@ -39,6 +39,7 @@ enum {
|
||||||
MAX8998_ENVICHG,
|
MAX8998_ENVICHG,
|
||||||
MAX8998_ESAFEOUT1,
|
MAX8998_ESAFEOUT1,
|
||||||
MAX8998_ESAFEOUT2,
|
MAX8998_ESAFEOUT2,
|
||||||
|
MAX8998_CHARGER,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue