diff options
Diffstat (limited to 'drivers/regulator/fixed.c')
| -rw-r--r-- | drivers/regulator/fixed.c | 63 |
1 files changed, 58 insertions, 5 deletions
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 2a9867abba20..a2d16e9abfb5 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -20,16 +20,18 @@ #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/pm_opp.h> +#include <linux/reboot.h> #include <linux/regulator/driver.h> #include <linux/regulator/fixed.h> #include <linux/gpio/consumer.h> #include <linux/slab.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/machine.h> #include <linux/clk.h> +/* Default time in millisecond to wait for emergency shutdown */ +#define FV_DEF_EMERG_SHUTDWN_TMO 10 struct fixed_voltage_data { struct regulator_desc desc; @@ -106,6 +108,49 @@ static int reg_is_enabled(struct regulator_dev *rdev) return priv->enable_counter > 0; } +static irqreturn_t reg_fixed_under_voltage_irq_handler(int irq, void *data) +{ + struct fixed_voltage_data *priv = data; + struct regulator_dev *rdev = priv->dev; + + regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE, + NULL); + + return IRQ_HANDLED; +} + +/** + * reg_fixed_get_irqs - Get and register the optional IRQ for fixed voltage + * regulator. + * @dev: Pointer to the device structure. + * @priv: Pointer to fixed_voltage_data structure containing private data. + * + * This function tries to get the IRQ from the device firmware node. + * If it's an optional IRQ and not found, it returns 0. + * Otherwise, it attempts to request the threaded IRQ. + * + * Return: 0 on success, or a negative error number on failure. + */ +static int reg_fixed_get_irqs(struct device *dev, + struct fixed_voltage_data *priv) +{ + int ret; + + ret = fwnode_irq_get(dev_fwnode(dev), 0); + /* This is optional IRQ. If not found we will get -EINVAL */ + if (ret == -EINVAL) + return 0; + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to get IRQ\n"); + + ret = devm_request_threaded_irq(dev, ret, NULL, + reg_fixed_under_voltage_irq_handler, + IRQF_ONESHOT, "under-voltage", priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to request IRQ\n"); + + return 0; +} /** * of_get_fixed_voltage_config - extract fixed_voltage_config structure info @@ -113,8 +158,10 @@ static int reg_is_enabled(struct regulator_dev *rdev) * @desc: regulator description * * Populates fixed_voltage_config structure by extracting data from device - * tree node, returns a pointer to the populated structure of NULL if memory - * alloc fails. + * tree node. + * + * Return: Pointer to a populated &struct fixed_voltage_config or %NULL if + * memory allocation fails. */ static struct fixed_voltage_config * of_get_fixed_voltage_config(struct device *dev, @@ -151,7 +198,7 @@ of_get_fixed_voltage_config(struct device *dev, of_property_read_u32(np, "startup-delay-us", &config->startup_delay); of_property_read_u32(np, "off-on-delay-us", &config->off_on_delay); - if (of_find_property(np, "vin-supply", NULL)) + if (of_property_present(np, "vin-supply")) config->input_supply = "vin"; return config; @@ -215,7 +262,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) drvdata->enable_clock = devm_clk_get(dev, NULL); if (IS_ERR(drvdata->enable_clock)) { dev_err(dev, "Can't get enable-clock from devicetree\n"); - return -ENOENT; + return PTR_ERR(drvdata->enable_clock); } } else if (drvtype && drvtype->has_performance_state) { drvdata->desc.ops = &fixed_voltage_domain_ops; @@ -287,6 +334,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) ret = dev_err_probe(&pdev->dev, PTR_ERR(drvdata->dev), "Failed to register regulator: %ld\n", PTR_ERR(drvdata->dev)); + gpiod_put(cfg.ena_gpiod); return ret; } @@ -295,6 +343,10 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name, drvdata->desc.fixed_uV); + ret = reg_fixed_get_irqs(dev, drvdata); + if (ret) + return ret; + return 0; } @@ -334,6 +386,7 @@ static struct platform_driver regulator_fixed_voltage_driver = { .probe = reg_fixed_voltage_probe, .driver = { .name = "reg-fixed-voltage", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(fixed_of_match), }, }; |
