[PATCH] [RFC] mfd: stpmic1: Add restart-on-vin-not-ok DT property

Marek Vasut marex at denx.de
Sat Oct 23 12:23:21 PDT 2021


Add DT property to set the MAIN_CR RREQ_EN bit in the PMIC, which
makes the PMIC restart the system already when VIN drops below the
VINOK_Fall threshold. The default behavior is that the restart
happens below VIN_POR_Fall threshold, which is lower than the
VINOK_Fall one. On shutdown, the bit is reset to permit actual
shutdown instead of reboot.

This works around an issue where the VIN drops slightly, which is
enough to lock up the SoC, but not enough to trigger reset. The
RREQ_EN bit cannot be permanently set in PMIC OTP, and it should
not be set on all systems, hence the DT property.

The downside is that once the first restart on low VIN happens,
the PMIC clears the bit, so if there is another drop on the VIN,
the system locks up all the same. So this is not a perfect fix.

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Alexandre Torgue <alexandre.torgue at foss.st.com>
Cc: Pascal Paillet <p.paillet at foss.st.com>
Cc: Patrice Chotard <patrice.chotard at foss.st.com>
Cc: Patrick Delaunay <patrick.delaunay at foss.st.com>
---
NOTE: I am sending this as RFC, to collect feedback, so dont waste
      your time with actual patch review. I would like to know what
      you think about this approach of setting the RREQ_EN bit.
---
 drivers/mfd/stpmic1.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c
index eb3da558c3fbd..8823386b18f32 100644
--- a/drivers/mfd/stpmic1.c
+++ b/drivers/mfd/stpmic1.c
@@ -149,6 +149,12 @@ static int stpmic1_probe(struct i2c_client *i2c,
 	}
 	dev_info(dev, "PMIC Chip Version: 0x%x\n", reg);
 
+	/* Restart the system in case VIN falls below VINOK */
+	if (of_property_read_bool(np, "st,restart-on-vin-not-ok")) {
+		regmap_set_bits(ddata->regmap, SWOFF_PWRCTRL_CR,
+				RESTART_REQUEST_ENABLED);
+	}
+
 	/* Initialize PMIC IRQ Chip & associated IRQ domains */
 	ret = devm_regmap_add_irq_chip(dev, ddata->regmap, ddata->irq,
 				       IRQF_ONESHOT | IRQF_SHARED,
@@ -162,6 +168,14 @@ static int stpmic1_probe(struct i2c_client *i2c,
 	return devm_of_platform_populate(dev);
 }
 
+static void stpmic1_shutdown(struct i2c_client *i2c)
+{
+	struct stpmic1 *pmic_dev = i2c_get_clientdata(i2c);
+
+	regmap_clear_bits(pmic_dev->regmap, SWOFF_PWRCTRL_CR,
+			  RESTART_REQUEST_ENABLED);
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int stpmic1_suspend(struct device *dev)
 {
@@ -204,6 +218,7 @@ static struct i2c_driver stpmic1_driver = {
 		.pm = &stpmic1_pm,
 	},
 	.probe = stpmic1_probe,
+	.shutdown = stpmic1_shutdown,
 };
 
 module_i2c_driver(stpmic1_driver);
-- 
2.33.0




More information about the linux-arm-kernel mailing list