Skip to content

Commit 8156c7d

Browse files
olerembroonie
authored andcommitted
regulator: Introduce handling for system-critical under-voltage events
Handle under-voltage events for crucial regulators to maintain system stability and avoid issues during power drops. Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> Link: https://lore.kernel.org/r/20231026144824.4065145-3-o.rempel@pengutronix.de Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 0e1c8dc commit 8156c7d

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

drivers/regulator/core.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/delay.h>
2020
#include <linux/gpio/consumer.h>
2121
#include <linux/of.h>
22+
#include <linux/reboot.h>
2223
#include <linux/regmap.h>
2324
#include <linux/regulator/of_regulator.h>
2425
#include <linux/regulator/consumer.h>
@@ -5061,6 +5062,41 @@ void regulator_bulk_free(int num_consumers,
50615062
}
50625063
EXPORT_SYMBOL_GPL(regulator_bulk_free);
50635064

5065+
/**
5066+
* regulator_handle_critical - Handle events for system-critical regulators.
5067+
* @rdev: The regulator device.
5068+
* @event: The event being handled.
5069+
*
5070+
* This function handles critical events such as under-voltage, over-current,
5071+
* and unknown errors for regulators deemed system-critical. On detecting such
5072+
* events, it triggers a hardware protection shutdown with a defined timeout.
5073+
*/
5074+
static void regulator_handle_critical(struct regulator_dev *rdev,
5075+
unsigned long event)
5076+
{
5077+
const char *reason = NULL;
5078+
5079+
if (!rdev->constraints->system_critical)
5080+
return;
5081+
5082+
switch (event) {
5083+
case REGULATOR_EVENT_UNDER_VOLTAGE:
5084+
reason = "System critical regulator: voltage drop detected";
5085+
break;
5086+
case REGULATOR_EVENT_OVER_CURRENT:
5087+
reason = "System critical regulator: over-current detected";
5088+
break;
5089+
case REGULATOR_EVENT_FAIL:
5090+
reason = "System critical regulator: unknown error";
5091+
}
5092+
5093+
if (!reason)
5094+
return;
5095+
5096+
hw_protection_shutdown(reason,
5097+
REGULATOR_DEF_UV_LESS_CRITICAL_WINDOW_MS);
5098+
}
5099+
50645100
/**
50655101
* regulator_notifier_call_chain - call regulator event notifier
50665102
* @rdev: regulator source
@@ -5073,6 +5109,8 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free);
50735109
int regulator_notifier_call_chain(struct regulator_dev *rdev,
50745110
unsigned long event, void *data)
50755111
{
5112+
regulator_handle_critical(rdev, event);
5113+
50765114
_notifier_call_chain(rdev, event, data);
50775115
return NOTIFY_DONE;
50785116

drivers/regulator/of_regulator.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ static int of_get_regulation_constraints(struct device *dev,
131131
constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
132132

133133
constraints->pull_down = of_property_read_bool(np, "regulator-pull-down");
134+
constraints->system_critical = of_property_read_bool(np,
135+
"system-critical-regulator");
134136

135137
if (of_property_read_bool(np, "regulator-allow-bypass"))
136138
constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;

include/linux/regulator/machine.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ struct regulator;
4949
#define DISABLE_IN_SUSPEND 1
5050
#define ENABLE_IN_SUSPEND 2
5151

52+
/*
53+
* Default time window (in milliseconds) following a critical under-voltage
54+
* event during which less critical actions can be safely carried out by the
55+
* system.
56+
*/
57+
#define REGULATOR_DEF_UV_LESS_CRITICAL_WINDOW_MS 10
58+
5259
/* Regulator active discharge flags */
5360
enum regulator_active_discharge {
5461
REGULATOR_ACTIVE_DISCHARGE_DEFAULT,
@@ -127,6 +134,8 @@ struct notification_limit {
127134
* @ramp_disable: Disable ramp delay when initialising or when setting voltage.
128135
* @soft_start: Enable soft start so that voltage ramps slowly.
129136
* @pull_down: Enable pull down when regulator is disabled.
137+
* @system_critical: Set if the regulator is critical to system stability or
138+
* functionality.
130139
* @over_current_protection: Auto disable on over current event.
131140
*
132141
* @over_current_detection: Configure over current limits.
@@ -214,6 +223,7 @@ struct regulation_constraints {
214223
unsigned ramp_disable:1; /* disable ramp delay */
215224
unsigned soft_start:1; /* ramp voltage slowly */
216225
unsigned pull_down:1; /* pull down resistor when regulator off */
226+
unsigned system_critical:1; /* critical to system stability */
217227
unsigned over_current_protection:1; /* auto disable on over current */
218228
unsigned over_current_detection:1; /* notify on over current */
219229
unsigned over_voltage_detection:1; /* notify on over voltage */

0 commit comments

Comments
 (0)