Commit 753e4d5c authored by Mark Brown's avatar Mark Brown

regulator: add under-voltage support (part 2)

Merge series from Oleksij Rempel <o.rempel@pengutronix.de>:

This series add under-voltage and emergency shutdown for system critical
regulators
parents 413cfaa7 1e22152a
...@@ -105,6 +105,8 @@ properties: ...@@ -105,6 +105,8 @@ properties:
description: description:
Interrupt signaling a critical under-voltage event. Interrupt signaling a critical under-voltage event.
system-critical-regulator: true
required: required:
- compatible - compatible
- regulator-name - regulator-name
......
...@@ -114,6 +114,11 @@ properties: ...@@ -114,6 +114,11 @@ properties:
description: Enable pull down resistor when the regulator is disabled. description: Enable pull down resistor when the regulator is disabled.
type: boolean type: boolean
system-critical-regulator:
description: Set if the regulator is critical to system stability or
functionality.
type: boolean
regulator-over-current-protection: regulator-over-current-protection:
description: Enable over current protection. description: Enable over current protection.
type: boolean type: boolean
...@@ -181,6 +186,14 @@ properties: ...@@ -181,6 +186,14 @@ properties:
be enabled but limit setting can be omitted. Limit is given as microvolt be enabled but limit setting can be omitted. Limit is given as microvolt
offset from voltage set to regulator. offset from voltage set to regulator.
regulator-uv-less-critical-window-ms:
description: Specifies the time window (in milliseconds) following a
critical under-voltage event during which the system can continue to
operate safely while performing less critical operations. This property
provides a defined duration before a more severe reaction to the
under-voltage event is needed, allowing for certain non-urgent actions to
be carried out in preparation for potential power loss.
regulator-temp-protection-kelvin: regulator-temp-protection-kelvin:
description: Set over temperature protection limit. This is a limit where description: Set over temperature protection limit. This is a limit where
hardware performs emergency shutdown. Zero can be passed to disable hardware performs emergency shutdown. Zero can be passed to disable
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/reboot.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
...@@ -5065,6 +5066,41 @@ void regulator_bulk_free(int num_consumers, ...@@ -5065,6 +5066,41 @@ void regulator_bulk_free(int num_consumers,
} }
EXPORT_SYMBOL_GPL(regulator_bulk_free); EXPORT_SYMBOL_GPL(regulator_bulk_free);
/**
* regulator_handle_critical - Handle events for system-critical regulators.
* @rdev: The regulator device.
* @event: The event being handled.
*
* This function handles critical events such as under-voltage, over-current,
* and unknown errors for regulators deemed system-critical. On detecting such
* events, it triggers a hardware protection shutdown with a defined timeout.
*/
static void regulator_handle_critical(struct regulator_dev *rdev,
unsigned long event)
{
const char *reason = NULL;
if (!rdev->constraints->system_critical)
return;
switch (event) {
case REGULATOR_EVENT_UNDER_VOLTAGE:
reason = "System critical regulator: voltage drop detected";
break;
case REGULATOR_EVENT_OVER_CURRENT:
reason = "System critical regulator: over-current detected";
break;
case REGULATOR_EVENT_FAIL:
reason = "System critical regulator: unknown error";
}
if (!reason)
return;
hw_protection_shutdown(reason,
rdev->constraints->uv_less_critical_window_ms);
}
/** /**
* regulator_notifier_call_chain - call regulator event notifier * regulator_notifier_call_chain - call regulator event notifier
* @rdev: regulator source * @rdev: regulator source
...@@ -5077,6 +5113,8 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free); ...@@ -5077,6 +5113,8 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free);
int regulator_notifier_call_chain(struct regulator_dev *rdev, int regulator_notifier_call_chain(struct regulator_dev *rdev,
unsigned long event, void *data) unsigned long event, void *data)
{ {
regulator_handle_critical(rdev, event);
_notifier_call_chain(rdev, event, data); _notifier_call_chain(rdev, event, data);
return NOTIFY_DONE; return NOTIFY_DONE;
......
...@@ -131,6 +131,8 @@ static int of_get_regulation_constraints(struct device *dev, ...@@ -131,6 +131,8 @@ static int of_get_regulation_constraints(struct device *dev,
constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
constraints->pull_down = of_property_read_bool(np, "regulator-pull-down"); constraints->pull_down = of_property_read_bool(np, "regulator-pull-down");
constraints->system_critical = of_property_read_bool(np,
"system-critical-regulator");
if (of_property_read_bool(np, "regulator-allow-bypass")) if (of_property_read_bool(np, "regulator-allow-bypass"))
constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS; constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
...@@ -173,6 +175,13 @@ static int of_get_regulation_constraints(struct device *dev, ...@@ -173,6 +175,13 @@ static int of_get_regulation_constraints(struct device *dev,
if (!ret) if (!ret)
constraints->enable_time = pval; constraints->enable_time = pval;
ret = of_property_read_u32(np, "regulator-uv-survival-time-ms", &pval);
if (!ret)
constraints->uv_less_critical_window_ms = pval;
else
constraints->uv_less_critical_window_ms =
REGULATOR_DEF_UV_LESS_CRITICAL_WINDOW_MS;
constraints->soft_start = of_property_read_bool(np, constraints->soft_start = of_property_read_bool(np,
"regulator-soft-start"); "regulator-soft-start");
ret = of_property_read_u32(np, "regulator-active-discharge", &pval); ret = of_property_read_u32(np, "regulator-active-discharge", &pval);
......
...@@ -49,6 +49,13 @@ struct regulator; ...@@ -49,6 +49,13 @@ struct regulator;
#define DISABLE_IN_SUSPEND 1 #define DISABLE_IN_SUSPEND 1
#define ENABLE_IN_SUSPEND 2 #define ENABLE_IN_SUSPEND 2
/*
* Default time window (in milliseconds) following a critical under-voltage
* event during which less critical actions can be safely carried out by the
* system.
*/
#define REGULATOR_DEF_UV_LESS_CRITICAL_WINDOW_MS 10
/* Regulator active discharge flags */ /* Regulator active discharge flags */
enum regulator_active_discharge { enum regulator_active_discharge {
REGULATOR_ACTIVE_DISCHARGE_DEFAULT, REGULATOR_ACTIVE_DISCHARGE_DEFAULT,
...@@ -127,6 +134,8 @@ struct notification_limit { ...@@ -127,6 +134,8 @@ struct notification_limit {
* @ramp_disable: Disable ramp delay when initialising or when setting voltage. * @ramp_disable: Disable ramp delay when initialising or when setting voltage.
* @soft_start: Enable soft start so that voltage ramps slowly. * @soft_start: Enable soft start so that voltage ramps slowly.
* @pull_down: Enable pull down when regulator is disabled. * @pull_down: Enable pull down when regulator is disabled.
* @system_critical: Set if the regulator is critical to system stability or
* functionality.
* @over_current_protection: Auto disable on over current event. * @over_current_protection: Auto disable on over current event.
* *
* @over_current_detection: Configure over current limits. * @over_current_detection: Configure over current limits.
...@@ -153,6 +162,13 @@ struct notification_limit { ...@@ -153,6 +162,13 @@ struct notification_limit {
* regulator_active_discharge values are used for * regulator_active_discharge values are used for
* initialisation. * initialisation.
* @enable_time: Turn-on time of the rails (unit: microseconds) * @enable_time: Turn-on time of the rails (unit: microseconds)
* @uv_less_critical_window_ms: Specifies the time window (in milliseconds)
* following a critical under-voltage (UV) event
* during which less critical actions can be
* safely carried out by the system (for example
* logging). After this time window more critical
* actions should be done (for example prevent
* HW damage).
*/ */
struct regulation_constraints { struct regulation_constraints {
...@@ -204,6 +220,7 @@ struct regulation_constraints { ...@@ -204,6 +220,7 @@ struct regulation_constraints {
unsigned int settling_time_up; unsigned int settling_time_up;
unsigned int settling_time_down; unsigned int settling_time_down;
unsigned int enable_time; unsigned int enable_time;
unsigned int uv_less_critical_window_ms;
unsigned int active_discharge; unsigned int active_discharge;
...@@ -214,6 +231,7 @@ struct regulation_constraints { ...@@ -214,6 +231,7 @@ struct regulation_constraints {
unsigned ramp_disable:1; /* disable ramp delay */ unsigned ramp_disable:1; /* disable ramp delay */
unsigned soft_start:1; /* ramp voltage slowly */ unsigned soft_start:1; /* ramp voltage slowly */
unsigned pull_down:1; /* pull down resistor when regulator off */ unsigned pull_down:1; /* pull down resistor when regulator off */
unsigned system_critical:1; /* critical to system stability */
unsigned over_current_protection:1; /* auto disable on over current */ unsigned over_current_protection:1; /* auto disable on over current */
unsigned over_current_detection:1; /* notify on over current */ unsigned over_current_detection:1; /* notify on over current */
unsigned over_voltage_detection:1; /* notify on over voltage */ unsigned over_voltage_detection:1; /* notify on over voltage */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment