mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
power: supply: sc89890: support boost converter operation
The SC89890H supports boost converter operation to deliver power from the battery to other portable devices through USB port. Signed-off-by: shengfei Xu <xsf@rock-chips.com> Change-Id: If182ddcee7e1f655cc9059df0b4f9ab5a9980667
This commit is contained in:
@@ -96,6 +96,7 @@ struct sc89890_device {
|
||||
|
||||
struct regulator_dev *otg_vbus_reg;
|
||||
unsigned long usb_event;
|
||||
struct gpio_desc *gpiod_otg_en;
|
||||
|
||||
struct regmap *rmap;
|
||||
struct regmap_field *rmap_fields[F_MAX_FIELDS];
|
||||
@@ -265,12 +266,12 @@ enum sc89890_table_ids {
|
||||
TBL_IILIM,
|
||||
TBL_VREG,
|
||||
TBL_BOOSTV,
|
||||
TBL_SYSVMIN,
|
||||
TBL_VBATCOMP,
|
||||
TBL_RBATCOMP,
|
||||
|
||||
/* lookup tables */
|
||||
TBL_TREG,
|
||||
TBL_SYSVMIN,
|
||||
TBL_BOOSTI,
|
||||
};
|
||||
|
||||
@@ -281,11 +282,17 @@ static const u32 sc89890_treg_tbl[] = { 60, 80, 100, 120 };
|
||||
|
||||
/* Boost mode current limit lookup table, in uA */
|
||||
static const u32 sc89890_boosti_tbl[] = {
|
||||
500000, 700000, 1100000, 1300000, 1600000, 1800000, 2100000, 2400000
|
||||
500000, 750000, 1200000, 1400000, 1650000, 1875000, 2150000, 2450000
|
||||
};
|
||||
|
||||
#define SC89890_BOOSTI_TBL_SIZE ARRAY_SIZE(sc89890_boosti_tbl)
|
||||
|
||||
/* sys min voltage lookup table, in uV */
|
||||
static const u32 sc89890_vsys_tbl[] = {
|
||||
2600000, 2800000, 3000000, 3200000, 3400000, 3500000, 3600000, 3700000
|
||||
};
|
||||
#define SC89890_VSYS_TBL_SIZE ARRAY_SIZE(sc89890_vsys_tbl)
|
||||
|
||||
struct sc89890_range {
|
||||
u32 min;
|
||||
u32 max;
|
||||
@@ -305,14 +312,14 @@ static const union {
|
||||
[TBL_ICHG] = { .rt = {0, 5056000, 64000} }, /* uA */
|
||||
[TBL_ITERM] = { .rt = {64000, 1024000, 64000} }, /* uA */
|
||||
[TBL_IILIM] = { .rt = {100000, 3250000, 50000} }, /* uA */
|
||||
[TBL_VREG] = { .rt = {3840000, 4608000, 16000} }, /* uV */
|
||||
[TBL_BOOSTV] = { .rt = {4550000, 5510000, 64000} }, /* uV */
|
||||
[TBL_SYSVMIN] = { .rt = {3000000, 3700000, 100000} }, /* uV */
|
||||
[TBL_VREG] = { .rt = {3840000, 4848000, 16000} }, /* uV */
|
||||
[TBL_BOOSTV] = { .rt = {3900000, 5400000, 100000} }, /* uV */
|
||||
[TBL_VBATCOMP] = { .rt = {0, 224000, 32000} }, /* uV */
|
||||
[TBL_RBATCOMP] = { .rt = {0, 140000, 20000} }, /* uOhm */
|
||||
|
||||
/* lookup tables */
|
||||
[TBL_TREG] = { .lt = {sc89890_treg_tbl, SC89890_TREG_TBL_SIZE} },
|
||||
[TBL_SYSVMIN] = { .lt = {sc89890_vsys_tbl, SC89890_VSYS_TBL_SIZE} }, /* uV */
|
||||
[TBL_BOOSTI] = { .lt = {sc89890_boosti_tbl, SC89890_BOOSTI_TBL_SIZE} }
|
||||
};
|
||||
|
||||
@@ -593,6 +600,16 @@ static int sc89890_power_supply_get_property(struct power_supply *psy,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sc89890_enable_charger(struct sc89890_device *sc89890)
|
||||
{
|
||||
return sc89890_field_write(sc89890, F_CHG_CFG, 1);
|
||||
}
|
||||
|
||||
static int sc89890_disable_charger(struct sc89890_device *sc89890)
|
||||
{
|
||||
return sc89890_field_write(sc89890, F_CHG_CFG, 0);
|
||||
}
|
||||
|
||||
static int sc89890_power_supply_set_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
const union power_supply_propval *val)
|
||||
@@ -615,6 +632,17 @@ static int sc89890_power_supply_set_property(struct power_supply *psy,
|
||||
dev_err(sc89890->dev, "set input current limit failed\n");
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
if (val->intval) {
|
||||
ret = sc89890_enable_charger(sc89890);
|
||||
if (ret < 0)
|
||||
dev_err(sc89890->dev, "enable charge failed\n");
|
||||
} else {
|
||||
ret = sc89890_disable_charger(sc89890);
|
||||
if (ret < 0)
|
||||
dev_err(sc89890->dev, "disable charge failed\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
@@ -809,6 +837,10 @@ static int sc89890_otg_vbus_enable(struct regulator_dev *dev)
|
||||
{
|
||||
struct sc89890_device *sc = rdev_get_drvdata(dev);
|
||||
|
||||
if (!IS_ERR_OR_NULL(sc->gpiod_otg_en))
|
||||
gpiod_direction_output(sc->gpiod_otg_en, 0x1);
|
||||
|
||||
sc89890_disable_charger(sc);
|
||||
sc89890_set_otg_vbus(sc, true);
|
||||
|
||||
return 0;
|
||||
@@ -818,6 +850,9 @@ static int sc89890_otg_vbus_disable(struct regulator_dev *dev)
|
||||
{
|
||||
struct sc89890_device *sc = rdev_get_drvdata(dev);
|
||||
|
||||
if (!IS_ERR_OR_NULL(sc->gpiod_otg_en))
|
||||
gpiod_direction_output(sc->gpiod_otg_en, 0x0);
|
||||
|
||||
sc89890_set_otg_vbus(sc, false);
|
||||
|
||||
return 0;
|
||||
@@ -858,9 +893,13 @@ static int sc89890_register_otg_vbus_regulator(struct sc89890_device *sc)
|
||||
np = of_get_child_by_name(sc->dev->of_node, "regulators");
|
||||
if (!np) {
|
||||
dev_warn(sc->dev, "cannot find regulators node\n");
|
||||
return -ENXIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sc->gpiod_otg_en = devm_gpiod_get_optional(sc->dev, "otg-en", GPIOD_OUT_LOW);
|
||||
if (IS_ERR_OR_NULL(sc->gpiod_otg_en))
|
||||
dev_warn(sc->dev, "failed to request GPIO otg en pin\n");
|
||||
|
||||
config.dev = sc->dev;
|
||||
config.driver_data = sc;
|
||||
|
||||
@@ -1112,7 +1151,9 @@ static int sc89890_probe(struct i2c_client *client,
|
||||
if (ret)
|
||||
goto irq_fail;
|
||||
|
||||
sc89890_register_otg_vbus_regulator(sc89890);
|
||||
ret = sc89890_register_otg_vbus_regulator(sc89890);
|
||||
if (ret)
|
||||
return ret;
|
||||
sc89890_create_device_node(sc89890->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user