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

Commit d0f24f3f authored by Harry Yang's avatar Harry Yang Committed by Guru Das Srinagesh
Browse files

power: smb5: Add support to read USBIN_I, USBIN_V, and charger temperature



Add driver support for reading USB input voltage and current, and
charger temperature for PM855B, which are obtained from VADC channels.
Also update the documentation to correct an error, add descriptions
for io-channels properties, and update the example device tree with
required properties.

CRs-Fixed: 2228622
Change-Id: Iaa230050b2c8c02a5dfbe0ed1de49c6b374074ed
Signed-off-by: default avatarHarry Yang <harryy@codeaurora.org>
Signed-off-by: default avatarGuru Das Srinagesh <gurus@codeaurora.org>
parent 45755331
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -27,6 +27,13 @@ Charger specific properties:
  Definition: Should specify the phandle of PMI's revid module. This is used to
		identify the PMI subtype.

- io-channels
- io-channel-names
  Usage:      optional
  Value type: <phandle>
  Definition: For details about IIO bindings see:
		Documentation/devicetree/bindings/iio/iio-bindings.txt

- qcom,batteryless-platform
  Usage:      optional
  Value type: <empty>
@@ -223,13 +230,22 @@ Peripheral specific properties:
Example
=======

pmi8998_charger: qcom,qpnp-smb5 {
pm855b_charger: qcom,qpnp-smb5 {
	compatible = "qcom,qpnp-smb5";
	#address-cells = <1>;
	#size-cells = <1>;

	qcom,pmic-revid = <&pm855b_revid>;

	dpdm-supply = <&qusb_phy0>;

	io-channels = <&pm855b_vadc ADC_USB_IN_V_16>,
	              <&pm855b_vadc ADC_USB_IN_I>,
	              <&pm855b_vadc ADC_CHG_TEMP>;
	io-channel-names = "usb_in_voltage",
	                   "usb_in_current",
	                   "chg_temp";

	qcom,chgr@1000 {
		reg = <0x1000 0x100>;
		interrupts =	<0x2 0x10 0x0 IRQ_TYPE_NONE>,
+64 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/machine.h>
#include <linux/iio/consumer.h>
#include <linux/pmic-voter.h>
#include "smb5-reg.h"
#include "smb5-lib.h"
@@ -363,6 +364,50 @@ static int smb5_parse_dt(struct smb5 *chip)
	if (rc < 0)
		chg->otg_delay_ms = OTG_DEFAULT_DEGLITCH_TIME_MS;

	rc = of_property_match_string(node, "io-channel-names",
			"usb_in_voltage");
	if (rc >= 0) {
		chg->iio.usbin_v_chan = iio_channel_get(chg->dev,
				"usb_in_voltage");
		if (IS_ERR(chg->iio.usbin_v_chan)) {
			rc = PTR_ERR(chg->iio.usbin_v_chan);
			if (rc != -EPROBE_DEFER)
				dev_err(chg->dev, "USBIN_V channel unavailable, %ld\n",
						rc);
			chg->iio.usbin_v_chan = NULL;
			return rc;
		}
	}

	rc = of_property_match_string(node, "io-channel-names",
			"chg_temp");
	if (rc >= 0) {
		chg->iio.temp_chan = iio_channel_get(chg->dev, "chg_temp");
		if (IS_ERR(chg->iio.temp_chan)) {
			rc = PTR_ERR(chg->iio.temp_chan);
			if (rc != -EPROBE_DEFER)
				dev_err(chg->dev, "CHG_TEMP channel unavailable, %ld\n",
						rc);
			chg->iio.temp_chan = NULL;
			return rc;
		}
	}

	rc = of_property_match_string(node, "io-channel-names",
			"usb_in_current");
	if (rc >= 0) {
		chg->iio.usbin_i_chan = iio_channel_get(chg->dev,
				"usb_in_current");
		if (IS_ERR(chg->iio.usbin_i_chan)) {
			rc = PTR_ERR(chg->iio.usbin_i_chan);
			if (rc != -EPROBE_DEFER)
				dev_err(chg->dev, "USBIN_I channel unavailable, %ld\n",
						rc);
			chg->iio.usbin_i_chan = NULL;
			return rc;
		}
	}

	return 0;
}

@@ -372,6 +417,7 @@ static int smb5_parse_dt(struct smb5 *chip)
static enum power_supply_property smb5_usb_props[] = {
	POWER_SUPPLY_PROP_PRESENT,
	POWER_SUPPLY_PROP_ONLINE,
	POWER_SUPPLY_PROP_VOLTAGE_NOW,
	POWER_SUPPLY_PROP_PD_CURRENT_MAX,
	POWER_SUPPLY_PROP_CURRENT_MAX,
	POWER_SUPPLY_PROP_TYPE,
@@ -426,6 +472,9 @@ static int smb5_usb_get_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
		rc = smblib_get_prop_usb_voltage_max(chg, val);
		break;
	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
		rc = smblib_get_prop_usb_voltage_now(chg, val);
		break;
	case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
		val->intval = get_client_vote(chg->usb_icl_votable, PD_VOTER);
		break;
@@ -462,6 +511,9 @@ static int smb5_usb_get_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED:
		rc = smblib_get_prop_input_current_settled(chg, val);
		break;
	case POWER_SUPPLY_PROP_INPUT_CURRENT_NOW:
		rc = smblib_get_prop_usb_current_now(chg, val);
		break;
	case POWER_SUPPLY_PROP_BOOST_CURRENT:
		val->intval = chg->boost_current_ua;
		break;
@@ -947,6 +999,7 @@ static enum power_supply_property smb5_batt_props[] = {
	POWER_SUPPLY_PROP_PRESENT,
	POWER_SUPPLY_PROP_CHARGE_TYPE,
	POWER_SUPPLY_PROP_CAPACITY,
	POWER_SUPPLY_PROP_CHARGER_TEMP,
	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
	POWER_SUPPLY_PROP_VOLTAGE_NOW,
	POWER_SUPPLY_PROP_VOLTAGE_MAX,
@@ -973,6 +1026,8 @@ static int smb5_batt_get_prop(struct power_supply *psy,
		union power_supply_propval *val)
{
	struct smb_charger *chg = power_supply_get_drvdata(psy);
	union power_supply_propval pval = {0, };

	int rc = 0;

	switch (psp) {
@@ -1000,6 +1055,15 @@ static int smb5_batt_get_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
		rc = smblib_get_prop_system_temp_level_max(chg, val);
		break;
	case POWER_SUPPLY_PROP_CHARGER_TEMP:
		rc = smblib_get_prop_usb_present(chg, &pval);
		if (rc < 0) {
			pr_err("Couldn't get usb present rc=%d\n", rc);
			break;
		}
		if (pval.intval)
			rc = smblib_get_prop_charger_temp(chg, val);
		break;
	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
		rc = smblib_get_prop_input_current_limited(chg, val);
		break;
+73 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/regulator/driver.h>
#include <linux/qpnp/qpnp-revid.h>
#include <linux/irq.h>
#include <linux/iio/consumer.h>
#include <linux/pmic-voter.h>
#include "smb5-lib.h"
#include "smb5-reg.h"
@@ -1788,6 +1789,36 @@ int smblib_get_prop_usb_voltage_max(struct smb_charger *chg,
	return 0;
}

int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
				    union power_supply_propval *val)
{
	if (chg->iio.usbin_v_chan)
		return iio_read_channel_processed(chg->iio.usbin_v_chan,
				&val->intval);
	else
		return -ENODATA;
}

int smblib_get_prop_charger_temp(struct smb_charger *chg,
				 union power_supply_propval *val)
{
	int rc;

	if (chg->iio.temp_chan) {
		rc = iio_read_channel_processed(chg->iio.temp_chan,
				&val->intval);
		if (rc < 0) {
			pr_err("Error in reading temp channel, rc=%d", rc);
			return rc;
		}
		val->intval /= 100;
	} else {
		return -ENODATA;
	}

	return rc;
}

int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
					 union power_supply_propval *val)
{
@@ -1936,6 +1967,36 @@ int smblib_get_prop_typec_power_role(struct smb_charger *chg,
	return rc;
}

int smblib_get_prop_usb_current_now(struct smb_charger *chg,
				    union power_supply_propval *val)
{
	int rc = 0;

	if (chg->iio.usbin_i_chan) {
		rc = iio_read_channel_processed(chg->iio.usbin_i_chan,
				&val->intval);

		/*
		 * For PM855B, scaling factor = reciprocal of
		 * 0.2V/A in Buck mode, 0.4V/A in Boost mode.
		 */
		if (smblib_get_prop_ufp_mode(chg) != POWER_SUPPLY_TYPEC_NONE) {
			val->intval *= 5;
			return rc;
		}

		if (smblib_get_prop_dfp_mode(chg) != POWER_SUPPLY_TYPEC_NONE) {
			val->intval = DIV_ROUND_CLOSEST(val->intval * 100, 40);
			return rc;
		}
	} else {
		rc = -ENODATA;
	}

	val->intval = 0;
	return rc;
}

int smblib_get_prop_input_current_settled(struct smb_charger *chg,
					  union power_supply_propval *val)
{
@@ -3531,6 +3592,16 @@ static void smblib_destroy_votables(struct smb_charger *chg)
		destroy_votable(chg->chg_disable_votable);
}

static void smblib_iio_deinit(struct smb_charger *chg)
{
	if (!IS_ERR_OR_NULL(chg->iio.usbin_v_chan))
		iio_channel_release(chg->iio.usbin_v_chan);
	if (!IS_ERR_OR_NULL(chg->iio.usbin_i_chan))
		iio_channel_release(chg->iio.usbin_i_chan);
	if (!IS_ERR_OR_NULL(chg->iio.temp_chan))
		iio_channel_release(chg->iio.temp_chan);
}

int smblib_init(struct smb_charger *chg)
{
	int rc = 0;
@@ -3622,5 +3693,7 @@ int smblib_deinit(struct smb_charger *chg)
		return -EINVAL;
	}

	smblib_iio_deinit(chg);

	return 0;
}
+6 −4
Original line number Diff line number Diff line
@@ -245,14 +245,10 @@ struct parallel_params {

struct smb_iio {
	struct iio_channel	*temp_chan;
	struct iio_channel	*temp_max_chan;
	struct iio_channel	*usbin_i_chan;
	struct iio_channel	*usbin_v_chan;
	struct iio_channel	*batt_i_chan;
	struct iio_channel	*connector_temp_chan;
	struct iio_channel	*connector_temp_thr1_chan;
	struct iio_channel	*connector_temp_thr2_chan;
	struct iio_channel	*connector_temp_thr3_chan;
};

struct smb_charger {
@@ -485,6 +481,10 @@ int smblib_get_prop_usb_suspend(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_usb_voltage_max(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_usb_current_now(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_typec_power_role(struct smb_charger *chg,
@@ -497,6 +497,8 @@ int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
			       union power_supply_propval *val);
int smblib_get_pe_start(struct smb_charger *chg,
			       union power_supply_propval *val);
int smblib_get_prop_charger_temp(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_prop_die_health(struct smb_charger *chg,
			       union power_supply_propval *val);
int smblib_set_prop_pd_current_max(struct smb_charger *chg,