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

Commit 407d4752 authored by Jishnu Prakash's avatar Jishnu Prakash
Browse files

iio: adc5: Skip USB_IN_V workaround for specific PMICs



SW workaround to read USB_IN_V channel through VADC is
not required on some PMIC versions, such as version 2 of
PM6150. Skip workaround for specified PMIC versions.

Change-Id: Ie45de8e239f1b535e09567ad9c683167951407cf
Signed-off-by: default avatarJishnu Prakash <jprakash@codeaurora.org>
parent 71644d76
Loading
Loading
Loading
Loading
+45 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/log2.h>
#include <linux/qpnp/qpnp-revid.h>

#include <dt-bindings/iio/qcom,spmi-vadc.h>

@@ -105,6 +106,11 @@ enum adc_cal_val {
	ADC_NEW_CAL
};

struct pmic_rev_data {
	int subtype;
	int rev4;
};

/**
 * struct adc_channel_prop - ADC channel property.
 * @channel: channel number, refer to the channel list.
@@ -156,6 +162,7 @@ struct adc_chip {
	bool			poll_eoc;
	struct completion	complete;
	struct mutex		lock;
	bool			skip_usb_wa;
	const struct adc_data	*data;
};

@@ -332,7 +339,8 @@ static int adc_post_configure_usb_in_read(struct adc_chip *adc,
{
	u8 data;

	if ((prop->channel == ADC_USB_IN_V_16) && adc->cal_addr) {
	if ((prop->channel == ADC_USB_IN_V_16) && adc->cal_addr &&
			!adc->skip_usb_wa) {
		data = ADC_CAL_DELAY_CTL_VAL_125MS;
		/* Set calibration measurement interval to 125ms */
		return regmap_bulk_write(adc->regmap,
@@ -448,7 +456,8 @@ static int adc_do_conversion(struct adc_chip *adc,

	mutex_lock(&adc->lock);

	if ((prop->channel == ADC_USB_IN_V_16) && adc->cal_addr) {
	if ((prop->channel == ADC_USB_IN_V_16) && adc->cal_addr &&
			!adc->skip_usb_wa) {
		ret = adc_pre_configure_usb_in_read(adc);
		if (ret) {
			pr_err("ADC configure failed with %d\n", ret);
@@ -877,9 +886,30 @@ static int adc_get_dt_data(struct adc_chip *adc, struct device_node *node)
	return 0;
}

static const struct pmic_rev_data pmic_data[] = {
	{PM6150_SUBTYPE,	1},
};

bool skip_usb_in_wa(struct pmic_revid_data *pmic_rev_id)
{
	int i = 0;
	uint32_t tablesize = ARRAY_SIZE(pmic_data);

	while (i < tablesize) {
		if (pmic_data[i].subtype == pmic_rev_id->pmic_subtype
		 && pmic_data[i].rev4 < pmic_rev_id->rev4) {
			return true;
		}
		i++;
	}
	return false;
}

static int adc_probe(struct platform_device *pdev)
{
	struct device_node *node = pdev->dev.of_node;
	struct device_node *revid_dev_node;
	struct pmic_revid_data	*pmic_rev_id;
	struct device *dev = &pdev->dev;
	struct iio_dev *indio_dev;
	struct adc_chip *adc;
@@ -887,6 +917,7 @@ static int adc_probe(struct platform_device *pdev)
	const __be32 *prop_addr;
	int ret, irq_eoc;
	u32 reg;
	bool skip_usb_wa = false;

	regmap = dev_get_regmap(dev->parent, NULL);
	if (!regmap)
@@ -896,6 +927,16 @@ static int adc_probe(struct platform_device *pdev)
	if (ret < 0)
		return ret;

	revid_dev_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
	if (revid_dev_node) {
		pmic_rev_id = get_revid_data(revid_dev_node);
		if (!(IS_ERR(pmic_rev_id)))
			skip_usb_wa = skip_usb_in_wa(pmic_rev_id);
		else
			pr_err("Unable to get revid\n");
		of_node_put(revid_dev_node);
	}

	indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
	if (!indio_dev)
		return -ENOMEM;
@@ -917,6 +958,8 @@ static int adc_probe(struct platform_device *pdev)
	else
		adc->cal_addr = be32_to_cpu(*prop_addr);

	adc->skip_usb_wa = skip_usb_wa;

	init_completion(&adc->complete);
	mutex_init(&adc->lock);