diff options
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/Kconfig | 23 | ||||
-rw-r--r-- | drivers/regulator/Makefile | 1 | ||||
-rw-r--r-- | drivers/regulator/adp5055-regulator.c | 424 | ||||
-rw-r--r-- | drivers/regulator/core.c | 2 | ||||
-rw-r--r-- | drivers/regulator/da9121-regulator.c | 2 | ||||
-rw-r--r-- | drivers/regulator/gpio-regulator.c | 10 | ||||
-rw-r--r-- | drivers/regulator/max20086-regulator.c | 4 | ||||
-rw-r--r-- | drivers/regulator/pca9450-regulator.c | 27 | ||||
-rw-r--r-- | drivers/regulator/pf9453-regulator.c | 3 | ||||
-rw-r--r-- | drivers/regulator/qcom_spmi-regulator.c | 69 | ||||
-rw-r--r-- | drivers/regulator/rpi-panel-attiny-regulator.c | 83 | ||||
-rw-r--r-- | drivers/regulator/s5m8767.c | 146 | ||||
-rw-r--r-- | drivers/regulator/tps65219-regulator.c | 242 |
13 files changed, 774 insertions, 262 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 05e32d764028..6d8988387da4 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -122,6 +122,17 @@ config REGULATOR_AD5398 This driver supports AD5398 and AD5821 current regulator chips. If building into module, its name is ad5398.ko. +config REGULATOR_ADP5055 + tristate "Analog Devices ADP5055 Triple Buck Regulator" + depends on I2C + select REGMAP_I2C + help + This driver controls an Analog Devices ADP5055 with triple buck + regulators using an I2C interface. + + Say M here if you want to include support for the regulator as a + module. + config REGULATOR_ANATOP tristate "Freescale i.MX on-chip ANATOP LDO regulators" depends on ARCH_MXC || COMPILE_TEST @@ -1579,10 +1590,16 @@ config REGULATOR_TPS65219 tristate "TI TPS65219 Power regulators" depends on MFD_TPS65219 && OF help - This driver supports TPS65219 voltage regulator chips. + This driver supports TPS65219, TPS65215, and TPS65214 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. + voltage regulators. + TPS65215 PMIC has 3 single phase BUCKs & 2 LDOs. + TPS65214 PMIC has 3 synchronous stepdown DC-DC converters & 2 + LDOs. One LDO supports a maximum output current of 300 mA and the + other a maximum of 500 mA + All 3 PMICs support software based voltage control for different + voltage domains. config REGULATOR_TPS6594 tristate "TI TPS6594 Power regulators" diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 524e026c0273..c0bc7a0f4e67 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_REGULATOR_AB8500) += ab8500-ext.o ab8500.o obj-$(CONFIG_REGULATOR_ACT8865) += act8865-regulator.o obj-$(CONFIG_REGULATOR_ACT8945A) += act8945a-regulator.o obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o +obj-$(CONFIG_REGULATOR_ADP5055) += adp5055-regulator.o obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o obj-$(CONFIG_REGULATOR_ARIZONA_LDO1) += arizona-ldo1.o obj-$(CONFIG_REGULATOR_ARIZONA_MICSUPP) += arizona-micsupp.o diff --git a/drivers/regulator/adp5055-regulator.c b/drivers/regulator/adp5055-regulator.c new file mode 100644 index 000000000000..4b004a6b2f84 --- /dev/null +++ b/drivers/regulator/adp5055-regulator.c @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Regulator driver for Analog Devices ADP5055 +// +// Copyright (C) 2025 Analog Devices, Inc. + +#include <linux/bitfield.h> +#include <linux/device.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> + +// ADP5055 Register Map. + +#define ADP5055_CTRL123 0xD1 +#define ADP5055_CTRL_MODE1 0xD3 +#define ADP5055_CTRL_MODE2 0xD4 +#define ADP5055_DLY0 0xD5 +#define ADP5055_DLY1 0xD6 +#define ADP5055_DLY2 0xD7 +#define ADP5055_VID0 0xD8 +#define ADP5055_VID1 0xD9 +#define ADP5055_VID2 0xDA +#define ADP5055_DVS_LIM0 0xDC +#define ADP5055_DVS_LIM1 0xDD +#define ADP5055_DVS_LIM2 0xDE +#define ADP5055_FT_CFG 0xDF +#define ADP5055_PG_CFG 0xE0 + +// ADP5055 Field Masks. + +#define ADP5055_MASK_EN_MODE BIT(0) +#define ADP5055_MASK_OCP_BLANKING BIT(7) +#define ADP5055_MASK_PSM BIT(4) +#define ADP5055_MASK_DIS2 BIT(2) +#define ADP5055_MASK_DIS1 BIT(1) +#define ADP5055_MASK_DIS0 BIT(0) +#define ADP5055_MASK_DIS_DLY GENMASK(6, 4) +#define ADP5055_MASK_EN_DLY GENMASK(2, 0) +#define ADP5055_MASK_DVS_LIM_UPPER GENMASK(7, 4) +#define ADP5055_MASK_DVS_LIM_LOWER GENMASK(3, 0) +#define ADP5055_MASK_FAST_TRANSIENT2 GENMASK(5, 4) +#define ADP5055_MASK_FAST_TRANSIENT1 GENMASK(3, 2) +#define ADP5055_MASK_FAST_TRANSIENT0 GENMASK(1, 0) +#define ADP5055_MASK_DLY_PWRGD BIT(4) +#define ADP5055_MASK_PWRGD2 BIT(2) +#define ADP5055_MASK_PWRGD1 BIT(1) +#define ADP5055_MASK_PWRGD0 BIT(0) + +#define ADP5055_MIN_VOUT 408000 +#define ADP5055_NUM_CH 3 + +struct adp5055 { + struct device *dev; + struct regmap *regmap; + u32 tset; + struct gpio_desc *en_gpiod[ADP5055_NUM_CH]; + bool en_mode_software; + int dvs_limit_upper[ADP5055_NUM_CH]; + int dvs_limit_lower[ADP5055_NUM_CH]; + u32 fast_transient[ADP5055_NUM_CH]; + bool mask_power_good[ADP5055_NUM_CH]; +}; + +static const unsigned int adp5055_tset_vals[] = { + 2600, + 20800, +}; + +static const unsigned int adp5055_enable_delay_vals_2_6[] = { + 0, + 2600, + 5200, + 7800, + 10400, + 13000, + 15600, + 18200, +}; + +static const unsigned int adp5055_enable_delay_vals_20_8[] = { + 0, + 20800, + 41600, + 62400, + 83200, + 104000, + 124800, + 145600, +}; + +static const char * const adp5055_fast_transient_vals[] = { + "none", + "3G_1.5%", + "5G_1.5%", + "5G_2.5%", +}; + +static int adp5055_get_prop_index(const u32 *table, size_t table_size, + u32 value) +{ + int i; + + for (i = 0; i < table_size; i++) + if (table[i] == value) + return i; + + return -EINVAL; +} + +static const struct regmap_range adp5055_reg_ranges[] = { + regmap_reg_range(0xD1, 0xE0), +}; + +static const struct regmap_access_table adp5055_access_ranges_table = { + .yes_ranges = adp5055_reg_ranges, + .n_yes_ranges = ARRAY_SIZE(adp5055_reg_ranges), +}; + +static const struct regmap_config adp5055_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xE0, + .wr_table = &adp5055_access_ranges_table, + .rd_table = &adp5055_access_ranges_table, +}; + +static const struct linear_range adp5055_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(ADP5055_MIN_VOUT, 0, 255, 1500), +}; + +static int adp5055_parse_fw(struct device *dev, struct adp5055 *adp5055) +{ + int i, ret; + struct regmap *regmap = adp5055->regmap; + int val; + bool ocp_blanking; + bool delay_power_good; + + ret = device_property_read_u32(dev, "adi,tset-us", &adp5055->tset); + if (!ret) { + ret = adp5055_get_prop_index(adp5055_tset_vals, + ARRAY_SIZE(adp5055_tset_vals), adp5055->tset); + if (ret < 0) + return dev_err_probe(dev, ret, + "Failed to initialize tset."); + adp5055->tset = adp5055_tset_vals[ret]; + } + + ocp_blanking = device_property_read_bool(dev, "adi,ocp-blanking"); + + delay_power_good = device_property_read_bool(dev, + "adi,delay-power-good"); + + for (i = 0; i < ADP5055_NUM_CH; i++) { + val = FIELD_PREP(ADP5055_MASK_DVS_LIM_UPPER, + DIV_ROUND_CLOSEST_ULL(192000 - adp5055->dvs_limit_upper[i], 12000)); + val |= FIELD_PREP(ADP5055_MASK_DVS_LIM_LOWER, + DIV_ROUND_CLOSEST_ULL(adp5055->dvs_limit_lower[i] + 190500, 12000)); + ret = regmap_write(regmap, ADP5055_DVS_LIM0 + i, val); + if (ret) + return ret; + } + + val = FIELD_PREP(ADP5055_MASK_EN_MODE, adp5055->en_mode_software); + ret = regmap_write(regmap, ADP5055_CTRL_MODE1, val); + if (ret) + return ret; + + val = FIELD_PREP(ADP5055_MASK_OCP_BLANKING, ocp_blanking); + ret = regmap_update_bits(regmap, ADP5055_CTRL_MODE2, + ADP5055_MASK_OCP_BLANKING, val); + if (ret) + return ret; + + val = FIELD_PREP(ADP5055_MASK_FAST_TRANSIENT2, adp5055->fast_transient[2]); + val |= FIELD_PREP(ADP5055_MASK_FAST_TRANSIENT1, adp5055->fast_transient[1]); + val |= FIELD_PREP(ADP5055_MASK_FAST_TRANSIENT0, adp5055->fast_transient[0]); + ret = regmap_write(regmap, ADP5055_FT_CFG, val); + if (ret) + return ret; + + val = FIELD_PREP(ADP5055_MASK_DLY_PWRGD, delay_power_good); + val |= FIELD_PREP(ADP5055_MASK_PWRGD2, adp5055->mask_power_good[2]); + val |= FIELD_PREP(ADP5055_MASK_PWRGD1, adp5055->mask_power_good[1]); + val |= FIELD_PREP(ADP5055_MASK_PWRGD0, adp5055->mask_power_good[0]); + ret = regmap_write(regmap, ADP5055_PG_CFG, val); + if (ret) + return ret; + + return 0; +} + +static int adp5055_of_parse_cb(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *config) +{ + struct adp5055 *adp5055 = config->driver_data; + int id, ret, pval, i; + + id = desc->id; + + if (of_property_read_bool(np, "enable-gpios")) { + adp5055->en_gpiod[id] = devm_fwnode_gpiod_get(config->dev, + of_fwnode_handle(np), "enable", + GPIOD_OUT_LOW, "enable"); + if (IS_ERR(adp5055->en_gpiod[id])) + return dev_err_probe(config->dev, PTR_ERR(adp5055->en_gpiod[id]), + "Failed to get enable GPIO\n"); + + config->ena_gpiod = adp5055->en_gpiod[id]; + } else { + adp5055->en_mode_software = true; + } + + ret = of_property_read_u32(np, "adi,dvs-limit-upper-microvolt", &pval); + if (ret) + adp5055->dvs_limit_upper[id] = 192000; + else + adp5055->dvs_limit_upper[id] = pval; + + if (adp5055->dvs_limit_upper[id] > 192000 || adp5055->dvs_limit_upper[id] < 12000) + return dev_err_probe(config->dev, adp5055->dvs_limit_upper[id], + "Out of range - dvs-limit-upper-microvolt value."); + + ret = of_property_read_u32(np, "adi,dvs-limit-lower-microvolt", &pval); + if (ret) + adp5055->dvs_limit_lower[id] = -190500; + else + adp5055->dvs_limit_lower[id] = pval; + + if (adp5055->dvs_limit_lower[id] > -10500 || adp5055->dvs_limit_lower[id] < -190500) + return dev_err_probe(config->dev, adp5055->dvs_limit_lower[id], + "Out of range - dvs-limit-lower-microvolt value."); + + for (i = 0; i < 4; i++) { + ret = of_property_match_string(np, "adi,fast-transient", + adp5055_fast_transient_vals[i]); + if (!ret) + break; + } + + if (ret < 0) + adp5055->fast_transient[id] = 3; + else + adp5055->fast_transient[id] = i; + + adp5055->mask_power_good[id] = of_property_read_bool(np, "adi,mask-power-good"); + + return 0; +} + +static int adp5055_set_mode(struct regulator_dev *rdev, u32 mode) +{ + struct adp5055 *adp5055 = rdev_get_drvdata(rdev); + int id, ret; + + id = rdev_get_id(rdev); + + switch (mode) { + case REGULATOR_MODE_NORMAL: + ret = regmap_update_bits(adp5055->regmap, ADP5055_CTRL_MODE2, + ADP5055_MASK_PSM << id, 0); + break; + case REGULATOR_MODE_IDLE: + ret = regmap_update_bits(adp5055->regmap, ADP5055_CTRL_MODE2, + ADP5055_MASK_PSM << id, ADP5055_MASK_PSM << id); + break; + default: + return dev_err_probe(&rdev->dev, -EINVAL, + "Unsupported mode: %d\n", mode); + } + + return ret; +} + +static unsigned int adp5055_get_mode(struct regulator_dev *rdev) +{ + struct adp5055 *adp5055 = rdev_get_drvdata(rdev); + int id, ret, regval; + + id = rdev_get_id(rdev); + + ret = regmap_read(adp5055->regmap, ADP5055_CTRL_MODE2, ®val); + if (ret) + return ret; + + if (regval & (ADP5055_MASK_PSM << id)) + return REGULATOR_MODE_IDLE; + else + return REGULATOR_MODE_NORMAL; +} + +static const struct regulator_ops adp5055_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_active_discharge = regulator_set_active_discharge_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_mode = adp5055_set_mode, + .get_mode = adp5055_get_mode, + .set_ramp_delay = regulator_set_ramp_delay_regmap, +}; + +#define ADP5055_REG_(_name, _id, _ch, _ops) \ + [_id] = { \ + .name = _name, \ + .of_match = of_match_ptr(_name), \ + .of_parse_cb = adp5055_of_parse_cb, \ + .id = _id, \ + .ops = _ops, \ + .linear_ranges = adp5055_voltage_ranges, \ + .n_linear_ranges = ARRAY_SIZE(adp5055_voltage_ranges), \ + .vsel_reg = ADP5055_VID##_ch, \ + .vsel_mask = GENMASK(7, 0), \ + .enable_reg = ADP5055_CTRL123, \ + .enable_mask = BIT(_ch), \ + .active_discharge_on = ADP5055_MASK_DIS##_id, \ + .active_discharge_off = 0, \ + .active_discharge_mask = ADP5055_MASK_DIS##_id, \ + .active_discharge_reg = ADP5055_CTRL_MODE2, \ + .ramp_reg = ADP5055_DLY##_ch, \ + .ramp_mask = ADP5055_MASK_EN_DLY, \ + .n_ramp_values = ARRAY_SIZE(adp5055_enable_delay_vals_2_6), \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + } + +#define ADP5055_REG(_name, _id, _ch) \ + ADP5055_REG_(_name, _id, _ch, &adp5055_ops) + +static struct regulator_desc adp5055_regulators[] = { + ADP5055_REG("buck0", 0, 0), + ADP5055_REG("buck1", 1, 1), + ADP5055_REG("buck2", 2, 2), +}; + +static int adp5055_probe(struct i2c_client *client) +{ + struct regulator_init_data *init_data; + struct device *dev = &client->dev; + struct adp5055 *adp5055; + int i, ret; + + init_data = of_get_regulator_init_data(dev, client->dev.of_node, + &adp5055_regulators[0]); + if (!init_data) + return -EINVAL; + + adp5055 = devm_kzalloc(dev, sizeof(struct adp5055), GFP_KERNEL); + if (!adp5055) + return -ENOMEM; + + adp5055->tset = 2600; + adp5055->en_mode_software = false; + + adp5055->regmap = devm_regmap_init_i2c(client, &adp5055_regmap_config); + if (IS_ERR(adp5055->regmap)) + return dev_err_probe(dev, PTR_ERR(adp5055->regmap), "Failed to allocate reg map"); + + for (i = 0; i < ADP5055_NUM_CH; i++) { + const struct regulator_desc *desc; + struct regulator_config config = { }; + struct regulator_dev *rdev; + + if (adp5055->tset == 2600) + adp5055_regulators[i].ramp_delay_table = adp5055_enable_delay_vals_2_6; + else + adp5055_regulators[i].ramp_delay_table = adp5055_enable_delay_vals_20_8; + + desc = &adp5055_regulators[i]; + + config.dev = dev; + config.driver_data = adp5055; + config.regmap = adp5055->regmap; + config.init_data = init_data; + + rdev = devm_regulator_register(dev, desc, &config); + if (IS_ERR(rdev)) { + return dev_err_probe(dev, PTR_ERR(rdev), + "Failed to register %s\n", desc->name); + } + } + + ret = adp5055_parse_fw(dev, adp5055); + if (ret < 0) + return ret; + + return 0; +} + +static const struct of_device_id adp5055_of_match[] = { + { .compatible = "adi,adp5055", }, + { } +}; +MODULE_DEVICE_TABLE(of, adp5055_of_match); + +static const struct i2c_device_id adp5055_ids[] = { + { .name = "adp5055"}, + { }, +}; +MODULE_DEVICE_TABLE(i2c, adp5055_ids); + +static struct i2c_driver adp5055_driver = { + .driver = { + .name = "adp5055", + .of_match_table = adp5055_of_match, + }, + .probe = adp5055_probe, + .id_table = adp5055_ids, +}; +module_i2c_driver(adp5055_driver); + +MODULE_DESCRIPTION("ADP5055 Voltage Regulator Driver"); +MODULE_AUTHOR("Alexis Czezar Torreno <alexisczezar.torreno@analog.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 90629a756693..7a248dc8d2e2 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2617,7 +2617,7 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev, mutex_lock(®ulator_list_mutex); list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { - if (pin->gpiod == gpiod) { + if (gpiod_is_equal(pin->gpiod, gpiod)) { rdev_dbg(rdev, "GPIO is already used\n"); goto update_ena_gpio_to_rdev; } diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c index 17527a3f53b4..ef161eb0ca27 100644 --- a/drivers/regulator/da9121-regulator.c +++ b/drivers/regulator/da9121-regulator.c @@ -1129,7 +1129,7 @@ static int da9121_i2c_probe(struct i2c_client *i2c) } chip->pdata = i2c->dev.platform_data; - chip->subvariant_id = (enum da9121_subvariant)i2c_get_match_data(i2c); + chip->subvariant_id = (kernel_ulong_t)i2c_get_match_data(i2c); ret = da9121_assign_chip_model(i2c, chip); if (ret < 0) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 65927fa2ef16..75bd53445ba7 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -240,7 +240,7 @@ static int gpio_regulator_probe(struct platform_device *pdev) struct regulator_config cfg = { }; struct regulator_dev *rdev; enum gpiod_flags gflags; - int ptr, ret, state, i; + int ptr, state, i; drvdata = devm_kzalloc(dev, sizeof(struct gpio_regulator_data), GFP_KERNEL); @@ -345,11 +345,9 @@ static int gpio_regulator_probe(struct platform_device *pdev) return PTR_ERR(cfg.ena_gpiod); rdev = devm_regulator_register(dev, &drvdata->desc, &cfg); - if (IS_ERR(rdev)) { - ret = PTR_ERR(rdev); - dev_err(dev, "Failed to register regulator: %d\n", ret); - return ret; - } + if (IS_ERR(rdev)) + return dev_err_probe(dev, PTR_ERR(rdev), + "Failed to register regulator\n"); platform_set_drvdata(pdev, drvdata); diff --git a/drivers/regulator/max20086-regulator.c b/drivers/regulator/max20086-regulator.c index 198d45f8e884..b4fe76e33ff2 100644 --- a/drivers/regulator/max20086-regulator.c +++ b/drivers/regulator/max20086-regulator.c @@ -28,7 +28,7 @@ #define MAX20086_REG_ADC4 0x09 /* DEVICE IDs */ -#define MAX20086_DEVICE_ID_MAX20086 0x40 +#define MAX20086_DEVICE_ID_MAX20086 0x30 #define MAX20086_DEVICE_ID_MAX20087 0x20 #define MAX20086_DEVICE_ID_MAX20088 0x10 #define MAX20086_DEVICE_ID_MAX20089 0x00 @@ -264,7 +264,7 @@ static int max20086_i2c_probe(struct i2c_client *i2c) * shutdown. */ flags = boot_on ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; - chip->ena_gpiod = devm_gpiod_get(chip->dev, "enable", flags); + chip->ena_gpiod = devm_gpiod_get_optional(chip->dev, "enable", flags); if (IS_ERR(chip->ena_gpiod)) { ret = PTR_ERR(chip->ena_gpiod); dev_err(chip->dev, "Failed to get enable GPIO: %d\n", ret); diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c index a56f3ab754fa..14d19a6d6655 100644 --- a/drivers/regulator/pca9450-regulator.c +++ b/drivers/regulator/pca9450-regulator.c @@ -9,6 +9,7 @@ #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/kernel.h> +#include <linux/reboot.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> @@ -33,6 +34,7 @@ struct pca9450 { struct device *dev; struct regmap *regmap; struct gpio_desc *sd_vsel_gpio; + struct notifier_block restart_nb; enum pca9450_chip_type type; unsigned int rcnt; int irq; @@ -965,6 +967,25 @@ static irqreturn_t pca9450_irq_handler(int irq, void *data) return IRQ_HANDLED; } +static int pca9450_i2c_restart_handler(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct pca9450 *pca9450 = container_of(nb, struct pca9450, restart_nb); + struct i2c_client *i2c = container_of(pca9450->dev, struct i2c_client, dev); + + dev_dbg(&i2c->dev, "Restarting device..\n"); + if (i2c_smbus_write_byte_data(i2c, PCA9450_REG_SWRST, SW_RST_COMMAND) == 0) { + /* tRESTART is 250ms, so 300 should be enough to make sure it happened */ + mdelay(300); + /* When we get here, the PMIC didn't power cycle for some reason. so warn.*/ + dev_warn(&i2c->dev, "Device didn't respond to restart command\n"); + } else { + dev_err(&i2c->dev, "Restart command failed\n"); + } + + return 0; +} + static int pca9450_i2c_probe(struct i2c_client *i2c) { enum pca9450_chip_type type = (unsigned int)(uintptr_t) @@ -1107,6 +1128,12 @@ static int pca9450_i2c_probe(struct i2c_client *i2c) pca9450->sd_vsel_fixed_low = of_property_read_bool(ldo5->dev.of_node, "nxp,sd-vsel-fixed-low"); + pca9450->restart_nb.notifier_call = pca9450_i2c_restart_handler; + pca9450->restart_nb.priority = PCA9450_RESTART_HANDLER_PRIORITY; + + if (register_restart_handler(&pca9450->restart_nb)) + dev_warn(&i2c->dev, "Failed to register restart handler\n"); + dev_info(&i2c->dev, "%s probed.\n", type == PCA9450_TYPE_PCA9450A ? "pca9450a" : (type == PCA9450_TYPE_PCA9451A ? "pca9451a" : "pca9450bc")); diff --git a/drivers/regulator/pf9453-regulator.c b/drivers/regulator/pf9453-regulator.c index ed6bf0f6c4fe..be627f49b617 100644 --- a/drivers/regulator/pf9453-regulator.c +++ b/drivers/regulator/pf9453-regulator.c @@ -214,7 +214,7 @@ static const struct regmap_config pf9453_regmap_config = { .val_bits = 8, .volatile_table = &pf9453_volatile_regs, .max_register = PF9453_MAX_REG - 1, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; /* @@ -412,6 +412,7 @@ static int find_closest_bigger(unsigned int target, const unsigned int *table, * pf9453_regulator_set_ramp_delay_regmap * * @rdev: regulator to operate on + * @ramp_delay: desired ramp delay value in microseconds * * Regulators that use regmap for their register I/O can set the ramp_reg * and ramp_mask fields in their descriptor and then use this as their diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index d66a0f61637e..c1a41ce70b36 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -400,7 +400,7 @@ struct spmi_voltage_range { * so that range[i].set_point_max_uV < range[i+1].set_point_min_uV. */ struct spmi_voltage_set_points { - struct spmi_voltage_range *range; + const struct spmi_voltage_range *range; int count; unsigned n_voltages; }; @@ -474,6 +474,9 @@ struct spmi_regulator_data { .set_point_max_uV = _set_point_max_uV, \ .step_uV = _step_uV, \ .range_sel = _range_sel, \ + .n_voltages = (_set_point_max_uV != 0) ? \ + ((_set_point_max_uV - _set_point_min_uV) / _step_uV) + 1 : \ + 0, \ } #define DEFINE_SPMI_SET_POINTS(name) \ @@ -489,110 +492,110 @@ struct spmi_voltage_set_points name##_set_points = { \ * increasing and unique. The set_voltage callback functions expect these * properties to hold. */ -static struct spmi_voltage_range pldo_ranges[] = { +static const struct spmi_voltage_range pldo_ranges[] = { SPMI_VOLTAGE_RANGE(2, 750000, 750000, 1537500, 1537500, 12500), SPMI_VOLTAGE_RANGE(3, 1500000, 1550000, 3075000, 3075000, 25000), SPMI_VOLTAGE_RANGE(4, 1750000, 3100000, 4900000, 4900000, 50000), }; -static struct spmi_voltage_range nldo1_ranges[] = { +static const struct spmi_voltage_range nldo1_ranges[] = { SPMI_VOLTAGE_RANGE(2, 750000, 750000, 1537500, 1537500, 12500), }; -static struct spmi_voltage_range nldo2_ranges[] = { +static const struct spmi_voltage_range nldo2_ranges[] = { SPMI_VOLTAGE_RANGE(0, 375000, 0, 0, 1537500, 12500), SPMI_VOLTAGE_RANGE(1, 375000, 375000, 768750, 768750, 6250), SPMI_VOLTAGE_RANGE(2, 750000, 775000, 1537500, 1537500, 12500), }; -static struct spmi_voltage_range nldo3_ranges[] = { +static const struct spmi_voltage_range nldo3_ranges[] = { SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1537500, 1537500, 12500), SPMI_VOLTAGE_RANGE(1, 375000, 0, 0, 1537500, 12500), SPMI_VOLTAGE_RANGE(2, 750000, 0, 0, 1537500, 12500), }; -static struct spmi_voltage_range ln_ldo_ranges[] = { +static const struct spmi_voltage_range ln_ldo_ranges[] = { SPMI_VOLTAGE_RANGE(1, 690000, 690000, 1110000, 1110000, 60000), SPMI_VOLTAGE_RANGE(0, 1380000, 1380000, 2220000, 2220000, 120000), }; -static struct spmi_voltage_range smps_ranges[] = { +static const struct spmi_voltage_range smps_ranges[] = { SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1562500, 1562500, 12500), SPMI_VOLTAGE_RANGE(1, 1550000, 1575000, 3125000, 3125000, 25000), }; -static struct spmi_voltage_range ftsmps_ranges[] = { +static const struct spmi_voltage_range ftsmps_ranges[] = { SPMI_VOLTAGE_RANGE(0, 0, 350000, 1275000, 1275000, 5000), SPMI_VOLTAGE_RANGE(1, 0, 1280000, 2040000, 2040000, 10000), }; -static struct spmi_voltage_range ftsmps2p5_ranges[] = { +static const struct spmi_voltage_range ftsmps2p5_ranges[] = { SPMI_VOLTAGE_RANGE(0, 80000, 350000, 1355000, 1355000, 5000), SPMI_VOLTAGE_RANGE(1, 160000, 1360000, 2200000, 2200000, 10000), }; -static struct spmi_voltage_range ftsmps426_ranges[] = { +static const struct spmi_voltage_range ftsmps426_ranges[] = { SPMI_VOLTAGE_RANGE(0, 0, 320000, 1352000, 1352000, 4000), }; -static struct spmi_voltage_range boost_ranges[] = { +static const struct spmi_voltage_range boost_ranges[] = { SPMI_VOLTAGE_RANGE(0, 4000000, 4000000, 5550000, 5550000, 50000), }; -static struct spmi_voltage_range boost_byp_ranges[] = { +static const struct spmi_voltage_range boost_byp_ranges[] = { SPMI_VOLTAGE_RANGE(0, 2500000, 2500000, 5200000, 5650000, 50000), }; -static struct spmi_voltage_range ult_lo_smps_ranges[] = { +static const struct spmi_voltage_range ult_lo_smps_ranges[] = { SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1562500, 1562500, 12500), SPMI_VOLTAGE_RANGE(1, 750000, 0, 0, 1525000, 25000), }; -static struct spmi_voltage_range ult_ho_smps_ranges[] = { +static const struct spmi_voltage_range ult_ho_smps_ranges[] = { SPMI_VOLTAGE_RANGE(0, 1550000, 1550000, 2325000, 2325000, 25000), }; -static struct spmi_voltage_range ult_nldo_ranges[] = { +static const struct spmi_voltage_range ult_nldo_ranges[] = { SPMI_VOLTAGE_RANGE(0, 375000, 375000, 1537500, 1537500, 12500), }; -static struct spmi_voltage_range ult_pldo_ranges[] = { +static const struct spmi_voltage_range ult_pldo_ranges[] = { SPMI_VOLTAGE_RANGE(0, 1750000, 1750000, 3337500, 3337500, 12500), }; -static struct spmi_voltage_range pldo660_ranges[] = { +static const struct spmi_voltage_range pldo660_ranges[] = { SPMI_VOLTAGE_RANGE(0, 1504000, 1504000, 3544000, 3544000, 8000), }; -static struct spmi_voltage_range nldo660_ranges[] = { +static const struct spmi_voltage_range nldo660_ranges[] = { SPMI_VOLTAGE_RANGE(0, 320000, 320000, 1304000, 1304000, 8000), }; -static struct spmi_voltage_range ht_lvpldo_ranges[] = { +static const struct spmi_voltage_range ht_lvpldo_ranges[] = { SPMI_VOLTAGE_RANGE(0, 1504000, 1504000, 2000000, 2000000, 8000), }; -static struct spmi_voltage_range ht_nldo_ranges[] = { +static const struct spmi_voltage_range ht_nldo_ranges[] = { SPMI_VOLTAGE_RANGE(0, 312000, 312000, 1304000, 1304000, 8000), }; -static struct spmi_voltage_range hfs430_ranges[] = { +static const struct spmi_voltage_range hfs430_ranges[] = { SPMI_VOLTAGE_RANGE(0, 320000, 320000, 2040000, 2040000, 8000), }; -static struct spmi_voltage_range ht_p150_ranges[] = { +static const struct spmi_voltage_range ht_p150_ranges[] = { SPMI_VOLTAGE_RANGE(0, 1616000, 1616000, 3304000, 3304000, 8000), }; -static struct spmi_voltage_range ht_p600_ranges[] = { +static const struct spmi_voltage_range ht_p600_ranges[] = { SPMI_VOLTAGE_RANGE(0, 1704000, 1704000, 1896000, 1896000, 8000), }; -static struct spmi_voltage_range nldo_510_ranges[] = { +static const struct spmi_voltage_range nldo_510_ranges[] = { SPMI_VOLTAGE_RANGE(0, 320000, 320000, 1304000, 1304000, 8000), }; -static struct spmi_voltage_range ftsmps510_ranges[] = { +static const struct spmi_voltage_range ftsmps510_ranges[] = { SPMI_VOLTAGE_RANGE(0, 300000, 300000, 1372000, 1372000, 4000), }; @@ -1676,18 +1679,10 @@ static const struct spmi_regulator_mapping supported_regulators[] = { static void spmi_calculate_num_voltages(struct spmi_voltage_set_points *points) { - unsigned int n; - struct spmi_voltage_range *range = points->range; - - for (; range < points->range + points->count; range++) { - n = 0; - if (range->set_point_max_uV) { - n = range->set_point_max_uV - range->set_point_min_uV; - n = (n / range->step_uV) + 1; - } - range->n_voltages = n; - points->n_voltages += n; - } + const struct spmi_voltage_range *range = points->range; + + for (; range < points->range + points->count; range++) + points->n_voltages += range->n_voltages; } static int spmi_regulator_match(struct spmi_regulator *vreg, u16 force_type) diff --git a/drivers/regulator/rpi-panel-attiny-regulator.c b/drivers/regulator/rpi-panel-attiny-regulator.c index 6c3b6bfac961..58dbf8bffa5d 100644 --- a/drivers/regulator/rpi-panel-attiny-regulator.c +++ b/drivers/regulator/rpi-panel-attiny-regulator.c @@ -6,12 +6,14 @@ */ #include <linux/backlight.h> +#include <linux/cleanup.h> #include <linux/err.h> #include <linux/gpio/driver.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> @@ -93,7 +95,7 @@ static int attiny_lcd_power_enable(struct regulator_dev *rdev) { struct attiny_lcd *state = rdev_get_drvdata(rdev); - mutex_lock(&state->lock); + guard(mutex)(&state->lock); /* Ensure bridge, and tp stay in reset */ attiny_set_port_state(state, REG_PORTC, 0); @@ -114,8 +116,6 @@ static int attiny_lcd_power_enable(struct regulator_dev *rdev) msleep(80); - mutex_unlock(&state->lock); - return 0; } @@ -123,7 +123,7 @@ static int attiny_lcd_power_disable(struct regulator_dev *rdev) { struct attiny_lcd *state = rdev_get_drvdata(rdev); - mutex_lock(&state->lock); + guard(mutex)(&state->lock); regmap_write(rdev->regmap, REG_PWM, 0); usleep_range(5000, 10000); @@ -135,8 +135,6 @@ static int attiny_lcd_power_disable(struct regulator_dev *rdev) attiny_set_port_state(state, REG_PORTC, 0); msleep(30); - mutex_unlock(&state->lock); - return 0; } @@ -144,19 +142,17 @@ static int attiny_lcd_power_is_enabled(struct regulator_dev *rdev) { struct attiny_lcd *state = rdev_get_drvdata(rdev); unsigned int data; - int ret, i; - - mutex_lock(&state->lock); - - for (i = 0; i < 10; i++) { - ret = regmap_read(rdev->regmap, REG_PORTC, &data); - if (!ret) - break; - usleep_range(10000, 12000); + int ret = 0, i; + + scoped_guard(mutex, &state->lock) { + for (i = 0; i < 10; i++) { + ret = regmap_read(rdev->regmap, REG_PORTC, &data); + if (!ret) + break; + usleep_range(10000, 12000); + } } - mutex_unlock(&state->lock); - if (ret < 0) return ret; @@ -189,7 +185,7 @@ static int attiny_update_status(struct backlight_device *bl) int brightness = backlight_get_brightness(bl); int ret, i; - mutex_lock(&state->lock); + guard(mutex)(&state->lock); for (i = 0; i < 10; i++) { ret = regmap_write(regmap, REG_PWM, brightness); @@ -197,8 +193,6 @@ static int attiny_update_status(struct backlight_device *bl) break; } - mutex_unlock(&state->lock); - return ret; } @@ -211,15 +205,12 @@ static int attiny_gpio_get_direction(struct gpio_chip *gc, unsigned int off) return GPIO_LINE_DIRECTION_OUT; } -static void attiny_gpio_set(struct gpio_chip *gc, unsigned int off, int val) +static int attiny_gpio_set(struct gpio_chip *gc, unsigned int off, int val) { struct attiny_lcd *state = gpiochip_get_data(gc); u8 last_val; - if (off >= NUM_GPIO) - return; - - mutex_lock(&state->lock); + guard(mutex)(&state->lock); last_val = attiny_get_port_state(state, mappings[off].reg); if (val) @@ -242,7 +233,7 @@ static void attiny_gpio_set(struct gpio_chip *gc, unsigned int off, int val) msleep(100); } - mutex_unlock(&state->lock); + return 0; } static int attiny_i2c_read(struct i2c_client *client, u8 reg, unsigned int *buf) @@ -296,7 +287,10 @@ static int attiny_i2c_probe(struct i2c_client *i2c) if (!state) return -ENOMEM; - mutex_init(&state->lock); + ret = devm_mutex_init(&i2c->dev, &state->lock); + if (ret) + return ret; + i2c_set_clientdata(i2c, state); regmap = devm_regmap_init_i2c(i2c, &attiny_regmap_config); @@ -304,13 +298,13 @@ static int attiny_i2c_probe(struct i2c_client *i2c) ret = PTR_ERR(regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", ret); - goto error; + return ret; } ret = attiny_i2c_read(i2c, REG_ID, &data); if (ret < 0) { dev_err(&i2c->dev, "Failed to read REG_ID reg: %d\n", ret); - goto error; + return ret; } switch (data) { @@ -319,8 +313,7 @@ static int attiny_i2c_probe(struct i2c_client *i2c) break; default: dev_err(&i2c->dev, "Unknown Atmel firmware revision: 0x%02x\n", data); - ret = -ENODEV; - goto error; + return -ENODEV; } regmap_write(regmap, REG_POWERON, 0); @@ -336,8 +329,7 @@ static int attiny_i2c_probe(struct i2c_client *i2c) rdev = devm_regulator_register(&i2c->dev, &attiny_regulator, &config); if (IS_ERR(rdev)) { dev_err(&i2c->dev, "Failed to register ATTINY regulator\n"); - ret = PTR_ERR(rdev); - goto error; + return PTR_ERR(rdev); } props.type = BACKLIGHT_RAW; @@ -348,10 +340,8 @@ static int attiny_i2c_probe(struct i2c_client *i2c) bl = devm_backlight_device_register(&i2c->dev, dev_name(&i2c->dev), &i2c->dev, state, &attiny_bl, &props); - if (IS_ERR(bl)) { - ret = PTR_ERR(bl); - goto error; - } + if (IS_ERR(bl)) + return PTR_ERR(bl); bl->props.brightness = 0xff; @@ -361,31 +351,17 @@ static int attiny_i2c_probe(struct i2c_client *i2c) state->gc.base = -1; state->gc.ngpio = NUM_GPIO; - state->gc.set = attiny_gpio_set; + state->gc.set_rv = attiny_gpio_set; state->gc.get_direction = attiny_gpio_get_direction; state->gc.can_sleep = true; ret = devm_gpiochip_add_data(&i2c->dev, &state->gc, state); - if (ret) { + if (ret) dev_err(&i2c->dev, "Failed to create gpiochip: %d\n", ret); - goto error; - } - - return 0; - -error: - mutex_destroy(&state->lock); return ret; } -static void attiny_i2c_remove(struct i2c_client *client) -{ - struct attiny_lcd *state = i2c_get_clientdata(client); - - mutex_destroy(&state->lock); -} - static const struct of_device_id attiny_dt_ids[] = { { .compatible = "raspberrypi,7inch-touchscreen-panel-regulator" }, {}, @@ -399,7 +375,6 @@ static struct i2c_driver attiny_regulator_driver = { .of_match_table = attiny_dt_ids, }, .probe = attiny_i2c_probe, - .remove = attiny_i2c_remove, }; module_i2c_driver(attiny_regulator_driver); diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index d25cd81e3f36..fe2631378ccd 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -5,7 +5,7 @@ #include <linux/cleanup.h> #include <linux/err.h> -#include <linux/of_gpio.h> +#include <linux/of.h> #include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -35,8 +35,8 @@ struct s5m8767_info { u8 buck2_vol[8]; u8 buck3_vol[8]; u8 buck4_vol[8]; - int buck_gpios[3]; - int buck_ds[3]; + struct gpio_desc *buck_gpios[3]; + struct gpio_desc *buck_ds[3]; int buck_gpioindex; }; @@ -272,9 +272,9 @@ static inline int s5m8767_set_high(struct s5m8767_info *s5m8767) { int temp_index = s5m8767->buck_gpioindex; - gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1); - gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1); - gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1); + gpiod_set_value(s5m8767->buck_gpios[0], !!(temp_index & BIT(2))); + gpiod_set_value(s5m8767->buck_gpios[1], !!(temp_index & BIT(1))); + gpiod_set_value(s5m8767->buck_gpios[2], !!(temp_index & BIT(0))); return 0; } @@ -283,9 +283,9 @@ static inline int s5m8767_set_low(struct s5m8767_info *s5m8767) { int temp_index = s5m8767->buck_gpioindex; - gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1); - gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1); - gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1); + gpiod_set_value(s5m8767->buck_gpios[2], !!(temp_index & BIT(0))); + gpiod_set_value(s5m8767->buck_gpios[1], !!(temp_index & BIT(1))); + gpiod_set_value(s5m8767->buck_gpios[0], !!(temp_index & BIT(2))); return 0; } @@ -482,42 +482,6 @@ static int s5m8767_enable_ext_control(struct s5m8767_info *s5m8767, #ifdef CONFIG_OF -static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev, - struct sec_platform_data *pdata, - struct device_node *pmic_np) -{ - int i, gpio; - - for (i = 0; i < 3; i++) { - gpio = of_get_named_gpio(pmic_np, - "s5m8767,pmic-buck-dvs-gpios", i); - if (!gpio_is_valid(gpio)) { - dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio); - return -EINVAL; - } - pdata->buck_gpios[i] = gpio; - } - return 0; -} - -static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev, - struct sec_platform_data *pdata, - struct device_node *pmic_np) -{ - int i, gpio; - - for (i = 0; i < 3; i++) { - gpio = of_get_named_gpio(pmic_np, - "s5m8767,pmic-buck-ds-gpios", i); - if (!gpio_is_valid(gpio)) { - dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio); - return -EINVAL; - } - pdata->buck_ds[i] = gpio; - } - return 0; -} - static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, struct sec_platform_data *pdata) { @@ -525,7 +489,7 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, struct device_node *pmic_np, *reg_np; struct sec_regulator_data *rdata; struct sec_opmode_data *rmode; - unsigned int i, dvs_voltage_nr = 8, ret; + unsigned int i, dvs_voltage_nr = 8; pmic_np = iodev->dev->of_node; if (!pmic_np) { @@ -635,10 +599,6 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs || pdata->buck4_gpiodvs) { - ret = s5m8767_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np); - if (ret) - return -EINVAL; - if (of_property_read_u32(pmic_np, "s5m8767,pmic-buck-default-dvs-idx", &pdata->buck_default_idx)) { @@ -652,10 +612,6 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, } } - ret = s5m8767_pmic_dt_parse_ds_gpio(iodev, pdata, pmic_np); - if (ret) - return -EINVAL; - pdata->buck2_ramp_enable = of_property_read_bool(pmic_np, "s5m8767,pmic-buck2-ramp-enable"); pdata->buck3_ramp_enable = of_property_read_bool(pmic_np, "s5m8767,pmic-buck3-ramp-enable"); pdata->buck4_ramp_enable = of_property_read_bool(pmic_np, "s5m8767,pmic-buck4-ramp-enable"); @@ -684,6 +640,8 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) struct regulator_config config = { }; struct s5m8767_info *s5m8767; int i, ret, buck_init; + const char *gpiods_names[3] = { "S5M8767 DS2", "S5M8767 DS3", "S5M8767 DS4" }; + const char *gpiodvs_names[3] = { "S5M8767 SET1", "S5M8767 SET2", "S5M8767 SET3" }; if (!pdata) { dev_err(pdev->dev.parent, "Platform data not supplied\n"); @@ -731,12 +689,6 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) s5m8767->buck2_gpiodvs = pdata->buck2_gpiodvs; s5m8767->buck3_gpiodvs = pdata->buck3_gpiodvs; s5m8767->buck4_gpiodvs = pdata->buck4_gpiodvs; - s5m8767->buck_gpios[0] = pdata->buck_gpios[0]; - s5m8767->buck_gpios[1] = pdata->buck_gpios[1]; - s5m8767->buck_gpios[2] = pdata->buck_gpios[2]; - s5m8767->buck_ds[0] = pdata->buck_ds[0]; - s5m8767->buck_ds[1] = pdata->buck_ds[1]; - s5m8767->buck_ds[2] = pdata->buck_ds[2]; s5m8767->ramp_delay = pdata->buck_ramp_delay; s5m8767->buck2_ramp = pdata->buck2_ramp_enable; @@ -787,58 +739,36 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs || pdata->buck4_gpiodvs) { + for (i = 0; i < 3; i++) { + enum gpiod_flags flags; - if (!gpio_is_valid(pdata->buck_gpios[0]) || - !gpio_is_valid(pdata->buck_gpios[1]) || - !gpio_is_valid(pdata->buck_gpios[2])) { - dev_err(&pdev->dev, "GPIO NOT VALID\n"); - return -EINVAL; - } - - ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[0], - "S5M8767 SET1"); - if (ret) - return ret; - - ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[1], - "S5M8767 SET2"); - if (ret) - return ret; - - ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[2], - "S5M8767 SET3"); - if (ret) - return ret; + if (s5m8767->buck_gpioindex & BIT(2 - i)) + flags = GPIOD_OUT_HIGH; + else + flags = GPIOD_OUT_LOW; + + s5m8767->buck_gpios[i] = devm_gpiod_get_index(iodev->dev, + "s5m8767,pmic-buck-dvs", i, + flags); + if (IS_ERR(s5m8767->buck_gpios[i])) { + return dev_err_probe(iodev->dev, PTR_ERR(s5m8767->buck_gpios[i]), + "invalid gpio[%d]\n", i); + } - /* SET1 GPIO */ - gpio_direction_output(pdata->buck_gpios[0], - (s5m8767->buck_gpioindex >> 2) & 0x1); - /* SET2 GPIO */ - gpio_direction_output(pdata->buck_gpios[1], - (s5m8767->buck_gpioindex >> 1) & 0x1); - /* SET3 GPIO */ - gpio_direction_output(pdata->buck_gpios[2], - (s5m8767->buck_gpioindex >> 0) & 0x1); + gpiod_set_consumer_name(s5m8767->buck_gpios[i], gpiodvs_names[i]); + } } - ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[0], "S5M8767 DS2"); - if (ret) - return ret; - - ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[1], "S5M8767 DS3"); - if (ret) - return ret; - - ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[2], "S5M8767 DS4"); - if (ret) - return ret; - - /* DS2 GPIO */ - gpio_direction_output(pdata->buck_ds[0], 0x0); - /* DS3 GPIO */ - gpio_direction_output(pdata->buck_ds[1], 0x0); - /* DS4 GPIO */ - gpio_direction_output(pdata->buck_ds[2], 0x0); + for (i = 0; i < 3; i++) { + s5m8767->buck_ds[i] = devm_gpiod_get_index(iodev->dev, + "s5m8767,pmic-buck-ds", i, + GPIOD_OUT_LOW); + if (IS_ERR(s5m8767->buck_ds[i])) { + return dev_err_probe(iodev->dev, PTR_ERR(s5m8767->buck_ds[i]), + "can't get GPIO %d\n", i); + } + gpiod_set_consumer_name(s5m8767->buck_ds[i], gpiods_names[i]); + } regmap_update_bits(s5m8767->iodev->regmap_pmic, S5M8767_REG_BUCK2CTRL, 1 << 1, diff --git a/drivers/regulator/tps65219-regulator.c b/drivers/regulator/tps65219-regulator.c index aa65077f9d41..b16b300d7f45 100644 --- a/drivers/regulator/tps65219-regulator.c +++ b/drivers/regulator/tps65219-regulator.c @@ -1,10 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 // -// tps65219-regulator.c -// -// Regulator driver for TPS65219 PMIC +// TPS65214/TPS65215/TPS65219 PMIC Regulator Driver // // Copyright (C) 2022 BayLibre Incorporated - https://www.baylibre.com/ +// Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/ // // This implementation derived from tps65218 authored by // "J Keerthy <j-keerthy@ti.com>" @@ -30,6 +29,11 @@ struct tps65219_regulator_irq_type { unsigned long event; }; +static struct tps65219_regulator_irq_type tps65215_regulator_irq_types[] = { + { "SENSOR_3_WARM", "SENSOR3", "warm temperature", REGULATOR_EVENT_OVER_TEMP_WARN}, + { "SENSOR_3_HOT", "SENSOR3", "hot temperature", REGULATOR_EVENT_OVER_TEMP}, +}; + 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 }, @@ -37,6 +41,16 @@ static struct tps65219_regulator_irq_type tps65219_regulator_irq_types[] = { { "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 }, + { "LDO3_RV", "LDO3", "residual voltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, + { "LDO4_RV", "LDO4", "residual voltage", 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_3_HOT", "SENSOR3", "hot temperature", REGULATOR_EVENT_OVER_TEMP}, +}; + +/* All of TPS65214's irq types are the same as common_regulator_irq_types */ +static struct tps65219_regulator_irq_type common_regulator_irq_types[] = { { "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 }, @@ -60,8 +74,6 @@ static struct tps65219_regulator_irq_type tps65219_regulator_irq_types[] = { { "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", @@ -70,13 +82,9 @@ static struct tps65219_regulator_irq_type tps65219_regulator_irq_types[] = { 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 }, @@ -125,12 +133,28 @@ static const struct linear_range bucks_ranges[] = { REGULATOR_LINEAR_RANGE(3400000, 0x34, 0x3f, 0), }; -static const struct linear_range ldos_1_2_ranges[] = { +static const struct linear_range ldo_1_range[] = { REGULATOR_LINEAR_RANGE(600000, 0x0, 0x37, 50000), REGULATOR_LINEAR_RANGE(3400000, 0x38, 0x3f, 0), }; -static const struct linear_range ldos_3_4_ranges[] = { +static const struct linear_range tps65214_ldo_1_2_range[] = { + REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2, 0), + REGULATOR_LINEAR_RANGE(650000, 0x3, 0x37, 50000), + REGULATOR_LINEAR_RANGE(3300000, 0x38, 0x3F, 0), +}; + +static const struct linear_range tps65215_ldo_2_range[] = { + REGULATOR_LINEAR_RANGE(1200000, 0x0, 0xC, 50000), + REGULATOR_LINEAR_RANGE(3300000, 0x36, 0x3F, 0), +}; + +static const struct linear_range tps65219_ldo_2_range[] = { + REGULATOR_LINEAR_RANGE(600000, 0x0, 0x37, 50000), + REGULATOR_LINEAR_RANGE(3400000, 0x38, 0x3f, 0), +}; + +static const struct linear_range tps65219_ldos_3_4_range[] = { REGULATOR_LINEAR_RANGE(1200000, 0x0, 0xC, 0), REGULATOR_LINEAR_RANGE(1250000, 0xD, 0x35, 50000), REGULATOR_LINEAR_RANGE(3300000, 0x36, 0x3F, 0), @@ -174,7 +198,7 @@ static unsigned int tps65219_get_mode(struct regulator_dev *dev) } /* Operations permitted on BUCK1/2/3 */ -static const struct regulator_ops tps65219_bucks_ops = { +static const struct regulator_ops bucks_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -189,7 +213,7 @@ static const struct regulator_ops tps65219_bucks_ops = { }; /* Operations permitted on LDO1/2 */ -static const struct regulator_ops tps65219_ldos_1_2_ops = { +static const struct regulator_ops ldos_1_2_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -204,7 +228,7 @@ static const struct regulator_ops tps65219_ldos_1_2_ops = { }; /* Operations permitted on LDO3/4 */ -static const struct regulator_ops tps65219_ldos_3_4_ops = { +static const struct regulator_ops ldos_3_4_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -216,55 +240,98 @@ static const struct regulator_ops tps65219_ldos_3_4_ops = { .map_voltage = regulator_map_voltage_linear_range, }; -static const struct regulator_desc regulators[] = { +static const struct regulator_desc common_regs[] = { TPS65219_REGULATOR("BUCK1", "buck1", TPS65219_BUCK_1, - REGULATOR_VOLTAGE, tps65219_bucks_ops, 64, + REGULATOR_VOLTAGE, 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, + REGULATOR_VOLTAGE, 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, + REGULATOR_VOLTAGE, 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), +}; + +static const struct regulator_desc tps65214_regs[] = { + // TPS65214's LDO3 pin maps to TPS65219's LDO3 pin + TPS65219_REGULATOR("LDO1", "ldo1", TPS65214_LDO_1, + REGULATOR_VOLTAGE, ldos_3_4_ops, 64, + TPS65214_REG_LDO1_VOUT, + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, + TPS65219_REG_ENABLE_CTRL, + TPS65219_ENABLE_LDO3_EN_MASK, 0, 0, tps65214_ldo_1_2_range, + 3, 0, 0, NULL, 0, 0), + TPS65219_REGULATOR("LDO2", "ldo2", TPS65214_LDO_2, + REGULATOR_VOLTAGE, ldos_3_4_ops, 64, + TPS65214_REG_LDO2_VOUT, + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, + TPS65219_REG_ENABLE_CTRL, + TPS65219_ENABLE_LDO2_EN_MASK, 0, 0, tps65214_ldo_1_2_range, + 3, 0, 0, NULL, 0, 0), +}; + +static const struct regulator_desc tps65215_regs[] = { + /* + * TPS65215's LDO1 is the same as TPS65219's LDO1. LDO1 is + * configurable as load switch and bypass-mode. + * TPS65215's LDO2 is the same as TPS65219's LDO3 + */ TPS65219_REGULATOR("LDO1", "ldo1", TPS65219_LDO_1, - REGULATOR_VOLTAGE, tps65219_ldos_1_2_ops, 64, + REGULATOR_VOLTAGE, 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, + TPS65219_ENABLE_LDO1_EN_MASK, 0, 0, ldo_1_range, + 2, 0, 0, NULL, 0, TPS65219_LDOS_BYP_CONFIG_MASK), + TPS65219_REGULATOR("LDO2", "ldo2", TPS65215_LDO_2, + REGULATOR_VOLTAGE, ldos_3_4_ops, 64, + TPS65215_REG_LDO2_VOUT, + TPS65219_BUCKS_LDOS_VOUT_VSET_MASK, + TPS65219_REG_ENABLE_CTRL, + TPS65215_ENABLE_LDO2_EN_MASK, 0, 0, tps65215_ldo_2_range, + 2, 0, 0, NULL, 0, 0), +}; + +static const struct regulator_desc tps65219_regs[] = { + TPS65219_REGULATOR("LDO1", "ldo1", TPS65219_LDO_1, + REGULATOR_VOLTAGE, 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, ldo_1_range, 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, + REGULATOR_VOLTAGE, 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, + TPS65219_ENABLE_LDO2_EN_MASK, 0, 0, tps65219_ldo_2_range, 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, + REGULATOR_VOLTAGE, 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, + TPS65219_ENABLE_LDO3_EN_MASK, 0, 0, tps65219_ldos_3_4_range, 3, 0, 0, NULL, 0, 0), TPS65219_REGULATOR("LDO4", "ldo4", TPS65219_LDO_4, - REGULATOR_VOLTAGE, tps65219_ldos_3_4_ops, 64, + REGULATOR_VOLTAGE, 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, + TPS65219_ENABLE_LDO4_EN_MASK, 0, 0, tps65219_ldos_3_4_range, 3, 0, 0, NULL, 0, 0), }; @@ -287,64 +354,141 @@ static irqreturn_t tps65219_regulator_irq_handler(int irq, void *data) return IRQ_HANDLED; } +struct tps65219_chip_data { + size_t rdesc_size; + size_t common_rdesc_size; + size_t dev_irq_size; + size_t common_irq_size; + const struct regulator_desc *rdesc; + const struct regulator_desc *common_rdesc; + struct tps65219_regulator_irq_type *irq_types; + struct tps65219_regulator_irq_type *common_irq_types; +}; + +static struct tps65219_chip_data chip_info_table[] = { + [TPS65214] = { + .rdesc = tps65214_regs, + .rdesc_size = ARRAY_SIZE(tps65214_regs), + .common_rdesc = common_regs, + .common_rdesc_size = ARRAY_SIZE(common_regs), + .irq_types = NULL, + .dev_irq_size = 0, + .common_irq_types = common_regulator_irq_types, + .common_irq_size = ARRAY_SIZE(common_regulator_irq_types), + }, + [TPS65215] = { + .rdesc = tps65215_regs, + .rdesc_size = ARRAY_SIZE(tps65215_regs), + .common_rdesc = common_regs, + .common_rdesc_size = ARRAY_SIZE(common_regs), + .irq_types = tps65215_regulator_irq_types, + .dev_irq_size = ARRAY_SIZE(tps65215_regulator_irq_types), + .common_irq_types = common_regulator_irq_types, + .common_irq_size = ARRAY_SIZE(common_regulator_irq_types), + }, + [TPS65219] = { + .rdesc = tps65219_regs, + .rdesc_size = ARRAY_SIZE(tps65219_regs), + .common_rdesc = common_regs, + .common_rdesc_size = ARRAY_SIZE(common_regs), + .irq_types = tps65219_regulator_irq_types, + .dev_irq_size = ARRAY_SIZE(tps65219_regulator_irq_types), + .common_irq_types = common_regulator_irq_types, + .common_irq_size = ARRAY_SIZE(common_regulator_irq_types), + }, +}; + static int tps65219_regulator_probe(struct platform_device *pdev) { - struct tps65219 *tps = dev_get_drvdata(pdev->dev.parent); + struct tps65219_regulator_irq_data *irq_data; + struct tps65219_regulator_irq_type *irq_type; + struct tps65219_chip_data *pmic; 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; + int i; + + struct tps65219 *tps = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = { }; + enum pmic_id chip = platform_get_device_id(pdev)->driver_data; + + pmic = &chip_info_table[chip]; config.dev = tps->dev; config.driver_data = tps; config.regmap = tps->regmap; - for (i = 0; i < ARRAY_SIZE(regulators); i++) { - rdev = devm_regulator_register(&pdev->dev, ®ulators[i], + for (i = 0; i < pmic->common_rdesc_size; i++) { + rdev = devm_regulator_register(&pdev->dev, &pmic->common_rdesc[i], + &config); + if (IS_ERR(rdev)) + return dev_err_probe(tps->dev, PTR_ERR(rdev), + "Failed to register %s regulator\n", + pmic->common_rdesc[i].name); + } + + for (i = 0; i < pmic->rdesc_size; i++) { + rdev = devm_regulator_register(&pdev->dev, &pmic->rdesc[i], &config); if (IS_ERR(rdev)) return dev_err_probe(tps->dev, PTR_ERR(rdev), - "Failed to register %s regulator\n", - regulators[i].name); + "Failed to register %s regulator\n", + pmic->rdesc[i].name); } - irq_data = devm_kmalloc(tps->dev, - ARRAY_SIZE(tps65219_regulator_irq_types) * - sizeof(struct tps65219_regulator_irq_data), - GFP_KERNEL); + irq_data = devm_kmalloc(tps->dev, pmic->common_irq_size, 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]; - + for (i = 0; i < pmic->common_irq_size; ++i) { + irq_type = &pmic->common_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; + error = devm_request_threaded_irq(tps->dev, irq, NULL, + tps65219_regulator_irq_handler, + IRQF_ONESHOT, + irq_type->irq_name, + &irq_data[i]); + if (error) + return dev_err_probe(tps->dev, PTR_ERR(rdev), + "Failed to request %s IRQ %d: %d\n", + irq_type->irq_name, irq, error); + } + + irq_data = devm_kmalloc(tps->dev, pmic->dev_irq_size, GFP_KERNEL); + if (!irq_data) + return -ENOMEM; + for (i = 0; i < pmic->dev_irq_size; ++i) { + irq_type = &pmic->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; 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; - } + if (error) + return dev_err_probe(tps->dev, PTR_ERR(rdev), + "Failed to request %s IRQ %d: %d\n", + irq_type->irq_name, irq, error); } return 0; } static const struct platform_device_id tps65219_regulator_id_table[] = { - { "tps65219-regulator", }, + { "tps65214-regulator", TPS65214 }, + { "tps65215-regulator", TPS65215 }, + { "tps65219-regulator", TPS65219 }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(platform, tps65219_regulator_id_table); @@ -361,5 +505,5 @@ static struct platform_driver tps65219_regulator_driver = { module_platform_driver(tps65219_regulator_driver); MODULE_AUTHOR("Jerome Neanne <j-neanne@baylibre.com>"); -MODULE_DESCRIPTION("TPS65219 voltage regulator driver"); +MODULE_DESCRIPTION("TPS65214/TPS65215/TPS65219 Regulator driver"); MODULE_LICENSE("GPL"); |