Skip to content

Commit ecb6f1f

Browse files
olerembroonie
authored andcommitted
regulator: fixed: add support for under-voltage IRQ
Add interrupt support for under-voltage notification. This functionality can be used on systems capable to detect under-voltage state and having enough capacity to let the SoC do some emergency preparation. This change enforce default policy to shutdown system as soon as interrupt is triggered. Signed-off-by: Oleksij Rempel <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 0ab1dc9 commit ecb6f1f

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

drivers/regulator/fixed.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/platform_device.h>
2121
#include <linux/pm_domain.h>
2222
#include <linux/pm_opp.h>
23+
#include <linux/reboot.h>
2324
#include <linux/regulator/driver.h>
2425
#include <linux/regulator/fixed.h>
2526
#include <linux/gpio/consumer.h>
@@ -29,6 +30,8 @@
2930
#include <linux/regulator/machine.h>
3031
#include <linux/clk.h>
3132

33+
/* Default time in millisecond to wait for emergency shutdown */
34+
#define FV_DEF_EMERG_SHUTDWN_TMO 10
3235

3336
struct fixed_voltage_data {
3437
struct regulator_desc desc;
@@ -105,6 +108,49 @@ static int reg_is_enabled(struct regulator_dev *rdev)
105108
return priv->enable_counter > 0;
106109
}
107110

111+
static irqreturn_t reg_fixed_under_voltage_irq_handler(int irq, void *data)
112+
{
113+
struct fixed_voltage_data *priv = data;
114+
struct regulator_dev *rdev = priv->dev;
115+
116+
regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE,
117+
NULL);
118+
119+
return IRQ_HANDLED;
120+
}
121+
122+
/**
123+
* reg_fixed_get_irqs - Get and register the optional IRQ for fixed voltage
124+
* regulator.
125+
* @dev: Pointer to the device structure.
126+
* @priv: Pointer to fixed_voltage_data structure containing private data.
127+
*
128+
* This function tries to get the IRQ from the device firmware node.
129+
* If it's an optional IRQ and not found, it returns 0.
130+
* Otherwise, it attempts to request the threaded IRQ.
131+
*
132+
* Return: 0 on success, or error code on failure.
133+
*/
134+
static int reg_fixed_get_irqs(struct device *dev,
135+
struct fixed_voltage_data *priv)
136+
{
137+
int ret;
138+
139+
ret = fwnode_irq_get(dev_fwnode(dev), 0);
140+
/* This is optional IRQ. If not found we will get -EINVAL */
141+
if (ret == -EINVAL)
142+
return 0;
143+
if (ret < 0)
144+
return dev_err_probe(dev, ret, "Failed to get IRQ\n");
145+
146+
ret = devm_request_threaded_irq(dev, ret, NULL,
147+
reg_fixed_under_voltage_irq_handler,
148+
IRQF_ONESHOT, "under-voltage", priv);
149+
if (ret)
150+
return dev_err_probe(dev, ret, "Failed to request IRQ\n");
151+
152+
return 0;
153+
}
108154

109155
/**
110156
* of_get_fixed_voltage_config - extract fixed_voltage_config structure info
@@ -294,6 +340,10 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
294340
dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name,
295341
drvdata->desc.fixed_uV);
296342

343+
ret = reg_fixed_get_irqs(dev, drvdata);
344+
if (ret)
345+
return ret;
346+
297347
return 0;
298348
}
299349

0 commit comments

Comments
 (0)