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

Commit d81e600c authored by Ashay Jaiswal's avatar Ashay Jaiswal Committed by Jishnu Prakash
Browse files

power: qpnp-fg-gen3: Add a property to reset FG BCL device



Add support to allow client to request FG to reset BCL
device through a power supply property.

Change-Id: I7c51adb1e9739c592c28943da8af8219661d38cc
Signed-off-by: default avatarAshay Jaiswal <ashayj@codeaurora.org>
parent 46efbcbb
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2017, 2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -522,4 +522,5 @@ extern void fg_circ_buf_clr(struct fg_circ_buf *);
extern int fg_circ_buf_avg(struct fg_circ_buf *, int *);
extern int fg_circ_buf_median(struct fg_circ_buf *, int *);
extern int fg_lerp(const struct fg_pt *, size_t, s32, s32 *);
extern int fg_dma_mem_req(struct fg_chip *, bool);
#endif
+59 −1
Original line number Diff line number Diff line
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2017, 2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -746,6 +746,64 @@ out:
	return rc;
}

int fg_dma_mem_req(struct fg_chip *chip, bool request)
{
	int ret, rc = 0, retry_count  = RETRY_COUNT;
	u8 val;

	if (request) {
		/* configure for DMA access */
		rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
				MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT,
				MEM_ACCESS_REQ_BIT);
		if (rc < 0) {
			pr_err("failed to set mem_access bit rc=%d\n", rc);
			return rc;
		}

		rc = fg_masked_write(chip, MEM_IF_MEM_ARB_CFG(chip),
				MEM_IF_ARB_REQ_BIT, MEM_IF_ARB_REQ_BIT);
		if (rc < 0) {
			pr_err("failed to set mem_arb bit rc=%d\n", rc);
			goto release_mem;
		}

		while (retry_count--) {
			rc = fg_read(chip, MEM_IF_INT_RT_STS(chip), &val, 1);
			if (rc < 0) {
				pr_err("failed to set ima_rt_sts rc=%d\n", rc);
				goto release_mem;
			}
			if (val & MEM_GNT_BIT)
				break;
			msleep(20);
		}
		if (!retry_count && !(val & MEM_GNT_BIT)) {
			pr_err("failed to get memory access\n");
			rc = -ETIMEDOUT;
			goto release_mem;
		}

		return 0;
	}

release_mem:
	/* Release access */
	rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
			MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, 0);
	if (rc < 0)
		pr_err("failed to reset mem_access bit rc = %d\n", rc);

	ret = fg_masked_write(chip, MEM_IF_MEM_ARB_CFG(chip),
			MEM_IF_ARB_REQ_BIT, 0);
	if (ret < 0) {
		pr_err("failed to release mem_arb bit rc=%d\n", ret);
		return ret;
	}

	return rc;
}

int fg_ima_init(struct fg_chip *chip)
{
	int rc;
+15 −2
Original line number Diff line number Diff line
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2017, 2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -29,6 +29,7 @@
#define BATT_SOC_STS_CLR(chip)			(chip->batt_soc_base + 0x4A)
#define BATT_SOC_LOW_PWR_CFG(chip)		(chip->batt_soc_base + 0x52)
#define BATT_SOC_LOW_PWR_STS(chip)		(chip->batt_soc_base + 0x56)
#define BATT_SOC_RST_CTRL0(chip)		(chip->batt_soc_base + 0xBA)

/* BATT_SOC_INT_RT_STS */
#define MSOC_EMPTY_BIT				BIT(5)
@@ -39,6 +40,9 @@
/* BATT_SOC_RESTART */
#define RESTART_GO_BIT				BIT(0)

/* BCL_RESET */
#define BCL_RESET_BIT				BIT(2)

/* FG_BATT_INFO register definitions */
#define BATT_INFO_BATT_TEMP_STS(chip)		(chip->batt_info_base + 0x06)
#define BATT_INFO_SYS_BATT(chip)		(chip->batt_info_base + 0x07)
@@ -58,7 +62,6 @@
#define BATT_INFO_JEITA_COLD(chip)		(chip->batt_info_base + 0x63)
#define BATT_INFO_JEITA_HOT(chip)		(chip->batt_info_base + 0x64)
#define BATT_INFO_JEITA_TOO_HOT(chip)		(chip->batt_info_base + 0x65)

/* only for v1.1 */
#define BATT_INFO_ESR_CFG(chip)			(chip->batt_info_base + 0x69)
/* starting from v2.0 */
@@ -95,6 +98,8 @@
#define BATT_INFO_IADC_MSB(chip)		(chip->batt_info_base + 0xAF)
#define BATT_INFO_TM_MISC(chip)			(chip->batt_info_base + 0xE5)
#define BATT_INFO_TM_MISC1(chip)		(chip->batt_info_base + 0xE6)
#define BATT_INFO_PEEK_MUX1(chip)		(chip->batt_info_base + 0xEB)
#define BATT_INFO_RDBACK(chip)			(chip->batt_info_base + 0xEF)

/* BATT_INFO_BATT_TEMP_STS */
#define JEITA_TOO_HOT_STS_BIT			BIT(7)
@@ -264,8 +269,12 @@
#define ESR_REQ_CTL_BIT				BIT(1)
#define ESR_REQ_CTL_EN_BIT			BIT(0)

/* BATT_INFO_PEEK_MUX1 */
#define PEEK_MUX1_BIT				BIT(0)

/* FG_MEM_IF register and bit definitions */
#define MEM_IF_INT_RT_STS(chip)			((chip->mem_if_base) + 0x10)
#define MEM_IF_MEM_ARB_CFG(chip)		((chip->mem_if_base) + 0x40)
#define MEM_IF_MEM_INTF_CFG(chip)		((chip->mem_if_base) + 0x50)
#define MEM_IF_IMA_CTL(chip)			((chip->mem_if_base) + 0x51)
#define MEM_IF_IMA_CFG(chip)			((chip->mem_if_base) + 0x52)
@@ -286,6 +295,7 @@

/* MEM_IF_INT_RT_STS */
#define MEM_XCP_BIT				BIT(1)
#define MEM_GNT_BIT				BIT(2)

/* MEM_IF_MEM_INTF_CFG */
#define MEM_ACCESS_REQ_BIT			BIT(7)
@@ -326,4 +336,7 @@

/* MEM_IF_DMA_CTL */
#define DMA_CLEAR_LOG_BIT			BIT(0)

/* MEM_IF_REQ */
#define MEM_IF_ARB_REQ_BIT			BIT(0)
#endif
+3 −3
Original line number Diff line number Diff line
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2017, 2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -420,7 +420,7 @@ int fg_write(struct fg_chip *chip, int addr, u8 *val, int len)
		return -ENXIO;

	mutex_lock(&chip->bus_lock);
	sec_access = (addr & 0x00FF) > 0xD0;
	sec_access = (addr & 0x00FF) >= 0xBA;
	if (sec_access) {
		rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5);
		if (rc < 0) {
@@ -460,7 +460,7 @@ int fg_masked_write(struct fg_chip *chip, int addr, u8 mask, u8 val)
		return -ENXIO;

	mutex_lock(&chip->bus_lock);
	sec_access = (addr & 0x00FF) > 0xD0;
	sec_access = (addr & 0x00FF) >= 0xBA;
	if (sec_access) {
		rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5);
		if (rc < 0) {
+105 −0
Original line number Diff line number Diff line
@@ -3850,6 +3850,9 @@ static int fg_psy_get_property(struct power_supply *psy,
	case POWER_SUPPLY_PROP_CC_STEP_SEL:
		pval->intval = chip->ttf.cc_step.sel;
		break;
	case POWER_SUPPLY_PROP_FG_RESET_CLOCK:
		pval->intval = 0;
		break;
	default:
		pr_err("unsupported property %d\n", psp);
		rc = -EINVAL;
@@ -3862,6 +3865,100 @@ static int fg_psy_get_property(struct power_supply *psy,
	return 0;
}

#define BCL_RESET_RETRY_COUNT 4
static int fg_bcl_reset(struct fg_chip *chip)
{
	int i, ret, rc = 0;
	u8 val, peek_mux;
	bool success = false;

	/* Read initial value of peek mux1 */
	rc = fg_read(chip, BATT_INFO_PEEK_MUX1(chip), &peek_mux, 1);
	if (rc < 0) {
		pr_err("Error in writing peek mux1, rc=%d\n", rc);
		return rc;
	}

	val = 0x83;
	rc = fg_write(chip, BATT_INFO_PEEK_MUX1(chip), &val, 1);
	if (rc < 0) {
		pr_err("Error in writing peek mux1, rc=%d\n", rc);
		return rc;
	}

	mutex_lock(&chip->sram_rw_lock);
	for (i = 0; i < BCL_RESET_RETRY_COUNT; i++) {
		rc = fg_dma_mem_req(chip, true);
		if (rc < 0) {
			pr_err("Error in locking memory, rc=%d\n", rc);
			goto unlock;
		}

		rc = fg_read(chip, BATT_INFO_RDBACK(chip), &val, 1);
		if (rc < 0) {
			pr_err("Error in reading rdback, rc=%d\n", rc);
			goto release_mem;
		}

		if (val & PEEK_MUX1_BIT) {
			rc = fg_masked_write(chip, BATT_SOC_RST_CTRL0(chip),
						BCL_RESET_BIT, BCL_RESET_BIT);
			if (rc < 0) {
				pr_err("Error in writing RST_CTRL0, rc=%d\n",
						rc);
				goto release_mem;
			}

			rc = fg_dma_mem_req(chip, false);
			if (rc < 0)
				pr_err("Error in unlocking memory, rc=%d\n",
						rc);

			/* Delay of 2ms */
			usleep_range(2000, 3000);
			ret = fg_masked_write(chip, BATT_SOC_RST_CTRL0(chip),
						BCL_RESET_BIT, 0);
			if (ret < 0)
				pr_err("Error in writing RST_CTRL0, rc=%d\n",
						rc);
			if (!rc && !ret)
				success = true;

			goto unlock;
		} else {
			rc = fg_dma_mem_req(chip, false);
			if (rc < 0) {
				pr_err("Error in unlocking memory, rc=%d\n",
						rc);
				goto unlock;
			}
			success = false;
			pr_err_ratelimited("PEEK_MUX1 not set retrying...\n");
			msleep(1000);
		}
	}

release_mem:
	rc = fg_dma_mem_req(chip, false);
	if (rc < 0)
		pr_err("Error in unlocking memory, rc=%d\n", rc);

unlock:
	ret = fg_write(chip, BATT_INFO_PEEK_MUX1(chip), &peek_mux, 1);
	if (ret < 0) {
		pr_err("Error in writing peek mux1, rc=%d\n", rc);
		mutex_unlock(&chip->sram_rw_lock);
		return ret;
	}

	mutex_unlock(&chip->sram_rw_lock);

	if (!success)
		return -EAGAIN;
	else
		return rc;
}

static int fg_psy_set_property(struct power_supply *psy,
				  enum power_supply_property psp,
				  const union power_supply_propval *pval)
@@ -3950,6 +4047,13 @@ static int fg_psy_set_property(struct power_supply *psy,
			return rc;
		}
		break;
	case POWER_SUPPLY_PROP_FG_RESET_CLOCK:
		rc = fg_bcl_reset(chip);
		if (rc < 0) {
			pr_err("Error in resetting BCL clock, rc=%d\n", rc);
			return rc;
		}
		break;
	default:
		break;
	}
@@ -4047,6 +4151,7 @@ static enum power_supply_property fg_psy_props[] = {
	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
	POWER_SUPPLY_PROP_CC_STEP,
	POWER_SUPPLY_PROP_CC_STEP_SEL,
	POWER_SUPPLY_PROP_FG_RESET_CLOCK,
};

static const struct power_supply_desc fg_psy_desc = {