Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2c731470 authored by Harry Yang's avatar Harry Yang
Browse files

power: smb138x: Add usb main power supply



The usb main power supply was initially introduced to expose all
the properties required to implement parallel charging for the main
charger. Sharing lib and votables with parallel algorithm, smb138x
standalone charger also need to have main charger type.

These properties are implemented/supported,

- CONSTANT_CHARGE_CURRENT_MAX, sets and gets the FCC of the main charger
- ICL_REDUCTION, indicates by how much the main charger should reduce
  its ICL. The parallel charger would draw some portion of the ICL and
  this implementation ensures that the main charger reduce its ICL in
  order to not exceed the adapter limits.
- VOLTAGE_MAX, sets the float voltage of the battery, we continue to
  raise float voltage for the parallel charger so that it operates as
  current source.
- INPUT_CURRENT_SETTLED: indicates the AICL results.
- FCC_DELTA: indicates the value by which the main is correcting the
  FCC. The main reduces FCC by few mA when in JEITA or Step
  charging. This helps in determining the exact FCC which in turn
  helps distribute it correctly.

Change-Id: I2860494c69da7422c8f9f121bc8a7abd9d1f1420
Signed-off-by: default avatarHarry Yang <harryy@codeaurora.org>
parent 21a1b0f4
Loading
Loading
Loading
Loading
+137 −0
Original line number Diff line number Diff line
@@ -332,6 +332,120 @@ static int smb138x_init_usb_psy(struct smb138x *chip)
	return 0;
}

/*****************************
 * USB MAIN PSY REGISTRATION *
 *****************************/

static enum power_supply_property smb138x_usb_main_props[] = {
	POWER_SUPPLY_PROP_VOLTAGE_MAX,
	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
	POWER_SUPPLY_PROP_TYPE,
	POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
	POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED,
	POWER_SUPPLY_PROP_FCC_DELTA,
	POWER_SUPPLY_PROP_CURRENT_MAX,
};

static int smb138x_usb_main_get_prop(struct power_supply *psy,
		enum power_supply_property psp,
		union power_supply_propval *val)
{
	struct smb138x *chip = power_supply_get_drvdata(psy);
	struct smb_charger *chg = &chip->chg;
	int rc = 0;

	switch (psp) {
	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
		rc = smblib_get_charge_param(chg, &chg->param.fv, &val->intval);
		break;
	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
		rc = smblib_get_charge_param(chg, &chg->param.fcc,
							&val->intval);
		break;
	case POWER_SUPPLY_PROP_TYPE:
		val->intval = POWER_SUPPLY_TYPE_MAIN;
		break;
	case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
		rc = smblib_get_prop_input_current_settled(chg, val);
		break;
	case POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED:
		rc = smblib_get_prop_input_voltage_settled(chg, val);
		break;
	case POWER_SUPPLY_PROP_FCC_DELTA:
		rc = smblib_get_prop_fcc_delta(chg, val);
		break;
	case POWER_SUPPLY_PROP_CURRENT_MAX:
		rc = smblib_get_icl_current(chg, &val->intval);
		break;
	default:
		pr_debug("get prop %d is not supported in usb-main\n", psp);
		rc = -EINVAL;
		break;
	}

	if (rc < 0) {
		pr_debug("Couldn't get prop %d rc = %d\n", psp, rc);
		return -ENODATA;
	}
	return 0;
}

static int smb138x_usb_main_set_prop(struct power_supply *psy,
		enum power_supply_property psp,
		const union power_supply_propval *val)
{
	struct smb138x *chip = power_supply_get_drvdata(psy);
	struct smb_charger *chg = &chip->chg;
	int rc = 0;

	switch (psp) {
	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
		rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval);
		break;
	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
		rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval);
		break;
	case POWER_SUPPLY_PROP_CURRENT_MAX:
		rc = smblib_set_icl_current(chg, val->intval);
		break;
	default:
		rc = -EINVAL;
		break;
	}

	if (rc < 0)
		pr_err("Couldn't set prop %d, rc=%d\n", psp, rc);

	return rc;
}

static const struct power_supply_desc usb_main_psy_desc = {
	.name           = "main",
	.type           = POWER_SUPPLY_TYPE_MAIN,
	.properties     = smb138x_usb_main_props,
	.num_properties = ARRAY_SIZE(smb138x_usb_main_props),
	.get_property   = smb138x_usb_main_get_prop,
	.set_property   = smb138x_usb_main_set_prop,
};

static int smb138x_init_usb_main_psy(struct smb138x *chip)
{
	struct power_supply_config usb_main_cfg = {};
	struct smb_charger *chg = &chip->chg;

	usb_main_cfg.drv_data = chip;
	usb_main_cfg.of_node = chg->dev->of_node;
	chg->usb_main_psy = devm_power_supply_register(chg->dev,
						  &usb_main_psy_desc,
						  &usb_main_cfg);
	if (IS_ERR(chg->usb_main_psy)) {
		pr_err("Couldn't register USB main power supply\n");
		return PTR_ERR(chg->usb_main_psy);
	}

	return 0;
}

/*************************
 * BATT PSY REGISTRATION *
 *************************/
@@ -1388,6 +1502,21 @@ static int smb138x_request_interrupts(struct smb138x *chip)
	return rc;
}

static void smb138x_free_interrupts(struct smb_charger *chg)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(smb138x_irqs); i++) {
		if (smb138x_irqs[i].irq > 0) {
			if (smb138x_irqs[i].wake)
				disable_irq_wake(smb138x_irqs[i].irq);

			devm_free_irq(chg->dev, smb138x_irqs[i].irq,
					smb138x_irqs[i].irq_data);
		}
	}
}

/*********
 * PROBE *
 *********/
@@ -1467,6 +1596,12 @@ static int smb138x_master_probe(struct smb138x *chip)
		goto cleanup;
	}

	rc = smb138x_init_usb_main_psy(chip);
	if (rc < 0) {
		pr_err("Couldn't initialize main usb psy rc=%d\n", rc);
		goto cleanup;
	}

	rc = smb138x_init_batt_psy(chip);
	if (rc < 0) {
		pr_err("Couldn't initialize batt psy rc=%d\n", rc);
@@ -1495,7 +1630,9 @@ static int smb138x_master_probe(struct smb138x *chip)
	return rc;

cleanup:
	smb138x_free_interrupts(chg);
	smblib_deinit(chg);

	return rc;
}