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

Commit d836ead7 authored by Ashay Jaiswal's avatar Ashay Jaiswal Committed by Umang Agrawal
Browse files

power: smb1355: force enable clock while device is active



To optimize on power the SMB hardware disables the Bandgap/clock
when the charger is removed. When this happens, the SMB1355 IRQ
line stays stuck in its last known state. I.e. if there was an
interrupt pending (the IRQ line is low) and if the Bandgap/clock
gets disabled, the line stays stuck low forever causing a storm of
interrupts.

Fix this by forcing SMB1355 clock "on" as long as device is up and
and running and turn off the clock in ship-mode and shutdown path.

Change-Id: If01e07c63119b6af555ffd064d1055417c6b3e46
Signed-off-by: default avatarAshay Jaiswal <ashayj@codeaurora.org>
Signed-off-by: default avatarUmang Agrawal <uagrawal@codeaurora.org>
parent b523954d
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
@@ -113,6 +113,9 @@
#define BARK_BITE_WDOG_PET_REG			(MISC_BASE + 0x43)
#define BARK_BITE_WDOG_PET_BIT			BIT(0)

#define CLOCK_REQUEST_REG			(MISC_BASE + 0x44)
#define CLOCK_REQUEST_CMD_BIT			BIT(0)

#define WD_CFG_REG				(MISC_BASE + 0x51)
#define WATCHDOG_TRIGGER_AFP_EN_BIT		BIT(7)
#define BARK_WDOG_INT_EN_BIT			BIT(6)
@@ -250,6 +253,9 @@ struct smb1355 {

static bool is_secure(struct smb1355 *chip, int addr)
{
	if (addr == CLOCK_REQUEST_REG)
		return true;

	/* assume everything above 0xA0 is secure */
	return (addr & 0xFF) >= 0xA0;
}
@@ -266,6 +272,25 @@ static int smb1355_read(struct smb1355 *chip, u16 addr, u8 *val)
	return rc;
}

static int smb1355_masked_force_write(struct smb1355 *chip, u16 addr, u8 mask,
					u8 val)
{
	int rc;

	mutex_lock(&chip->write_lock);
	if (is_secure(chip, addr)) {
		rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5);
		if (rc < 0)
			goto unlock;
	}

	rc = regmap_write_bits(chip->regmap, addr, mask, val);

unlock:
	mutex_unlock(&chip->write_lock);
	return rc;
}

static int smb1355_masked_write(struct smb1355 *chip, u16 addr, u8 mask, u8 val)
{
	int rc;
@@ -495,6 +520,7 @@ static enum power_supply_property smb1355_parallel_props[] = {
	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
	POWER_SUPPLY_PROP_MIN_ICL,
	POWER_SUPPLY_PROP_CURRENT_MAX,
	POWER_SUPPLY_PROP_SET_SHIP_MODE,
};

static int smb1355_get_prop_batt_charge_type(struct smb1355 *chip,
@@ -618,6 +644,10 @@ static int smb1355_parallel_get_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_PARALLEL_FCC_MAX:
		val->intval = chip->max_fcc;
		break;
	case POWER_SUPPLY_PROP_SET_SHIP_MODE:
		/* Not in ship mode as long as device is active */
		val->intval = 0;
		break;
	default:
		pr_err_ratelimited("parallel psy get prop %d not supported\n",
			prop);
@@ -709,6 +739,20 @@ static int smb1355_set_current_max(struct smb1355 *chip, int curr)
	return rc;
}

static int smb1355_clk_request(struct smb1355 *chip, bool enable)
{
	int rc;

	rc = smb1355_masked_force_write(chip, CLOCK_REQUEST_REG,
				CLOCK_REQUEST_CMD_BIT,
				enable ? CLOCK_REQUEST_CMD_BIT : 0);
	if (rc < 0)
		pr_err("Couldn't %s clock rc=%d\n",
			       enable ? "enable" : "disable", rc);

	return rc;
}

static int smb1355_parallel_set_prop(struct power_supply *psy,
				     enum power_supply_property prop,
				     const union power_supply_propval *val)
@@ -737,6 +781,10 @@ static int smb1355_parallel_set_prop(struct power_supply *psy,
		break;
	case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
		chip->c_charger_temp_max = val->intval;
	case POWER_SUPPLY_PROP_SET_SHIP_MODE:
		if (!val->intval)
			break;
		rc = smb1355_clk_request(chip, false);
		break;
	default:
		pr_debug("parallel power supply set prop %d not supported\n",
@@ -917,6 +965,11 @@ static int smb1355_init_hw(struct smb1355 *chip)
{
	int rc;

	/* request clock always on */
	rc = smb1355_clk_request(chip, true);
	if (rc < 0)
		return rc;

	/* Change to let SMB1355 only respond to address 0x0C  */
	rc = smb1355_masked_write(chip, I2C_SS_DIG_PMIC_SID_REG,
					PMIC_SID_MASK, PMIC_SID0_BIT);
@@ -1337,6 +1390,8 @@ static void smb1355_shutdown(struct platform_device *pdev)
	rc = smb1355_set_parallel_charging(chip, true);
	if (rc < 0)
		pr_err("Couldn't disable parallel path rc=%d\n", rc);

	smb1355_clk_request(chip, false);
}

static struct platform_driver smb1355_driver = {