diff options
Diffstat (limited to 'drivers/regulator')
22 files changed, 2224 insertions, 364 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 23e3e4a35cc9..070e4403c6c2 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -787,6 +787,24 @@ config REGULATOR_MT6323 This driver supports the control of different power rails of device through regulator interface. +config REGULATOR_MT6331 + tristate "MediaTek MT6331 PMIC" + depends on MFD_MT6397 + help + Say y here to select this option to enable the power regulator of + MediaTek MT6331 PMIC. + This driver supports the control of different power rails of device + through regulator interface + +config REGULATOR_MT6332 + tristate "MediaTek MT6332 PMIC" + depends on MFD_MT6397 + help + Say y here to select this option to enable the power regulator of + MediaTek MT6332 PMIC. + This driver supports the control of different power rails of device + through regulator interface + config REGULATOR_MT6358 tristate "MediaTek MT6358 PMIC" depends on MFD_MT6397 @@ -1264,6 +1282,7 @@ config REGULATOR_STW481X_VMMC config REGULATOR_SY7636A tristate "Silergy SY7636A voltage regulator" + depends on MFD_SY7636A help This driver supports Silergy SY3686A voltage regulator. @@ -1384,6 +1403,15 @@ config REGULATOR_TPS65218 voltage regulators. It supports software based voltage control for different voltage domains +config REGULATOR_TPS65219 + tristate "TI TPS65219 Power regulators" + depends on MFD_TPS65219 && OF + help + This driver supports TPS65219 voltage regulator chips. + TPS65219 series of PMICs have 3 single phase BUCKs & 4 LDOs + voltage regulators. It supports software based voltage control + for different voltage domains. + config REGULATOR_TPS6524X tristate "TI TPS6524X Power regulators" depends on SPI diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index fa49bb6cc544..5962307e1130 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -95,6 +95,8 @@ obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o obj-$(CONFIG_REGULATOR_MT6315) += mt6315-regulator.o obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o +obj-$(CONFIG_REGULATOR_MT6331) += mt6331-regulator.o +obj-$(CONFIG_REGULATOR_MT6332) += mt6332-regulator.o obj-$(CONFIG_REGULATOR_MT6358) += mt6358-regulator.o obj-$(CONFIG_REGULATOR_MT6359) += mt6359-regulator.o obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o @@ -162,6 +164,7 @@ obj-$(CONFIG_REGULATOR_TPS65086) += tps65086-regulator.o obj-$(CONFIG_REGULATOR_TPS65090) += tps65090-regulator.o obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o obj-$(CONFIG_REGULATOR_TPS65218) += tps65218-regulator.o +obj-$(CONFIG_REGULATOR_TPS65219) += tps65219-regulator.o obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o diff --git a/drivers/regulator/bd71815-regulator.c b/drivers/regulator/bd71815-regulator.c index acaa6607898e..c2b8b8be7824 100644 --- a/drivers/regulator/bd71815-regulator.c +++ b/drivers/regulator/bd71815-regulator.c @@ -571,11 +571,10 @@ static int bd7181x_probe(struct platform_device *pdev) dev_err(&pdev->dev, "No parent regmap\n"); return -ENODEV; } - ldo4_en = devm_gpiod_get_from_of_node(&pdev->dev, - pdev->dev.parent->of_node, - "rohm,vsel-gpios", 0, - GPIOD_ASIS, "ldo4-en"); + ldo4_en = devm_fwnode_gpiod_get(&pdev->dev, + dev_fwnode(pdev->dev.parent), + "rohm,vsel", GPIOD_ASIS, "ldo4-en"); if (IS_ERR(ldo4_en)) { ret = PTR_ERR(ldo4_en); if (ret != -ENOENT) diff --git a/drivers/regulator/bd9576-regulator.c b/drivers/regulator/bd9576-regulator.c index aa42da4d141e..393c8693b327 100644 --- a/drivers/regulator/bd9576-regulator.c +++ b/drivers/regulator/bd9576-regulator.c @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> @@ -939,8 +940,8 @@ static int bd957x_probe(struct platform_device *pdev) } ic_data->regmap = regmap; - vout_mode = of_property_read_bool(pdev->dev.parent->of_node, - "rohm,vout1-en-low"); + vout_mode = device_property_read_bool(pdev->dev.parent, + "rohm,vout1-en-low"); if (vout_mode) { struct gpio_desc *en; @@ -948,10 +949,10 @@ static int bd957x_probe(struct platform_device *pdev) /* VOUT1 enable state judged by VOUT1_EN pin */ /* See if we have GPIO defined */ - en = devm_gpiod_get_from_of_node(&pdev->dev, - pdev->dev.parent->of_node, - "rohm,vout1-en-gpios", 0, - GPIOD_OUT_LOW, "vout1-en"); + en = devm_fwnode_gpiod_get(&pdev->dev, + dev_fwnode(pdev->dev.parent), + "rohm,vout1-en", GPIOD_OUT_LOW, + "vout1-en"); if (!IS_ERR(en)) { /* VOUT1_OPS gpio ctrl */ /* @@ -986,8 +987,8 @@ static int bd957x_probe(struct platform_device *pdev) * like DDR voltage selection. */ platform_set_drvdata(pdev, ic_data); - ddr_sel = of_property_read_bool(pdev->dev.parent->of_node, - "rohm,ddr-sel-low"); + ddr_sel = device_property_read_bool(pdev->dev.parent, + "rohm,ddr-sel-low"); if (ddr_sel) ic_data->regulator_data[2].desc.fixed_uV = 1350000; else diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 7150b1d0159e..bcccad8f7516 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -977,12 +977,27 @@ static int drms_uA_update(struct regulator_dev *rdev) rdev_err(rdev, "failed to set load %d: %pe\n", current_uA, ERR_PTR(err)); } else { + /* + * Unfortunately in some cases the constraints->valid_ops has + * REGULATOR_CHANGE_DRMS but there are no valid modes listed. + * That's not really legit but we won't consider it a fatal + * error here. We'll treat it as if REGULATOR_CHANGE_DRMS + * wasn't set. + */ + if (!rdev->constraints->valid_modes_mask) { + rdev_dbg(rdev, "Can change modes; but no valid mode\n"); + return 0; + } + /* get output voltage */ output_uV = regulator_get_voltage_rdev(rdev); - if (output_uV <= 0) { - rdev_err(rdev, "invalid output voltage found\n"); - return -EINVAL; - } + + /* + * Don't return an error; if regulator driver cares about + * output_uV then it's up to the driver to validate. + */ + if (output_uV <= 0) + rdev_dbg(rdev, "invalid output voltage found\n"); /* get input voltage */ input_uV = 0; @@ -990,10 +1005,13 @@ static int drms_uA_update(struct regulator_dev *rdev) input_uV = regulator_get_voltage(rdev->supply); if (input_uV <= 0) input_uV = rdev->constraints->input_uV; - if (input_uV <= 0) { - rdev_err(rdev, "invalid input voltage found\n"); - return -EINVAL; - } + + /* + * Don't return an error; if regulator driver cares about + * input_uV then it's up to the driver to validate. + */ + if (input_uV <= 0) + rdev_dbg(rdev, "invalid input voltage found\n"); /* now get the optimum mode for our new total regulator load */ mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, @@ -2681,7 +2699,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev) * return -ETIMEDOUT. */ if (rdev->desc->poll_enabled_time) { - unsigned int time_remaining = delay; + int time_remaining = delay; while (time_remaining > 0) { _regulator_delay_helper(rdev->desc->poll_enabled_time); @@ -2733,13 +2751,18 @@ static int _regulator_do_enable(struct regulator_dev *rdev) */ static int _regulator_handle_consumer_enable(struct regulator *regulator) { + int ret; struct regulator_dev *rdev = regulator->rdev; lockdep_assert_held_once(&rdev->mutex.base); regulator->enable_count++; - if (regulator->uA_load && regulator->enable_count == 1) - return drms_uA_update(rdev); + if (regulator->uA_load && regulator->enable_count == 1) { + ret = drms_uA_update(rdev); + if (ret) + regulator->enable_count--; + return ret; + } return 0; } @@ -3497,10 +3520,8 @@ static int _regulator_set_voltage_time(struct regulator_dev *rdev, (new_uV < old_uV)) return rdev->constraints->settling_time_down; - if (ramp_delay == 0) { - rdev_dbg(rdev, "ramp_delay not set\n"); + if (ramp_delay == 0) return 0; - } return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay); } @@ -4784,10 +4805,10 @@ int regulator_bulk_get(struct device *dev, int num_consumers, consumers[i].consumer = regulator_get(dev, consumers[i].supply); if (IS_ERR(consumers[i].consumer)) { - consumers[i].consumer = NULL; ret = dev_err_probe(dev, PTR_ERR(consumers[i].consumer), "Failed to get supply '%s'", consumers[i].supply); + consumers[i].consumer = NULL; goto err; } @@ -5393,6 +5414,7 @@ regulator_register(const struct regulator_desc *regulator_desc, bool dangling_of_gpiod = false; struct device *dev; int ret, i; + bool resolved_early = false; if (cfg == NULL) return ERR_PTR(-EINVAL); @@ -5496,24 +5518,10 @@ regulator_register(const struct regulator_desc *regulator_desc, BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); - /* preform any regulator specific init */ - if (init_data && init_data->regulator_init) { - ret = init_data->regulator_init(rdev->reg_data); - if (ret < 0) - goto clean; - } - - if (config->ena_gpiod) { - ret = regulator_ena_gpio_request(rdev, config); - if (ret != 0) { - rdev_err(rdev, "Failed to request enable GPIO: %pe\n", - ERR_PTR(ret)); - goto clean; - } - /* The regulator core took over the GPIO descriptor */ - dangling_cfg_gpiod = false; - dangling_of_gpiod = false; - } + if (init_data && init_data->supply_regulator) + rdev->supply_name = init_data->supply_regulator; + else if (regulator_desc->supply_name) + rdev->supply_name = regulator_desc->supply_name; /* register with sysfs */ rdev->dev.class = ®ulator_class; @@ -5535,13 +5543,38 @@ regulator_register(const struct regulator_desc *regulator_desc, goto wash; } - if (init_data && init_data->supply_regulator) - rdev->supply_name = init_data->supply_regulator; - else if (regulator_desc->supply_name) - rdev->supply_name = regulator_desc->supply_name; + if ((rdev->supply_name && !rdev->supply) && + (rdev->constraints->always_on || + rdev->constraints->boot_on)) { + ret = regulator_resolve_supply(rdev); + if (ret) + rdev_dbg(rdev, "unable to resolve supply early: %pe\n", + ERR_PTR(ret)); + + resolved_early = true; + } + + /* perform any regulator specific init */ + if (init_data && init_data->regulator_init) { + ret = init_data->regulator_init(rdev->reg_data); + if (ret < 0) + goto wash; + } + + if (config->ena_gpiod) { + ret = regulator_ena_gpio_request(rdev, config); + if (ret != 0) { + rdev_err(rdev, "Failed to request enable GPIO: %pe\n", + ERR_PTR(ret)); + goto wash; + } + /* The regulator core took over the GPIO descriptor */ + dangling_cfg_gpiod = false; + dangling_of_gpiod = false; + } ret = set_machine_constraints(rdev); - if (ret == -EPROBE_DEFER) { + if (ret == -EPROBE_DEFER && !resolved_early) { /* Regulator might be in bypass mode and so needs its supply * to set the constraints */ diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c index 76e0e23bf598..e4c753b83088 100644 --- a/drivers/regulator/da9121-regulator.c +++ b/drivers/regulator/da9121-regulator.c @@ -1164,7 +1164,7 @@ error: return ret; } -static int da9121_i2c_remove(struct i2c_client *i2c) +static void da9121_i2c_remove(struct i2c_client *i2c) { struct da9121 *chip = i2c_get_clientdata(i2c); const int mask_all[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; @@ -1176,7 +1176,6 @@ static int da9121_i2c_remove(struct i2c_client *i2c) ret = regmap_bulk_write(chip->regmap, DA9121_REG_SYS_MASK_0, mask_all, 4); if (ret != 0) dev_err(chip->dev, "Failed to set IRQ masks: %d\n", ret); - return 0; } static const struct i2c_device_id da9121_i2c_id[] = { diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c index 32823a87fd40..3265e75e97ab 100644 --- a/drivers/regulator/devres.c +++ b/drivers/regulator/devres.c @@ -70,6 +70,65 @@ struct regulator *devm_regulator_get_exclusive(struct device *dev, } EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive); +static void regulator_action_disable(void *d) +{ + struct regulator *r = (struct regulator *)d; + + regulator_disable(r); +} + +static int _devm_regulator_get_enable(struct device *dev, const char *id, + int get_type) +{ + struct regulator *r; + int ret; + + r = _devm_regulator_get(dev, id, get_type); + if (IS_ERR(r)) + return PTR_ERR(r); + + ret = regulator_enable(r); + if (!ret) + ret = devm_add_action_or_reset(dev, ®ulator_action_disable, r); + + if (ret) + devm_regulator_put(r); + + return ret; +} + +/** + * devm_regulator_get_enable_optional - Resource managed regulator get and enable + * @dev: device to supply + * @id: supply name or regulator ID. + * + * Get and enable regulator for duration of the device life-time. + * regulator_disable() and regulator_put() are automatically called on driver + * detach. See regulator_get_optional() and regulator_enable() for more + * information. + */ +int devm_regulator_get_enable_optional(struct device *dev, const char *id) +{ + return _devm_regulator_get_enable(dev, id, OPTIONAL_GET); +} +EXPORT_SYMBOL_GPL(devm_regulator_get_enable_optional); + +/** + * devm_regulator_get_enable - Resource managed regulator get and enable + * @dev: device to supply + * @id: supply name or regulator ID. + * + * Get and enable regulator for duration of the device life-time. + * regulator_disable() and regulator_put() are automatically called on driver + * detach. See regulator_get() and regulator_enable() for more + * information. + */ +int devm_regulator_get_enable(struct device *dev, const char *id) +{ + return _devm_regulator_get_enable(dev, id, NORMAL_GET); +} +EXPORT_SYMBOL_GPL(devm_regulator_get_enable); + /** * devm_regulator_get_optional - Resource managed regulator_get_optional() * @dev: device to supply @@ -194,6 +253,111 @@ int devm_regulator_bulk_get_const(struct device *dev, int num_consumers, } EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_const); +static int devm_regulator_bulk_match(struct device *dev, void *res, + void *data) +{ + struct regulator_bulk_devres *match = res; + struct regulator_bulk_data *target = data; + + /* + * We check the put uses same consumer list as the get did. + * We _could_ scan all entries in consumer array and check the + * regulators match but ATM I don't see the need. We can change this + * later if needed. + */ + return match->consumers == target; +} + +/** + * devm_regulator_bulk_put - Resource managed regulator_bulk_put() + * @consumers: consumers to free + * + * Deallocate regulators allocated with devm_regulator_bulk_get(). Normally + * this function will not need to be called and the resource management + * code will ensure that the resource is freed. + */ +void devm_regulator_bulk_put(struct regulator_bulk_data *consumers) +{ + int rc; + struct regulator *regulator = consumers[0].consumer; + + rc = devres_release(regulator->dev, devm_regulator_bulk_release, + devm_regulator_bulk_match, consumers); + if (rc != 0) + WARN_ON(rc); +} +EXPORT_SYMBOL_GPL(devm_regulator_bulk_put); + +static void devm_regulator_bulk_disable(void *res) +{ + struct regulator_bulk_devres *devres = res; + int i; + + for (i = 0; i < devres->num_consumers; i++) + regulator_disable(devres->consumers[i].consumer); +} + +/** + * devm_regulator_bulk_get_enable - managed get'n enable multiple regulators + * + * @dev: device to supply + * @num_consumers: number of consumers to register + * @id: list of supply names or regulator IDs + * + * @return 0 on success, an errno on failure. + * + * This helper function allows drivers to get several regulator + * consumers in one operation with management, the regulators will + * automatically be freed when the device is unbound. If any of the + * regulators cannot be acquired then any regulators that were + * allocated will be freed before returning to the caller. + */ +int devm_regulator_bulk_get_enable(struct device *dev, int num_consumers, + const char * const *id) +{ + struct regulator_bulk_devres *devres; + struct regulator_bulk_data *consumers; + int i, ret; + + devres = devm_kmalloc(dev, sizeof(*devres), GFP_KERNEL); + if (!devres) + return -ENOMEM; + + devres->consumers = devm_kcalloc(dev, num_consumers, sizeof(*consumers), + GFP_KERNEL); + consumers = devres->consumers; + if (!consumers) + return -ENOMEM; + + devres->num_consumers = num_consumers; + + for (i = 0; i < num_consumers; i++) + consumers[i].supply = id[i]; + + ret = devm_regulator_bulk_get(dev, num_consumers, consumers); + if (ret) + return ret; + + for (i = 0; i < num_consumers; i++) { + ret = regulator_enable(consumers[i].consumer); + if (ret) + goto unwind; + } + + ret = devm_add_action(dev, devm_regulator_bulk_disable, devres); + if (!ret) + return 0; + +unwind: + while (--i >= 0) + regulator_disable(consumers[i].consumer); + + devm_regulator_bulk_put(consumers); + + return ret; +} +EXPORT_SYMBOL_GPL(devm_regulator_bulk_get_enable); + static void devm_rdev_release(struct device *dev, void *res) { regulator_unregister(*(struct regulator_dev **)res); diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 5927d4f3eabd..95e61a2f43f5 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -220,6 +220,9 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np, regtype); } + if (of_find_property(np, "vin-supply", NULL)) + config->input_supply = "vin"; + return config; } @@ -259,6 +262,18 @@ static int gpio_regulator_probe(struct platform_device *pdev) drvdata->gpiods = devm_kzalloc(dev, sizeof(struct gpio_desc *), GFP_KERNEL); + + if (config->input_supply) { + drvdata->desc.supply_name = devm_kstrdup(&pdev->dev, + config->input_supply, + GFP_KERNEL); + if (!drvdata->desc.supply_name) { + dev_err(&pdev->dev, + "Failed to allocate input supply\n"); + return -ENOMEM; + } + } + if (!drvdata->gpiods) return -ENOMEM; for (i = 0; i < config->ngpios; i++) { diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index 321bec6e3f8d..31b43426d47c 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -422,15 +422,13 @@ err: return ret; } -static int lp8755_remove(struct i2c_client *client) +static void lp8755_remove(struct i2c_client *client) { int icnt; struct lp8755_chip *pchip = i2c_get_clientdata(client); for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) regmap_write(pchip->regmap, icnt, 0x00); - - return 0; } static const struct i2c_device_id lp8755_id[] = { diff --git a/drivers/regulator/max597x-regulator.c b/drivers/regulator/max597x-regulator.c index 03c6027682d8..39f803ff0a90 100644 --- a/drivers/regulator/max597x-regulator.c +++ b/drivers/regulator/max597x-regulator.c @@ -137,7 +137,7 @@ static int max597x_set_ovp(struct regulator_dev *rdev, int lim_uV, int severity, static int max597x_set_ocp(struct regulator_dev *rdev, int lim_uA, int severity, bool enable) { - int ret, val, reg; + int val, reg; unsigned int vthst, vthfst; struct max597x_regulator *data = rdev_get_drvdata(rdev); @@ -183,9 +183,8 @@ static int max597x_set_ocp(struct regulator_dev *rdev, int lim_uA, val = 0xFF; reg = MAX5970_REG_DAC_FAST(rdev_id); - ret = regmap_write(rdev->regmap, reg, val); - return ret; + return regmap_write(rdev->regmap, reg, val); } static int max597x_get_status(struct regulator_dev *rdev) diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index fdcb0f508984..596cc36aaff6 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -434,9 +434,9 @@ static int max8973_init_dcdc(struct max8973_chip *max, return ret; } -static int max8973_thermal_read_temp(void *data, int *temp) +static int max8973_thermal_read_temp(struct thermal_zone_device *tz, int *temp) { - struct max8973_chip *mchip = data; + struct max8973_chip *mchip = tz->devdata; unsigned int val; int ret; @@ -465,7 +465,7 @@ static irqreturn_t max8973_thermal_irq(int irq, void *data) return IRQ_HANDLED; } -static const struct thermal_zone_of_device_ops max77621_tz_ops = { +static const struct thermal_zone_device_ops max77621_tz_ops = { .get_temp = max8973_thermal_read_temp, }; @@ -479,8 +479,8 @@ static int max8973_thermal_init(struct max8973_chip *mchip) if (mchip->id != MAX77621) return 0; - tzd = devm_thermal_zone_of_sensor_register(mchip->dev, 0, mchip, - &max77621_tz_ops); + tzd = devm_thermal_of_zone_register(mchip->dev, 0, mchip, + &max77621_tz_ops); if (IS_ERR(tzd)) { ret = PTR_ERR(tzd); dev_err(mchip->dev, "Failed to register thermal sensor: %d\n", diff --git a/drivers/regulator/mt6331-regulator.c b/drivers/regulator/mt6331-regulator.c new file mode 100644 index 000000000000..56be9a3a84ab --- /dev/null +++ b/drivers/regulator/mt6331-regulator.c @@ -0,0 +1,507 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2022 Collabora Ltd. +// Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> +// +// Based on mt6323-regulator.c, +// Copyright (c) 2016 MediaTek Inc. +// + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/mfd/mt6397/core.h> +#include <linux/mfd/mt6331/registers.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/mt6331-regulator.h> +#include <linux/regulator/of_regulator.h> + +#define MT6331_LDO_MODE_NORMAL 0 +#define MT6331_LDO_MODE_LP 1 + +/* + * MT6331 regulators information + * + * @desc: standard fields of regulator description. + * @qi: Mask for query enable signal status of regulators + * @vselon_reg: Register sections for hardware control mode of bucks + * @vselctrl_reg: Register for controlling the buck control mode. + * @vselctrl_mask: Mask for query buck's voltage control mode. + * @status_reg: Register for regulator enable status where qi unavailable + * @status_mask: Mask for querying regulator enable status + */ +struct mt6331_regulator_info { + struct regulator_desc desc; + u32 qi; + u32 vselon_reg; + u32 vselctrl_reg; + u32 vselctrl_mask; + u32 modeset_reg; + u32 modeset_mask; + u32 status_reg; + u32 status_mask; +}; + +#define MT6331_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \ + vosel, vosel_mask, voselon, vosel_ctrl) \ +[MT6331_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6331_volt_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6331_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = (max - min)/step + 1, \ + .linear_ranges = volt_ranges, \ + .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = enreg, \ + .enable_mask = BIT(0), \ + }, \ + .qi = BIT(13), \ + .vselon_reg = voselon, \ + .vselctrl_reg = vosel_ctrl, \ + .vselctrl_mask = BIT(1), \ + .status_mask = 0, \ +} + +#define MT6331_LDO_AO(match, vreg, ldo_volt_table, vosel, vosel_mask) \ +[MT6331_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6331_volt_table_ao_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6331_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(ldo_volt_table), \ + .volt_table = ldo_volt_table, \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + }, \ +} + +#define MT6331_LDO_S(match, vreg, ldo_volt_table, enreg, enbit, vosel, \ + vosel_mask, _modeset_reg, _modeset_mask, \ + _status_reg, _status_mask) \ +[MT6331_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6331_volt_table_no_qi_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6331_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(ldo_volt_table), \ + .volt_table = ldo_volt_table, \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = enreg, \ + .enable_mask = BIT(enbit), \ + }, \ + .modeset_reg = _modeset_reg, \ + .modeset_mask = _modeset_mask, \ + .status_reg = _status_reg, \ + .status_mask = _status_mask, \ +} + +#define MT6331_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \ + vosel_mask, _modeset_reg, _modeset_mask) \ +[MT6331_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = (_modeset_reg ? \ + &mt6331_volt_table_ops : \ + &mt6331_volt_table_no_ms_ops), \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6331_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(ldo_volt_table), \ + .volt_table = ldo_volt_table, \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = enreg, \ + .enable_mask = BIT(enbit), \ + }, \ + .qi = BIT(15), \ + .modeset_reg = _modeset_reg, \ + .modeset_mask = _modeset_mask, \ +} + +#define MT6331_REG_FIXED(match, vreg, enreg, enbit, qibit, volt, \ + _modeset_reg, _modeset_mask) \ +[MT6331_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = (_modeset_reg ? \ + &mt6331_volt_fixed_ops : \ + &mt6331_volt_fixed_no_ms_ops), \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6331_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = 1, \ + .enable_reg = enreg, \ + .enable_mask = BIT(enbit), \ + .min_uV = volt, \ + }, \ + .qi = BIT(qibit), \ + .modeset_reg = _modeset_reg, \ + .modeset_mask = _modeset_mask, \ +} + +static const struct linear_range buck_volt_range[] = { + REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250), +}; + +static const unsigned int ldo_volt_table1[] = { + 2800000, 3000000, 0, 3200000 +}; + +static const unsigned int ldo_volt_table2[] = { + 1500000, 1800000, 2500000, 2800000, +}; + +static const unsigned int ldo_volt_table3[] = { + 1200000, 1300000, 1500000, 1800000, 2000000, 2800000, 3000000, 3300000, +}; + +static const unsigned int ldo_volt_table4[] = { + 0, 0, 1700000, 1800000, 1860000, 2760000, 3000000, 3100000, +}; + +static const unsigned int ldo_volt_table5[] = { + 1800000, 3300000, 1800000, 3300000, +}; + +static const unsigned int ldo_volt_table6[] = { + 3000000, 3300000, +}; + +static const unsigned int ldo_volt_table7[] = { + 1200000, 1600000, 1700000, 1800000, 1900000, 2000000, 2100000, 2200000, +}; + +static const unsigned int ldo_volt_table8[] = { + 900000, 1000000, 1100000, 1220000, 1300000, 1500000, 1500000, 1500000, +}; + +static const unsigned int ldo_volt_table9[] = { + 1000000, 1050000, 1100000, 1150000, 1200000, 1250000, 1300000, 1300000, +}; + +static const unsigned int ldo_volt_table10[] = { + 1200000, 1300000, 1500000, 1800000, +}; + +static const unsigned int ldo_volt_table11[] = { + 1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1800000, +}; + +static int mt6331_get_status(struct regulator_dev *rdev) +{ + struct mt6331_regulator_info *info = rdev_get_drvdata(rdev); + u32 regval; + int ret; + + ret = regmap_read(rdev->regmap, info->desc.enable_reg, ®val); + if (ret != 0) { + dev_err(&rdev->dev, "Failed to get enable reg: %d\n", ret); + return ret; + } + + return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF; +} + +static int mt6331_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct mt6331_regulator_info *info = rdev_get_drvdata(rdev); + int val; + + switch (mode) { + case REGULATOR_MODE_STANDBY: + val = MT6331_LDO_MODE_LP; + break; + case REGULATOR_MODE_NORMAL: + val = MT6331_LDO_MODE_NORMAL; + break; + default: + return -EINVAL; + } + + val <<= ffs(info->modeset_mask) - 1; + + return regmap_update_bits(rdev->regmap, info->modeset_reg, + info->modeset_mask, val); +} + +static unsigned int mt6331_ldo_get_mode(struct regulator_dev *rdev) +{ + struct mt6331_regulator_info *info = rdev_get_drvdata(rdev); + unsigned int val; + int ret; + + ret = regmap_read(rdev->regmap, info->modeset_reg, &val); + if (ret < 0) + return ret; + + val &= info->modeset_mask; + val >>= ffs(info->modeset_mask) - 1; + + return (val & BIT(0)) ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; +} + +static const struct regulator_ops mt6331_volt_range_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6331_get_status, +}; + +static const struct regulator_ops mt6331_volt_table_no_ms_ops = { + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_iterate, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6331_get_status, +}; + +static const struct regulator_ops mt6331_volt_table_no_qi_ops = { + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_iterate, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_mode = mt6331_ldo_set_mode, + .get_mode = mt6331_ldo_get_mode, +}; + +static const struct regulator_ops mt6331_volt_table_ops = { + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_iterate, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6331_get_status, + .set_mode = mt6331_ldo_set_mode, + .get_mode = mt6331_ldo_get_mode, +}; + +static const struct regulator_ops mt6331_volt_table_ao_ops = { + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_iterate, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, +}; + +static const struct regulator_ops mt6331_volt_fixed_no_ms_ops = { + .list_voltage = regulator_list_voltage_linear, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6331_get_status, +}; + +static const struct regulator_ops mt6331_volt_fixed_ops = { + .list_voltage = regulator_list_voltage_linear, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6331_get_status, + .set_mode = mt6331_ldo_set_mode, + .get_mode = mt6331_ldo_get_mode, +}; + +/* The array is indexed by id(MT6331_ID_XXX) */ +static struct mt6331_regulator_info mt6331_regulators[] = { + MT6331_BUCK("buck-vdvfs11", VDVFS11, 700000, 1493750, 6250, + buck_volt_range, MT6331_VDVFS11_CON9, + MT6331_VDVFS11_CON11, GENMASK(6, 0), + MT6331_VDVFS11_CON12, MT6331_VDVFS11_CON7), + MT6331_BUCK("buck-vdvfs12", VDVFS12, 700000, 1493750, 6250, + buck_volt_range, MT6331_VDVFS12_CON9, + MT6331_VDVFS12_CON11, GENMASK(6, 0), + MT6331_VDVFS12_CON12, MT6331_VDVFS12_CON7), + MT6331_BUCK("buck-vdvfs13", VDVFS13, 700000, 1493750, 6250, + buck_volt_range, MT6331_VDVFS13_CON9, + MT6331_VDVFS13_CON11, GENMASK(6, 0), + MT6331_VDVFS13_CON12, MT6331_VDVFS13_CON7), + MT6331_BUCK("buck-vdvfs14", VDVFS14, 700000, 1493750, 6250, + buck_volt_range, MT6331_VDVFS14_CON9, + MT6331_VDVFS14_CON11, GENMASK(6, 0), + MT6331_VDVFS14_CON12, MT6331_VDVFS14_CON7), + MT6331_BUCK("buck-vcore2", VCORE2, 700000, 1493750, 6250, + buck_volt_range, MT6331_VCORE2_CON9, + MT6331_VCORE2_CON11, GENMASK(6, 0), + MT6331_VCORE2_CON12, MT6331_VCORE2_CON7), + MT6331_REG_FIXED("buck-vio18", VIO18, MT6331_VIO18_CON9, 0, 13, 1800000, 0, 0), + MT6331_REG_FIXED("ldo-vrtc", VRTC, MT6331_DIGLDO_CON11, 8, 15, 2800000, 0, 0), + MT6331_REG_FIXED("ldo-vtcxo1", VTCXO1, MT6331_ANALDO_CON1, 10, 15, 2800000, + MT6331_ANALDO_CON1, GENMASK(1, 0)), + MT6331_REG_FIXED("ldo-vtcxo2", VTCXO2, MT6331_ANALDO_CON2, 10, 15, 2800000, + MT6331_ANALDO_CON2, GENMASK(1, 0)), + MT6331_REG_FIXED("ldo-vsram", VSRAM_DVFS1, MT6331_SYSLDO_CON4, 10, 15, 1012500, + MT6331_SYSLDO_CON4, GENMASK(1, 0)), + MT6331_REG_FIXED("ldo-vio28", VIO28, MT6331_DIGLDO_CON1, 10, 15, 2800000, + MT6331_DIGLDO_CON1, GENMASK(1, 0)), + MT6331_LDO("ldo-avdd32aud", AVDD32_AUD, ldo_volt_table1, MT6331_ANALDO_CON3, 10, + MT6331_ANALDO_CON10, GENMASK(6, 5), MT6331_ANALDO_CON3, GENMASK(1, 0)), + MT6331_LDO("ldo-vauxa32", VAUXA32, ldo_volt_table1, MT6331_ANALDO_CON4, 10, + MT6331_ANALDO_CON6, GENMASK(6, 5), MT6331_ANALDO_CON4, GENMASK(1, 0)), + MT6331_LDO("ldo-vemc33", VEMC33, ldo_volt_table6, MT6331_DIGLDO_CON5, 10, + MT6331_DIGLDO_CON17, BIT(6), MT6331_DIGLDO_CON5, GENMASK(1, 0)), + MT6331_LDO("ldo-vibr", VIBR, ldo_volt_table3, MT6331_DIGLDO_CON12, 10, + MT6331_DIGLDO_CON20, GENMASK(6, 4), MT6331_DIGLDO_CON12, GENMASK(1, 0)), + MT6331_LDO("ldo-vmc", VMC, ldo_volt_table5, MT6331_DIGLDO_CON3, 10, + MT6331_DIGLDO_CON15, GENMASK(5, 4), MT6331_DIGLDO_CON3, GENMASK(1, 0)), + MT6331_LDO("ldo-vmch", VMCH, ldo_volt_table6, MT6331_DIGLDO_CON4, 10, + MT6331_DIGLDO_CON16, BIT(6), MT6331_DIGLDO_CON4, GENMASK(1, 0)), + MT6331_LDO("ldo-vmipi", VMIPI, ldo_volt_table3, MT6331_SYSLDO_CON5, 10, + MT6331_SYSLDO_CON13, GENMASK(5, 3), MT6331_SYSLDO_CON5, GENMASK(1, 0)), + MT6331_LDO("ldo-vsim1", VSIM1, ldo_volt_table4, MT6331_DIGLDO_CON8, 10, + MT6331_DIGLDO_CON21, GENMASK(6, 4), MT6331_DIGLDO_CON8, GENMASK(1, 0)), + MT6331_LDO("ldo-vsim2", VSIM2, ldo_volt_table4, MT6331_DIGLDO_CON9, 10, + MT6331_DIGLDO_CON22, GENMASK(6, 4), MT6331_DIGLDO_CON9, GENMASK(1, 0)), + MT6331_LDO("ldo-vusb10", VUSB10, ldo_volt_table9, MT6331_SYSLDO_CON2, 10, + MT6331_SYSLDO_CON10, GENMASK(5, 3), MT6331_SYSLDO_CON2, GENMASK(1, 0)), + MT6331_LDO("ldo-vcama", VCAMA, ldo_volt_table2, MT6331_ANALDO_CON5, 15, + MT6331_ANALDO_CON9, GENMASK(5, 4), 0, 0), + MT6331_LDO_S("ldo-vcamaf", VCAM_AF, ldo_volt_table3, MT6331_DIGLDO_CON2, 10, + MT6331_DIGLDO_CON14, GENMASK(6, 4), MT6331_DIGLDO_CON2, GENMASK(1, 0), + MT6331_EN_STATUS1, BIT(0)), + MT6331_LDO_S("ldo-vcamd", VCAMD, ldo_volt_table8, MT6331_SYSLDO_CON1, 15, + MT6331_SYSLDO_CON9, GENMASK(6, 4), MT6331_SYSLDO_CON1, GENMASK(1, 0), + MT6331_EN_STATUS1, BIT(11)), + MT6331_LDO_S("ldo-vcamio", VCAM_IO, ldo_volt_table10, MT6331_SYSLDO_CON3, 10, + MT6331_SYSLDO_CON11, GENMASK(4, 3), MT6331_SYSLDO_CON3, GENMASK(1, 0), + MT6331_EN_STATUS1, BIT(13)), + MT6331_LDO_S("ldo-vgp1", VGP1, ldo_volt_table3, MT6331_DIGLDO_CON6, 10, + MT6331_DIGLDO_CON19, GENMASK(6, 4), MT6331_DIGLDO_CON6, GENMASK(1, 0), + MT6331_EN_STATUS1, BIT(4)), + MT6331_LDO_S("ldo-vgp2", VGP2, ldo_volt_table10, MT6331_SYSLDO_CON6, 10, + MT6331_SYSLDO_CON14, GENMASK(4, 3), MT6331_SYSLDO_CON6, GENMASK(1, 0), + MT6331_EN_STATUS1, BIT(15)), + MT6331_LDO_S("ldo-vgp3", VGP3, ldo_volt_table10, MT6331_SYSLDO_CON7, 10, + MT6331_SYSLDO_CON15, GENMASK(4, 3), MT6331_SYSLDO_CON7, GENMASK(1, 0), + MT6331_EN_STATUS2, BIT(0)), + MT6331_LDO_S("ldo-vgp4", VGP4, ldo_volt_table7, MT6331_DIGLDO_CON7, 10, + MT6331_DIGLDO_CON18, GENMASK(6, 4), MT6331_DIGLDO_CON7, GENMASK(1, 0), + MT6331_EN_STATUS1, BIT(5)), + MT6331_LDO_AO("ldo-vdig18", VDIG18, ldo_volt_table11, + MT6331_DIGLDO_CON28, GENMASK(14, 12)), +}; + +static int mt6331_set_buck_vosel_reg(struct platform_device *pdev) +{ + struct mt6397_chip *mt6331 = dev_get_drvdata(pdev->dev.parent); + int i; + u32 regval; + + for (i = 0; i < MT6331_ID_VREG_MAX; i++) { + if (mt6331_regulators[i].vselctrl_reg) { + if (regmap_read(mt6331->regmap, + mt6331_regulators[i].vselctrl_reg, + ®val) < 0) { + dev_err(&pdev->dev, + "Failed to read buck ctrl\n"); + return -EIO; + } + + if (regval & mt6331_regulators[i].vselctrl_mask) { + mt6331_regulators[i].desc.vsel_reg = + mt6331_regulators[i].vselon_reg; + } + } + } + + return 0; +} + +static int mt6331_regulator_probe(struct platform_device *pdev) +{ + struct mt6397_chip *mt6331 = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = {}; + struct regulator_dev *rdev; + int i; + u32 reg_value; + + /* Query buck controller to select activated voltage register part */ + if (mt6331_set_buck_vosel_reg(pdev)) + return -EIO; + + /* Read PMIC chip revision to update constraints and voltage table */ + if (regmap_read(mt6331->regmap, MT6331_HWCID, ®_value) < 0) { + dev_err(&pdev->dev, "Failed to read Chip ID\n"); + return -EIO; + } + reg_value &= GENMASK(7, 0); + + dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value); + + /* + * ChipID 0x10 is "MT6331 E1", has a different voltage table and + * it's currently not supported in this driver. Upon detection of + * this ID, refuse to register the regulators, as we will wrongly + * interpret the VSEL for this revision, potentially overvolting + * some device. + */ + if (reg_value == 0x10) { + dev_err(&pdev->dev, "Chip version not supported. Bailing out.\n"); + return -EINVAL; + } + + for (i = 0; i < MT6331_ID_VREG_MAX; i++) { + config.dev = &pdev->dev; + config.driver_data = &mt6331_regulators[i]; + config.regmap = mt6331->regmap; + rdev = devm_regulator_register(&pdev->dev, + &mt6331_regulators[i].desc, &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "failed to register %s\n", + mt6331_regulators[i].desc.name); + return PTR_ERR(rdev); + } + } + return 0; +} + +static const struct platform_device_id mt6331_platform_ids[] = { + {"mt6331-regulator", 0}, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(platform, mt6331_platform_ids); + +static struct platform_driver mt6331_regulator_driver = { + .driver = { + .name = "mt6331-regulator", + }, + .probe = mt6331_regulator_probe, + .id_table = mt6331_platform_ids, +}; + +module_platform_driver(mt6331_regulator_driver); + +MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>"); +MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6331 PMIC"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/mt6332-regulator.c b/drivers/regulator/mt6332-regulator.c new file mode 100644 index 000000000000..77a27d8127a3 --- /dev/null +++ b/drivers/regulator/mt6332-regulator.c @@ -0,0 +1,422 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2022 Collabora Ltd. +// Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> +// +// Based on mt6323-regulator.c, +// Copyright (c) 2016 MediaTek Inc. +// + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/mfd/mt6397/core.h> +#include <linux/mfd/mt6332/registers.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/mt6332-regulator.h> +#include <linux/regulator/of_regulator.h> + +#define MT6332_LDO_MODE_NORMAL 0 +#define MT6332_LDO_MODE_LP 1 + +/* + * MT6332 regulators information + * + * @desc: standard fields of regulator description. + * @qi: Mask for query enable signal status of regulators + * @vselon_reg: Register sections for hardware control mode of bucks + * @vselctrl_reg: Register for controlling the buck control mode. + * @vselctrl_mask: Mask for query buck's voltage control mode. + * @status_reg: Register for regulator enable status where qi unavailable + * @status_mask: Mask for querying regulator enable status + */ +struct mt6332_regulator_info { + struct regulator_desc desc; + u32 qi; + u32 vselon_reg; + u32 vselctrl_reg; + u32 vselctrl_mask; + u32 modeset_reg; + u32 modeset_mask; + u32 status_reg; + u32 status_mask; +}; + +#define MT6332_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \ + vosel, vosel_mask, voselon, vosel_ctrl) \ +[MT6332_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6332_buck_volt_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6332_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = (max - min)/step + 1, \ + .linear_ranges = volt_ranges, \ + .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = enreg, \ + .enable_mask = BIT(0), \ + }, \ + .qi = BIT(13), \ + .vselon_reg = voselon, \ + .vselctrl_reg = vosel_ctrl, \ + .vselctrl_mask = BIT(1), \ + .status_mask = 0, \ +} + +#define MT6332_LDO_LINEAR(match, vreg, min, max, step, volt_ranges, \ + enreg, vosel, vosel_mask, voselon, \ + vosel_ctrl, _modeset_reg, _modeset_mask) \ +[MT6332_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6332_ldo_volt_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6332_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = (max - min)/step + 1, \ + .linear_ranges = volt_ranges, \ + .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = enreg, \ + .enable_mask = BIT(0), \ + }, \ + .qi = BIT(15), \ + .vselon_reg = voselon, \ + .vselctrl_reg = vosel_ctrl, \ + .vselctrl_mask = BIT(1), \ + .modeset_reg = _modeset_reg, \ + .modeset_mask = _modeset_mask, \ + .status_mask = 0, \ +} + +#define MT6332_LDO_AO(match, vreg, ldo_volt_table, vosel, vosel_mask) \ +[MT6332_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6332_volt_table_ao_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6332_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(ldo_volt_table), \ + .volt_table = ldo_volt_table, \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + }, \ +} + +#define MT6332_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \ + vosel_mask, _modeset_reg, _modeset_mask) \ +[MT6332_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6332_volt_table_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6332_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(ldo_volt_table), \ + .volt_table = ldo_volt_table, \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = enreg, \ + .enable_mask = BIT(enbit), \ + }, \ + .qi = BIT(15), \ + .modeset_reg = _modeset_reg, \ + .modeset_mask = _modeset_mask, \ + .status_mask = 0, \ +} + +#define MT6332_REG_FIXED(match, vreg, enreg, enbit, qibit, volt, stbit) \ +[MT6332_ID_##vreg] = { \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ + .ops = &mt6332_volt_fixed_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6332_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = 1, \ + .enable_reg = enreg, \ + .enable_mask = BIT(enbit), \ + .min_uV = volt, \ + }, \ + .qi = BIT(qibit), \ + .status_reg = MT6332_EN_STATUS0, \ + .status_mask = BIT(stbit), \ +} + +static const struct linear_range boost_volt_range[] = { + REGULATOR_LINEAR_RANGE(3500000, 0, 0x7f, 31250), +}; + +static const struct linear_range buck_volt_range[] = { + REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250), +}; + +static const struct linear_range buck_pa_volt_range[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000), +}; + +static const struct linear_range buck_rf_volt_range[] = { + REGULATOR_LINEAR_RANGE(1050000, 0, 0x7f, 9375), +}; + +static const unsigned int ldo_volt_table1[] = { + 2800000, 3000000, 0, 3200000 +}; + +static const unsigned int ldo_volt_table2[] = { + 1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1800000, +}; + +static int mt6332_get_status(struct regulator_dev *rdev) +{ + struct mt6332_regulator_info *info = rdev_get_drvdata(rdev); + u32 reg, en_mask, regval; + int ret; + + if (info->qi > 0) { + reg = info->desc.enable_reg; + en_mask = info->qi; + } else { + reg = info->status_reg; + en_mask = info->status_mask; + } + + ret = regmap_read(rdev->regmap, reg, ®val); + if (ret != 0) { + dev_err(&rdev->dev, "Failed to get enable reg: %d\n", ret); + return ret; + } + + return (regval & en_mask) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF; +} + +static int mt6332_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct mt6332_regulator_info *info = rdev_get_drvdata(rdev); + int val; + + switch (mode) { + case REGULATOR_MODE_STANDBY: + val = MT6332_LDO_MODE_LP; + break; + case REGULATOR_MODE_NORMAL: + val = MT6332_LDO_MODE_NORMAL; + break; + default: + return -EINVAL; + } + + val <<= ffs(info->modeset_mask) - 1; + + return regmap_update_bits(rdev->regmap, info->modeset_reg, + info->modeset_mask, val); +} + +static unsigned int mt6332_ldo_get_mode(struct regulator_dev *rdev) +{ + struct mt6332_regulator_info *info = rdev_get_drvdata(rdev); + unsigned int val; + int ret; + + ret = regmap_read(rdev->regmap, info->modeset_reg, &val); + if (ret < 0) + return ret; + + val &= info->modeset_mask; + val >>= ffs(info->modeset_mask) - 1; + + return (val & BIT(0)) ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; +} + +static const struct regulator_ops mt6332_buck_volt_range_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6332_get_status, +}; + +static const struct regulator_ops mt6332_ldo_volt_range_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6332_get_status, + .set_mode = mt6332_ldo_set_mode, + .get_mode = mt6332_ldo_get_mode, +}; + +static const struct regulator_ops mt6332_volt_table_ops = { + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_iterate, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6332_get_status, + .set_mode = mt6332_ldo_set_mode, + .get_mode = mt6332_ldo_get_mode, +}; + +static const struct regulator_ops mt6332_volt_table_ao_ops = { + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_iterate, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, +}; + +static const struct regulator_ops mt6332_volt_fixed_ops = { + .list_voltage = regulator_list_voltage_linear, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = mt6332_get_status, +}; + +/* The array is indexed by id(MT6332_ID_XXX) */ +static struct mt6332_regulator_info mt6332_regulators[] = { + MT6332_BUCK("buck-vdram", VDRAM, 700000, 1493750, 6250, buck_volt_range, + MT6332_EN_STATUS0, MT6332_VDRAM_CON11, GENMASK(6, 0), + MT6332_VDRAM_CON12, MT6332_VDRAM_CON7), + MT6332_BUCK("buck-vdvfs2", VDVFS2, 700000, 1312500, 6250, buck_volt_range, + MT6332_VDVFS2_CON9, MT6332_VDVFS2_CON11, GENMASK(6, 0), + MT6332_VDVFS2_CON12, MT6332_VDVFS2_CON7), + MT6332_BUCK("buck-vpa", VPA, 500000, 3400000, 50000, buck_pa_volt_range, + MT6332_VPA_CON9, MT6332_VPA_CON11, GENMASK(5, 0), + MT6332_VPA_CON12, MT6332_VPA_CON7), + MT6332_BUCK("buck-vrf18a", VRF1, 1050000, 2240625, 9375, buck_rf_volt_range, + MT6332_VRF1_CON9, MT6332_VRF1_CON11, GENMASK(6, 0), + MT6332_VRF1_CON12, MT6332_VRF1_CON7), + MT6332_BUCK("buck-vrf18b", VRF2, 1050000, 2240625, 9375, buck_rf_volt_range, + MT6332_VRF2_CON9, MT6332_VRF2_CON11, GENMASK(6, 0), + MT6332_VRF2_CON12, MT6332_VRF2_CON7), + MT6332_BUCK("buck-vsbst", VSBST, 3500000, 7468750, 31250, boost_volt_range, + MT6332_VSBST_CON8, MT6332_VSBST_CON12, GENMASK(6, 0), + MT6332_VSBST_CON13, MT6332_VSBST_CON8), + MT6332_LDO("ldo-vauxb32", VAUXB32, ldo_volt_table1, MT6332_LDO_CON1, 10, + MT6332_LDO_CON9, GENMASK(6, 5), MT6332_LDO_CON1, GENMASK(1, 0)), + MT6332_REG_FIXED("ldo-vbif28", VBIF28, MT6332_LDO_CON2, 10, 0, 2800000, 1), + MT6332_REG_FIXED("ldo-vusb33", VUSB33, MT6332_LDO_CON3, 10, 0, 3300000, 2), + MT6332_LDO_LINEAR("ldo-vsram", VSRAM_DVFS2, 700000, 1493750, 6250, buck_volt_range, + MT6332_EN_STATUS0, MT6332_LDO_CON8, GENMASK(15, 9), + MT6332_VDVFS2_CON23, MT6332_VDVFS2_CON22, + MT6332_LDO_CON5, GENMASK(1, 0)), + MT6332_LDO_AO("ldo-vdig18", VDIG18, ldo_volt_table2, MT6332_LDO_CON12, GENMASK(11, 9)), +}; + +static int mt6332_set_buck_vosel_reg(struct platform_device *pdev) +{ + struct mt6397_chip *mt6332 = dev_get_drvdata(pdev->dev.parent); + int i; + u32 regval; + + for (i = 0; i < MT6332_ID_VREG_MAX; i++) { + if (mt6332_regulators[i].vselctrl_reg) { + if (regmap_read(mt6332->regmap, + mt6332_regulators[i].vselctrl_reg, + ®val) < 0) { + dev_err(&pdev->dev, + "Failed to read buck ctrl\n"); + return -EIO; + } + + if (regval & mt6332_regulators[i].vselctrl_mask) { + mt6332_regulators[i].desc.vsel_reg = + mt6332_regulators[i].vselon_reg; + } + } + } + + return 0; +} + +static int mt6332_regulator_probe(struct platform_device *pdev) +{ + struct mt6397_chip *mt6332 = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = {}; + struct regulator_dev *rdev; + int i; + u32 reg_value; + + /* Query buck controller to select activated voltage register part */ + if (mt6332_set_buck_vosel_reg(pdev)) + return -EIO; + + /* Read PMIC chip revision to update constraints and voltage table */ + if (regmap_read(mt6332->regmap, MT6332_HWCID, ®_value) < 0) { + dev_err(&pdev->dev, "Failed to read Chip ID\n"); + return -EIO; + } + reg_value &= GENMASK(7, 0); + + dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value); + + /* + * ChipID 0x10 is "MT6332 E1", has a different voltage table and + * it's currently not supported in this driver. Upon detection of + * this ID, refuse to register the regulators, as we will wrongly + * interpret the VSEL for this revision, potentially overvolting + * some device. + */ + if (reg_value == 0x10) { + dev_err(&pdev->dev, "Chip version not supported. Bailing out.\n"); + return -EINVAL; + } + + for (i = 0; i < MT6332_ID_VREG_MAX; i++) { + config.dev = &pdev->dev; + config.driver_data = &mt6332_regulators[i]; + config.regmap = mt6332->regmap; + rdev = devm_regulator_register(&pdev->dev, + &mt6332_regulators[i].desc, &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "failed to register %s\n", + mt6332_regulators[i].desc.name); + return PTR_ERR(rdev); + } + } + return 0; +} + +static const struct platform_device_id mt6332_platform_ids[] = { + {"mt6332-regulator", 0}, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(platform, mt6332_platform_ids); + +static struct platform_driver mt6332_regulator_driver = { + .driver = { + .name = "mt6332-regulator", + }, + .probe = mt6332_regulator_probe, + .id_table = mt6332_platform_ids, +}; + +module_platform_driver(mt6332_regulator_driver); + +MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>"); +MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6332 PMIC"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index e12b681c72e5..0aff1c2886b5 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -676,7 +676,7 @@ clean: } /** - * of_parse_coupled regulator - Get regulator_dev pointer from rdev's property + * of_parse_coupled_regulator() - Get regulator_dev pointer from rdev's property * @rdev: Pointer to regulator_dev, whose DTS is used as a source to parse * "regulator-coupled-with" property * @index: Index in phandles array diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 6b617024a67d..d899d6e98fb8 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -766,7 +766,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client, ((pfuze_chip->chip_id == PFUZE3000) ? "3000" : "3001")))); memcpy(pfuze_chip->regulator_descs, pfuze_chip->pfuze_regulators, - sizeof(pfuze_chip->regulator_descs)); + regulator_num * sizeof(struct pfuze_regulator)); ret = pfuze_parse_regulators_dt(pfuze_chip); if (ret) diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index 561de6b2e6e3..4158ff126a67 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -306,9 +306,10 @@ static unsigned int rpmh_regulator_vrm_get_mode(struct regulator_dev *rdev) } /** - * rpmh_regulator_vrm_set_load() - set the regulator mode based upon the load - * current requested + * rpmh_regulator_vrm_get_optimum_mode() - get the mode based on the load * @rdev: Regulator device pointer for the rpmh-regulator + * @input_uV: Input voltage + * @output_uV: Output voltage * @load_uA: Aggregated load current in microamps * * This function is used in the regulator_ops for VRM type RPMh regulator @@ -316,17 +317,15 @@ static unsigned int rpmh_regulator_vrm_get_mode(struct regulator_dev *rdev) * * Return: 0 on success, errno on failure */ -static int rpmh_regulator_vrm_set_load(struct regulator_dev *rdev, int load_uA) +static unsigned int rpmh_regulator_vrm_get_optimum_mode( + struct regulator_dev *rdev, int input_uV, int output_uV, int load_uA) { struct rpmh_vreg *vreg = rdev_get_drvdata(rdev); - unsigned int mode; if (load_uA >= vreg->hw_data->hpm_min_load_uA) - mode = REGULATOR_MODE_NORMAL; + return REGULATOR_MODE_NORMAL; else - mode = REGULATOR_MODE_IDLE; - - return rpmh_regulator_vrm_set_mode(rdev, mode); + return REGULATOR_MODE_IDLE; } static int rpmh_regulator_vrm_set_bypass(struct regulator_dev *rdev, @@ -375,7 +374,7 @@ static const struct regulator_ops rpmh_regulator_vrm_drms_ops = { .list_voltage = regulator_list_voltage_linear_range, .set_mode = rpmh_regulator_vrm_set_mode, .get_mode = rpmh_regulator_vrm_get_mode, - .set_load = rpmh_regulator_vrm_set_load, + .get_optimum_mode = rpmh_regulator_vrm_get_optimum_mode, }; static const struct regulator_ops rpmh_regulator_vrm_bypass_ops = { @@ -1199,6 +1198,52 @@ static const struct rpmh_vreg_init_data pmr735a_vreg_data[] = { {} }; +static const struct rpmh_vreg_init_data pm660_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic4_ftsmps426, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic4_ftsmps426, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic4_ftsmps426, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic4_hfsmps3, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic4_hfsmps3, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic4_hfsmps3, "vdd-s6"), + RPMH_VREG("ldo1", "ldo%s1", &pmic4_nldo, "vdd-l1-l6-l7"), + RPMH_VREG("ldo2", "ldo%s2", &pmic4_nldo, "vdd-l2-l3"), + RPMH_VREG("ldo3", "ldo%s3", &pmic4_nldo, "vdd-l2-l3"), + /* ldo4 is inaccessible on PM660 */ + RPMH_VREG("ldo5", "ldo%s5", &pmic4_nldo, "vdd-l5"), + RPMH_VREG("ldo6", "ldo%s6", &pmic4_nldo, "vdd-l1-l6-l7"), + RPMH_VREG("ldo7", "ldo%s7", &pmic4_nldo, "vdd-l1-l6-l7"), + RPMH_VREG("ldo8", "ldo%s8", &pmic4_pldo_lv, "vdd-l8-l9-l10-l11-l12-l13-l14"), + RPMH_VREG("ldo9", "ldo%s9", &pmic4_pldo_lv, "vdd-l8-l9-l10-l11-l12-l13-l14"), + RPMH_VREG("ldo10", "ldo%s10", &pmic4_pldo_lv, "vdd-l8-l9-l10-l11-l12-l13-l14"), + RPMH_VREG("ldo11", "ldo%s11", &pmic4_pldo_lv, "vdd-l8-l9-l10-l11-l12-l13-l14"), + RPMH_VREG("ldo12", "ldo%s12", &pmic4_pldo_lv, "vdd-l8-l9-l10-l11-l12-l13-l14"), + RPMH_VREG("ldo13", "ldo%s13", &pmic4_pldo_lv, "vdd-l8-l9-l10-l11-l12-l13-l14"), + RPMH_VREG("ldo14", "ldo%s14", &pmic4_pldo_lv, "vdd-l8-l9-l10-l11-l12-l13-l14"), + RPMH_VREG("ldo15", "ldo%s15", &pmic4_pldo, "vdd-l15-l16-l17-l18-l19"), + RPMH_VREG("ldo16", "ldo%s16", &pmic4_pldo, "vdd-l15-l16-l17-l18-l19"), + RPMH_VREG("ldo17", "ldo%s17", &pmic4_pldo, "vdd-l15-l16-l17-l18-l19"), + RPMH_VREG("ldo18", "ldo%s18", &pmic4_pldo, "vdd-l15-l16-l17-l18-l19"), + RPMH_VREG("ldo19", "ldo%s19", &pmic4_pldo, "vdd-l15-l16-l17-l18-l19"), + {} +}; + +static const struct rpmh_vreg_init_data pm660l_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic4_ftsmps426, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic4_ftsmps426, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic4_ftsmps426, "vdd-s3-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic4_ftsmps426, "vdd-s5"), + RPMH_VREG("ldo1", "ldo%s1", &pmic4_nldo, "vdd-l1-l9-l10"), + RPMH_VREG("ldo2", "ldo%s2", &pmic4_pldo, "vdd-l2"), + RPMH_VREG("ldo3", "ldo%s3", &pmic4_pldo, "vdd-l3-l5-l7-l8"), + RPMH_VREG("ldo4", "ldo%s4", &pmic4_pldo, "vdd-l4-l6"), + RPMH_VREG("ldo5", "ldo%s5", &pmic4_pldo, "vdd-l3-l5-l7-l8"), + RPMH_VREG("ldo6", "ldo%s6", &pmic4_pldo, "vdd-l4-l6"), + RPMH_VREG("ldo7", "ldo%s7", &pmic4_pldo, "vdd-l3-l5-l7-l8"), + RPMH_VREG("ldo8", "ldo%s8", &pmic4_pldo, "vdd-l3-l5-l7-l8"), + RPMH_VREG("bob", "bob%s1", &pmic4_bob, "vdd-bob"), + {} +}; + static int rpmh_regulator_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1321,6 +1366,14 @@ static const struct of_device_id __maybe_unused rpmh_regulator_match_table[] = { .compatible = "qcom,pmr735a-rpmh-regulators", .data = pmr735a_vreg_data, }, + { + .compatible = "qcom,pm660-rpmh-regulators", + .data = pm660_vreg_data, + }, + { + .compatible = "qcom,pm660l-rpmh-regulators", + .data = pm660l_vreg_data, + }, {} }; MODULE_DEVICE_TABLE(of, rpmh_regulator_match_table); diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c index 7f9d66ac37ff..3c41b71a1f52 100644 --- a/drivers/regulator/qcom_rpm-regulator.c +++ b/drivers/regulator/qcom_rpm-regulator.c @@ -802,6 +802,12 @@ static const struct rpm_regulator_data rpm_pm8018_regulators[] = { }; static const struct rpm_regulator_data rpm_pm8058_regulators[] = { + { "s0", QCOM_RPM_PM8058_SMPS0, &pm8058_smps, "vdd_s0" }, + { "s1", QCOM_RPM_PM8058_SMPS1, &pm8058_smps, "vdd_s1" }, + { "s2", QCOM_RPM_PM8058_SMPS2, &pm8058_smps, "vdd_s2" }, + { "s3", QCOM_RPM_PM8058_SMPS3, &pm8058_smps, "vdd_s3" }, + { "s4", QCOM_RPM_PM8058_SMPS4, &pm8058_smps, "vdd_s4" }, + { "l0", QCOM_RPM_PM8058_LDO0, &pm8058_nldo, "vdd_l0_l1_lvs" }, { "l1", QCOM_RPM_PM8058_LDO1, &pm8058_nldo, "vdd_l0_l1_lvs" }, { "l2", QCOM_RPM_PM8058_LDO2, &pm8058_pldo, "vdd_l2_l11_l12" }, @@ -829,12 +835,6 @@ static const struct rpm_regulator_data rpm_pm8058_regulators[] = { { "l24", QCOM_RPM_PM8058_LDO24, &pm8058_nldo, "vdd_l23_l24_l25" }, { "l25", QCOM_RPM_PM8058_LDO25, &pm8058_nldo, "vdd_l23_l24_l25" }, - { "s0", QCOM_RPM_PM8058_SMPS0, &pm8058_smps, "vdd_s0" }, - { "s1", QCOM_RPM_PM8058_SMPS1, &pm8058_smps, "vdd_s1" }, - { "s2", QCOM_RPM_PM8058_SMPS2, &pm8058_smps, "vdd_s2" }, - { "s3", QCOM_RPM_PM8058_SMPS3, &pm8058_smps, "vdd_s3" }, - { "s4", QCOM_RPM_PM8058_SMPS4, &pm8058_smps, "vdd_s4" }, - { "lvs0", QCOM_RPM_PM8058_LVS0, &pm8058_switch, "vdd_l0_l1_lvs" }, { "lvs1", QCOM_RPM_PM8058_LVS1, &pm8058_switch, "vdd_l0_l1_lvs" }, @@ -843,6 +843,12 @@ static const struct rpm_regulator_data rpm_pm8058_regulators[] = { }; static const struct rpm_regulator_data rpm_pm8901_regulators[] = { + { "s0", QCOM_RPM_PM8901_SMPS0, &pm8901_ftsmps, "vdd_s0" }, + { "s1", QCOM_RPM_PM8901_SMPS1, &pm8901_ftsmps, "vdd_s1" }, + { "s2", QCOM_RPM_PM8901_SMPS2, &pm8901_ftsmps, "vdd_s2" }, + { "s3", QCOM_RPM_PM8901_SMPS3, &pm8901_ftsmps, "vdd_s3" }, + { "s4", QCOM_RPM_PM8901_SMPS4, &pm8901_ftsmps, "vdd_s4" }, + { "l0", QCOM_RPM_PM8901_LDO0, &pm8901_nldo, "vdd_l0" }, { "l1", QCOM_RPM_PM8901_LDO1, &pm8901_pldo, "vdd_l1" }, { "l2", QCOM_RPM_PM8901_LDO2, &pm8901_pldo, "vdd_l2" }, @@ -851,12 +857,6 @@ static const struct rpm_regulator_data rpm_pm8901_regulators[] = { { "l5", QCOM_RPM_PM8901_LDO5, &pm8901_pldo, "vdd_l5" }, { "l6", QCOM_RPM_PM8901_LDO6, &pm8901_pldo, "vdd_l6" }, - { "s0", QCOM_RPM_PM8901_SMPS0, &pm8901_ftsmps, "vdd_s0" }, - { "s1", QCOM_RPM_PM8901_SMPS1, &pm8901_ftsmps, "vdd_s1" }, - { "s2", QCOM_RPM_PM8901_SMPS2, &pm8901_ftsmps, "vdd_s2" }, - { "s3", QCOM_RPM_PM8901_SMPS3, &pm8901_ftsmps, "vdd_s3" }, - { "s4", QCOM_RPM_PM8901_SMPS4, &pm8901_ftsmps, "vdd_s4" }, - { "lvs0", QCOM_RPM_PM8901_LVS0, &pm8901_switch, "lvs0_in" }, { "lvs1", QCOM_RPM_PM8901_LVS1, &pm8901_switch, "lvs1_in" }, { "lvs2", QCOM_RPM_PM8901_LVS2, &pm8901_switch, "lvs2_in" }, diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c index 59024c639141..f98168d58dce 100644 --- a/drivers/regulator/qcom_smd-regulator.c +++ b/drivers/regulator/qcom_smd-regulator.c @@ -668,6 +668,15 @@ static const struct regulator_desc pm660l_bob = { .ops = &rpm_bob_ops, }; +static const struct regulator_desc pm6125_ftsmps = { + .linear_ranges = (struct linear_range[]) { + REGULATOR_LINEAR_RANGE(300000, 0, 268, 4000), + }, + .n_linear_ranges = 1, + .n_voltages = 269, + .ops = &rpm_smps_ldo_ops, +}; + static const struct regulator_desc pms405_hfsmps3 = { .linear_ranges = (struct linear_range[]) { REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000), @@ -772,6 +781,158 @@ static const struct rpm_regulator_data rpm_mp5496_regulators[] = { {} }; +static const struct rpm_regulator_data rpm_pm2250_regulators[] = { + { "s1", QCOM_SMD_RPM_SMPA, 1, &pm2250_lvftsmps, "vdd_s1" }, + { "s2", QCOM_SMD_RPM_SMPA, 2, &pm2250_lvftsmps, "vdd_s2" }, + { "s3", QCOM_SMD_RPM_SMPA, 3, &pm2250_lvftsmps, "vdd_s3" }, + { "s4", QCOM_SMD_RPM_SMPA, 4, &pm2250_ftsmps, "vdd_s4" }, + { "l1", QCOM_SMD_RPM_LDOA, 1, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, + { "l2", QCOM_SMD_RPM_LDOA, 2, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, + { "l3", QCOM_SMD_RPM_LDOA, 3, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, + { "l4", QCOM_SMD_RPM_LDOA, 4, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, + { "l5", QCOM_SMD_RPM_LDOA, 5, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, + { "l6", QCOM_SMD_RPM_LDOA, 6, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, + { "l7", QCOM_SMD_RPM_LDOA, 7, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, + { "l8", QCOM_SMD_RPM_LDOA, 8, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, + { "l9", QCOM_SMD_RPM_LDOA, 9, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, + { "l10", QCOM_SMD_RPM_LDOA, 10, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, + { "l11", QCOM_SMD_RPM_LDOA, 11, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, + { "l12", QCOM_SMD_RPM_LDOA, 12, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, + { "l13", QCOM_SMD_RPM_LDOA, 13, &pm660_ht_lvpldo, "vdd_l13_l14_l15_l16" }, + { "l14", QCOM_SMD_RPM_LDOA, 14, &pm660_ht_lvpldo, "vdd_l13_l14_l15_l16" }, + { "l15", QCOM_SMD_RPM_LDOA, 15, &pm660_ht_lvpldo, "vdd_l13_l14_l15_l16" }, + { "l16", QCOM_SMD_RPM_LDOA, 16, &pm660_ht_lvpldo, "vdd_l13_l14_l15_l16" }, + { "l17", QCOM_SMD_RPM_LDOA, 17, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, + { "l18", QCOM_SMD_RPM_LDOA, 18, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, + { "l19", QCOM_SMD_RPM_LDOA, 19, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, + { "l20", QCOM_SMD_RPM_LDOA, 20, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, + { "l21", QCOM_SMD_RPM_LDOA, 21, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, + { "l22", QCOM_SMD_RPM_LDOA, 22, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, + {} +}; + +static const struct rpm_regulator_data rpm_pm6125_regulators[] = { + { "s1", QCOM_SMD_RPM_SMPA, 1, &pm6125_ftsmps, "vdd_s1" }, + { "s2", QCOM_SMD_RPM_SMPA, 2, &pm6125_ftsmps, "vdd_s2" }, + { "s3", QCOM_SMD_RPM_SMPA, 3, &pm6125_ftsmps, "vdd_s3" }, + { "s4", QCOM_SMD_RPM_SMPA, 4, &pm6125_ftsmps, "vdd_s4" }, + { "s5", QCOM_SMD_RPM_SMPA, 5, &pm8998_hfsmps, "vdd_s5" }, + { "s6", QCOM_SMD_RPM_SMPA, 6, &pm8998_hfsmps, "vdd_s6" }, + { "s7", QCOM_SMD_RPM_SMPA, 7, &pm8998_hfsmps, "vdd_s7" }, + { "s8", QCOM_SMD_RPM_SMPA, 8, &pm6125_ftsmps, "vdd_s8" }, + { "l1", QCOM_SMD_RPM_LDOA, 1, &pm660_nldo660, "vdd_l1_l7_l17_l18" }, + { "l2", QCOM_SMD_RPM_LDOA, 2, &pm660_nldo660, "vdd_l2_l3_l4" }, + { "l3", QCOM_SMD_RPM_LDOA, 3, &pm660_nldo660, "vdd_l2_l3_l4" }, + { "l4", QCOM_SMD_RPM_LDOA, 4, &pm660_nldo660, "vdd_l2_l3_l4" }, + { "l5", QCOM_SMD_RPM_LDOA, 5, &pm660_pldo660, "vdd_l5_l15_l19_l20_l21_l22" }, + { "l6", QCOM_SMD_RPM_LDOA, 6, &pm660_nldo660, "vdd_l6_l8" }, + { "l7", QCOM_SMD_RPM_LDOA, 7, &pm660_nldo660, "vdd_l1_l7_l17_l18" }, + { "l8", QCOM_SMD_RPM_LDOA, 8, &pm660_nldo660, "vdd_l6_l8" }, + { "l9", QCOM_SMD_RPM_LDOA, 9, &pm660_ht_lvpldo, "vdd_l9_l11" }, + { "l10", QCOM_SMD_RPM_LDOA, 10, &pm660_ht_lvpldo, "vdd_l10_l13_l14" }, + { "l11", QCOM_SMD_RPM_LDOA, 11, &pm660_ht_lvpldo, "vdd_l9_l11" }, + { "l12", QCOM_SMD_RPM_LDOA, 12, &pm660_ht_lvpldo, "vdd_l12_l16" }, + { "l13", QCOM_SMD_RPM_LDOA, 13, &pm660_ht_lvpldo, "vdd_l10_l13_l14" }, + { "l14", QCOM_SMD_RPM_LDOA, 14, &pm660_ht_lvpldo, "vdd_l10_l13_l14" }, + { "l15", QCOM_SMD_RPM_LDOA, 15, &pm660_pldo660, "vdd_l5_l15_l19_l20_l21_l22" }, + { "l16", QCOM_SMD_RPM_LDOA, 16, &pm660_ht_lvpldo, "vdd_l12_l16" }, + { "l17", QCOM_SMD_RPM_LDOA, 17, &pm660_nldo660, "vdd_l1_l7_l17_l18" }, + { "l18", QCOM_SMD_RPM_LDOA, 18, &pm660_nldo660, "vdd_l1_l7_l17_l18" }, + { "l19", QCOM_SMD_RPM_LDOA, 19, &pm660_pldo660, "vdd_l5_l15_l19_l20_l21_l22" }, + { "l20", QCOM_SMD_RPM_LDOA, 20, &pm660_pldo660, "vdd_l5_l15_l19_l20_l21_l22" }, + { "l21", QCOM_SMD_RPM_LDOA, 21, &pm660_pldo660, "vdd_l5_l15_l19_l20_l21_l22" }, + { "l22", QCOM_SMD_RPM_LDOA, 22, &pm660_pldo660, "vdd_l5_l15_l19_l20_l21_l22" }, + { "l23", QCOM_SMD_RPM_LDOA, 23, &pm660_pldo660, "vdd_l23_l24" }, + { "l24", QCOM_SMD_RPM_LDOA, 24, &pm660_pldo660, "vdd_l23_l24" }, + { } +}; + +static const struct rpm_regulator_data rpm_pm660_regulators[] = { + { "s1", QCOM_SMD_RPM_SMPA, 1, &pm660_ftsmps, "vdd_s1" }, + { "s2", QCOM_SMD_RPM_SMPA, 2, &pm660_ftsmps, "vdd_s2" }, + { "s3", QCOM_SMD_RPM_SMPA, 3, &pm660_ftsmps, "vdd_s3" }, + { "s4", QCOM_SMD_RPM_SMPA, 4, &pm660_hfsmps, "vdd_s4" }, + { "s5", QCOM_SMD_RPM_SMPA, 5, &pm660_hfsmps, "vdd_s5" }, + { "s6", QCOM_SMD_RPM_SMPA, 6, &pm660_hfsmps, "vdd_s6" }, + { "l1", QCOM_SMD_RPM_LDOA, 1, &pm660_nldo660, "vdd_l1_l6_l7" }, + { "l2", QCOM_SMD_RPM_LDOA, 2, &pm660_ht_nldo, "vdd_l2_l3" }, + { "l3", QCOM_SMD_RPM_LDOA, 3, &pm660_nldo660, "vdd_l2_l3" }, + /* l4 is unaccessible on PM660 */ + { "l5", QCOM_SMD_RPM_LDOA, 5, &pm660_ht_nldo, "vdd_l5" }, + { "l6", QCOM_SMD_RPM_LDOA, 6, &pm660_ht_nldo, "vdd_l1_l6_l7" }, + { "l7", QCOM_SMD_RPM_LDOA, 7, &pm660_ht_nldo, "vdd_l1_l6_l7" }, + { "l8", QCOM_SMD_RPM_LDOA, 8, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l9", QCOM_SMD_RPM_LDOA, 9, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l10", QCOM_SMD_RPM_LDOA, 10, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l11", QCOM_SMD_RPM_LDOA, 11, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l12", QCOM_SMD_RPM_LDOA, 12, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l13", QCOM_SMD_RPM_LDOA, 13, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l14", QCOM_SMD_RPM_LDOA, 14, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, + { "l15", QCOM_SMD_RPM_LDOA, 15, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, + { "l16", QCOM_SMD_RPM_LDOA, 16, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, + { "l17", QCOM_SMD_RPM_LDOA, 17, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, + { "l18", QCOM_SMD_RPM_LDOA, 18, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, + { "l19", QCOM_SMD_RPM_LDOA, 19, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, + { } +}; + +static const struct rpm_regulator_data rpm_pm660l_regulators[] = { + { "s1", QCOM_SMD_RPM_SMPB, 1, &pm660_ftsmps, "vdd_s1" }, + { "s2", QCOM_SMD_RPM_SMPB, 2, &pm660_ftsmps, "vdd_s2" }, + { "s3", QCOM_SMD_RPM_RWCX, 0, &pm660_ftsmps, "vdd_s3_s4" }, + { "s5", QCOM_SMD_RPM_RWMX, 0, &pm660_ftsmps, "vdd_s5" }, + { "l1", QCOM_SMD_RPM_LDOB, 1, &pm660_nldo660, "vdd_l1_l9_l10" }, + { "l2", QCOM_SMD_RPM_LDOB, 2, &pm660_pldo660, "vdd_l2" }, + { "l3", QCOM_SMD_RPM_LDOB, 3, &pm660_pldo660, "vdd_l3_l5_l7_l8" }, + { "l4", QCOM_SMD_RPM_LDOB, 4, &pm660_pldo660, "vdd_l4_l6" }, + { "l5", QCOM_SMD_RPM_LDOB, 5, &pm660_pldo660, "vdd_l3_l5_l7_l8" }, + { "l6", QCOM_SMD_RPM_LDOB, 6, &pm660_pldo660, "vdd_l4_l6" }, + { "l7", QCOM_SMD_RPM_LDOB, 7, &pm660_pldo660, "vdd_l3_l5_l7_l8" }, + { "l8", QCOM_SMD_RPM_LDOB, 8, &pm660_pldo660, "vdd_l3_l5_l7_l8" }, + { "l9", QCOM_SMD_RPM_RWLC, 0, &pm660_ht_nldo, "vdd_l1_l9_l10" }, + { "l10", QCOM_SMD_RPM_RWLM, 0, &pm660_ht_nldo, "vdd_l1_l9_l10" }, + { "bob", QCOM_SMD_RPM_BOBB, 1, &pm660l_bob, "vdd_bob", }, + { } +}; + +static const struct rpm_regulator_data rpm_pm8226_regulators[] = { + { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8226_hfsmps, "vdd_s1" }, + { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8226_ftsmps, "vdd_s2" }, + { "s3", QCOM_SMD_RPM_SMPA, 3, &pm8226_hfsmps, "vdd_s3" }, + { "s4", QCOM_SMD_RPM_SMPA, 4, &pm8226_hfsmps, "vdd_s4" }, + { "s5", QCOM_SMD_RPM_SMPA, 5, &pm8226_hfsmps, "vdd_s5" }, + { "l1", QCOM_SMD_RPM_LDOA, 1, &pm8226_nldo, "vdd_l1_l2_l4_l5" }, + { "l2", QCOM_SMD_RPM_LDOA, 2, &pm8226_nldo, "vdd_l1_l2_l4_l5" }, + { "l3", QCOM_SMD_RPM_LDOA, 3, &pm8226_nldo, "vdd_l3_l24_l26" }, + { "l4", QCOM_SMD_RPM_LDOA, 4, &pm8226_nldo, "vdd_l1_l2_l4_l5" }, + { "l5", QCOM_SMD_RPM_LDOA, 5, &pm8226_nldo, "vdd_l1_l2_l4_l5" }, + { "l6", QCOM_SMD_RPM_LDOA, 6, &pm8226_pldo, "vdd_l6_l7_l8_l9_l27" }, + { "l7", QCOM_SMD_RPM_LDOA, 7, &pm8226_pldo, "vdd_l6_l7_l8_l9_l27" }, + { "l8", QCOM_SMD_RPM_LDOA, 8, &pm8226_pldo, "vdd_l6_l7_l8_l9_l27" }, + { "l9", QCOM_SMD_RPM_LDOA, 9, &pm8226_pldo, "vdd_l6_l7_l8_l9_l27" }, + { "l10", QCOM_SMD_RPM_LDOA, 10, &pm8226_pldo, "vdd_l10_l11_l13" }, + { "l11", QCOM_SMD_RPM_LDOA, 11, &pm8226_pldo, "vdd_l10_l11_l13" }, + { "l12", QCOM_SMD_RPM_LDOA, 12, &pm8226_pldo, "vdd_l12_l14" }, + { "l13", QCOM_SMD_RPM_LDOA, 13, &pm8226_pldo, "vdd_l10_l11_l13" }, + { "l14", QCOM_SMD_RPM_LDOA, 14, &pm8226_pldo, "vdd_l12_l14" }, + { "l15", QCOM_SMD_RPM_LDOA, 15, &pm8226_pldo, "vdd_l15_l16_l17_l18" }, + { "l16", QCOM_SMD_RPM_LDOA, 16, &pm8226_pldo, "vdd_l15_l16_l17_l18" }, + { "l17", QCOM_SMD_RPM_LDOA, 17, &pm8226_pldo, "vdd_l15_l16_l17_l18" }, + { "l18", QCOM_SMD_RPM_LDOA, 18, &pm8226_pldo, "vdd_l15_l16_l17_l18" }, + { "l19", QCOM_SMD_RPM_LDOA, 19, &pm8226_pldo, "vdd_l19_l20_l21_l22_l23_l28" }, + { "l20", QCOM_SMD_RPM_LDOA, 20, &pm8226_pldo, "vdd_l19_l20_l21_l22_l23_l28" }, + { "l21", QCOM_SMD_RPM_LDOA, 21, &pm8226_pldo, "vdd_l19_l20_l21_l22_l23_l28" }, + { "l22", QCOM_SMD_RPM_LDOA, 22, &pm8226_pldo, "vdd_l19_l20_l21_l22_l23_l28" }, + { "l23", QCOM_SMD_RPM_LDOA, 23, &pm8226_pldo, "vdd_l19_l20_l21_l22_l23_l28" }, + { "l24", QCOM_SMD_RPM_LDOA, 24, &pm8226_nldo, "vdd_l3_l24_l26" }, + { "l25", QCOM_SMD_RPM_LDOA, 25, &pm8226_pldo, "vdd_l25" }, + { "l26", QCOM_SMD_RPM_LDOA, 26, &pm8226_nldo, "vdd_l3_l24_l26" }, + { "l27", QCOM_SMD_RPM_LDOA, 27, &pm8226_pldo, "vdd_l6_l7_l8_l9_l27" }, + { "l28", QCOM_SMD_RPM_LDOA, 28, &pm8226_pldo, "vdd_l19_l20_l21_l22_l23_l28" }, + { "lvs1", QCOM_SMD_RPM_VSA, 1, &pm8226_switch, "vdd_lvs1" }, + {} +}; + static const struct rpm_regulator_data rpm_pm8841_regulators[] = { { "s1", QCOM_SMD_RPM_SMPB, 1, &pm8x41_hfsmps, "vdd_s1" }, { "s2", QCOM_SMD_RPM_SMPB, 2, &pm8841_ftsmps, "vdd_s2" }, @@ -833,44 +994,6 @@ static const struct rpm_regulator_data rpm_pm8916_regulators[] = { {} }; -static const struct rpm_regulator_data rpm_pm8226_regulators[] = { - { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8226_hfsmps, "vdd_s1" }, - { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8226_ftsmps, "vdd_s2" }, - { "s3", QCOM_SMD_RPM_SMPA, 3, &pm8226_hfsmps, "vdd_s3" }, - { "s4", QCOM_SMD_RPM_SMPA, 4, &pm8226_hfsmps, "vdd_s4" }, - { "s5", QCOM_SMD_RPM_SMPA, 5, &pm8226_hfsmps, "vdd_s5" }, - { "l1", QCOM_SMD_RPM_LDOA, 1, &pm8226_nldo, "vdd_l1_l2_l4_l5" }, - { "l2", QCOM_SMD_RPM_LDOA, 2, &pm8226_nldo, "vdd_l1_l2_l4_l5" }, - { "l3", QCOM_SMD_RPM_LDOA, 3, &pm8226_nldo, "vdd_l3_l24_l26" }, - { "l4", QCOM_SMD_RPM_LDOA, 4, &pm8226_nldo, "vdd_l1_l2_l4_l5" }, - { "l5", QCOM_SMD_RPM_LDOA, 5, &pm8226_nldo, "vdd_l1_l2_l4_l5" }, - { "l6", QCOM_SMD_RPM_LDOA, 6, &pm8226_pldo, "vdd_l6_l7_l8_l9_l27" }, - { "l7", QCOM_SMD_RPM_LDOA, 7, &pm8226_pldo, "vdd_l6_l7_l8_l9_l27" }, - { "l8", QCOM_SMD_RPM_LDOA, 8, &pm8226_pldo, "vdd_l6_l7_l8_l9_l27" }, - { "l9", QCOM_SMD_RPM_LDOA, 9, &pm8226_pldo, "vdd_l6_l7_l8_l9_l27" }, - { "l10", QCOM_SMD_RPM_LDOA, 10, &pm8226_pldo, "vdd_l10_l11_l13" }, - { "l11", QCOM_SMD_RPM_LDOA, 11, &pm8226_pldo, "vdd_l10_l11_l13" }, - { "l12", QCOM_SMD_RPM_LDOA, 12, &pm8226_pldo, "vdd_l12_l14" }, - { "l13", QCOM_SMD_RPM_LDOA, 13, &pm8226_pldo, "vdd_l10_l11_l13" }, - { "l14", QCOM_SMD_RPM_LDOA, 14, &pm8226_pldo, "vdd_l12_l14" }, - { "l15", QCOM_SMD_RPM_LDOA, 15, &pm8226_pldo, "vdd_l15_l16_l17_l18" }, - { "l16", QCOM_SMD_RPM_LDOA, 16, &pm8226_pldo, "vdd_l15_l16_l17_l18" }, - { "l17", QCOM_SMD_RPM_LDOA, 17, &pm8226_pldo, "vdd_l15_l16_l17_l18" }, - { "l18", QCOM_SMD_RPM_LDOA, 18, &pm8226_pldo, "vdd_l15_l16_l17_l18" }, - { "l19", QCOM_SMD_RPM_LDOA, 19, &pm8226_pldo, "vdd_l19_l20_l21_l22_l23_l28" }, - { "l20", QCOM_SMD_RPM_LDOA, 20, &pm8226_pldo, "vdd_l19_l20_l21_l22_l23_l28" }, - { "l21", QCOM_SMD_RPM_LDOA, 21, &pm8226_pldo, "vdd_l19_l20_l21_l22_l23_l28" }, - { "l22", QCOM_SMD_RPM_LDOA, 22, &pm8226_pldo, "vdd_l19_l20_l21_l22_l23_l28" }, - { "l23", QCOM_SMD_RPM_LDOA, 23, &pm8226_pldo, "vdd_l19_l20_l21_l22_l23_l28" }, - { "l24", QCOM_SMD_RPM_LDOA, 24, &pm8226_nldo, "vdd_l3_l24_l26" }, - { "l25", QCOM_SMD_RPM_LDOA, 25, &pm8226_pldo, "vdd_l25" }, - { "l26", QCOM_SMD_RPM_LDOA, 26, &pm8226_nldo, "vdd_l3_l24_l26" }, - { "l27", QCOM_SMD_RPM_LDOA, 27, &pm8226_pldo, "vdd_l6_l7_l8_l9_l27" }, - { "l28", QCOM_SMD_RPM_LDOA, 28, &pm8226_pldo, "vdd_l19_l20_l21_l22_l23_l28" }, - { "lvs1", QCOM_SMD_RPM_VSA, 1, &pm8226_switch, "vdd_lvs1" }, - {} -}; - static const struct rpm_regulator_data rpm_pm8941_regulators[] = { { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8x41_hfsmps, "vdd_s1" }, { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8x41_hfsmps, "vdd_s2" }, @@ -912,57 +1035,6 @@ static const struct rpm_regulator_data rpm_pm8941_regulators[] = { {} }; -static const struct rpm_regulator_data rpm_pma8084_regulators[] = { - { "s1", QCOM_SMD_RPM_SMPA, 1, &pma8084_ftsmps, "vdd_s1" }, - { "s2", QCOM_SMD_RPM_SMPA, 2, &pma8084_ftsmps, "vdd_s2" }, - { "s3", QCOM_SMD_RPM_SMPA, 3, &pma8084_hfsmps, "vdd_s3" }, - { "s4", QCOM_SMD_RPM_SMPA, 4, &pma8084_hfsmps, "vdd_s4" }, - { "s5", QCOM_SMD_RPM_SMPA, 5, &pma8084_hfsmps, "vdd_s5" }, - { "s6", QCOM_SMD_RPM_SMPA, 6, &pma8084_ftsmps, "vdd_s6" }, - { "s7", QCOM_SMD_RPM_SMPA, 7, &pma8084_ftsmps, "vdd_s7" }, - { "s8", QCOM_SMD_RPM_SMPA, 8, &pma8084_ftsmps, "vdd_s8" }, - { "s9", QCOM_SMD_RPM_SMPA, 9, &pma8084_ftsmps, "vdd_s9" }, - { "s10", QCOM_SMD_RPM_SMPA, 10, &pma8084_ftsmps, "vdd_s10" }, - { "s11", QCOM_SMD_RPM_SMPA, 11, &pma8084_ftsmps, "vdd_s11" }, - { "s12", QCOM_SMD_RPM_SMPA, 12, &pma8084_ftsmps, "vdd_s12" }, - - { "l1", QCOM_SMD_RPM_LDOA, 1, &pma8084_nldo, "vdd_l1_l11" }, - { "l2", QCOM_SMD_RPM_LDOA, 2, &pma8084_nldo, "vdd_l2_l3_l4_l27" }, - { "l3", QCOM_SMD_RPM_LDOA, 3, &pma8084_nldo, "vdd_l2_l3_l4_l27" }, - { "l4", QCOM_SMD_RPM_LDOA, 4, &pma8084_nldo, "vdd_l2_l3_l4_l27" }, - { "l5", QCOM_SMD_RPM_LDOA, 5, &pma8084_pldo, "vdd_l5_l7" }, - { "l6", QCOM_SMD_RPM_LDOA, 6, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" }, - { "l7", QCOM_SMD_RPM_LDOA, 7, &pma8084_pldo, "vdd_l5_l7" }, - { "l8", QCOM_SMD_RPM_LDOA, 8, &pma8084_pldo, "vdd_l8" }, - { "l9", QCOM_SMD_RPM_LDOA, 9, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" }, - { "l10", QCOM_SMD_RPM_LDOA, 10, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" }, - { "l11", QCOM_SMD_RPM_LDOA, 11, &pma8084_nldo, "vdd_l1_l11" }, - { "l12", QCOM_SMD_RPM_LDOA, 12, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" }, - { "l13", QCOM_SMD_RPM_LDOA, 13, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" }, - { "l14", QCOM_SMD_RPM_LDOA, 14, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" }, - { "l15", QCOM_SMD_RPM_LDOA, 15, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" }, - { "l16", QCOM_SMD_RPM_LDOA, 16, &pma8084_pldo, "vdd_l16_l25" }, - { "l17", QCOM_SMD_RPM_LDOA, 17, &pma8084_pldo, "vdd_l17" }, - { "l18", QCOM_SMD_RPM_LDOA, 18, &pma8084_pldo, "vdd_l18" }, - { "l19", QCOM_SMD_RPM_LDOA, 19, &pma8084_pldo, "vdd_l19" }, - { "l20", QCOM_SMD_RPM_LDOA, 20, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" }, - { "l21", QCOM_SMD_RPM_LDOA, 21, &pma8084_pldo, "vdd_l21" }, - { "l22", QCOM_SMD_RPM_LDOA, 22, &pma8084_pldo, "vdd_l22" }, - { "l23", QCOM_SMD_RPM_LDOA, 23, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" }, - { "l24", QCOM_SMD_RPM_LDOA, 24, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" }, - { "l25", QCOM_SMD_RPM_LDOA, 25, &pma8084_pldo, "vdd_l16_l25" }, - { "l26", QCOM_SMD_RPM_LDOA, 26, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" }, - { "l27", QCOM_SMD_RPM_LDOA, 27, &pma8084_nldo, "vdd_l2_l3_l4_l27" }, - - { "lvs1", QCOM_SMD_RPM_VSA, 1, &pma8084_switch }, - { "lvs2", QCOM_SMD_RPM_VSA, 2, &pma8084_switch }, - { "lvs3", QCOM_SMD_RPM_VSA, 3, &pma8084_switch }, - { "lvs4", QCOM_SMD_RPM_VSA, 4, &pma8084_switch }, - { "5vs1", QCOM_SMD_RPM_VSA, 5, &pma8084_switch }, - - {} -}; - static const struct rpm_regulator_data rpm_pm8950_regulators[] = { { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8950_hfsmps, "vdd_s1" }, { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8950_hfsmps, "vdd_s2" }, @@ -1082,14 +1154,6 @@ static const struct rpm_regulator_data rpm_pm8994_regulators[] = { {} }; -static const struct rpm_regulator_data rpm_pmi8994_regulators[] = { - { "s1", QCOM_SMD_RPM_SMPB, 1, &pmi8994_ftsmps, "vdd_s1" }, - { "s2", QCOM_SMD_RPM_SMPB, 2, &pmi8994_hfsmps, "vdd_s2" }, - { "s3", QCOM_SMD_RPM_SMPB, 3, &pmi8994_hfsmps, "vdd_s3" }, - { "boost-bypass", QCOM_SMD_RPM_BBYB, 1, &pmi8994_bby, "vdd_bst_byp" }, - {} -}; - static const struct rpm_regulator_data rpm_pm8998_regulators[] = { { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8998_ftsmps, "vdd_s1" }, { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8998_ftsmps, "vdd_s2" }, @@ -1137,57 +1201,68 @@ static const struct rpm_regulator_data rpm_pm8998_regulators[] = { {} }; -static const struct rpm_regulator_data rpm_pmi8998_regulators[] = { - { "bob", QCOM_SMD_RPM_BOBB, 1, &pmi8998_bob, "vdd_bob" }, +static const struct rpm_regulator_data rpm_pma8084_regulators[] = { + { "s1", QCOM_SMD_RPM_SMPA, 1, &pma8084_ftsmps, "vdd_s1" }, + { "s2", QCOM_SMD_RPM_SMPA, 2, &pma8084_ftsmps, "vdd_s2" }, + { "s3", QCOM_SMD_RPM_SMPA, 3, &pma8084_hfsmps, "vdd_s3" }, + { "s4", QCOM_SMD_RPM_SMPA, 4, &pma8084_hfsmps, "vdd_s4" }, + { "s5", QCOM_SMD_RPM_SMPA, 5, &pma8084_hfsmps, "vdd_s5" }, + { "s6", QCOM_SMD_RPM_SMPA, 6, &pma8084_ftsmps, "vdd_s6" }, + { "s7", QCOM_SMD_RPM_SMPA, 7, &pma8084_ftsmps, "vdd_s7" }, + { "s8", QCOM_SMD_RPM_SMPA, 8, &pma8084_ftsmps, "vdd_s8" }, + { "s9", QCOM_SMD_RPM_SMPA, 9, &pma8084_ftsmps, "vdd_s9" }, + { "s10", QCOM_SMD_RPM_SMPA, 10, &pma8084_ftsmps, "vdd_s10" }, + { "s11", QCOM_SMD_RPM_SMPA, 11, &pma8084_ftsmps, "vdd_s11" }, + { "s12", QCOM_SMD_RPM_SMPA, 12, &pma8084_ftsmps, "vdd_s12" }, + + { "l1", QCOM_SMD_RPM_LDOA, 1, &pma8084_nldo, "vdd_l1_l11" }, + { "l2", QCOM_SMD_RPM_LDOA, 2, &pma8084_nldo, "vdd_l2_l3_l4_l27" }, + { "l3", QCOM_SMD_RPM_LDOA, 3, &pma8084_nldo, "vdd_l2_l3_l4_l27" }, + { "l4", QCOM_SMD_RPM_LDOA, 4, &pma8084_nldo, "vdd_l2_l3_l4_l27" }, + { "l5", QCOM_SMD_RPM_LDOA, 5, &pma8084_pldo, "vdd_l5_l7" }, + { "l6", QCOM_SMD_RPM_LDOA, 6, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" }, + { "l7", QCOM_SMD_RPM_LDOA, 7, &pma8084_pldo, "vdd_l5_l7" }, + { "l8", QCOM_SMD_RPM_LDOA, 8, &pma8084_pldo, "vdd_l8" }, + { "l9", QCOM_SMD_RPM_LDOA, 9, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" }, + { "l10", QCOM_SMD_RPM_LDOA, 10, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" }, + { "l11", QCOM_SMD_RPM_LDOA, 11, &pma8084_nldo, "vdd_l1_l11" }, + { "l12", QCOM_SMD_RPM_LDOA, 12, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" }, + { "l13", QCOM_SMD_RPM_LDOA, 13, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" }, + { "l14", QCOM_SMD_RPM_LDOA, 14, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" }, + { "l15", QCOM_SMD_RPM_LDOA, 15, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" }, + { "l16", QCOM_SMD_RPM_LDOA, 16, &pma8084_pldo, "vdd_l16_l25" }, + { "l17", QCOM_SMD_RPM_LDOA, 17, &pma8084_pldo, "vdd_l17" }, + { "l18", QCOM_SMD_RPM_LDOA, 18, &pma8084_pldo, "vdd_l18" }, + { "l19", QCOM_SMD_RPM_LDOA, 19, &pma8084_pldo, "vdd_l19" }, + { "l20", QCOM_SMD_RPM_LDOA, 20, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" }, + { "l21", QCOM_SMD_RPM_LDOA, 21, &pma8084_pldo, "vdd_l21" }, + { "l22", QCOM_SMD_RPM_LDOA, 22, &pma8084_pldo, "vdd_l22" }, + { "l23", QCOM_SMD_RPM_LDOA, 23, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" }, + { "l24", QCOM_SMD_RPM_LDOA, 24, &pma8084_pldo, "vdd_l9_l10_l13_l20_l23_l24" }, + { "l25", QCOM_SMD_RPM_LDOA, 25, &pma8084_pldo, "vdd_l16_l25" }, + { "l26", QCOM_SMD_RPM_LDOA, 26, &pma8084_pldo, "vdd_l6_l12_l14_l15_l26" }, + { "l27", QCOM_SMD_RPM_LDOA, 27, &pma8084_nldo, "vdd_l2_l3_l4_l27" }, + + { "lvs1", QCOM_SMD_RPM_VSA, 1, &pma8084_switch }, + { "lvs2", QCOM_SMD_RPM_VSA, 2, &pma8084_switch }, + { "lvs3", QCOM_SMD_RPM_VSA, 3, &pma8084_switch }, + { "lvs4", QCOM_SMD_RPM_VSA, 4, &pma8084_switch }, + { "5vs1", QCOM_SMD_RPM_VSA, 5, &pma8084_switch }, + {} }; -static const struct rpm_regulator_data rpm_pm660_regulators[] = { - { "s1", QCOM_SMD_RPM_SMPA, 1, &pm660_ftsmps, "vdd_s1" }, - { "s2", QCOM_SMD_RPM_SMPA, 2, &pm660_ftsmps, "vdd_s2" }, - { "s3", QCOM_SMD_RPM_SMPA, 3, &pm660_ftsmps, "vdd_s3" }, - { "s4", QCOM_SMD_RPM_SMPA, 4, &pm660_hfsmps, "vdd_s4" }, - { "s5", QCOM_SMD_RPM_SMPA, 5, &pm660_hfsmps, "vdd_s5" }, - { "s6", QCOM_SMD_RPM_SMPA, 6, &pm660_hfsmps, "vdd_s6" }, - { "l1", QCOM_SMD_RPM_LDOA, 1, &pm660_nldo660, "vdd_l1_l6_l7" }, - { "l2", QCOM_SMD_RPM_LDOA, 2, &pm660_ht_nldo, "vdd_l2_l3" }, - { "l3", QCOM_SMD_RPM_LDOA, 3, &pm660_nldo660, "vdd_l2_l3" }, - /* l4 is unaccessible on PM660 */ - { "l5", QCOM_SMD_RPM_LDOA, 5, &pm660_ht_nldo, "vdd_l5" }, - { "l6", QCOM_SMD_RPM_LDOA, 6, &pm660_ht_nldo, "vdd_l1_l6_l7" }, - { "l7", QCOM_SMD_RPM_LDOA, 7, &pm660_ht_nldo, "vdd_l1_l6_l7" }, - { "l8", QCOM_SMD_RPM_LDOA, 8, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, - { "l9", QCOM_SMD_RPM_LDOA, 9, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, - { "l10", QCOM_SMD_RPM_LDOA, 10, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, - { "l11", QCOM_SMD_RPM_LDOA, 11, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, - { "l12", QCOM_SMD_RPM_LDOA, 12, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, - { "l13", QCOM_SMD_RPM_LDOA, 13, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, - { "l14", QCOM_SMD_RPM_LDOA, 14, &pm660_ht_lvpldo, "vdd_l8_l9_l10_l11_l12_l13_l14" }, - { "l15", QCOM_SMD_RPM_LDOA, 15, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, - { "l16", QCOM_SMD_RPM_LDOA, 16, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, - { "l17", QCOM_SMD_RPM_LDOA, 17, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, - { "l18", QCOM_SMD_RPM_LDOA, 18, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, - { "l19", QCOM_SMD_RPM_LDOA, 19, &pm660_pldo660, "vdd_l15_l16_l17_l18_l19" }, - { } +static const struct rpm_regulator_data rpm_pmi8994_regulators[] = { + { "s1", QCOM_SMD_RPM_SMPB, 1, &pmi8994_ftsmps, "vdd_s1" }, + { "s2", QCOM_SMD_RPM_SMPB, 2, &pmi8994_hfsmps, "vdd_s2" }, + { "s3", QCOM_SMD_RPM_SMPB, 3, &pmi8994_hfsmps, "vdd_s3" }, + { "boost-bypass", QCOM_SMD_RPM_BBYB, 1, &pmi8994_bby, "vdd_bst_byp" }, + {} }; -static const struct rpm_regulator_data rpm_pm660l_regulators[] = { - { "s1", QCOM_SMD_RPM_SMPB, 1, &pm660_ftsmps, "vdd_s1" }, - { "s2", QCOM_SMD_RPM_SMPB, 2, &pm660_ftsmps, "vdd_s2" }, - { "s3", QCOM_SMD_RPM_RWCX, 0, &pm660_ftsmps, "vdd_s3_s4" }, - { "s5", QCOM_SMD_RPM_RWMX, 0, &pm660_ftsmps, "vdd_s5" }, - { "l1", QCOM_SMD_RPM_LDOB, 1, &pm660_nldo660, "vdd_l1_l9_l10" }, - { "l2", QCOM_SMD_RPM_LDOB, 2, &pm660_pldo660, "vdd_l2" }, - { "l3", QCOM_SMD_RPM_LDOB, 3, &pm660_pldo660, "vdd_l3_l5_l7_l8" }, - { "l4", QCOM_SMD_RPM_LDOB, 4, &pm660_pldo660, "vdd_l4_l6" }, - { "l5", QCOM_SMD_RPM_LDOB, 5, &pm660_pldo660, "vdd_l3_l5_l7_l8" }, - { "l6", QCOM_SMD_RPM_LDOB, 6, &pm660_pldo660, "vdd_l4_l6" }, - { "l7", QCOM_SMD_RPM_LDOB, 7, &pm660_pldo660, "vdd_l3_l5_l7_l8" }, - { "l8", QCOM_SMD_RPM_LDOB, 8, &pm660_pldo660, "vdd_l3_l5_l7_l8" }, - { "l9", QCOM_SMD_RPM_RWLC, 0, &pm660_ht_nldo, "vdd_l1_l9_l10" }, - { "l10", QCOM_SMD_RPM_RWLM, 0, &pm660_ht_nldo, "vdd_l1_l9_l10" }, - { "bob", QCOM_SMD_RPM_BOBB, 1, &pm660l_bob, "vdd_bob", }, - { } +static const struct rpm_regulator_data rpm_pmi8998_regulators[] = { + { "bob", QCOM_SMD_RPM_BOBB, 1, &pmi8998_bob, "vdd_bob" }, + {} }; static const struct rpm_regulator_data rpm_pms405_regulators[] = { @@ -1212,54 +1287,25 @@ static const struct rpm_regulator_data rpm_pms405_regulators[] = { {} }; -static const struct rpm_regulator_data rpm_pm2250_regulators[] = { - { "s1", QCOM_SMD_RPM_SMPA, 1, &pm2250_lvftsmps, "vdd_s1" }, - { "s2", QCOM_SMD_RPM_SMPA, 2, &pm2250_lvftsmps, "vdd_s2" }, - { "s3", QCOM_SMD_RPM_SMPA, 3, &pm2250_lvftsmps, "vdd_s3" }, - { "s4", QCOM_SMD_RPM_SMPA, 4, &pm2250_ftsmps, "vdd_s4" }, - { "l1", QCOM_SMD_RPM_LDOA, 1, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, - { "l2", QCOM_SMD_RPM_LDOA, 2, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, - { "l3", QCOM_SMD_RPM_LDOA, 3, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, - { "l4", QCOM_SMD_RPM_LDOA, 4, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, - { "l5", QCOM_SMD_RPM_LDOA, 5, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, - { "l6", QCOM_SMD_RPM_LDOA, 6, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, - { "l7", QCOM_SMD_RPM_LDOA, 7, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, - { "l8", QCOM_SMD_RPM_LDOA, 8, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, - { "l9", QCOM_SMD_RPM_LDOA, 9, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, - { "l10", QCOM_SMD_RPM_LDOA, 10, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, - { "l11", QCOM_SMD_RPM_LDOA, 11, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, - { "l12", QCOM_SMD_RPM_LDOA, 12, &pm660_nldo660, "vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12" }, - { "l13", QCOM_SMD_RPM_LDOA, 13, &pm660_ht_lvpldo, "vdd_l13_l14_l15_l16" }, - { "l14", QCOM_SMD_RPM_LDOA, 14, &pm660_ht_lvpldo, "vdd_l13_l14_l15_l16" }, - { "l15", QCOM_SMD_RPM_LDOA, 15, &pm660_ht_lvpldo, "vdd_l13_l14_l15_l16" }, - { "l16", QCOM_SMD_RPM_LDOA, 16, &pm660_ht_lvpldo, "vdd_l13_l14_l15_l16" }, - { "l17", QCOM_SMD_RPM_LDOA, 17, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, - { "l18", QCOM_SMD_RPM_LDOA, 18, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, - { "l19", QCOM_SMD_RPM_LDOA, 19, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, - { "l20", QCOM_SMD_RPM_LDOA, 20, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, - { "l21", QCOM_SMD_RPM_LDOA, 21, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, - { "l22", QCOM_SMD_RPM_LDOA, 22, &pm660_pldo660, "vdd_l4_l17_l18_l19_l20_l21_l22" }, - {} -}; - static const struct of_device_id rpm_of_match[] = { { .compatible = "qcom,rpm-mp5496-regulators", .data = &rpm_mp5496_regulators }, + { .compatible = "qcom,rpm-pm2250-regulators", .data = &rpm_pm2250_regulators }, + { .compatible = "qcom,rpm-pm6125-regulators", .data = &rpm_pm6125_regulators }, + { .compatible = "qcom,rpm-pm660-regulators", .data = &rpm_pm660_regulators }, + { .compatible = "qcom,rpm-pm660l-regulators", .data = &rpm_pm660l_regulators }, + { .compatible = "qcom,rpm-pm8226-regulators", .data = &rpm_pm8226_regulators }, { .compatible = "qcom,rpm-pm8841-regulators", .data = &rpm_pm8841_regulators }, { .compatible = "qcom,rpm-pm8909-regulators", .data = &rpm_pm8909_regulators }, { .compatible = "qcom,rpm-pm8916-regulators", .data = &rpm_pm8916_regulators }, - { .compatible = "qcom,rpm-pm8226-regulators", .data = &rpm_pm8226_regulators }, { .compatible = "qcom,rpm-pm8941-regulators", .data = &rpm_pm8941_regulators }, { .compatible = "qcom,rpm-pm8950-regulators", .data = &rpm_pm8950_regulators }, { .compatible = "qcom,rpm-pm8953-regulators", .data = &rpm_pm8953_regulators }, { .compatible = "qcom,rpm-pm8994-regulators", .data = &rpm_pm8994_regulators }, { .compatible = "qcom,rpm-pm8998-regulators", .data = &rpm_pm8998_regulators }, - { .compatible = "qcom,rpm-pm660-regulators", .data = &rpm_pm660_regulators }, - { .compatible = "qcom,rpm-pm660l-regulators", .data = &rpm_pm660l_regulators }, { .compatible = "qcom,rpm-pma8084-regulators", .data = &rpm_pma8084_regulators }, { .compatible = "qcom,rpm-pmi8994-regulators", .data = &rpm_pmi8994_regulators }, { .compatible = "qcom,rpm-pmi8998-regulators", .data = &rpm_pmi8998_regulators }, { .compatible = "qcom,rpm-pms405-regulators", .data = &rpm_pms405_regulators }, - { .compatible = "qcom,rpm-pm2250-regulators", .data = &rpm_pm2250_regulators }, {} }; MODULE_DEVICE_TABLE(of, rpm_of_match); diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index a2d0292a92fd..3e312729741e 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -99,6 +99,9 @@ enum spmi_regulator_logical_type { SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO, SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS426, SPMI_REGULATOR_LOGICAL_TYPE_HFS430, + SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS3, + SPMI_REGULATOR_LOGICAL_TYPE_LDO_510, + SPMI_REGULATOR_LOGICAL_TYPE_HFSMPS, }; enum spmi_regulator_type { @@ -166,6 +169,17 @@ enum spmi_regulator_subtype { SPMI_REGULATOR_SUBTYPE_HFS430 = 0x0a, SPMI_REGULATOR_SUBTYPE_HT_P150 = 0x35, SPMI_REGULATOR_SUBTYPE_HT_P600 = 0x3d, + SPMI_REGULATOR_SUBTYPE_HFSMPS_510 = 0x0a, + SPMI_REGULATOR_SUBTYPE_FTSMPS_510 = 0x0b, + SPMI_REGULATOR_SUBTYPE_LV_P150_510 = 0x71, + SPMI_REGULATOR_SUBTYPE_LV_P300_510 = 0x72, + SPMI_REGULATOR_SUBTYPE_LV_P600_510 = 0x73, + SPMI_REGULATOR_SUBTYPE_N300_510 = 0x6a, + SPMI_REGULATOR_SUBTYPE_N600_510 = 0x6b, + SPMI_REGULATOR_SUBTYPE_N1200_510 = 0x6c, + SPMI_REGULATOR_SUBTYPE_MV_P50_510 = 0x7a, + SPMI_REGULATOR_SUBTYPE_MV_P150_510 = 0x7b, + SPMI_REGULATOR_SUBTYPE_MV_P600_510 = 0x7d, }; enum spmi_common_regulator_registers { @@ -193,6 +207,14 @@ enum spmi_ftsmps426_regulator_registers { SPMI_FTSMPS426_REG_VOLTAGE_ULS_MSB = 0x69, }; +/* + * Third common register layout + */ +enum spmi_hfsmps_regulator_registers { + SPMI_HFSMPS_REG_STEP_CTRL = 0x3c, + SPMI_HFSMPS_REG_PULL_DOWN = 0xa0, +}; + enum spmi_vs_registers { SPMI_VS_REG_OCP = 0x4a, SPMI_VS_REG_SOFT_START = 0x4c, @@ -260,6 +282,15 @@ enum spmi_common_control_register_index { #define SPMI_FTSMPS426_MODE_MASK 0x07 +/* Third common regulator mode register values */ +#define SPMI_HFSMPS_MODE_BYPASS_MASK 2 +#define SPMI_HFSMPS_MODE_RETENTION_MASK 3 +#define SPMI_HFSMPS_MODE_LPM_MASK 4 +#define SPMI_HFSMPS_MODE_AUTO_MASK 6 +#define SPMI_HFSMPS_MODE_HPM_MASK 7 + +#define SPMI_HFSMPS_MODE_MASK 0x07 + /* Common regulator pull down control register layout */ #define SPMI_COMMON_PULL_DOWN_ENABLE_MASK 0x80 @@ -305,6 +336,9 @@ enum spmi_common_control_register_index { #define SPMI_FTSMPS_STEP_MARGIN_NUM 4 #define SPMI_FTSMPS_STEP_MARGIN_DEN 5 +/* slew_rate has units of uV/us. */ +#define SPMI_HFSMPS_SLEW_RATE_38p4 38400 + #define SPMI_FTSMPS426_STEP_CTRL_DELAY_MASK 0x03 #define SPMI_FTSMPS426_STEP_CTRL_DELAY_SHIFT 0 @@ -554,6 +588,14 @@ static struct spmi_voltage_range ht_p600_ranges[] = { SPMI_VOLTAGE_RANGE(0, 1704000, 1704000, 1896000, 1896000, 8000), }; +static struct spmi_voltage_range nldo_510_ranges[] = { + SPMI_VOLTAGE_RANGE(0, 320000, 320000, 1304000, 1304000, 8000), +}; + +static struct spmi_voltage_range ftsmps510_ranges[] = { + SPMI_VOLTAGE_RANGE(0, 300000, 300000, 1372000, 1372000, 4000), +}; + static DEFINE_SPMI_SET_POINTS(pldo); static DEFINE_SPMI_SET_POINTS(nldo1); static DEFINE_SPMI_SET_POINTS(nldo2); @@ -576,6 +618,8 @@ static DEFINE_SPMI_SET_POINTS(ht_nldo); static DEFINE_SPMI_SET_POINTS(hfs430); static DEFINE_SPMI_SET_POINTS(ht_p150); static DEFINE_SPMI_SET_POINTS(ht_p600); +static DEFINE_SPMI_SET_POINTS(nldo_510); +static DEFINE_SPMI_SET_POINTS(ftsmps510); static inline int spmi_vreg_read(struct spmi_regulator *vreg, u16 addr, u8 *buf, int len) @@ -1062,6 +1106,23 @@ static unsigned int spmi_regulator_ftsmps426_get_mode(struct regulator_dev *rdev } } +static unsigned int spmi_regulator_hfsmps_get_mode(struct regulator_dev *rdev) +{ + struct spmi_regulator *vreg = rdev_get_drvdata(rdev); + u8 reg; + + spmi_vreg_read(vreg, SPMI_COMMON_REG_MODE, ®, 1); + + switch (reg) { + case SPMI_HFSMPS_MODE_HPM_MASK: + return REGULATOR_MODE_NORMAL; + case SPMI_HFSMPS_MODE_AUTO_MASK: + return REGULATOR_MODE_FAST; + default: + return REGULATOR_MODE_IDLE; + } +} + static int spmi_regulator_common_set_mode(struct regulator_dev *rdev, unsigned int mode) { @@ -1109,6 +1170,33 @@ spmi_regulator_ftsmps426_set_mode(struct regulator_dev *rdev, unsigned int mode) } static int +spmi_regulator_hfsmps_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct spmi_regulator *vreg = rdev_get_drvdata(rdev); + u8 mask = SPMI_HFSMPS_MODE_MASK; + u8 val; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + val = SPMI_HFSMPS_MODE_HPM_MASK; + break; + case REGULATOR_MODE_FAST: + val = SPMI_HFSMPS_MODE_AUTO_MASK; + break; + case REGULATOR_MODE_IDLE: + val = vreg->logical_type == + SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS3 ? + SPMI_HFSMPS_MODE_RETENTION_MASK : + SPMI_HFSMPS_MODE_LPM_MASK; + break; + default: + return -EINVAL; + } + + return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask); +} + +static int spmi_regulator_common_set_load(struct regulator_dev *rdev, int load_uA) { struct spmi_regulator *vreg = rdev_get_drvdata(rdev); @@ -1131,6 +1219,15 @@ static int spmi_regulator_common_set_pull_down(struct regulator_dev *rdev) mask, mask); } +static int spmi_regulator_hfsmps_set_pull_down(struct regulator_dev *rdev) +{ + struct spmi_regulator *vreg = rdev_get_drvdata(rdev); + unsigned int mask = SPMI_COMMON_PULL_DOWN_ENABLE_MASK; + + return spmi_vreg_update_bits(vreg, SPMI_HFSMPS_REG_PULL_DOWN, + mask, mask); +} + static int spmi_regulator_common_set_soft_start(struct regulator_dev *rdev) { struct spmi_regulator *vreg = rdev_get_drvdata(rdev); @@ -1465,6 +1562,21 @@ static const struct regulator_ops spmi_hfs430_ops = { .get_mode = spmi_regulator_ftsmps426_get_mode, }; +static const struct regulator_ops spmi_hfsmps_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_voltage_sel = spmi_regulator_ftsmps426_set_voltage, + .set_voltage_time_sel = spmi_regulator_set_voltage_time_sel, + .get_voltage_sel = spmi_regulator_ftsmps426_get_voltage, + .map_voltage = spmi_regulator_single_map_voltage, + .list_voltage = spmi_regulator_common_list_voltage, + .set_mode = spmi_regulator_hfsmps_set_mode, + .get_mode = spmi_regulator_hfsmps_get_mode, + .set_load = spmi_regulator_common_set_load, + .set_pull_down = spmi_regulator_hfsmps_set_pull_down, +}; + /* Maximum possible digital major revision value */ #define INF 0xFF @@ -1473,7 +1585,8 @@ static const struct spmi_regulator_mapping supported_regulators[] = { SPMI_VREG(LDO, HT_P600, 0, INF, HFS430, hfs430, ht_p600, 10000), SPMI_VREG(LDO, HT_P150, 0, INF, HFS430, hfs430, ht_p150, 10000), SPMI_VREG(BUCK, GP_CTL, 0, INF, SMPS, smps, smps, 100000), - SPMI_VREG(BUCK, HFS430, 0, INF, HFS430, hfs430, hfs430, 10000), + SPMI_VREG(BUCK, HFS430, 0, 3, HFS430, hfs430, hfs430, 10000), + SPMI_VREG(BUCK, HFSMPS_510, 4, INF, HFSMPS, hfsmps, hfs430, 100000), SPMI_VREG(LDO, N300, 0, INF, LDO, ldo, nldo1, 10000), SPMI_VREG(LDO, N600, 0, 0, LDO, ldo, nldo2, 10000), SPMI_VREG(LDO, N1200, 0, 0, LDO, ldo, nldo2, 10000), @@ -1549,6 +1662,16 @@ static const struct spmi_regulator_mapping supported_regulators[] = { SPMI_VREG(ULT_LDO, P300, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), SPMI_VREG(ULT_LDO, P150, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 10000), SPMI_VREG(ULT_LDO, P50, 0, INF, ULT_LDO, ult_ldo, ult_pldo, 5000), + SPMI_VREG(LDO, LV_P150_510, 0, INF, LDO_510, hfsmps, ht_lvpldo, 10000), + SPMI_VREG(LDO, LV_P300_510, 0, INF, LDO_510, hfsmps, ht_lvpldo, 10000), + SPMI_VREG(LDO, LV_P600_510, 0, INF, LDO_510, hfsmps, ht_lvpldo, 10000), + SPMI_VREG(LDO, MV_P50_510, 0, INF, LDO_510, hfsmps, pldo660, 10000), + SPMI_VREG(LDO, MV_P150_510, 0, INF, LDO_510, hfsmps, pldo660, 10000), + SPMI_VREG(LDO, MV_P600_510, 0, INF, LDO_510, hfsmps, pldo660, 10000), + SPMI_VREG(LDO, N300_510, 0, INF, LDO_510, hfsmps, nldo_510, 10000), + SPMI_VREG(LDO, N600_510, 0, INF, LDO_510, hfsmps, nldo_510, 10000), + SPMI_VREG(LDO, N1200_510, 0, INF, LDO_510, hfsmps, nldo_510, 10000), + SPMI_VREG(FTS, FTSMPS_510, 0, INF, FTSMPS3, hfsmps, ftsmps510, 100000), }; static void spmi_calculate_num_voltages(struct spmi_voltage_set_points *points) @@ -1696,6 +1819,26 @@ static int spmi_regulator_init_slew_rate_ftsmps426(struct spmi_regulator *vreg, return ret; } +static int spmi_regulator_init_slew_rate_hfsmps(struct spmi_regulator *vreg) +{ + int ret; + u8 reg = 0; + int delay; + + ret = spmi_vreg_read(vreg, SPMI_HFSMPS_REG_STEP_CTRL, ®, 1); + if (ret) { + dev_err(vreg->dev, "spmi read failed, ret=%d\n", ret); + return ret; + } + + delay = reg & SPMI_FTSMPS426_STEP_CTRL_DELAY_MASK; + delay >>= SPMI_FTSMPS426_STEP_CTRL_DELAY_SHIFT; + + vreg->slew_rate = SPMI_HFSMPS_SLEW_RATE_38p4 >> delay; + + return ret; +} + static int spmi_regulator_init_registers(struct spmi_regulator *vreg, const struct spmi_regulator_init_data *data) { @@ -1846,6 +1989,12 @@ static int spmi_regulator_of_parse(struct device_node *node, if (ret) return ret; break; + case SPMI_REGULATOR_LOGICAL_TYPE_HFSMPS: + case SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS3: + ret = spmi_regulator_init_slew_rate_hfsmps(vreg); + if (ret) + return ret; + break; default: break; } @@ -1872,40 +2021,100 @@ static int spmi_regulator_of_parse(struct device_node *node, return 0; } -static const struct spmi_regulator_data pm8941_regulators[] = { +static const struct spmi_regulator_data pm6125_regulators[] = { + { "s1", 0x1400, "vdd_s1" }, + { "s2", 0x1700, "vdd_s2" }, + { "s3", 0x1a00, "vdd_s3" }, + { "s4", 0x1d00, "vdd_s4" }, + { "s5", 0x2000, "vdd_s5" }, + { "s6", 0x2300, "vdd_s6" }, + { "s7", 0x2600, "vdd_s7" }, + { "s8", 0x2900, "vdd_s8" }, + { "l1", 0x4000, "vdd_l1_l7_l17_l18" }, + { "l2", 0x4100, "vdd_l2_l3_l4" }, + { "l3", 0x4200, "vdd_l2_l3_l4" }, + { "l4", 0x4300, "vdd_l2_l3_l4" }, + { "l5", 0x4400, "vdd_l5_l15_l19_l20_l21_l22" }, + { "l6", 0x4500, "vdd_l6_l8" }, + { "l7", 0x4600, "vdd_l1_l7_l17_l18" }, + { "l8", 0x4700, "vdd_l6_l8" }, + { "l9", 0x4800, "vdd_l9_l11" }, + { "l10", 0x4900, "vdd_l10_l13_l14" }, + { "l11", 0x4a00, "vdd_l9_l11" }, + { "l12", 0x4b00, "vdd_l12_l16" }, + { "l13", 0x4c00, "vdd_l10_l13_l14" }, + { "l14", 0x4d00, "vdd_l10_l13_l14" }, + { "l15", 0x4e00, "vdd_l5_l15_l19_l20_l21_l22" }, + { "l16", 0x4f00, "vdd_l12_l16" }, + { "l17", 0x5000, "vdd_l1_l7_l17_l18" }, + { "l18", 0x5100, "vdd_l1_l7_l17_l18" }, + { "l19", 0x5200, "vdd_l5_l15_l19_l20_l21_l22" }, + { "l20", 0x5300, "vdd_l5_l15_l19_l20_l21_l22" }, + { "l21", 0x5400, "vdd_l5_l15_l19_l20_l21_l22" }, + { "l22", 0x5500, "vdd_l5_l15_l19_l20_l21_l22" }, + { "l23", 0x5600, "vdd_l23_l24" }, + { "l24", 0x5700, "vdd_l23_l24" }, +}; + +static const struct spmi_regulator_data pm660_regulators[] = { { "s1", 0x1400, "vdd_s1", }, { "s2", 0x1700, "vdd_s2", }, { "s3", 0x1a00, "vdd_s3", }, - { "s4", 0xa000, }, - { "l1", 0x4000, "vdd_l1_l3", }, - { "l2", 0x4100, "vdd_l2_lvs_1_2_3", }, - { "l3", 0x4200, "vdd_l1_l3", }, - { "l4", 0x4300, "vdd_l4_l11", }, - { "l5", 0x4400, "vdd_l5_l7", NULL, 0x0410 }, - { "l6", 0x4500, "vdd_l6_l12_l14_l15", }, - { "l7", 0x4600, "vdd_l5_l7", NULL, 0x0410 }, - { "l8", 0x4700, "vdd_l8_l16_l18_19", }, - { "l9", 0x4800, "vdd_l9_l10_l17_l22", }, - { "l10", 0x4900, "vdd_l9_l10_l17_l22", }, - { "l11", 0x4a00, "vdd_l4_l11", }, - { "l12", 0x4b00, "vdd_l6_l12_l14_l15", }, - { "l13", 0x4c00, "vdd_l13_l20_l23_l24", }, - { "l14", 0x4d00, "vdd_l6_l12_l14_l15", }, - { "l15", 0x4e00, "vdd_l6_l12_l14_l15", }, - { "l16", 0x4f00, "vdd_l8_l16_l18_19", }, - { "l17", 0x5000, "vdd_l9_l10_l17_l22", }, - { "l18", 0x5100, "vdd_l8_l16_l18_19", }, - { "l19", 0x5200, "vdd_l8_l16_l18_19", }, - { "l20", 0x5300, "vdd_l13_l20_l23_l24", }, - { "l21", 0x5400, "vdd_l21", }, - { "l22", 0x5500, "vdd_l9_l10_l17_l22", }, - { "l23", 0x5600, "vdd_l13_l20_l23_l24", }, - { "l24", 0x5700, "vdd_l13_l20_l23_l24", }, - { "lvs1", 0x8000, "vdd_l2_lvs_1_2_3", }, - { "lvs2", 0x8100, "vdd_l2_lvs_1_2_3", }, - { "lvs3", 0x8200, "vdd_l2_lvs_1_2_3", }, - { "5vs1", 0x8300, "vin_5vs", "ocp-5vs1", }, - { "5vs2", 0x8400, "vin_5vs", "ocp-5vs2", }, + { "s4", 0x1d00, "vdd_s3", }, + { "s5", 0x2000, "vdd_s5", }, + { "s6", 0x2300, "vdd_s6", }, + { "l1", 0x4000, "vdd_l1_l6_l7", }, + { "l2", 0x4100, "vdd_l2_l3", }, + { "l3", 0x4200, "vdd_l2_l3", }, + /* l4 is unaccessible on PM660 */ + { "l5", 0x4400, "vdd_l5", }, + { "l6", 0x4500, "vdd_l1_l6_l7", }, + { "l7", 0x4600, "vdd_l1_l6_l7", }, + { "l8", 0x4700, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l9", 0x4800, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l10", 0x4900, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l11", 0x4a00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l12", 0x4b00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l13", 0x4c00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l14", 0x4d00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, + { "l15", 0x4e00, "vdd_l15_l16_l17_l18_l19", }, + { "l16", 0x4f00, "vdd_l15_l16_l17_l18_l19", }, + { "l17", 0x5000, "vdd_l15_l16_l17_l18_l19", }, + { "l18", 0x5100, "vdd_l15_l16_l17_l18_l19", }, + { "l19", 0x5200, "vdd_l15_l16_l17_l18_l19", }, + { } +}; + +static const struct spmi_regulator_data pm660l_regulators[] = { + { "s1", 0x1400, "vdd_s1", }, + { "s2", 0x1700, "vdd_s2", }, + { "s3", 0x1a00, "vdd_s3", }, + { "s4", 0x1d00, "vdd_s4", }, + { "s5", 0x2000, "vdd_s5", }, + { "l1", 0x4000, "vdd_l1_l9_l10", }, + { "l2", 0x4100, "vdd_l2", }, + { "l3", 0x4200, "vdd_l3_l5_l7_l8", }, + { "l4", 0x4300, "vdd_l4_l6", }, + { "l5", 0x4400, "vdd_l3_l5_l7_l8", }, + { "l6", 0x4500, "vdd_l4_l6", }, + { "l7", 0x4600, "vdd_l3_l5_l7_l8", }, + { "l8", 0x4700, "vdd_l3_l5_l7_l8", }, + { "l9", 0x4800, "vdd_l1_l9_l10", }, + { "l10", 0x4900, "vdd_l1_l9_l10", }, + { } +}; + +static const struct spmi_regulator_data pm8004_regulators[] = { + { "s2", 0x1700, "vdd_s2", }, + { "s5", 0x2000, "vdd_s5", }, + { } +}; + +static const struct spmi_regulator_data pm8005_regulators[] = { + { "s1", 0x1400, "vdd_s1", }, + { "s2", 0x1700, "vdd_s2", }, + { "s3", 0x1a00, "vdd_s3", }, + { "s4", 0x1d00, "vdd_s4", }, { } }; @@ -1985,6 +2194,43 @@ static const struct spmi_regulator_data pm8916_regulators[] = { { } }; +static const struct spmi_regulator_data pm8941_regulators[] = { + { "s1", 0x1400, "vdd_s1", }, + { "s2", 0x1700, "vdd_s2", }, + { "s3", 0x1a00, "vdd_s3", }, + { "s4", 0xa000, }, + { "l1", 0x4000, "vdd_l1_l3", }, + { "l2", 0x4100, "vdd_l2_lvs_1_2_3", }, + { "l3", 0x4200, "vdd_l1_l3", }, + { "l4", 0x4300, "vdd_l4_l11", }, + { "l5", 0x4400, "vdd_l5_l7", NULL, 0x0410 }, + { "l6", 0x4500, "vdd_l6_l12_l14_l15", }, + { "l7", 0x4600, "vdd_l5_l7", NULL, 0x0410 }, + { "l8", 0x4700, "vdd_l8_l16_l18_19", }, + { "l9", 0x4800, "vdd_l9_l10_l17_l22", }, + { "l10", 0x4900, "vdd_l9_l10_l17_l22", }, + { "l11", 0x4a00, "vdd_l4_l11", }, + { "l12", 0x4b00, "vdd_l6_l12_l14_l15", }, + { "l13", 0x4c00, "vdd_l13_l20_l23_l24", }, + { "l14", 0x4d00, "vdd_l6_l12_l14_l15", }, + { "l15", 0x4e00, "vdd_l6_l12_l14_l15", }, + { "l16", 0x4f00, "vdd_l8_l16_l18_19", }, + { "l17", 0x5000, "vdd_l9_l10_l17_l22", }, + { "l18", 0x5100, "vdd_l8_l16_l18_19", }, + { "l19", 0x5200, "vdd_l8_l16_l18_19", }, + { "l20", 0x5300, "vdd_l13_l20_l23_l24", }, + { "l21", 0x5400, "vdd_l21", }, + { "l22", 0x5500, "vdd_l9_l10_l17_l22", }, + { "l23", 0x5600, "vdd_l13_l20_l23_l24", }, + { "l24", 0x5700, "vdd_l13_l20_l23_l24", }, + { "lvs1", 0x8000, "vdd_l2_lvs_1_2_3", }, + { "lvs2", 0x8100, "vdd_l2_lvs_1_2_3", }, + { "lvs3", 0x8200, "vdd_l2_lvs_1_2_3", }, + { "5vs1", 0x8300, "vin_5vs", "ocp-5vs1", }, + { "5vs2", 0x8400, "vin_5vs", "ocp-5vs2", }, + { } +}; + static const struct spmi_regulator_data pm8950_regulators[] = { { "s1", 0x1400, "vdd_s1", }, { "s2", 0x1700, "vdd_s2", }, @@ -2076,69 +2322,6 @@ static const struct spmi_regulator_data pmi8994_regulators[] = { { } }; -static const struct spmi_regulator_data pm660_regulators[] = { - { "s1", 0x1400, "vdd_s1", }, - { "s2", 0x1700, "vdd_s2", }, - { "s3", 0x1a00, "vdd_s3", }, - { "s4", 0x1d00, "vdd_s3", }, - { "s5", 0x2000, "vdd_s5", }, - { "s6", 0x2300, "vdd_s6", }, - { "l1", 0x4000, "vdd_l1_l6_l7", }, - { "l2", 0x4100, "vdd_l2_l3", }, - { "l3", 0x4200, "vdd_l2_l3", }, - /* l4 is unaccessible on PM660 */ - { "l5", 0x4400, "vdd_l5", }, - { "l6", 0x4500, "vdd_l1_l6_l7", }, - { "l7", 0x4600, "vdd_l1_l6_l7", }, - { "l8", 0x4700, "vdd_l8_l9_l10_l11_l12_l13_l14", }, - { "l9", 0x4800, "vdd_l8_l9_l10_l11_l12_l13_l14", }, - { "l10", 0x4900, "vdd_l8_l9_l10_l11_l12_l13_l14", }, - { "l11", 0x4a00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, - { "l12", 0x4b00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, - { "l13", 0x4c00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, - { "l14", 0x4d00, "vdd_l8_l9_l10_l11_l12_l13_l14", }, - { "l15", 0x4e00, "vdd_l15_l16_l17_l18_l19", }, - { "l16", 0x4f00, "vdd_l15_l16_l17_l18_l19", }, - { "l17", 0x5000, "vdd_l15_l16_l17_l18_l19", }, - { "l18", 0x5100, "vdd_l15_l16_l17_l18_l19", }, - { "l19", 0x5200, "vdd_l15_l16_l17_l18_l19", }, - { } -}; - -static const struct spmi_regulator_data pm660l_regulators[] = { - { "s1", 0x1400, "vdd_s1", }, - { "s2", 0x1700, "vdd_s2", }, - { "s3", 0x1a00, "vdd_s3", }, - { "s4", 0x1d00, "vdd_s4", }, - { "s5", 0x2000, "vdd_s5", }, - { "l1", 0x4000, "vdd_l1_l9_l10", }, - { "l2", 0x4100, "vdd_l2", }, - { "l3", 0x4200, "vdd_l3_l5_l7_l8", }, - { "l4", 0x4300, "vdd_l4_l6", }, - { "l5", 0x4400, "vdd_l3_l5_l7_l8", }, - { "l6", 0x4500, "vdd_l4_l6", }, - { "l7", 0x4600, "vdd_l3_l5_l7_l8", }, - { "l8", 0x4700, "vdd_l3_l5_l7_l8", }, - { "l9", 0x4800, "vdd_l1_l9_l10", }, - { "l10", 0x4900, "vdd_l1_l9_l10", }, - { } -}; - - -static const struct spmi_regulator_data pm8004_regulators[] = { - { "s2", 0x1700, "vdd_s2", }, - { "s5", 0x2000, "vdd_s5", }, - { } -}; - -static const struct spmi_regulator_data pm8005_regulators[] = { - { "s1", 0x1400, "vdd_s1", }, - { "s2", 0x1700, "vdd_s2", }, - { "s3", 0x1a00, "vdd_s3", }, - { "s4", 0x1d00, "vdd_s4", }, - { } -}; - static const struct spmi_regulator_data pmp8074_regulators[] = { { "s1", 0x1400, "vdd_s1"}, { "s2", 0x1700, "vdd_s2"}, @@ -2167,6 +2350,9 @@ static const struct spmi_regulator_data pms405_regulators[] = { }; static const struct of_device_id qcom_spmi_regulator_match[] = { + { .compatible = "qcom,pm6125-regulators", .data = &pm6125_regulators }, + { .compatible = "qcom,pm660-regulators", .data = &pm660_regulators }, + { .compatible = "qcom,pm660l-regulators", .data = &pm660l_regulators }, { .compatible = "qcom,pm8004-regulators", .data = &pm8004_regulators }, { .compatible = "qcom,pm8005-regulators", .data = &pm8005_regulators }, { .compatible = "qcom,pm8226-regulators", .data = &pm8226_regulators }, @@ -2176,8 +2362,6 @@ static const struct of_device_id qcom_spmi_regulator_match[] = { { .compatible = "qcom,pm8950-regulators", .data = &pm8950_regulators }, { .compatible = "qcom,pm8994-regulators", .data = &pm8994_regulators }, { .compatible = "qcom,pmi8994-regulators", .data = &pmi8994_regulators }, - { .compatible = "qcom,pm660-regulators", .data = &pm660_regulators }, - { .compatible = "qcom,pm660l-regulators", .data = &pm660l_regulators }, { .compatible = "qcom,pmp8074-regulators", .data = &pmp8074_regulators }, { .compatible = "qcom,pms405-regulators", .data = &pms405_regulators }, { } diff --git a/drivers/regulator/rpi-panel-attiny-regulator.c b/drivers/regulator/rpi-panel-attiny-regulator.c index 105f694a67e6..308f7972941b 100644 --- a/drivers/regulator/rpi-panel-attiny-regulator.c +++ b/drivers/regulator/rpi-panel-attiny-regulator.c @@ -381,13 +381,11 @@ error: return ret; } -static int attiny_i2c_remove(struct i2c_client *client) +static void attiny_i2c_remove(struct i2c_client *client) { struct attiny_lcd *state = i2c_get_clientdata(client); mutex_destroy(&state->lock); - - return 0; } static const struct of_device_id attiny_dt_ids[] = { diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c index ce00db27589a..115345e9fded 100644 --- a/drivers/regulator/ti-abb-regulator.c +++ b/drivers/regulator/ti-abb-regulator.c @@ -151,7 +151,7 @@ static inline void ti_abb_clear_txdone(const struct ti_abb *abb) }; /** - * ti_abb_wait_tranx() - waits for ABB tranxdone event + * ti_abb_wait_txdone() - waits for ABB tranxdone event * @dev: device * @abb: pointer to the abb instance * diff --git a/drivers/regulator/tps65219-regulator.c b/drivers/regulator/tps65219-regulator.c new file mode 100644 index 000000000000..c484c943e467 --- /dev/null +++ b/drivers/regulator/tps65219-regulator.c @@ -0,0 +1,411 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// tps65219-regulator.c +// +// Regulator driver for TPS65219 PMIC +// +// Copyright (C) 2022 BayLibre Incorporated - https://www.baylibre.com/ +// +// This implementation derived from tps65218 authored by +// "J Keerthy <j-keerthy@ti.com>" +// + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/of_device.h> +#include <linux/regmap.h> +#include <linux/regulator/of_regulator.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/mfd/tps65219.h> + +struct tps65219_regulator_irq_type { + const char *irq_name; + const char *regulator_name; + const char *event_name; + unsigned long event; +}; + +static struct tps65219_regulator_irq_type tps65219_regulator_irq_types[] = { + { "LDO3_SCG", "LDO3", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, + { "LDO3_OC", "LDO3", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, + { "LDO3_UV", "LDO3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { "LDO4_SCG", "LDO4", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, + { "LDO4_OC", "LDO4", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, + { "LDO4_UV", "LDO4", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { "LDO1_SCG", "LDO1", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, + { "LDO1_OC", "LDO1", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, + { "LDO1_UV", "LDO1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { "LDO2_SCG", "LDO2", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, + { "LDO2_OC", "LDO2", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, + { "LDO2_UV", "LDO2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { "BUCK3_SCG", "BUCK3", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, + { "BUCK3_OC", "BUCK3", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, + { "BUCK3_NEG_OC", "BUCK3", "negative overcurrent", REGULATOR_EVENT_OVER_CURRENT }, + { "BUCK3_UV", "BUCK3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { "BUCK1_SCG", "BUCK1", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, + { "BUCK1_OC", "BUCK1", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, + { "BUCK1_NEG_OC", "BUCK1", "negative overcurrent", REGULATOR_EVENT_OVER_CURRENT }, + { "BUCK1_UV", "BUCK1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { "BUCK2_SCG", "BUCK2", "short circuit to ground", REGULATOR_EVENT_REGULATION_OUT }, + { "BUCK2_OC", "BUCK2", "overcurrent", REGULATOR_EVENT_OVER_CURRENT }, + { "BUCK2_NEG_OC", "BUCK2", "negative overcurrent", REGULATOR_EVENT_OVER_CURRENT }, + { "BUCK2_UV", "BUCK2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, + { "BUCK1_RV", "BUCK1", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "BUCK2_RV", "BUCK2", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "BUCK3_RV", "BUCK3", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "LDO1_RV", "LDO1", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "LDO2_RV", "LDO2", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "LDO3_RV", "LDO3", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "LDO4_RV", "LDO4", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "BUCK1_RV_SD", "BUCK1", "residual voltage on shutdown", + REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "BUCK2_RV_SD", "BUCK2", "residual voltage on shutdown", + REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "BUCK3_RV_SD", "BUCK3", "residual voltage on shutdown", + REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "LDO1_RV_SD", "LDO1", "residual voltage on shutdown", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "LDO2_RV_SD", "LDO2", "residual voltage on shutdown", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "LDO3_RV_SD", "LDO3", "residual voltage on shutdown", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "LDO4_RV_SD", "LDO4", "residual voltage on shutdown", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "SENSOR_3_WARM", "SENSOR3", "warm temperature", REGULATOR_EVENT_OVER_TEMP_WARN}, + { "SENSOR_2_WARM", "SENSOR2", "warm temperature", REGULATOR_EVENT_OVER_TEMP_WARN }, + { "SENSOR_1_WARM", "SENSOR1", "warm temperature", REGULATOR_EVENT_OVER_TEMP_WARN }, + { "SENSOR_0_WARM", "SENSOR0", "warm temperature", REGULATOR_EVENT_OVER_TEMP_WARN }, + { "SENSOR_3_HOT", "SENSOR3", "hot temperature", REGULATOR_EVENT_OVER_TEMP}, + { "SENSOR_2_HOT", "SENSOR2", "hot temperature", REGULATOR_EVENT_OVER_TEMP }, + { "SENSOR_1_HOT", "SENSOR1", "hot temperature", REGULATOR_EVENT_OVER_TEMP }, + { "SENSOR_0_HOT", "SENSOR0", "hot temperature", REGULATOR_EVENT_OVER_TEMP }, + { "TIMEOUT", "", "", REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE }, +}; + +struct tps65219_regulator_irq_data { + struct device *dev; + struct tps65219_regulator_irq_type *type; + struct regulator_dev *rdev; +}; + +#define TPS65219_REGULATOR(_name, _of, _id, _type, _ops, _n, _vr, _vm, _er, \ + _em, _cr, _cm, _lr, _nlr, _delay, _fuv, \ + _ct, _ncl, _bpm) \ + { \ + .name = _name, \ + .of_match = _of, \ + .regulators_node = of_match_ptr("regulators"), \ + .supply_name = _of, \ + .id = _id, \ + .ops = &(_ops), \ + .n_voltages = _n, \ + .type = _type, \ + .owner = THIS_MODULE, \ + .vsel_reg = _vr, \ + .vsel_mask = _vm, \ + .csel_reg = _cr, \ + .csel_mask = _cm, \ + .curr_table = _ct, \ + .n_current_limits = _ncl, \ + .enable_reg = _er, \ + .enable_mask = _em, \ + .volt_table = NULL, \ + .linear_ranges = _lr, \ + .n_linear_ranges = _nlr, \ + .ramp_delay = _delay, \ + .fixed_uV = _fuv, \ + .bypass_reg = _vr, \ + .bypass_mask = _bpm, \ + } \ + +static const struct linear_range bucks_ranges[] = { + REGULATOR_LINEAR_RANGE(600000, 0x0, 0x1f, 25000), + REGULATOR_LINEAR_RANGE(1400000, 0x20, 0x33, 100000), + REGULATOR_LINEAR_RANGE(3400000, 0x34, 0x3f, 0), +}; + +static const struct linear_range ldos_1_2_ranges[] = { + REGULATOR_LINEAR_RANGE(600000, 0x0, 0x37, 50000), + REGULATOR_LINEAR_RANGE(3400000, 0x38, 0x3f, 0), +}; + +static const struct linear_range ldos_3_4_ranges[] = { + REGULATOR_LINEAR_RANGE(1200000, 0x0, 0xC, 0), + REGULATOR_LINEAR_RANGE(1250000, 0xD, 0x35, 50000), + REGULATOR_LINEAR_RANGE(3300000, 0x36, 0x3F, 0), +}; + +static int tps65219_set_mode(struct regulator_dev *dev, unsigned int mode) +{ + struct tps65219 *tps = rdev_get_drvdata(dev); + + switch (mode) { + case REGULATOR_MODE_NORMAL: + return regmap_set_bits(tps->regmap, TPS65219_REG_STBY_1_CONFIG, + dev->desc->enable_mask); + + case REGULATOR_MODE_STANDBY: + return regmap_clear_bits(tps->regmap, + TPS65219_REG_STBY_1_CONFIG, + dev->desc->enable_mask); + default: + return -EINVAL; + } +} + +static unsigned int tps65219_get_mode(struct regulator_dev *dev) +{ + struct tps65219 *tps = rdev_get_drvdata(dev); + unsigned int rid = rdev_get_id(dev); + int ret, value = 0; + + ret = regmap_read(tps->regmap, TPS65219_REG_STBY_1_CONFIG, &value); + if (ret) { + dev_dbg(tps->dev, "%s failed for regulator %s: %d ", + __func__, dev->desc->name, ret); + return ret; + } + value = (value & BIT(rid)) >> rid; + if (value) + return REGULATOR_MODE_STANDBY; + else + return REGULATOR_MODE_NORMAL; +} + +/* + * generic regulator_set_bypass_regmap does not fully match requirements + * TPS65219 Requires explicitly that regulator is disabled before switch + */ +static int tps65219_set_bypass(struct regulator_dev *dev, bool enable) +{ + struct tps65219 *tps = rdev_get_drvdata(dev); + unsigned int rid = rdev_get_id(dev); + + if (dev->desc->ops->is_enabled(dev)) { + dev_err(tps->dev, + "%s LDO%d enabled, must be shut down to set bypass ", + __func__, rid); + return -EBUSY; + } + return regulator_set_bypass_regmap(dev, enable); +} + +/* Operations permitted on BUCK1/2/3 */ +static const struct regulator_ops tps65219_bucks_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .set_mode = tps65219_set_mode, + .get_mode = tps65219_get_mode, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + +}; + +/* Operations permitted on LDO1/2 */ +static const struct regulator_ops tps65219_ldos_1_2_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .set_mode = tps65219_set_mode, + .get_mode = tps65219_get_mode, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .set_bypass = tps65219_set_bypass, + .get_bypass = regulator_get_bypass_regmap, +}; + +/* Operations permitted on LDO3/4 */ +static const struct regulator_ops tps65219_ldos_3_4_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .set_mode = tps65219_set_mode, + .get_mode = tps65219_get_mode, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, +}; + +static const struct regulator_desc regulators[] = { + TPS65219_REGULATOR("BUCK1", "buck1", TPS65219_BUCK_1, + REGULATOR_VOLTAGE, tps65219_bucks_ops, 64, + TPS65219_REG_BUCK1_VOUT, + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, + TPS65219_REG_ENABLE_CTRL, + TPS65219_ENABLE_BUCK1_EN_MASK, 0, 0, bucks_ranges, + 3, 4000, 0, NULL, 0, 0), + TPS65219_REGULATOR("BUCK2", "buck2", TPS65219_BUCK_2, + REGULATOR_VOLTAGE, tps65219_bucks_ops, 64, + TPS65219_REG_BUCK2_VOUT, + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, + TPS65219_REG_ENABLE_CTRL, + TPS65219_ENABLE_BUCK2_EN_MASK, 0, 0, bucks_ranges, + 3, 4000, 0, NULL, 0, 0), + TPS65219_REGULATOR("BUCK3", "buck3", TPS65219_BUCK_3, + REGULATOR_VOLTAGE, tps65219_bucks_ops, 64, + TPS65219_REG_BUCK3_VOUT, + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, + TPS65219_REG_ENABLE_CTRL, + TPS65219_ENABLE_BUCK3_EN_MASK, 0, 0, bucks_ranges, + 3, 0, 0, NULL, 0, 0), + TPS65219_REGULATOR("LDO1", "ldo1", TPS65219_LDO_1, + REGULATOR_VOLTAGE, tps65219_ldos_1_2_ops, 64, + TPS65219_REG_LDO1_VOUT, + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, + TPS65219_REG_ENABLE_CTRL, + TPS65219_ENABLE_LDO1_EN_MASK, 0, 0, ldos_1_2_ranges, + 2, 0, 0, NULL, 0, TPS65219_LDOS_BYP_CONFIG_MASK), + TPS65219_REGULATOR("LDO2", "ldo2", TPS65219_LDO_2, + REGULATOR_VOLTAGE, tps65219_ldos_1_2_ops, 64, + TPS65219_REG_LDO2_VOUT, + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, + TPS65219_REG_ENABLE_CTRL, + TPS65219_ENABLE_LDO2_EN_MASK, 0, 0, ldos_1_2_ranges, + 2, 0, 0, NULL, 0, TPS65219_LDOS_BYP_CONFIG_MASK), + TPS65219_REGULATOR("LDO3", "ldo3", TPS65219_LDO_3, + REGULATOR_VOLTAGE, tps65219_ldos_3_4_ops, 64, + TPS65219_REG_LDO3_VOUT, + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, + TPS65219_REG_ENABLE_CTRL, + TPS65219_ENABLE_LDO3_EN_MASK, 0, 0, ldos_3_4_ranges, + 3, 0, 0, NULL, 0, 0), + TPS65219_REGULATOR("LDO4", "ldo4", TPS65219_LDO_4, + REGULATOR_VOLTAGE, tps65219_ldos_3_4_ops, 64, + TPS65219_REG_LDO4_VOUT, + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, + TPS65219_REG_ENABLE_CTRL, + TPS65219_ENABLE_LDO4_EN_MASK, 0, 0, ldos_3_4_ranges, + 3, 0, 0, NULL, 0, 0), +}; + +static irqreturn_t tps65219_regulator_irq_handler(int irq, void *data) +{ + struct tps65219_regulator_irq_data *irq_data = data; + + if (irq_data->type->event_name[0] == '\0') { + /* This is the timeout interrupt no specific regulator */ + dev_err(irq_data->dev, + "System was put in shutdown due to timeout during an active or standby transition.\n"); + return IRQ_HANDLED; + } + + regulator_notifier_call_chain(irq_data->rdev, + irq_data->type->event, NULL); + + dev_err(irq_data->dev, "Error IRQ trap %s for %s\n", + irq_data->type->event_name, irq_data->type->regulator_name); + return IRQ_HANDLED; +} + +static int tps65219_get_rdev_by_name(const char *regulator_name, + struct regulator_dev *rdevtbl[7], + struct regulator_dev *dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(regulators); i++) { + if (strcmp(regulator_name, regulators[i].name) == 0) { + dev = rdevtbl[i]; + return 0; + } + } + return -EINVAL; +} + +static int tps65219_regulator_probe(struct platform_device *pdev) +{ + struct tps65219 *tps = dev_get_drvdata(pdev->dev.parent); + struct regulator_dev *rdev; + struct regulator_config config = { }; + int i; + int error; + int irq; + struct tps65219_regulator_irq_data *irq_data; + struct tps65219_regulator_irq_type *irq_type; + struct regulator_dev *rdevtbl[7]; + + config.dev = tps->dev; + config.driver_data = tps; + config.regmap = tps->regmap; + + for (i = 0; i < ARRAY_SIZE(regulators); i++) { + dev_dbg(tps->dev, "%s regul i= %d START", __func__, i); + rdev = devm_regulator_register(&pdev->dev, ®ulators[i], + &config); + if (IS_ERR(rdev)) { + dev_err(tps->dev, "failed to register %s regulator\n", + pdev->name); + return PTR_ERR(rdev); + } + rdevtbl[i] = rdev; + dev_dbg(tps->dev, "%s regul i= %d COMPLETED", __func__, i); + } + + irq_data = devm_kmalloc(tps->dev, + ARRAY_SIZE(tps65219_regulator_irq_types) * + sizeof(struct tps65219_regulator_irq_data), + GFP_KERNEL); + if (!irq_data) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(tps65219_regulator_irq_types); ++i) { + irq_type = &tps65219_regulator_irq_types[i]; + + irq = platform_get_irq_byname(pdev, irq_type->irq_name); + if (irq < 0) + return -EINVAL; + + irq_data[i].dev = tps->dev; + irq_data[i].type = irq_type; + + tps65219_get_rdev_by_name(irq_type->regulator_name, rdevtbl, rdev); + if (rdev < 0) { + dev_err(tps->dev, "Failed to get rdev for %s\n", + irq_type->regulator_name); + return -EINVAL; + } + irq_data[i].rdev = rdev; + + error = devm_request_threaded_irq(tps->dev, irq, NULL, + tps65219_regulator_irq_handler, + IRQF_ONESHOT, + irq_type->irq_name, + &irq_data[i]); + if (error) { + dev_err(tps->dev, "failed to request %s IRQ %d: %d\n", + irq_type->irq_name, irq, error); + return error; + } + } + + return 0; +} + +static const struct platform_device_id tps65219_regulator_id_table[] = { + { "tps65219-regulator", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, tps65219_regulator_id_table); + +static struct platform_driver tps65219_regulator_driver = { + .driver = { + .name = "tps65219-pmic", + }, + .probe = tps65219_regulator_probe, + .id_table = tps65219_regulator_id_table, +}; + +module_platform_driver(tps65219_regulator_driver); + +MODULE_AUTHOR("Jerome Neanne <j-neanne@baylibre.com>"); +MODULE_DESCRIPTION("TPS65219 voltage regulator driver"); +MODULE_ALIAS("platform:tps65219-pmic"); +MODULE_LICENSE("GPL"); |