Exemple #1
0
static u8 lp8788_select_buck_vout_addr(struct lp8788_buck *buck,
                                       enum lp8788_buck_id id)
{
    enum lp8788_dvs_mode mode = lp8788_get_buck_dvs_ctrl_mode(buck, id);
    struct lp8788_buck1_dvs *b1_dvs;
    struct lp8788_buck2_dvs *b2_dvs;
    u8 val, idx, addr;
    int pin1, pin2;

    switch (id) {
    case BUCK1:
        if (mode == EXTPIN) {
            b1_dvs = (struct lp8788_buck1_dvs *)buck->dvs;
            if (!b1_dvs)
                goto err;

            idx = gpio_get_value(b1_dvs->gpio) ? 1 : 0;
        } else {
            lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
            idx = (val & LP8788_BUCK1_DVS_M) >> LP8788_BUCK1_DVS_S;
        }
        addr = LP8788_BUCK1_VOUT0 + idx;
        break;
    case BUCK2:
        if (mode == EXTPIN) {
            b2_dvs = (struct lp8788_buck2_dvs *)buck->dvs;
            if (!b2_dvs)
                goto err;

            pin1 = gpio_get_value(b2_dvs->gpio[0]);
            pin2 = gpio_get_value(b2_dvs->gpio[1]);

            if (pin1 == PIN_LOW && pin2 == PIN_LOW)
                idx = 0;
            else if (pin1 == PIN_LOW && pin2 == PIN_HIGH)
                idx = 2;
            else if (pin1 == PIN_HIGH && pin2 == PIN_LOW)
                idx = 1;
            else
                idx = 3;
        } else {
            lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
            idx = (val & LP8788_BUCK2_DVS_M) >> LP8788_BUCK2_DVS_S;
        }
        addr = LP8788_BUCK2_VOUT0 + idx;
        break;
    default:
        goto err;
    }

    return addr;
err:
    return INVALID_ADDR;
}
static int lp8788_get_battery_status(struct lp8788_charger *pchg,
				union power_supply_propval *val)
{
	enum lp8788_charging_state state;
	u8 data;
	int ret;

	ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
	if (ret)
		return ret;

	state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S;
	switch (state) {
	case LP8788_OFF:
		val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
		break;
	case LP8788_PRECHARGE:
	case LP8788_CC:
	case LP8788_CV:
	case LP8788_HIGH_CURRENT:
		val->intval = POWER_SUPPLY_STATUS_CHARGING;
		break;
	case LP8788_MAINTENANCE:
		val->intval = POWER_SUPPLY_STATUS_FULL;
		break;
	default:
		val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
		break;
	}

	return 0;
}
static bool lp8788_is_charger_detected(struct lp8788_charger *pchg)
{
	u8 data;

	lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
	data &= LP8788_CHG_INPUT_STATE_M;

	return data == LP8788_SYSTEM_SUPPLY || data == LP8788_FULL_FUNCTION;
}
static int lp8788_get_charging_termination_voltage(struct lp8788_charger *pchg,
				union power_supply_propval *val)
{
	u8 read;

	lp8788_read_byte(pchg->lp, LP8788_CHG_VTERM, &read);
	read &= LP8788_CHG_VTERM_M;
	val->intval = LP8788_VTERM_MIN + LP8788_VTERM_STEP * read;

	return 0;
}
static int lp8788_get_battery_charging_current(struct lp8788_charger *pchg,
				union power_supply_propval *val)
{
	u8 read;

	lp8788_read_byte(pchg->lp, LP8788_CHG_IBATT, &read);
	read &= LP8788_CHG_IBATT_M;
	val->intval = LP8788_ISEL_STEP *
			(min_t(int, read, LP8788_ISEL_MAX) + 1);

	return 0;
}
Exemple #6
0
static int lp8788_buck_enable_time(struct regulator_dev *rdev)
{
    struct lp8788_buck *buck = rdev_get_drvdata(rdev);
    enum lp8788_buck_id id = rdev_get_id(rdev);
    u8 val, addr = LP8788_BUCK1_TIMESTEP + id;

    if (lp8788_read_byte(buck->lp, addr, &val))
        return -EINVAL;

    val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S;

    return ENABLE_TIME_USEC * val;
}
static int lp8788_get_battery_present(struct lp8788_charger *pchg,
				union power_supply_propval *val)
{
	u8 data;
	int ret;

	ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
	if (ret)
		return ret;

	val->intval = !(data & LP8788_NO_BATT_M);
	return 0;
}
Exemple #8
0
static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev)
{
    struct lp8788_buck *buck = rdev_get_drvdata(rdev);
    enum lp8788_buck_id id = rdev_get_id(rdev);
    u8 val;
    int ret;

    ret = lp8788_read_byte(buck->lp, LP8788_BUCK_PWM, &val);
    if (ret)
        return ret;

    return val & BUCK_FPWM_MASK(id) ?
           REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
}
static ssize_t lp8788_show_eoc_time(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	struct lp8788_charger *pchg = dev_get_drvdata(dev);
	char *stime[] = { "400ms", "5min", "10min", "15min",
			"20min", "25min", "30min" "No timeout" };
	u8 val;

	lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val);
	val = (val & LP8788_CHG_EOC_TIME_M) >> LP8788_CHG_EOC_TIME_S;

	return scnprintf(buf, PAGE_SIZE, "End Of Charge Time: %s\n",
			stime[val]);
}
Exemple #10
0
static int lp8788_buck12_get_voltage_sel(struct regulator_dev *rdev)
{
    struct lp8788_buck *buck = rdev_get_drvdata(rdev);
    enum lp8788_buck_id id = rdev_get_id(rdev);
    int ret;
    u8 val, addr;

    addr = lp8788_select_buck_vout_addr(buck, id);
    if (!lp8788_is_valid_buck_addr(addr))
        return -EINVAL;

    ret = lp8788_read_byte(buck->lp, addr, &val);
    if (ret)
        return ret;

    return val & LP8788_VOUT_M;
}
static ssize_t lp8788_show_eoc_level(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	struct lp8788_charger *pchg = dev_get_drvdata(dev);
	char *abs_level[] = { "25mA", "49mA", "75mA", "98mA" };
	char *relative_level[] = { "5%", "10%", "15%", "20%" };
	char *level;
	u8 val;
	u8 mode;

	lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val);

	mode = val & LP8788_CHG_EOC_MODE_M;
	val = (val & LP8788_CHG_EOC_LEVEL_M) >> LP8788_CHG_EOC_LEVEL_S;
	level = mode ? abs_level[val] : relative_level[val];

	return scnprintf(buf, PAGE_SIZE, "End Of Charge Level: %s\n", level);
}
static int lp8788_get_battery_health(struct lp8788_charger *pchg,
				union power_supply_propval *val)
{
	u8 data;
	int ret;

	ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
	if (ret)
		return ret;

	if (data & LP8788_NO_BATT_M)
		val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
	else if (data & LP8788_BAD_BATT_M)
		val->intval = POWER_SUPPLY_HEALTH_DEAD;
	else
		val->intval = POWER_SUPPLY_HEALTH_GOOD;

	return 0;
}
Exemple #13
0
static enum lp8788_dvs_mode
lp8788_get_buck_dvs_ctrl_mode(struct lp8788_buck *buck, enum lp8788_buck_id id)
{
    u8 val, mask;

    switch (id) {
    case BUCK1:
        mask = LP8788_BUCK1_DVS_SEL_M;
        break;
    case BUCK2:
        mask = LP8788_BUCK2_DVS_SEL_M;
        break;
    default:
        return REGISTER;
    }

    lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);

    return val & mask ? REGISTER : EXTPIN;
}
static int lp8788_charger_get_property(struct power_supply *psy,
					enum power_supply_property psp,
					union power_supply_propval *val)
{
	struct lp8788_charger *pchg = dev_get_drvdata(psy->dev->parent);
	u8 read;

	switch (psp) {
	case POWER_SUPPLY_PROP_ONLINE:
		val->intval = lp8788_is_charger_detected(pchg);
		break;
	case POWER_SUPPLY_PROP_CURRENT_MAX:
		lp8788_read_byte(pchg->lp, LP8788_CHG_IDCIN, &read);
		val->intval = LP8788_ISEL_STEP *
				(min_t(int, read, LP8788_ISEL_MAX) + 1);
		break;
	default:
		return -EINVAL;
	}

	return 0;
}
static int lp8788_get_battery_capacity(struct lp8788_charger *pchg,
				union power_supply_propval *val)
{
	struct lp8788 *lp = pchg->lp;
	struct lp8788_charger_platform_data *pdata = pchg->pdata;
	unsigned int max_vbatt;
	int vbatt;
	enum lp8788_charging_state state;
	u8 data;
	int ret;

	if (!pdata)
		return -EINVAL;

	max_vbatt = pdata->max_vbatt_mv;
	if (max_vbatt == 0)
		return -EINVAL;

	ret = lp8788_read_byte(lp, LP8788_CHG_STATUS, &data);
	if (ret)
		return ret;

	state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S;

	if (state == LP8788_MAINTENANCE) {
		val->intval = LP8788_MAX_BATT_CAPACITY;
	} else {
		ret = lp8788_get_vbatt_adc(pchg, &vbatt);
		if (ret)
			return ret;

		val->intval = (vbatt * LP8788_MAX_BATT_CAPACITY) / max_vbatt;
		val->intval = min(val->intval, LP8788_MAX_BATT_CAPACITY);
	}

	return 0;
}
static ssize_t lp8788_show_charger_status(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	struct lp8788_charger *pchg = dev_get_drvdata(dev);
	enum lp8788_charging_state state;
	char *desc[LP8788_MAX_CHG_STATE] = {
		[LP8788_OFF] = "CHARGER OFF",
		[LP8788_WARM_UP] = "WARM UP",
		[LP8788_LOW_INPUT] = "LOW INPUT STATE",
		[LP8788_PRECHARGE] = "CHARGING - PRECHARGE",
		[LP8788_CC] = "CHARGING - CC",
		[LP8788_CV] = "CHARGING - CV",
		[LP8788_MAINTENANCE] = "NO CHARGING - MAINTENANCE",
		[LP8788_BATTERY_FAULT] = "BATTERY FAULT",
		[LP8788_SYSTEM_SUPPORT] = "SYSTEM SUPPORT",
		[LP8788_HIGH_CURRENT] = "HIGH CURRENT",
	};
	u8 data;

	lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
	state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S;

	return scnprintf(buf, PAGE_SIZE, "%s\n", desc[state]);
}