diff options
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/core.c | 15 | ||||
-rw-r--r-- | drivers/regulator/fixed.c | 6 | ||||
-rw-r--r-- | drivers/regulator/pfuze100-regulator.c | 86 |
3 files changed, 107 insertions, 0 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index fa2f87b504d5..00161bd9cf0f 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -32,6 +32,7 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/module.h> +#include <linux/clk.h> #define CREATE_TRACE_POINTS #include <trace/events/regulator.h> @@ -2123,6 +2124,11 @@ static int _regulator_do_enable(struct regulator_dev *rdev) ret = rdev->desc->ops->enable(rdev); if (ret < 0) return ret; + } else if (rdev->ena_clk) { + ret = clk_prepare_enable(rdev->ena_clk); + if (ret) + return ret; + rdev->ena_clk_state++; } else { return -EINVAL; } @@ -2230,6 +2236,9 @@ static int _regulator_do_disable(struct regulator_dev *rdev) ret = rdev->desc->ops->disable(rdev); if (ret != 0) return ret; + } else if (rdev->ena_clk) { + clk_disable_unprepare(rdev->ena_clk); + rdev->ena_clk_state--; } /* cares about last_off_jiffy only if off_on_delay is required by @@ -2443,6 +2452,9 @@ static int _regulator_is_enabled(struct regulator_dev *rdev) if (rdev->ena_pin) return rdev->ena_gpio_state; + if (rdev->ena_clk) + return (rdev->ena_clk_state > 0) ? 1 : 0; + /* If we don't know then assume that the regulator is always on */ if (!rdev->desc->ops->is_enabled) return 1; @@ -4008,6 +4020,9 @@ regulator_register(const struct regulator_desc *regulator_desc, } } + if (cfg->ena_clk) + rdev->ena_clk = cfg->ena_clk; + /* register with sysfs */ rdev->dev.class = ®ulator_class; rdev->dev.parent = dev; diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 136a9a3c7e30..23eebdceeb17 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -31,6 +31,7 @@ #include <linux/regulator/of_regulator.h> #include <linux/regulator/machine.h> #include <linux/pinctrl/consumer.h> +#include <linux/clk.h> struct fixed_voltage_data { struct regulator_desc desc; @@ -93,6 +94,10 @@ of_get_fixed_voltage_config(struct device *dev, if (of_find_property(np, "vin-supply", NULL)) config->input_supply = "vin"; + config->ena_clk = devm_clk_get(dev, NULL); + if (IS_ERR(config->ena_clk)) + config->ena_clk = NULL; + return config; } @@ -177,6 +182,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) cfg.init_data = config->init_data; cfg.driver_data = drvdata; cfg.of_node = pdev->dev.of_node; + cfg.ena_clk = config->ena_clk; drvdata->dev = devm_regulator_register(&pdev->dev, &drvdata->desc, &cfg); diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 92bf0c952583..0b89314370b9 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -742,6 +742,91 @@ err_ret: return index; } +static void pfuze100_regulator_shutdown(struct i2c_client *client) +{ + struct pfuze_chip *pfuze_chip; + int ret; + + if (!of_machine_is_compatible("toradex,colibri_imx6dl") && + !of_machine_is_compatible("toradex,apalis_imx6q")) + return; + + /* Configure all regulators to off on PMIC standby. For Colibri iMX6 + * we use the PMIC_STBY_REQ after shutdown, as the PMIC_ON_REQ signal + * together with VCC_BATT supplied from a battery leads to a + * nonbooting system. + * After the system has been shutdown with PMIC_ON_REQ it will never + * restart either by RESET or power cycle. + */ + pfuze_chip = i2c_get_clientdata(client); + + ret = regmap_update_bits(pfuze_chip->regmap, + PFUZE100_SW1ABVOL + PFUZE100_MODE_OFFSET, + 0x0f, 4); + if (ret < 0) + dev_err(pfuze_chip->dev, "stby config failed %d\n", ret); + + ret = regmap_update_bits(pfuze_chip->regmap, + PFUZE100_SW1CVOL + PFUZE100_MODE_OFFSET, + 0x0f, 4); + if (ret < 0) + dev_err(pfuze_chip->dev, "stby config failed %d\n", ret); + + ret = regmap_update_bits(pfuze_chip->regmap, + PFUZE100_SW3AVOL + PFUZE100_MODE_OFFSET, + 0x0f, 4); + if (ret < 0) + dev_err(pfuze_chip->dev, "stby config failed %d\n", ret); + + ret = regmap_update_bits(pfuze_chip->regmap, + PFUZE100_SW3BVOL + PFUZE100_MODE_OFFSET, + 0x0f, 4); + if (ret < 0) + dev_err(pfuze_chip->dev, "stby config failed %d\n", ret); + + ret = regmap_update_bits(pfuze_chip->regmap, + PFUZE100_SWBSTCON1, + 0x60, 0); + if (ret < 0) + dev_err(pfuze_chip->dev, "stby config failed %d\n", ret); + + ret = regmap_update_bits(pfuze_chip->regmap, + PFUZE100_VGEN1VOL, + 0x20, 0x20); + if (ret < 0) + dev_err(pfuze_chip->dev, "stby vgen config failed %d\n", ret); + + ret = regmap_update_bits(pfuze_chip->regmap, + PFUZE100_VGEN2VOL, + 0x20, 0x20); + if (ret < 0) + dev_err(pfuze_chip->dev, "stby vgen config failed %d\n", ret); + + ret = regmap_update_bits(pfuze_chip->regmap, + PFUZE100_VGEN3VOL, + 0x20, 0x20); + if (ret < 0) + dev_err(pfuze_chip->dev, "stby vgen config failed %d\n", ret); + + ret = regmap_update_bits(pfuze_chip->regmap, + PFUZE100_VGEN4VOL, + 0x20, 0x20); + if (ret < 0) + dev_err(pfuze_chip->dev, "stby vgen config failed %d\n", ret); + + ret = regmap_update_bits(pfuze_chip->regmap, + PFUZE100_VGEN5VOL, + 0x20, 0x20); + if (ret < 0) + dev_err(pfuze_chip->dev, "stby vgen config failed %d\n", ret); + + ret = regmap_update_bits(pfuze_chip->regmap, + PFUZE100_VGEN6VOL, + 0x20, 0x20); + if (ret < 0) + dev_err(pfuze_chip->dev, "stby vgen config failed %d\n", ret); +} + static const struct dev_pm_ops pfuze_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(pfuze_suspend, pfuze_resume) }; @@ -754,6 +839,7 @@ static struct i2c_driver pfuze_driver = { .pm = &pfuze_pm_ops, }, .probe = pfuze100_regulator_probe, + .shutdown = pfuze100_regulator_shutdown, }; module_i2c_driver(pfuze_driver); |