static irqreturn_t pm860x_done_handler(int irq, void *data) { struct pm860x_charger_info *info = data; struct power_supply *psy; union power_supply_propval val; int ret; int vbatt; mutex_lock(&info->lock); /* pre-charge done, will transimit to fast-charge stage */ if (info->state == FSM_PRECHARGE) { info->allowed = 1; goto out; } /* * Fast charge done, delay to read * the correct status of CHG_DET. */ mdelay(5); info->allowed = 0; psy = power_supply_get_by_name(pm860x_supplied_to[0]); if (!psy) goto out; ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &val); if (ret) goto out_psy_put; vbatt = val.intval / 1000; /* * CHG_DONE interrupt is faster than CHG_DET interrupt when * plug in/out usb, So we can not rely on info->online, we * need check pm8607 status register to check usb is online * or not, then we can decide it is real charge done * automatically or it is triggered by usb plug out; */ ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2); if (ret < 0) goto out_psy_put; if (vbatt > CHARGE_THRESHOLD && ret & STATUS2_CHG) power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGE_FULL, &val); out_psy_put: power_supply_put(psy); out: mutex_unlock(&info->lock); dev_dbg(info->dev, "%s, Allowed: %d\n", __func__, info->allowed); set_charging_fsm(info); return IRQ_HANDLED; }
static ssize_t power_supply_store_property(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { ssize_t ret; struct power_supply *psy = dev_get_drvdata(dev); const ptrdiff_t off = attr - power_supply_attrs; union power_supply_propval value; long long_val; /* TODO: support other types than int */ ret = kstrtol(buf, 10, &long_val); if (ret < 0) return ret; value.intval = long_val; ret = power_supply_set_property(psy, off, &value); if (ret < 0) return ret; return count; }