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

Commit 7c5d7965 authored by Rama Krishna Phani A's avatar Rama Krishna Phani A Committed by Jishnu Prakash
Browse files

iio: qcom-rradc: Update logic to monitor health of RRADC peripheral



Update logic to support monitoring health of RRADC peripheral by
registering to power supply framework and check RRADC peripheral
status in case of charging events.

Change-Id: I0ac99b04ffe3aad7c2880d47ecf3c8ce135f06a2
Signed-off-by: default avatarRama Krishna Phani A <rphani@codeaurora.org>
parent cedc9d93
Loading
Loading
Loading
Loading
+130 −4
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2016-2017, 2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2017, 2020-2021, The Linux Foundation. All rights reserved.
 */

#define pr_fmt(fmt) "RRADC: %s: " fmt, __func__
@@ -186,6 +186,7 @@
#define FG_RR_ADC_STS_CHANNEL_STS		0x2

#define FG_RR_CONV_CONTINUOUS_TIME_MIN_MS	50
#define FG_RR_CONV_CONT_CBK_TIME_MIN_MS	10
#define FG_RR_CONV_MAX_RETRY_CNT		50
#define FG_RR_TP_REV_VERSION1		21
#define FG_RR_TP_REV_VERSION2		29
@@ -228,6 +229,12 @@ struct rradc_chip {
	struct pmic_revid_data		*pmic_fab_id;
	int volt;
	struct power_supply		*usb_trig;
	struct power_supply		*batt_psy;
	struct power_supply		*bms_psy;
	struct notifier_block		nb;
	bool				conv_cbk;
	bool				rradc_fg_reset_wa;
	struct work_struct	psy_notify_work;
};

struct rradc_channels {
@@ -672,6 +679,28 @@ static const struct rradc_channels rradc_chans[] = {
			FG_ADC_RR_AUX_THERM_STS)
};

static bool rradc_is_batt_psy_available(struct rradc_chip *chip)
{
	if (!chip->batt_psy)
		chip->batt_psy = power_supply_get_by_name("battery");

	if (!chip->batt_psy)
		return false;

	return true;
}

static bool rradc_is_bms_psy_available(struct rradc_chip *chip)
{
	if (!chip->bms_psy)
		chip->bms_psy = power_supply_get_by_name("bms");

	if (!chip->bms_psy)
		return false;

	return true;
}

static int rradc_enable_continuous_mode(struct rradc_chip *chip)
{
	int rc = 0;
@@ -741,6 +770,7 @@ static int rradc_check_status_ready_with_retry(struct rradc_chip *chip,
		struct rradc_chan_prop *prop, u8 *buf, u16 status)
{
	int rc = 0, retry_cnt = 0, mask = 0;
	union power_supply_propval pval = {0, };

	switch (prop->channel) {
	case RR_ADC_BATT_ID:
@@ -766,7 +796,11 @@ static int rradc_check_status_ready_with_retry(struct rradc_chip *chip,
			break;
		}

		if ((chip->conv_cbk) && (prop->channel == RR_ADC_USBIN_V))
			msleep(FG_RR_CONV_CONT_CBK_TIME_MIN_MS);
		else
			msleep(FG_RR_CONV_CONTINUOUS_TIME_MIN_MS);

		retry_cnt++;
		rc = rradc_read(chip, status, buf, 1);
		if (rc < 0) {
@@ -775,8 +809,27 @@ static int rradc_check_status_ready_with_retry(struct rradc_chip *chip,
		}
	}

	if ((retry_cnt >= FG_RR_CONV_MAX_RETRY_CNT) &&
		((prop->channel != RR_ADC_DCIN_V) ||
		(prop->channel != RR_ADC_DCIN_I)) &&
		chip->rradc_fg_reset_wa) {
		pr_err("rradc is hung, Proceed to recovery\n");
		if (rradc_is_bms_psy_available(chip)) {
			rc = power_supply_set_property(chip->bms_psy,
					POWER_SUPPLY_PROP_FG_RESET_CLOCK,
					&pval);
			if (rc < 0) {
				pr_err("Couldn't reset FG clock rc=%d\n", rc);
				return rc;
			}
		} else {
			pr_err("Error obtaining bms power supply\n");
			rc = -EINVAL;
		}
	} else {
		if (retry_cnt >= FG_RR_CONV_MAX_RETRY_CNT)
			rc = -ENODATA;
	}

	return rc;
}
@@ -1088,6 +1141,67 @@ static int rradc_read_raw(struct iio_dev *indio_dev,
	return rc;
}

static void psy_notify_work(struct work_struct *work)
{
	struct rradc_chip *chip = container_of(work,
			struct rradc_chip, psy_notify_work);

	struct rradc_chan_prop *prop;
	union power_supply_propval pval = {0, };
	u16 adc_code;
	int rc = 0;

	if (rradc_is_batt_psy_available(chip)) {
		rc = power_supply_get_property(chip->batt_psy,
			POWER_SUPPLY_PROP_STATUS, &pval);
		if (rc < 0)
			pr_err("Error obtaining battery status, rc=%d\n", rc);

		if (pval.intval == POWER_SUPPLY_STATUS_CHARGING) {
			chip->conv_cbk = true;
			prop = &chip->chan_props[RR_ADC_USBIN_V];
			rc = rradc_do_conversion(chip, prop, &adc_code);
			if (rc == -ENODATA) {
				pr_err("rradc is hung, Proceed to recovery\n");
				if (rradc_is_bms_psy_available(chip)) {
					rc = power_supply_set_property
						(chip->bms_psy,
						POWER_SUPPLY_PROP_FG_RESET_CLOCK,
						&pval);
					if (rc < 0)
						pr_err("Couldn't reset FG clock rc=%d\n",
								rc);
					prop = &chip->chan_props[RR_ADC_BATT_ID];
					rc = rradc_do_conversion(chip, prop,
							&adc_code);
					if (rc == -ENODATA)
						pr_err("RRADC read failed after reset\n");
				} else {
					pr_err("Error obtaining bms power supply\n");
				}
			}
		}
	} else {
		pr_err("Error obtaining battery power supply\n");
	}
	chip->conv_cbk = false;
	pm_relax(chip->dev);
}

static int rradc_psy_notifier_cb(struct notifier_block *nb,
		unsigned long event, void *data)
{
	struct power_supply *psy = data;
	struct rradc_chip *chip = container_of(nb, struct rradc_chip, nb);

	if (strcmp(psy->desc->name, "battery") == 0) {
		pm_stay_awake(chip->dev);
		schedule_work(&chip->psy_notify_work);
	}

	return NOTIFY_OK;
}

static const struct iio_info rradc_info = {
	.read_raw	= &rradc_read_raw,
};
@@ -1140,6 +1254,9 @@ static int rradc_get_dt_data(struct rradc_chip *chip, struct device_node *node)
		}
	}

	chip->rradc_fg_reset_wa =
		of_property_read_bool(node, "qcom,rradc-fg-reset-wa");

	iio_chan = chip->iio_chans;

	for (i = 0; i < RR_ADC_MAX; i++) {
@@ -1201,6 +1318,15 @@ static int rradc_probe(struct platform_device *pdev)
	if (!chip->usb_trig)
		pr_debug("Error obtaining usb power supply\n");

	if (chip->rradc_fg_reset_wa) {
		chip->nb.notifier_call = rradc_psy_notifier_cb;
		rc = power_supply_reg_notifier(&chip->nb);
		if (rc < 0)
			pr_err("Error registering psy notifier rc = %d\n", rc);

		INIT_WORK(&chip->psy_notify_work, psy_notify_work);
	}

	return devm_iio_device_register(dev, indio_dev);
}