|
@@ -48,6 +48,8 @@ struct bq24735 {
|
|
|
struct power_supply_desc charger_desc;
|
|
|
struct i2c_client *client;
|
|
|
struct bq24735_platform *pdata;
|
|
|
+ struct mutex lock;
|
|
|
+ bool charging;
|
|
|
};
|
|
|
|
|
|
static inline struct bq24735 *to_bq24735(struct power_supply *psy)
|
|
@@ -56,9 +58,23 @@ static inline struct bq24735 *to_bq24735(struct power_supply *psy)
|
|
|
}
|
|
|
|
|
|
static enum power_supply_property bq24735_charger_properties[] = {
|
|
|
+ POWER_SUPPLY_PROP_STATUS,
|
|
|
POWER_SUPPLY_PROP_ONLINE,
|
|
|
};
|
|
|
|
|
|
+static int bq24735_charger_property_is_writeable(struct power_supply *psy,
|
|
|
+ enum power_supply_property psp)
|
|
|
+{
|
|
|
+ switch (psp) {
|
|
|
+ case POWER_SUPPLY_PROP_STATUS:
|
|
|
+ return 1;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static inline int bq24735_write_word(struct i2c_client *client, u8 reg,
|
|
|
u16 value)
|
|
|
{
|
|
@@ -174,16 +190,30 @@ static bool bq24735_charger_is_present(struct bq24735 *charger)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+static int bq24735_charger_is_charging(struct bq24735 *charger)
|
|
|
+{
|
|
|
+ int ret = bq24735_read_word(charger->client, BQ24735_CHG_OPT);
|
|
|
+
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ return !(ret & BQ24735_CHG_OPT_CHARGE_DISABLE);
|
|
|
+}
|
|
|
+
|
|
|
static irqreturn_t bq24735_charger_isr(int irq, void *devid)
|
|
|
{
|
|
|
struct power_supply *psy = devid;
|
|
|
struct bq24735 *charger = to_bq24735(psy);
|
|
|
|
|
|
- if (bq24735_charger_is_present(charger))
|
|
|
+ mutex_lock(&charger->lock);
|
|
|
+
|
|
|
+ if (charger->charging && bq24735_charger_is_present(charger))
|
|
|
bq24735_enable_charging(charger);
|
|
|
else
|
|
|
bq24735_disable_charging(charger);
|
|
|
|
|
|
+ mutex_unlock(&charger->lock);
|
|
|
+
|
|
|
power_supply_changed(psy);
|
|
|
|
|
|
return IRQ_HANDLED;
|
|
@@ -199,6 +229,19 @@ static int bq24735_charger_get_property(struct power_supply *psy,
|
|
|
case POWER_SUPPLY_PROP_ONLINE:
|
|
|
val->intval = bq24735_charger_is_present(charger) ? 1 : 0;
|
|
|
break;
|
|
|
+ case POWER_SUPPLY_PROP_STATUS:
|
|
|
+ switch (bq24735_charger_is_charging(charger)) {
|
|
|
+ case 1:
|
|
|
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
|
|
|
+ break;
|
|
|
+ case 0:
|
|
|
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
default:
|
|
|
return -EINVAL;
|
|
|
}
|
|
@@ -206,6 +249,46 @@ static int bq24735_charger_get_property(struct power_supply *psy,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int bq24735_charger_set_property(struct power_supply *psy,
|
|
|
+ enum power_supply_property psp,
|
|
|
+ const union power_supply_propval *val)
|
|
|
+{
|
|
|
+ struct bq24735 *charger = to_bq24735(psy);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ switch (psp) {
|
|
|
+ case POWER_SUPPLY_PROP_STATUS:
|
|
|
+ switch (val->intval) {
|
|
|
+ case POWER_SUPPLY_STATUS_CHARGING:
|
|
|
+ mutex_lock(&charger->lock);
|
|
|
+ charger->charging = true;
|
|
|
+ ret = bq24735_enable_charging(charger);
|
|
|
+ mutex_unlock(&charger->lock);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ bq24735_config_charger(charger);
|
|
|
+ break;
|
|
|
+ case POWER_SUPPLY_STATUS_DISCHARGING:
|
|
|
+ case POWER_SUPPLY_STATUS_NOT_CHARGING:
|
|
|
+ mutex_lock(&charger->lock);
|
|
|
+ charger->charging = false;
|
|
|
+ ret = bq24735_disable_charging(charger);
|
|
|
+ mutex_unlock(&charger->lock);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ power_supply_changed(psy);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return -EPERM;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static struct bq24735_platform *bq24735_parse_dt_data(struct i2c_client *client)
|
|
|
{
|
|
|
struct bq24735_platform *pdata;
|
|
@@ -255,6 +338,8 @@ static int bq24735_charger_probe(struct i2c_client *client,
|
|
|
if (!charger)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
+ mutex_init(&charger->lock);
|
|
|
+ charger->charging = true;
|
|
|
charger->pdata = client->dev.platform_data;
|
|
|
|
|
|
if (IS_ENABLED(CONFIG_OF) && !charger->pdata && client->dev.of_node)
|
|
@@ -285,6 +370,9 @@ static int bq24735_charger_probe(struct i2c_client *client,
|
|
|
supply_desc->properties = bq24735_charger_properties;
|
|
|
supply_desc->num_properties = ARRAY_SIZE(bq24735_charger_properties);
|
|
|
supply_desc->get_property = bq24735_charger_get_property;
|
|
|
+ supply_desc->set_property = bq24735_charger_set_property;
|
|
|
+ supply_desc->property_is_writeable =
|
|
|
+ bq24735_charger_property_is_writeable;
|
|
|
|
|
|
psy_cfg.supplied_to = charger->pdata->supplied_to;
|
|
|
psy_cfg.num_supplicants = charger->pdata->num_supplicants;
|