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

Commit 69d7a1d4 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ARM: dts: msm: Add FG GEN3 and RRADC device node for PM660"

parents 55b5671d bca93934
Loading
Loading
Loading
Loading
+74 −0
Original line number Diff line number Diff line
@@ -302,6 +302,7 @@
		};

		pm660_charger: qcom,qpnp-smb2 {
			spmi-dev-container;
			compatible = "qcom,qpnp-smb2";
			#address-cells = <1>;
			#size-cells = <1>;
@@ -424,6 +425,79 @@
			};
		};

		pm660_rradc: rradc@4500 {
			compatible = "qcom,rradc";
			reg = <0x4500 0x100>;
			#address-cells = <1>;
			#size-cells = <0>;
			#io-channel-cells = <1>;
			qcom,pmic-revid = <&pm660_revid>;
		};

		pm660_fg: qpnp,fg {
			spmi-dev-container;
			compatible = "qcom,fg-gen3";
			#address-cells = <1>;
			#size-cells = <1>;
			qcom,pmic-revid = <&pm660_revid>;
			io-channels = <&pm660_rradc 0>,
				      <&pm660_rradc 7>;
			io-channel-names = "rradc_batt_id",
					   "rradc_die_temp";
			qcom,rradc-base = <0x4500>;
			qcom,fg-esr-timer-awake = <96 96>;
			qcom,fg-esr-timer-asleep = <256 256>;
			qcom,fg-esr-timer-charging = <0 96>;
			qcom,cycle-counter-en;
			status = "okay";

			qcom,fg-batt-soc@4000 {
				status = "okay";
				reg = <0x4000 0x100>;
				interrupts = <0x0 0x40 0x0>,
					     <0x0 0x40 0x1>,
					     <0x0 0x40 0x2>,
					     <0x0 0x40 0x3>,
					     <0x0 0x40 0x4>,
					     <0x0 0x40 0x5>,
					     <0x0 0x40 0x6>,
					     <0x0 0x40 0x7>;
				interrupt-names = "soc-update",
						  "soc-ready",
						  "bsoc-delta",
						  "msoc-delta",
						  "msoc-low",
						  "msoc-empty",
						  "msoc-high",
						  "msoc-full";
			};

			qcom,fg-batt-info@4100 {
				status = "okay";
				reg = <0x4100 0x100>;
				interrupts = <0x0 0x41 0x0>,
					     <0x0 0x41 0x1>,
					     <0x0 0x41 0x2>,
					     <0x0 0x41 0x3>,
					     <0x0 0x41 0x6>;
				interrupt-names = "vbatt-pred-delta",
						  "vbatt-low",
						  "esr-delta",
						  "batt-missing",
						  "batt-temp-delta";
			};

			qcom,fg-memif@4400 {
				status = "okay";
				reg = <0x4400 0x100>;
				interrupts = <0x0 0x44 0x0>,
					     <0x0 0x44 0x1>,
					     <0x0 0x44 0x2>;
				interrupt-names = "ima-rdy",
						  "mem-xcp",
						  "dma-grant";
			};
		};

		pm660_pbs: qcom,pbs@7300 {
			compatible = "qcom,qpnp-pbs";
+116 −43
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/regmap.h>
#include <linux/delay.h>
#include <linux/qpnp/qpnp-revid.h>
#include <linux/spmi.h>

#define FG_ADC_RR_EN_CTL			0x46
#define FG_ADC_RR_SKIN_TEMP_LSB			0x50
@@ -223,6 +224,9 @@ struct rradc_chip {
	struct mutex			lock;
	struct regmap			*regmap;
	u16				base;
	struct spmi_device		*spmi;
	u8				slave;
	u16			offset;
	struct iio_chan_spec		*iio_chans;
	unsigned int			nchannels;
	struct rradc_chan_prop		*chan_props;
@@ -248,21 +252,36 @@ struct rradc_chan_prop {
					u16 adc_code, int *result);
};

static int rradc_masked_write(struct rradc_chip *rr_adc, u16 offset, u8 mask,
						u8 val)
static int rradc_spmi_read(struct rradc_chip *rr_adc, unsigned int reg,
						u8 *data, int len)
{
	int rc;

	rc = regmap_update_bits(rr_adc->regmap, rr_adc->base + offset,
								mask, val);
	if (rc) {
		pr_err("spmi write failed: addr=%03X, rc=%d\n", offset, rc);
	rc = spmi_ext_register_readl(rr_adc->spmi->ctrl, rr_adc->slave,
		reg, data, len);
	if (rc < 0) {
		pr_err("rradc spmi read reg %x failed with %d\n", reg, rc);
		return rc;
	}

	return 0;
}

static int rradc_spmi_write(struct rradc_chip *rr_adc, u16 reg,
						u8 *buf, int len)
{
	int rc;

	rc = spmi_ext_register_writel(rr_adc->spmi->ctrl, rr_adc->slave,
		reg, buf, len);
	if (rc < 0) {
		pr_err("rradc spmi write reg %d failed with %d\n", reg, rc);
		return rc;
	}

	return 0;
}

static int rradc_read(struct rradc_chip *rr_adc, u16 offset, u8 *data, int len)
{
	int rc = 0, retry_cnt = 0, i = 0;
@@ -275,14 +294,14 @@ static int rradc_read(struct rradc_chip *rr_adc, u16 offset, u8 *data, int len)
	}

	while (retry_cnt < FG_RR_ADC_COHERENT_CHECK_RETRY) {
		rc = regmap_bulk_read(rr_adc->regmap, rr_adc->base + offset,
		rc = rradc_spmi_read(rr_adc, rr_adc->base + offset,
							data, len);
		if (rc < 0) {
			pr_err("rr_adc reg 0x%x failed :%d\n", offset, rc);
			return rc;
		}

		rc = regmap_bulk_read(rr_adc->regmap, rr_adc->base + offset,
		rc = rradc_spmi_read(rr_adc, rr_adc->base + offset,
							data_check, len);
		if (rc < 0) {
			pr_err("rr_adc reg 0x%x failed :%d\n", offset, rc);
@@ -635,27 +654,35 @@ static const struct rradc_channels rradc_chans[] = {
static int rradc_enable_continuous_mode(struct rradc_chip *chip)
{
	int rc = 0;
	u8 result, value;

	/* Clear channel log */
	rc = rradc_masked_write(chip, FG_ADC_RR_ADC_LOG,
			FG_ADC_RR_ADC_LOG_CLR_CTRL,
			FG_ADC_RR_ADC_LOG_CLR_CTRL);
	rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_ADC_LOG,
			&result, 1);
	value = (result) | FG_ADC_RR_ADC_LOG_CLR_CTRL;
	rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_ADC_LOG,
			&value, 1);
	if (rc < 0) {
		pr_err("log ctrl update to clear failed:%d\n", rc);
		return rc;
	}

	rc = rradc_masked_write(chip, FG_ADC_RR_ADC_LOG,
		FG_ADC_RR_ADC_LOG_CLR_CTRL, 0);
	rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_ADC_LOG,
			&result, 1);
	value = (result) & ~(FG_ADC_RR_ADC_LOG_CLR_CTRL);
	rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_ADC_LOG,
			&value, 1);
	if (rc < 0) {
		pr_err("log ctrl update to not clear failed:%d\n", rc);
		return rc;
	}

	/* Switch to continuous mode */
	rc = rradc_masked_write(chip, FG_ADC_RR_RR_ADC_CTL,
		FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK,
		FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL);
	rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_RR_ADC_CTL,
			&result, 1);
	value = (result) | FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL;
	rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_RR_ADC_CTL,
			&value, 1);
	if (rc < 0) {
		pr_err("Update to continuous mode failed:%d\n", rc);
		return rc;
@@ -667,10 +694,14 @@ static int rradc_enable_continuous_mode(struct rradc_chip *chip)
static int rradc_disable_continuous_mode(struct rradc_chip *chip)
{
	int rc = 0;
	u8 result, value;

	/* Switch to non continuous mode */
	rc = rradc_masked_write(chip, FG_ADC_RR_RR_ADC_CTL,
			FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK, 0);
	rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_RR_ADC_CTL,
			&result, 1);
	value = (result) & ~(FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL);
	rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_RR_ADC_CTL,
			&value, 1);
	if (rc < 0) {
		pr_err("Update to non-continuous mode failed:%d\n", rc);
		return rc;
@@ -752,18 +783,24 @@ static int rradc_read_channel_with_continuous_mode(struct rradc_chip *chip,
static int rradc_enable_batt_id_channel(struct rradc_chip *chip, bool enable)
{
	int rc = 0;
	u8 result, value;

	if (enable) {
		rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_CTRL,
				FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV,
				FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV);
		rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_BATT_ID_CTRL,
				&result, 1);
		value = (result) | FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV;
		rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_BATT_ID_CTRL,
				&value, 1);
		if (rc < 0) {
			pr_err("Enabling BATT ID channel failed:%d\n", rc);
			return rc;
		}
	} else {
		rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_CTRL,
				FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV, 0);
		rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_BATT_ID_CTRL,
				&result, 1);
		value = (result) & ~(FG_ADC_RR_BATT_ID_CTRL_CHANNEL_CONV);
		rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_BATT_ID_CTRL,
				&value, 1);
		if (rc < 0) {
			pr_err("Disabling BATT ID channel failed:%d\n", rc);
			return rc;
@@ -777,6 +814,7 @@ static int rradc_do_batt_id_conversion(struct rradc_chip *chip,
		struct rradc_chan_prop *prop, u16 *data, u8 *buf)
{
	int rc = 0, ret = 0;
	u8 result, value;

	rc = rradc_enable_batt_id_channel(chip, true);
	if (rc < 0) {
@@ -784,9 +822,11 @@ static int rradc_do_batt_id_conversion(struct rradc_chip *chip,
		return rc;
	}

	rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_TRIGGER,
				FG_ADC_RR_BATT_ID_TRIGGER_CTL,
				FG_ADC_RR_BATT_ID_TRIGGER_CTL);
	rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_BATT_ID_TRIGGER,
			&result, 1);
	value = (result) | FG_ADC_RR_BATT_ID_TRIGGER_CTL;
	rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_BATT_ID_TRIGGER,
			&value, 1);
	if (rc < 0) {
		pr_err("BATT_ID trigger set failed:%d\n", rc);
		ret = rc;
@@ -802,8 +842,11 @@ static int rradc_do_batt_id_conversion(struct rradc_chip *chip,
		ret = rc;
	}

	rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_TRIGGER,
			FG_ADC_RR_BATT_ID_TRIGGER_CTL, 0);
	rc = rradc_spmi_read(chip, chip->base + FG_ADC_RR_BATT_ID_TRIGGER,
			&result, 1);
	value = (result) & ~(FG_ADC_RR_BATT_ID_TRIGGER_CTL);
	rc = rradc_spmi_write(chip, chip->base + FG_ADC_RR_BATT_ID_TRIGGER,
			&value, 1);
	if (rc < 0) {
		pr_err("BATT_ID trigger re-set failed:%d\n", rc);
		ret = rc;
@@ -825,6 +868,7 @@ static int rradc_do_conversion(struct rradc_chip *chip,
	u8 buf[6];
	u16 offset = 0, batt_id_5 = 0, batt_id_15 = 0, batt_id_150 = 0;
	u16 status = 0;
	u8 result, value;

	mutex_lock(&chip->lock);

@@ -838,9 +882,13 @@ static int rradc_do_conversion(struct rradc_chip *chip,
		break;
	case RR_ADC_USBIN_V:
		/* Force conversion every cycle */
		rc = rradc_masked_write(chip, FG_ADC_RR_USB_IN_V_TRIGGER,
				FG_ADC_RR_USB_IN_V_EVERY_CYCLE_MASK,
				FG_ADC_RR_USB_IN_V_EVERY_CYCLE);
		rc = rradc_spmi_read(chip,
				chip->base + FG_ADC_RR_USB_IN_V_TRIGGER,
				&result, 1);
		value = (result) | FG_ADC_RR_USB_IN_V_EVERY_CYCLE;
		rc = rradc_spmi_write(chip,
				chip->base + FG_ADC_RR_USB_IN_V_TRIGGER,
				&value, 1);
		if (rc < 0) {
			pr_err("Force every cycle update failed:%d\n", rc);
			goto fail;
@@ -853,8 +901,13 @@ static int rradc_do_conversion(struct rradc_chip *chip,
		}

		/* Restore usb_in trigger */
		rc = rradc_masked_write(chip, FG_ADC_RR_USB_IN_V_TRIGGER,
				FG_ADC_RR_USB_IN_V_EVERY_CYCLE_MASK, 0);
		rc = rradc_spmi_read(chip,
				chip->base + FG_ADC_RR_USB_IN_V_TRIGGER,
				&result, 1);
		value = (result) & ~(FG_ADC_RR_USB_IN_V_EVERY_CYCLE);
		rc = rradc_spmi_write(chip,
				chip->base + FG_ADC_RR_USB_IN_V_TRIGGER,
				&value, 1);
		if (rc < 0) {
			pr_err("Restore every cycle update failed:%d\n", rc);
			goto fail;
@@ -1053,10 +1106,11 @@ static int rradc_get_dt_data(struct rradc_chip *chip, struct device_node *node)
	return 0;
}

static int rradc_probe(struct platform_device *pdev)
static int rradc_probe(struct spmi_device *spmi)
{
	struct device_node *node = pdev->dev.of_node;
	struct device *dev = &pdev->dev;
	struct device_node *node = spmi->dev.of_node;
	struct device *dev = &(spmi->dev);
	struct resource *res;
	struct iio_dev *indio_dev;
	struct rradc_chip *chip;
	int rc = 0;
@@ -1066,12 +1120,21 @@ static int rradc_probe(struct platform_device *pdev)
		return -ENOMEM;

	chip = iio_priv(indio_dev);
	chip->regmap = dev_get_regmap(pdev->dev.parent, NULL);
	chip->regmap = dev_get_regmap(&(spmi->dev), NULL);
	if (!chip->regmap) {
		dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
		pr_debug("Couldn't get parent's regmap\n");
	}

	chip->spmi = spmi;
	res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
	if (!res) {
		pr_err("RRADC No base address definition\n");
		return -EINVAL;
	}

	chip->slave = spmi->sid;
	chip->offset = res->start;

	chip->dev = dev;
	mutex_init(&chip->lock);

@@ -1081,7 +1144,7 @@ static int rradc_probe(struct platform_device *pdev)

	indio_dev->dev.parent = dev;
	indio_dev->dev.of_node = node;
	indio_dev->name = pdev->name;
	indio_dev->name = spmi->name;
	indio_dev->modes = INDIO_DIRECT_MODE;
	indio_dev->info = &rradc_info;
	indio_dev->channels = chip->iio_chans;
@@ -1094,16 +1157,26 @@ static const struct of_device_id rradc_match_table[] = {
	{ .compatible = "qcom,rradc" },
	{ }
};
MODULE_DEVICE_TABLE(of, rradc_match_table);

static struct platform_driver rradc_driver = {
static struct spmi_driver qpnp_rradc_driver = {
	.driver		= {
		.name		= "qcom-rradc",
		.of_match_table	= rradc_match_table,
	},
	.probe = rradc_probe,
};
module_platform_driver(rradc_driver);

static int __init qpnp_rradc_init(void)
{
	return spmi_driver_register(&qpnp_rradc_driver);
}
module_init(qpnp_rradc_init);

static void __exit qpnp_rradc_exit(void)
{
	spmi_driver_unregister(&qpnp_rradc_driver);
}
module_exit(qpnp_rradc_exit);

MODULE_DESCRIPTION("QPNP PMIC RR ADC driver");
MODULE_LICENSE("GPL v2");
+1 −1
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ obj-$(CONFIG_BATTERY_BQ28400) += bq28400_battery.o
obj-$(CONFIG_QPNP_BMS)		+= qpnp-bms.o batterydata-lib.o
obj-$(CONFIG_QPNP_VM_BMS)	+= qpnp-vm-bms.o batterydata-lib.o batterydata-interface.o
obj-$(CONFIG_QPNP_FG)		+= qpnp-fg.o
obj-$(CONFIG_QPNP_FG_GEN3)	+= qpnp-fg-gen3.o fg-memif.o fg-util.o
obj-$(CONFIG_QPNP_FG_GEN3)	+= qpnp-fg-gen3.o fg-memif.o fg-util.o pmic-voter.o
obj-$(CONFIG_QPNP_CHARGER)	+= qpnp-charger.o
obj-$(CONFIG_QPNP_LINEAR_CHARGER)	+= qpnp-linear-charger.o
obj-$(CONFIG_QPNP_SMBCHARGER)	+= qpnp-smbcharger.o pmic-voter.o
+4 −3
Original line number Diff line number Diff line
@@ -23,8 +23,8 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/spmi.h>
#include <linux/power_supply.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/string_helpers.h>
#include <linux/types.h>
@@ -306,6 +306,7 @@ struct fg_irq_info {
	const irq_handler_t	handler;
	bool			wakeable;
	int			irq;
	int			flags;
};

struct fg_circ_buf {
@@ -351,9 +352,9 @@ static const struct fg_pt fg_tsmc_osc_table[] = {
struct fg_chip {
	struct device		*dev;
	struct pmic_revid_data	*pmic_rev_id;
	struct regmap		*regmap;
	struct spmi_device	*spmi;
	struct dentry		*dfs_root;
	struct power_supply	*fg_psy;
	struct power_supply	fg_psy;
	struct power_supply	*batt_psy;
	struct power_supply	*usb_psy;
	struct power_supply	*dc_psy;
+34 −23
Original line number Diff line number Diff line
@@ -353,15 +353,14 @@ int fg_sram_masked_write(struct fg_chip *chip, u16 address, u8 offset,
int fg_read(struct fg_chip *chip, int addr, u8 *val, int len)
{
	int rc, i;
	struct spmi_device *spmi = chip->spmi;

	if (!chip || !chip->regmap)
	if (!chip || !chip->spmi)
		return -ENXIO;

	rc = regmap_bulk_read(chip->regmap, addr, val, len);

	if (rc < 0) {
		dev_err(chip->dev, "regmap_read failed for address %04x rc=%d\n",
			addr, rc);
	rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, val, len);
	if (rc) {
		pr_err("SPMI read failed addr=0x%02x rc=%d\n", addr, rc);
		return rc;
	}

@@ -378,26 +377,25 @@ int fg_write(struct fg_chip *chip, int addr, u8 *val, int len)
{
	int rc, i;
	bool sec_access = false;
	u8 sec_addr_val = 0xA5;
	struct spmi_device *spmi = chip->spmi;

	if (!chip || !chip->regmap)
	if (!chip || !chip->spmi)
		return -ENXIO;

	mutex_lock(&chip->bus_lock);
	sec_access = (addr & 0x00FF) > 0xD0;
	if (sec_access) {
		rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5);
		rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid,
				(addr & 0xFF00) | 0xD0, &sec_addr_val, 1);
		if (rc < 0) {
			dev_err(chip->dev, "regmap_write failed for address %x rc=%d\n",
			pr_err("SPMI write failed addr=0x%02x rc=%d\n",
							addr, rc);
			goto out;
		}
	}

	if (len > 1)
		rc = regmap_bulk_write(chip->regmap, addr, val, len);
	else
		rc = regmap_write(chip->regmap, addr, *val);

	rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, val, len);
	if (rc < 0) {
		dev_err(chip->dev, "regmap_write failed for address %04x rc=%d\n",
			addr, rc);
@@ -418,30 +416,43 @@ int fg_masked_write(struct fg_chip *chip, int addr, u8 mask, u8 val)
{
	int rc;
	bool sec_access = false;
	u8 reg, sec_addr_val = 0xA5;
	struct spmi_device *spmi = chip->spmi;

	if (!chip || !chip->regmap)
	if (!chip || !chip->spmi)
		return -ENXIO;

	mutex_lock(&chip->bus_lock);
	rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, &reg, 1);
	if (rc) {
		pr_err("SPMI read failed addr=0x%02x rc=%d\n", addr, rc);
		goto out;
	}

	reg &= ~mask;
	reg |= val & mask;

	sec_access = (addr & 0x00FF) > 0xD0;
	if (sec_access) {
		rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5);
		rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid,
				(addr & 0xFF00) | 0xD0, &sec_addr_val, 1);
		if (rc < 0) {
			dev_err(chip->dev, "regmap_write failed for address %x rc=%d\n",
			pr_err("SPMI write failed addr=0x%02x rc=%d\n",
							addr, rc);
			goto out;
		}
	}

	rc = regmap_update_bits(chip->regmap, addr, mask, val);
	rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, &reg, 1);
	if (rc < 0) {
		dev_err(chip->dev, "regmap_update_bits failed for address %04x rc=%d\n",
		dev_err(chip->dev, "regmap_write failed for address %04x rc=%d\n",
			addr, rc);
		goto out;
	}

	fg_dbg(chip, FG_BUS_WRITE, "addr=%04x mask: %02x val: %02x\n", addr,
		mask, val);
	if (*chip->debug_mask & FG_BUS_WRITE)
		pr_info("addr=%04x val=%04x\n", addr, val);

out:
	mutex_unlock(&chip->bus_lock);
	return rc;
Loading