Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <o.rempel@pengutronix.de>
Link: https://lore.kernel.org/r/20231025084614.3092295-6-o.rempel@pengutronix.de
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Oleksij Rempel and committed by
Mark Brown
ecb6f1f4 0ab1dc9c

+50
+50
drivers/regulator/fixed.c
··· 20 20 #include <linux/platform_device.h> 21 21 #include <linux/pm_domain.h> 22 22 #include <linux/pm_opp.h> 23 + #include <linux/reboot.h> 23 24 #include <linux/regulator/driver.h> 24 25 #include <linux/regulator/fixed.h> 25 26 #include <linux/gpio/consumer.h> ··· 30 29 #include <linux/regulator/machine.h> 31 30 #include <linux/clk.h> 32 31 32 + /* Default time in millisecond to wait for emergency shutdown */ 33 + #define FV_DEF_EMERG_SHUTDWN_TMO 10 33 34 34 35 struct fixed_voltage_data { 35 36 struct regulator_desc desc; ··· 108 105 return priv->enable_counter > 0; 109 106 } 110 107 108 + static irqreturn_t reg_fixed_under_voltage_irq_handler(int irq, void *data) 109 + { 110 + struct fixed_voltage_data *priv = data; 111 + struct regulator_dev *rdev = priv->dev; 112 + 113 + regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE, 114 + NULL); 115 + 116 + return IRQ_HANDLED; 117 + } 118 + 119 + /** 120 + * reg_fixed_get_irqs - Get and register the optional IRQ for fixed voltage 121 + * regulator. 122 + * @dev: Pointer to the device structure. 123 + * @priv: Pointer to fixed_voltage_data structure containing private data. 124 + * 125 + * This function tries to get the IRQ from the device firmware node. 126 + * If it's an optional IRQ and not found, it returns 0. 127 + * Otherwise, it attempts to request the threaded IRQ. 128 + * 129 + * Return: 0 on success, or error code on failure. 130 + */ 131 + static int reg_fixed_get_irqs(struct device *dev, 132 + struct fixed_voltage_data *priv) 133 + { 134 + int ret; 135 + 136 + ret = fwnode_irq_get(dev_fwnode(dev), 0); 137 + /* This is optional IRQ. If not found we will get -EINVAL */ 138 + if (ret == -EINVAL) 139 + return 0; 140 + if (ret < 0) 141 + return dev_err_probe(dev, ret, "Failed to get IRQ\n"); 142 + 143 + ret = devm_request_threaded_irq(dev, ret, NULL, 144 + reg_fixed_under_voltage_irq_handler, 145 + IRQF_ONESHOT, "under-voltage", priv); 146 + if (ret) 147 + return dev_err_probe(dev, ret, "Failed to request IRQ\n"); 148 + 149 + return 0; 150 + } 111 151 112 152 /** 113 153 * of_get_fixed_voltage_config - extract fixed_voltage_config structure info ··· 339 293 340 294 dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name, 341 295 drvdata->desc.fixed_uV); 296 + 297 + ret = reg_fixed_get_irqs(dev, drvdata); 298 + if (ret) 299 + return ret; 342 300 343 301 return 0; 344 302 }