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

Commit a28fedea authored by David Keitel's avatar David Keitel
Browse files

msm: qpnp-power-on: add dload_upon_uvlo module parameter



When 1 is written to this dload_on_uvlo module parameter,
BIT 7 in XVDD_RB_SPARE will be set. This XVDD-backed
register will retain its value during an UVLO event.

When the device boots up again SBL will check both
the PON reason for UVLO and if this bit is set download
mode will be entered instead of a normal boot.

One can enable this feature as follows:

  echo 1 > /sys/module/qpnp_power_on/parameters/dload_on_uvlo

Alternatively one can specify the parameter on the command line:

  qpnp_power_on.dload_on_uvlo=1

CRs-Fixed: 678229
Change-Id: I46d2d4c0586ddce9f64a02c954c37f4b367c33b2
Signed-off-by: default avatarDavid Keitel <dkeitel@codeaurora.org>
parent 54757847
Loading
Loading
Loading
Loading
+76 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@
#define QPNP_PON_S3_SRC(base)			(base + 0x74)
#define QPNP_PON_S3_DBC_CTL(base)		(base + 0x75)
#define QPNP_PON_TRIGGER_EN(base)		(base + 0x80)
#define QPNP_PON_XVDD_RB_SPARE(base)		(base + 0x8E)

#define QPNP_PON_WARM_RESET_TFT			BIT(4)

@@ -96,6 +97,8 @@
#define QPNP_PON_S3_SRC_KPDPWR_OR_RESIN		3
#define QPNP_PON_S3_SRC_MASK			0x3

#define QPNP_PON_UVLO_DLOAD_EN		BIT(7)

/* Ranges */
#define QPNP_PON_S1_TIMER_MAX			10256
#define QPNP_PON_S2_TIMER_MAX			2000
@@ -1254,6 +1257,79 @@ free_input_dev:
	return rc;
}

static bool dload_on_uvlo;

static int qpnp_pon_debugfs_uvlo_dload_get(char *buf,
		const struct kernel_param *kp)
{
	struct qpnp_pon *pon = sys_reset_dev;
	int rc = 0;
	u8 reg;

	if (!pon)
		return -ENODEV;

	rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
			QPNP_PON_XVDD_RB_SPARE(pon->base), &reg, 1);
	if (rc) {
		dev_err(&pon->spmi->dev,
			"Unable to read addr=%x, rc(%d)\n",
			QPNP_PON_XVDD_RB_SPARE(pon->base), rc);
		return rc;
	}

	return snprintf(buf, PAGE_SIZE, "%d",
			!!(QPNP_PON_UVLO_DLOAD_EN & reg));
}

static int qpnp_pon_debugfs_uvlo_dload_set(const char *val,
		const struct kernel_param *kp)
{
	struct qpnp_pon *pon = sys_reset_dev;
	int rc = 0;
	u8 reg;

	if (!pon)
		return -ENODEV;

	rc = param_set_bool(val, kp);
	if (rc) {
		pr_err("Unable to set bms_reset: %d\n", rc);
		return rc;
	}

	rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
			QPNP_PON_XVDD_RB_SPARE(pon->base), &reg, 1);
	if (rc) {
		dev_err(&pon->spmi->dev,
			"Unable to read addr=%x, rc(%d)\n",
			QPNP_PON_XVDD_RB_SPARE(pon->base), rc);
		return rc;
	}

	reg &= ~QPNP_PON_UVLO_DLOAD_EN;
	if (*(bool *)kp->arg)
		reg |= QPNP_PON_UVLO_DLOAD_EN;

	rc = spmi_ext_register_writel(pon->spmi->ctrl, pon->spmi->sid,
			QPNP_PON_XVDD_RB_SPARE(pon->base), &reg, 1);
	if (rc) {
		dev_err(&pon->spmi->dev,
			"Unable to write to addr=%hx, rc(%d)\n",
				QPNP_PON_XVDD_RB_SPARE(pon->base), rc);
		return rc;
	}

	return 0;
}

static struct kernel_param_ops dload_on_uvlo_ops = {
	.set = qpnp_pon_debugfs_uvlo_dload_set,
	.get = qpnp_pon_debugfs_uvlo_dload_get,
};

module_param_cb(dload_on_uvlo, &dload_on_uvlo_ops, &dload_on_uvlo, 0644);

#if defined(CONFIG_DEBUG_FS)

static int qpnp_pon_debugfs_uvlo_get(void *data, u64 *val)