From 68ce3a4461726ebd3acf9d94841a46386402a058 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 4 May 2019 11:33:36 +0800 Subject: regulator: core: Slightly improve readability of _regulator_get_enable_time The logic is equivalent, but it looks more straightforward this way: If rdev->desc->ops->enable_time is set, call it. Otherwise fallback to return rdev->desc->enable_time. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 955a0a15b9cb..bf4cdbcf0653 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1650,9 +1650,9 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev) { if (rdev->constraints && rdev->constraints->enable_time) return rdev->constraints->enable_time; - if (!rdev->desc->ops->enable_time) - return rdev->desc->enable_time; - return rdev->desc->ops->enable_time(rdev); + if (rdev->desc->ops->enable_time) + return rdev->desc->ops->enable_time(rdev); + return rdev->desc->enable_time; } static struct regulator_supply_alias *regulator_find_supply_alias( -- cgit v1.2.3 From 3df4235ac41c2b8c3c5cd9c7798bc4a3105c0bc4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 25 Mar 2019 21:55:57 +0800 Subject: regulator: max77650: Convert MAX77651 SBB1 to pickable linear range The pickable linear range is suitable for The MAX77651 SBB1. According to MAX77651 TV_SBB1 Code Table: Use BIT[1:0] as range selectors. Use BIT[5:2] as selectors for each linear range. The MAX77651 SBB1 supports up to selector 57, selector 58 ~ 63 are RSVD, thus set n_voltage to 58. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max77650-regulator.c | 134 +++++++++++---------------------- 1 file changed, 45 insertions(+), 89 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/max77650-regulator.c b/drivers/regulator/max77650-regulator.c index 5c4f86c98510..ecf8cf7aad20 100644 --- a/drivers/regulator/max77650-regulator.c +++ b/drivers/regulator/max77650-regulator.c @@ -20,6 +20,8 @@ #define MAX77650_REGULATOR_V_LDO_MASK GENMASK(6, 0) #define MAX77650_REGULATOR_V_SBB_MASK GENMASK(5, 0) +#define MAX77651_REGULATOR_V_SBB1_MASK GENMASK(5, 2) +#define MAX77651_REGULATOR_V_SBB1_RANGE_MASK GENMASK(1, 0) #define MAX77650_REGULATOR_AD_MASK BIT(3) #define MAX77650_REGULATOR_AD_DISABLED 0x00 @@ -27,6 +29,8 @@ #define MAX77650_REGULATOR_CURR_LIM_MASK GENMASK(7, 6) +static struct max77650_regulator_desc max77651_SBB1_desc; + enum { MAX77650_REGULATOR_ID_LDO = 0, MAX77650_REGULATOR_ID_SBB0, @@ -41,43 +45,20 @@ struct max77650_regulator_desc { unsigned int regB; }; -static const unsigned int max77651_sbb1_regulator_volt_table[] = { - 2400000, 3200000, 4000000, 4800000, - 2450000, 3250000, 4050000, 4850000, - 2500000, 3300000, 4100000, 4900000, - 2550000, 3350000, 4150000, 4950000, - 2600000, 3400000, 4200000, 5000000, - 2650000, 3450000, 4250000, 5050000, - 2700000, 3500000, 4300000, 5100000, - 2750000, 3550000, 4350000, 5150000, - 2800000, 3600000, 4400000, 5200000, - 2850000, 3650000, 4450000, 5250000, - 2900000, 3700000, 4500000, 0, - 2950000, 3750000, 4550000, 0, - 3000000, 3800000, 4600000, 0, - 3050000, 3850000, 4650000, 0, - 3100000, 3900000, 4700000, 0, - 3150000, 3950000, 4750000, 0, +static const unsigned int max77651_sbb1_volt_range_sel[] = { + 0x0, 0x1, 0x2, 0x3 }; -#define MAX77651_REGULATOR_SBB1_SEL_DEC(_val) \ - (((_val & 0x3c) >> 2) | ((_val & 0x03) << 4)) -#define MAX77651_REGULATOR_SBB1_SEL_ENC(_val) \ - (((_val & 0x30) >> 4) | ((_val & 0x0f) << 2)) - -#define MAX77650_REGULATOR_SBB1_SEL_DECR(_val) \ - do { \ - _val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \ - _val--; \ - _val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \ - } while (0) - -#define MAX77650_REGULATOR_SBB1_SEL_INCR(_val) \ - do { \ - _val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \ - _val++; \ - _val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \ - } while (0) +static const struct regulator_linear_range max77651_sbb1_volt_ranges[] = { + /* range index 0 */ + REGULATOR_LINEAR_RANGE(2400000, 0x00, 0x0f, 50000), + /* range index 1 */ + REGULATOR_LINEAR_RANGE(3200000, 0x00, 0x0f, 50000), + /* range index 2 */ + REGULATOR_LINEAR_RANGE(4000000, 0x00, 0x0f, 50000), + /* range index 3 */ + REGULATOR_LINEAR_RANGE(4800000, 0x00, 0x09, 50000), +}; static const unsigned int max77650_current_limit_table[] = { 1000000, 866000, 707000, 500000, @@ -130,6 +111,7 @@ static int max77650_regulator_disable(struct regulator_dev *rdev) static int max77650_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) { + struct max77650_regulator_desc *rdesc = rdev_get_drvdata(rdev); int rv = 0, curr, diff; bool ascending; @@ -137,15 +119,24 @@ static int max77650_regulator_set_voltage_sel(struct regulator_dev *rdev, * If the regulator is disabled, we can program the desired * voltage right away. */ - if (!max77650_regulator_is_enabled(rdev)) - return regulator_set_voltage_sel_regmap(rdev, sel); + if (!max77650_regulator_is_enabled(rdev)) { + if (rdesc == &max77651_SBB1_desc) + return regulator_set_voltage_sel_pickable_regmap(rdev, + sel); + else + return regulator_set_voltage_sel_regmap(rdev, sel); + } /* * Otherwise we need to manually ramp the output voltage up/down * one step at a time. */ - curr = regulator_get_voltage_sel_regmap(rdev); + if (rdesc == &max77651_SBB1_desc) + curr = regulator_get_voltage_sel_pickable_regmap(rdev); + else + curr = regulator_get_voltage_sel_regmap(rdev); + if (curr < 0) return curr; @@ -162,57 +153,18 @@ static int max77650_regulator_set_voltage_sel(struct regulator_dev *rdev, * the selector equals 0. */ for (ascending ? curr++ : curr--;; ascending ? curr++ : curr--) { - rv = regulator_set_voltage_sel_regmap(rdev, curr); - if (rv) - return rv; - - if (curr == sel) - break; - } - - return 0; -} - -/* - * Special case: non-linear voltage table for max77651 SBB1 - software - * must ensure the voltage is ramped in 50mV increments. - */ -static int max77651_regulator_sbb1_set_voltage_sel(struct regulator_dev *rdev, - unsigned int sel) -{ - int rv = 0, curr, vcurr, vdest, vdiff; - - /* - * If the regulator is disabled, we can program the desired - * voltage right away. - */ - if (!max77650_regulator_is_enabled(rdev)) - return regulator_set_voltage_sel_regmap(rdev, sel); - - curr = regulator_get_voltage_sel_regmap(rdev); - if (curr < 0) - return curr; - - if (curr == sel) - return 0; /* Already there. */ - - vcurr = max77651_sbb1_regulator_volt_table[curr]; - vdest = max77651_sbb1_regulator_volt_table[sel]; - vdiff = vcurr - vdest; - - for (;;) { - if (vdiff > 0) - MAX77650_REGULATOR_SBB1_SEL_DECR(curr); + if (rdesc == &max77651_SBB1_desc) + rv = regulator_set_voltage_sel_pickable_regmap(rdev, + curr); else - MAX77650_REGULATOR_SBB1_SEL_INCR(curr); + rv = regulator_set_voltage_sel_regmap(rdev, curr); - rv = regulator_set_voltage_sel_regmap(rdev, curr); if (rv) return rv; if (curr == sel) break; - }; + } return 0; } @@ -241,14 +193,14 @@ static const struct regulator_ops max77650_regulator_SBB_ops = { .set_active_discharge = regulator_set_active_discharge_regmap, }; -/* Special case for max77651 SBB1 - non-linear voltage mapping. */ +/* Special case for max77651 SBB1 - pickable linear-range voltage mapping. */ static const struct regulator_ops max77651_SBB1_regulator_ops = { .is_enabled = max77650_regulator_is_enabled, .enable = max77650_regulator_enable, .disable = max77650_regulator_disable, - .list_voltage = regulator_list_voltage_table, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = max77651_regulator_sbb1_set_voltage_sel, + .list_voltage = regulator_list_voltage_pickable_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, + .set_voltage_sel = max77650_regulator_set_voltage_sel, .get_current_limit = regulator_get_current_limit_regmap, .set_current_limit = regulator_set_current_limit_regmap, .set_active_discharge = regulator_set_active_discharge_regmap, @@ -345,9 +297,13 @@ static struct max77650_regulator_desc max77651_SBB1_desc = { .supply_name = "in-sbb1", .id = MAX77650_REGULATOR_ID_SBB1, .ops = &max77651_SBB1_regulator_ops, - .volt_table = max77651_sbb1_regulator_volt_table, - .n_voltages = ARRAY_SIZE(max77651_sbb1_regulator_volt_table), - .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, + .linear_range_selectors = max77651_sbb1_volt_range_sel, + .linear_ranges = max77651_sbb1_volt_ranges, + .n_linear_ranges = ARRAY_SIZE(max77651_sbb1_volt_ranges), + .n_voltages = 58, + .vsel_range_mask = MAX77651_REGULATOR_V_SBB1_RANGE_MASK, + .vsel_range_reg = MAX77650_REG_CNFG_SBB1_A, + .vsel_mask = MAX77651_REGULATOR_V_SBB1_MASK, .vsel_reg = MAX77650_REG_CNFG_SBB1_A, .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED, -- cgit v1.2.3 From a867bde3dd037ea5e9f1c5268d22d4bc4fa399b9 Mon Sep 17 00:00:00 2001 From: Eric Jeong Date: Thu, 18 Apr 2019 15:09:44 +0900 Subject: regulator: slg51000: add slg51000 regulator driver Adding regulator driver for the device Dialog SLG51000. The SLG51000 device contains seven compact and customizable low dropout regulators and is designed for high performance camera modules and other small multi-rail applications. Signed-off-by: Eric Jeong Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 9 + drivers/regulator/Makefile | 1 + drivers/regulator/slg51000-regulator.c | 528 +++++++++++++++++++++++++++++++++ drivers/regulator/slg51000-regulator.h | 505 +++++++++++++++++++++++++++++++ 4 files changed, 1043 insertions(+) create mode 100644 drivers/regulator/slg51000-regulator.c create mode 100644 drivers/regulator/slg51000-regulator.h (limited to 'drivers/regulator') diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 6c37f0df9323..b8e39109cbc6 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -828,6 +828,15 @@ config REGULATOR_SKY81452 This driver can also be built as a module. If so, the module will be called sky81452-regulator. +config REGULATOR_SLG51000 + tristate "Dialog Semiconductor SLG51000 regulators" + depends on I2C + select REGMAP_I2C + help + Say y here to support for the Dialog Semiconductor SLG51000. + The SLG51000 is seven compact and customizable low dropout + regulators. + config REGULATOR_STM32_VREFBUF tristate "STMicroelectronics STM32 VREFBUF" depends on ARCH_STM32 || COMPILE_TEST diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 93f53840e8f1..76e78fa449a2 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -104,6 +104,7 @@ obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o +obj-$(CONFIG_REGULATOR_SLG51000) += slg51000-regulator.o obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c new file mode 100644 index 000000000000..12e21d43030b --- /dev/null +++ b/drivers/regulator/slg51000-regulator.c @@ -0,0 +1,528 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// SLG51000 High PSRR, Multi-Output Regulators +// Copyright (C) 2019 Dialog Semiconductor +// +// Author: Eric Jeong + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "slg51000-regulator.h" + +#define SLG51000_SCTL_EVT 7 +#define SLG51000_MAX_EVT_REGISTER 8 +#define SLG51000_LDOHP_LV_MIN 1200000 +#define SLG51000_LDOHP_HV_MIN 2400000 + +enum slg51000_regulators { + SLG51000_REGULATOR_LDO1 = 0, + SLG51000_REGULATOR_LDO2, + SLG51000_REGULATOR_LDO3, + SLG51000_REGULATOR_LDO4, + SLG51000_REGULATOR_LDO5, + SLG51000_REGULATOR_LDO6, + SLG51000_REGULATOR_LDO7, + SLG51000_MAX_REGULATORS, +}; + +struct slg51000_pdata { + struct gpio_desc *ena_gpiod; +}; + +struct slg51000 { + struct device *dev; + struct regmap *regmap; + struct slg51000_pdata regl_pdata[SLG51000_MAX_REGULATORS]; + struct regulator_desc *rdesc[SLG51000_MAX_REGULATORS]; + struct regulator_dev *rdev[SLG51000_MAX_REGULATORS]; + struct gpio_desc *cs_gpiod; + int chip_irq; +}; + +struct slg51000_evt_sta { + unsigned int ereg; + unsigned int sreg; +}; + +static const struct slg51000_evt_sta es_reg[SLG51000_MAX_EVT_REGISTER] = { + {SLG51000_LDO1_EVENT, SLG51000_LDO1_STATUS}, + {SLG51000_LDO2_EVENT, SLG51000_LDO2_STATUS}, + {SLG51000_LDO3_EVENT, SLG51000_LDO3_STATUS}, + {SLG51000_LDO4_EVENT, SLG51000_LDO4_STATUS}, + {SLG51000_LDO5_EVENT, SLG51000_LDO5_STATUS}, + {SLG51000_LDO6_EVENT, SLG51000_LDO6_STATUS}, + {SLG51000_LDO7_EVENT, SLG51000_LDO7_STATUS}, + {SLG51000_SYSCTL_EVENT, SLG51000_SYSCTL_STATUS}, +}; + +static const struct regmap_range slg51000_writeable_ranges[] = { + regmap_reg_range(SLG51000_SYSCTL_MATRIX_CONF_A, + SLG51000_SYSCTL_MATRIX_CONF_A), + regmap_reg_range(SLG51000_LDO1_VSEL, SLG51000_LDO1_VSEL), + regmap_reg_range(SLG51000_LDO1_MINV, SLG51000_LDO1_MAXV), + regmap_reg_range(SLG51000_LDO1_IRQ_MASK, SLG51000_LDO1_IRQ_MASK), + regmap_reg_range(SLG51000_LDO2_VSEL, SLG51000_LDO2_VSEL), + regmap_reg_range(SLG51000_LDO2_MINV, SLG51000_LDO2_MAXV), + regmap_reg_range(SLG51000_LDO2_IRQ_MASK, SLG51000_LDO2_IRQ_MASK), + regmap_reg_range(SLG51000_LDO3_VSEL, SLG51000_LDO3_VSEL), + regmap_reg_range(SLG51000_LDO3_MINV, SLG51000_LDO3_MAXV), + regmap_reg_range(SLG51000_LDO3_IRQ_MASK, SLG51000_LDO3_IRQ_MASK), + regmap_reg_range(SLG51000_LDO4_VSEL, SLG51000_LDO4_VSEL), + regmap_reg_range(SLG51000_LDO4_MINV, SLG51000_LDO4_MAXV), + regmap_reg_range(SLG51000_LDO4_IRQ_MASK, SLG51000_LDO4_IRQ_MASK), + regmap_reg_range(SLG51000_LDO5_VSEL, SLG51000_LDO5_VSEL), + regmap_reg_range(SLG51000_LDO5_MINV, SLG51000_LDO5_MAXV), + regmap_reg_range(SLG51000_LDO5_IRQ_MASK, SLG51000_LDO5_IRQ_MASK), + regmap_reg_range(SLG51000_LDO6_VSEL, SLG51000_LDO6_VSEL), + regmap_reg_range(SLG51000_LDO6_MINV, SLG51000_LDO6_MAXV), + regmap_reg_range(SLG51000_LDO6_IRQ_MASK, SLG51000_LDO6_IRQ_MASK), + regmap_reg_range(SLG51000_LDO7_VSEL, SLG51000_LDO7_VSEL), + regmap_reg_range(SLG51000_LDO7_MINV, SLG51000_LDO7_MAXV), + regmap_reg_range(SLG51000_LDO7_IRQ_MASK, SLG51000_LDO7_IRQ_MASK), + regmap_reg_range(SLG51000_OTP_IRQ_MASK, SLG51000_OTP_IRQ_MASK), +}; + +static const struct regmap_range slg51000_readable_ranges[] = { + regmap_reg_range(SLG51000_SYSCTL_PATN_ID_B0, + SLG51000_SYSCTL_PATN_ID_B2), + regmap_reg_range(SLG51000_SYSCTL_SYS_CONF_A, + SLG51000_SYSCTL_SYS_CONF_A), + regmap_reg_range(SLG51000_SYSCTL_SYS_CONF_D, + SLG51000_SYSCTL_MATRIX_CONF_B), + regmap_reg_range(SLG51000_SYSCTL_REFGEN_CONF_C, + SLG51000_SYSCTL_UVLO_CONF_A), + regmap_reg_range(SLG51000_SYSCTL_FAULT_LOG1, SLG51000_SYSCTL_IRQ_MASK), + regmap_reg_range(SLG51000_IO_GPIO1_CONF, SLG51000_IO_GPIO_STATUS), + regmap_reg_range(SLG51000_LUTARRAY_LUT_VAL_0, + SLG51000_LUTARRAY_LUT_VAL_11), + regmap_reg_range(SLG51000_MUXARRAY_INPUT_SEL_0, + SLG51000_MUXARRAY_INPUT_SEL_63), + regmap_reg_range(SLG51000_PWRSEQ_RESOURCE_EN_0, + SLG51000_PWRSEQ_INPUT_SENSE_CONF_B), + regmap_reg_range(SLG51000_LDO1_VSEL, SLG51000_LDO1_VSEL), + regmap_reg_range(SLG51000_LDO1_MINV, SLG51000_LDO1_MAXV), + regmap_reg_range(SLG51000_LDO1_MISC1, SLG51000_LDO1_VSEL_ACTUAL), + regmap_reg_range(SLG51000_LDO1_EVENT, SLG51000_LDO1_IRQ_MASK), + regmap_reg_range(SLG51000_LDO2_VSEL, SLG51000_LDO2_VSEL), + regmap_reg_range(SLG51000_LDO2_MINV, SLG51000_LDO2_MAXV), + regmap_reg_range(SLG51000_LDO2_MISC1, SLG51000_LDO2_VSEL_ACTUAL), + regmap_reg_range(SLG51000_LDO2_EVENT, SLG51000_LDO2_IRQ_MASK), + regmap_reg_range(SLG51000_LDO3_VSEL, SLG51000_LDO3_VSEL), + regmap_reg_range(SLG51000_LDO3_MINV, SLG51000_LDO3_MAXV), + regmap_reg_range(SLG51000_LDO3_CONF1, SLG51000_LDO3_VSEL_ACTUAL), + regmap_reg_range(SLG51000_LDO3_EVENT, SLG51000_LDO3_IRQ_MASK), + regmap_reg_range(SLG51000_LDO4_VSEL, SLG51000_LDO4_VSEL), + regmap_reg_range(SLG51000_LDO4_MINV, SLG51000_LDO4_MAXV), + regmap_reg_range(SLG51000_LDO4_CONF1, SLG51000_LDO4_VSEL_ACTUAL), + regmap_reg_range(SLG51000_LDO4_EVENT, SLG51000_LDO4_IRQ_MASK), + regmap_reg_range(SLG51000_LDO5_VSEL, SLG51000_LDO5_VSEL), + regmap_reg_range(SLG51000_LDO5_MINV, SLG51000_LDO5_MAXV), + regmap_reg_range(SLG51000_LDO5_TRIM2, SLG51000_LDO5_TRIM2), + regmap_reg_range(SLG51000_LDO5_CONF1, SLG51000_LDO5_VSEL_ACTUAL), + regmap_reg_range(SLG51000_LDO5_EVENT, SLG51000_LDO5_IRQ_MASK), + regmap_reg_range(SLG51000_LDO6_VSEL, SLG51000_LDO6_VSEL), + regmap_reg_range(SLG51000_LDO6_MINV, SLG51000_LDO6_MAXV), + regmap_reg_range(SLG51000_LDO6_TRIM2, SLG51000_LDO6_TRIM2), + regmap_reg_range(SLG51000_LDO6_CONF1, SLG51000_LDO6_VSEL_ACTUAL), + regmap_reg_range(SLG51000_LDO6_EVENT, SLG51000_LDO6_IRQ_MASK), + regmap_reg_range(SLG51000_LDO7_VSEL, SLG51000_LDO7_VSEL), + regmap_reg_range(SLG51000_LDO7_MINV, SLG51000_LDO7_MAXV), + regmap_reg_range(SLG51000_LDO7_CONF1, SLG51000_LDO7_VSEL_ACTUAL), + regmap_reg_range(SLG51000_LDO7_EVENT, SLG51000_LDO7_IRQ_MASK), + regmap_reg_range(SLG51000_OTP_EVENT, SLG51000_OTP_EVENT), + regmap_reg_range(SLG51000_OTP_IRQ_MASK, SLG51000_OTP_IRQ_MASK), + regmap_reg_range(SLG51000_OTP_LOCK_OTP_PROG, SLG51000_OTP_LOCK_CTRL), + regmap_reg_range(SLG51000_LOCK_GLOBAL_LOCK_CTRL1, + SLG51000_LOCK_GLOBAL_LOCK_CTRL1), +}; + +static const struct regmap_range slg51000_volatile_ranges[] = { + regmap_reg_range(SLG51000_SYSCTL_FAULT_LOG1, SLG51000_SYSCTL_STATUS), + regmap_reg_range(SLG51000_IO_GPIO_STATUS, SLG51000_IO_GPIO_STATUS), + regmap_reg_range(SLG51000_LDO1_EVENT, SLG51000_LDO1_STATUS), + regmap_reg_range(SLG51000_LDO2_EVENT, SLG51000_LDO2_STATUS), + regmap_reg_range(SLG51000_LDO3_EVENT, SLG51000_LDO3_STATUS), + regmap_reg_range(SLG51000_LDO4_EVENT, SLG51000_LDO4_STATUS), + regmap_reg_range(SLG51000_LDO5_EVENT, SLG51000_LDO5_STATUS), + regmap_reg_range(SLG51000_LDO6_EVENT, SLG51000_LDO6_STATUS), + regmap_reg_range(SLG51000_LDO7_EVENT, SLG51000_LDO7_STATUS), + regmap_reg_range(SLG51000_OTP_EVENT, SLG51000_OTP_EVENT), +}; + +static const struct regmap_access_table slg51000_writeable_table = { + .yes_ranges = slg51000_writeable_ranges, + .n_yes_ranges = ARRAY_SIZE(slg51000_writeable_ranges), +}; + +static const struct regmap_access_table slg51000_readable_table = { + .yes_ranges = slg51000_readable_ranges, + .n_yes_ranges = ARRAY_SIZE(slg51000_readable_ranges), +}; + +static const struct regmap_access_table slg51000_volatile_table = { + .yes_ranges = slg51000_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(slg51000_volatile_ranges), +}; + +static const struct regmap_config slg51000_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .max_register = 0x8000, + .wr_table = &slg51000_writeable_table, + .rd_table = &slg51000_readable_table, + .volatile_table = &slg51000_volatile_table, +}; + +static struct regulator_ops slg51000_regl_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +}; + +static struct regulator_ops slg51000_switch_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static int slg51000_of_parse_cb(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *config) +{ + struct slg51000 *chip = config->driver_data; + struct slg51000_pdata *rpdata = &chip->regl_pdata[desc->id]; + enum gpiod_flags gflags = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE; + + rpdata->ena_gpiod = devm_gpiod_get_from_of_node(chip->dev, np, + "enable-gpios", 0, + gflags, "gpio-en-ldo"); + if (rpdata->ena_gpiod) { + config->ena_gpiod = rpdata->ena_gpiod; + devm_gpiod_unhinge(chip->dev, config->ena_gpiod); + } + + return 0; +} + +#define SLG51000_REGL_DESC(_id, _name, _s_name, _min, _step) \ + [SLG51000_REGULATOR_##_id] = { \ + .name = #_name, \ + .supply_name = _s_name, \ + .id = SLG51000_REGULATOR_##_id, \ + .of_match = of_match_ptr(#_name), \ + .of_parse_cb = slg51000_of_parse_cb, \ + .ops = &slg51000_regl_ops, \ + .regulators_node = of_match_ptr("regulators"), \ + .n_voltages = 256, \ + .min_uV = _min, \ + .uV_step = _step, \ + .linear_min_sel = 0, \ + .vsel_mask = SLG51000_VSEL_MASK, \ + .vsel_reg = SLG51000_##_id##_VSEL, \ + .enable_reg = SLG51000_SYSCTL_MATRIX_CONF_A, \ + .enable_mask = BIT(SLG51000_REGULATOR_##_id), \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + } + +static struct regulator_desc regls_desc[SLG51000_MAX_REGULATORS] = { + SLG51000_REGL_DESC(LDO1, ldo1, NULL, 2400000, 5000), + SLG51000_REGL_DESC(LDO2, ldo2, NULL, 2400000, 5000), + SLG51000_REGL_DESC(LDO3, ldo3, "vin3", 1200000, 10000), + SLG51000_REGL_DESC(LDO4, ldo4, "vin4", 1200000, 10000), + SLG51000_REGL_DESC(LDO5, ldo5, "vin5", 400000, 5000), + SLG51000_REGL_DESC(LDO6, ldo6, "vin6", 400000, 5000), + SLG51000_REGL_DESC(LDO7, ldo7, "vin7", 1200000, 10000), +}; + +static int slg51000_regulator_init(struct slg51000 *chip) +{ + struct regulator_config config = { }; + struct regulator_desc *rdesc; + unsigned int reg, val; + u8 vsel_range[2]; + int id, ret = 0; + const unsigned int min_regs[SLG51000_MAX_REGULATORS] = { + SLG51000_LDO1_MINV, SLG51000_LDO2_MINV, SLG51000_LDO3_MINV, + SLG51000_LDO4_MINV, SLG51000_LDO5_MINV, SLG51000_LDO6_MINV, + SLG51000_LDO7_MINV, + }; + + for (id = 0; id < SLG51000_MAX_REGULATORS; id++) { + chip->rdesc[id] = ®ls_desc[id]; + rdesc = chip->rdesc[id]; + config.regmap = chip->regmap; + config.dev = chip->dev; + config.driver_data = chip; + + ret = regmap_bulk_read(chip->regmap, min_regs[id], + vsel_range, 2); + if (ret < 0) { + dev_err(chip->dev, + "Failed to read the MIN register\n"); + return ret; + } + + switch (id) { + case SLG51000_REGULATOR_LDO1: + case SLG51000_REGULATOR_LDO2: + if (id == SLG51000_REGULATOR_LDO1) + reg = SLG51000_LDO1_MISC1; + else + reg = SLG51000_LDO2_MISC1; + + ret = regmap_read(chip->regmap, reg, &val); + if (ret < 0) { + dev_err(chip->dev, + "Failed to read voltage range of ldo%d\n", + id + 1); + return ret; + } + + rdesc->linear_min_sel = vsel_range[0]; + rdesc->n_voltages = vsel_range[1] + 1; + if (val & SLG51000_SEL_VRANGE_MASK) + rdesc->min_uV = SLG51000_LDOHP_HV_MIN + + (vsel_range[0] + * rdesc->uV_step); + else + rdesc->min_uV = SLG51000_LDOHP_LV_MIN + + (vsel_range[0] + * rdesc->uV_step); + break; + + case SLG51000_REGULATOR_LDO5: + case SLG51000_REGULATOR_LDO6: + if (id == SLG51000_REGULATOR_LDO5) + reg = SLG51000_LDO5_TRIM2; + else + reg = SLG51000_LDO6_TRIM2; + + ret = regmap_read(chip->regmap, reg, &val); + if (ret < 0) { + dev_err(chip->dev, + "Failed to read LDO mode register\n"); + return ret; + } + + if (val & SLG51000_SEL_BYP_MODE_MASK) { + rdesc->ops = &slg51000_switch_ops; + rdesc->n_voltages = 0; + rdesc->min_uV = 0; + rdesc->uV_step = 0; + rdesc->linear_min_sel = 0; + break; + } + /* Fall through - to the check below.*/ + + default: + rdesc->linear_min_sel = vsel_range[0]; + rdesc->n_voltages = vsel_range[1] + 1; + rdesc->min_uV = rdesc->min_uV + + (vsel_range[0] * rdesc->uV_step); + break; + } + + chip->rdev[id] = devm_regulator_register(chip->dev, rdesc, + &config); + if (IS_ERR(chip->rdev[id])) { + ret = PTR_ERR(chip->rdev[id]); + dev_err(chip->dev, + "Failed to register regulator(%s):%d\n", + chip->rdesc[id]->name, ret); + return ret; + } + } + + return 0; +} + +static irqreturn_t slg51000_irq_handler(int irq, void *data) +{ + struct slg51000 *chip = data; + struct regmap *regmap = chip->regmap; + enum { R0 = 0, R1, R2, REG_MAX }; + u8 evt[SLG51000_MAX_EVT_REGISTER][REG_MAX]; + int ret, i, handled = IRQ_NONE; + unsigned int evt_otp, mask_otp; + + /* Read event[R0], status[R1] and mask[R2] register */ + for (i = 0; i < SLG51000_MAX_EVT_REGISTER; i++) { + ret = regmap_bulk_read(regmap, es_reg[i].ereg, evt[i], REG_MAX); + if (ret < 0) { + dev_err(chip->dev, + "Failed to read event registers(%d)\n", ret); + return IRQ_NONE; + } + } + + ret = regmap_read(regmap, SLG51000_OTP_EVENT, &evt_otp); + if (ret < 0) { + dev_err(chip->dev, + "Failed to read otp event registers(%d)\n", ret); + return IRQ_NONE; + } + + ret = regmap_read(regmap, SLG51000_OTP_IRQ_MASK, &mask_otp); + if (ret < 0) { + dev_err(chip->dev, + "Failed to read otp mask register(%d)\n", ret); + return IRQ_NONE; + } + + if ((evt_otp & SLG51000_EVT_CRC_MASK) && + !(mask_otp & SLG51000_IRQ_CRC_MASK)) { + dev_info(chip->dev, + "OTP has been read or OTP crc is not zero\n"); + handled = IRQ_HANDLED; + } + + for (i = 0; i < SLG51000_MAX_REGULATORS; i++) { + if (!(evt[i][R2] & SLG51000_IRQ_ILIM_FLAG_MASK) && + (evt[i][R0] & SLG51000_EVT_ILIM_FLAG_MASK)) { + regulator_lock(chip->rdev[i]); + regulator_notifier_call_chain(chip->rdev[i], + REGULATOR_EVENT_OVER_CURRENT, NULL); + regulator_unlock(chip->rdev[i]); + + if (evt[i][R1] & SLG51000_STA_ILIM_FLAG_MASK) + dev_warn(chip->dev, + "Over-current limit(ldo%d)\n", i + 1); + handled = IRQ_HANDLED; + } + } + + if (!(evt[SLG51000_SCTL_EVT][R2] & SLG51000_IRQ_HIGH_TEMP_WARN_MASK) && + (evt[SLG51000_SCTL_EVT][R0] & SLG51000_EVT_HIGH_TEMP_WARN_MASK)) { + for (i = 0; i < SLG51000_MAX_REGULATORS; i++) { + if (!(evt[i][R1] & SLG51000_STA_ILIM_FLAG_MASK) && + (evt[i][R1] & SLG51000_STA_VOUT_OK_FLAG_MASK)) { + regulator_lock(chip->rdev[i]); + regulator_notifier_call_chain(chip->rdev[i], + REGULATOR_EVENT_OVER_TEMP, NULL); + regulator_unlock(chip->rdev[i]); + } + } + handled = IRQ_HANDLED; + if (evt[SLG51000_SCTL_EVT][R1] & + SLG51000_STA_HIGH_TEMP_WARN_MASK) + dev_warn(chip->dev, "High temperature warning!\n"); + } + + return handled; +} + +static void slg51000_clear_fault_log(struct slg51000 *chip) +{ + unsigned int val = 0; + int ret = 0; + + ret = regmap_read(chip->regmap, SLG51000_SYSCTL_FAULT_LOG1, &val); + if (ret < 0) { + dev_err(chip->dev, "Failed to read Fault log register\n"); + return; + } + + if (val & SLG51000_FLT_OVER_TEMP_MASK) + dev_dbg(chip->dev, "Fault log: FLT_OVER_TEMP\n"); + if (val & SLG51000_FLT_POWER_SEQ_CRASH_REQ_MASK) + dev_dbg(chip->dev, "Fault log: FLT_POWER_SEQ_CRASH_REQ\n"); + if (val & SLG51000_FLT_RST_MASK) + dev_dbg(chip->dev, "Fault log: FLT_RST\n"); + if (val & SLG51000_FLT_POR_MASK) + dev_dbg(chip->dev, "Fault log: FLT_POR\n"); +} + +static int slg51000_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct slg51000 *chip; + struct gpio_desc *cs_gpiod = NULL; + int error, ret; + + chip = devm_kzalloc(dev, sizeof(struct slg51000), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + cs_gpiod = devm_gpiod_get_from_of_node(dev, dev->of_node, + "dlg,cs-gpios", 0, + GPIOD_OUT_HIGH + | GPIOD_FLAGS_BIT_NONEXCLUSIVE, + "slg51000-cs"); + if (cs_gpiod) { + dev_info(dev, "Found chip selector property\n"); + chip->cs_gpiod = cs_gpiod; + } + + i2c_set_clientdata(client, chip); + chip->chip_irq = client->irq; + chip->dev = dev; + chip->regmap = devm_regmap_init_i2c(client, &slg51000_regmap_config); + if (IS_ERR(chip->regmap)) { + error = PTR_ERR(chip->regmap); + dev_err(dev, "Failed to allocate register map: %d\n", + error); + return error; + } + + ret = slg51000_regulator_init(chip); + if (ret < 0) { + dev_err(chip->dev, "Failed to init regulator(%d)\n", ret); + return ret; + } + + slg51000_clear_fault_log(chip); + + if (chip->chip_irq) { + ret = devm_request_threaded_irq(dev, chip->chip_irq, NULL, + slg51000_irq_handler, + (IRQF_TRIGGER_HIGH | + IRQF_ONESHOT), + "slg51000-irq", chip); + if (ret != 0) { + dev_err(dev, "Failed to request IRQ: %d\n", + chip->chip_irq); + return ret; + } + } else { + dev_info(dev, "No IRQ configured\n"); + } + + return ret; +} + +static const struct i2c_device_id slg51000_i2c_id[] = { + {"slg51000", 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, slg51000_i2c_id); + +static struct i2c_driver slg51000_regulator_driver = { + .driver = { + .name = "slg51000-regulator", + }, + .probe = slg51000_i2c_probe, + .id_table = slg51000_i2c_id, +}; + +module_i2c_driver(slg51000_regulator_driver); + +MODULE_AUTHOR("Eric Jeong "); +MODULE_DESCRIPTION("SLG51000 regulator driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/regulator/slg51000-regulator.h b/drivers/regulator/slg51000-regulator.h new file mode 100644 index 000000000000..20feb7f91942 --- /dev/null +++ b/drivers/regulator/slg51000-regulator.h @@ -0,0 +1,505 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * SLG51000 High PSRR, Multi-Output Regulators + * Copyright (C) 2019 Dialog Semiconductor + * + * Author: Eric Jeong + */ + +#ifndef __SLG51000_REGISTERS_H__ +#define __SLG51000_REGISTERS_H__ + +/* Registers */ + +#define SLG51000_SYSCTL_PATN_ID_B0 0x1105 +#define SLG51000_SYSCTL_PATN_ID_B1 0x1106 +#define SLG51000_SYSCTL_PATN_ID_B2 0x1107 +#define SLG51000_SYSCTL_SYS_CONF_A 0x1109 +#define SLG51000_SYSCTL_SYS_CONF_D 0x110c +#define SLG51000_SYSCTL_MATRIX_CONF_A 0x110d +#define SLG51000_SYSCTL_MATRIX_CONF_B 0x110e +#define SLG51000_SYSCTL_REFGEN_CONF_C 0x1111 +#define SLG51000_SYSCTL_UVLO_CONF_A 0x1112 +#define SLG51000_SYSCTL_FAULT_LOG1 0x1115 +#define SLG51000_SYSCTL_EVENT 0x1116 +#define SLG51000_SYSCTL_STATUS 0x1117 +#define SLG51000_SYSCTL_IRQ_MASK 0x1118 +#define SLG51000_IO_GPIO1_CONF 0x1500 +#define SLG51000_IO_GPIO2_CONF 0x1501 +#define SLG51000_IO_GPIO3_CONF 0x1502 +#define SLG51000_IO_GPIO4_CONF 0x1503 +#define SLG51000_IO_GPIO5_CONF 0x1504 +#define SLG51000_IO_GPIO6_CONF 0x1505 +#define SLG51000_IO_GPIO_STATUS 0x1506 +#define SLG51000_LUTARRAY_LUT_VAL_0 0x1600 +#define SLG51000_LUTARRAY_LUT_VAL_1 0x1601 +#define SLG51000_LUTARRAY_LUT_VAL_2 0x1602 +#define SLG51000_LUTARRAY_LUT_VAL_3 0x1603 +#define SLG51000_LUTARRAY_LUT_VAL_4 0x1604 +#define SLG51000_LUTARRAY_LUT_VAL_5 0x1605 +#define SLG51000_LUTARRAY_LUT_VAL_6 0x1606 +#define SLG51000_LUTARRAY_LUT_VAL_7 0x1607 +#define SLG51000_LUTARRAY_LUT_VAL_8 0x1608 +#define SLG51000_LUTARRAY_LUT_VAL_9 0x1609 +#define SLG51000_LUTARRAY_LUT_VAL_10 0x160a +#define SLG51000_LUTARRAY_LUT_VAL_11 0x160b +#define SLG51000_MUXARRAY_INPUT_SEL_0 0x1700 +#define SLG51000_MUXARRAY_INPUT_SEL_1 0x1701 +#define SLG51000_MUXARRAY_INPUT_SEL_2 0x1702 +#define SLG51000_MUXARRAY_INPUT_SEL_3 0x1703 +#define SLG51000_MUXARRAY_INPUT_SEL_4 0x1704 +#define SLG51000_MUXARRAY_INPUT_SEL_5 0x1705 +#define SLG51000_MUXARRAY_INPUT_SEL_6 0x1706 +#define SLG51000_MUXARRAY_INPUT_SEL_7 0x1707 +#define SLG51000_MUXARRAY_INPUT_SEL_8 0x1708 +#define SLG51000_MUXARRAY_INPUT_SEL_9 0x1709 +#define SLG51000_MUXARRAY_INPUT_SEL_10 0x170a +#define SLG51000_MUXARRAY_INPUT_SEL_11 0x170b +#define SLG51000_MUXARRAY_INPUT_SEL_12 0x170c +#define SLG51000_MUXARRAY_INPUT_SEL_13 0x170d +#define SLG51000_MUXARRAY_INPUT_SEL_14 0x170e +#define SLG51000_MUXARRAY_INPUT_SEL_15 0x170f +#define SLG51000_MUXARRAY_INPUT_SEL_16 0x1710 +#define SLG51000_MUXARRAY_INPUT_SEL_17 0x1711 +#define SLG51000_MUXARRAY_INPUT_SEL_18 0x1712 +#define SLG51000_MUXARRAY_INPUT_SEL_19 0x1713 +#define SLG51000_MUXARRAY_INPUT_SEL_20 0x1714 +#define SLG51000_MUXARRAY_INPUT_SEL_21 0x1715 +#define SLG51000_MUXARRAY_INPUT_SEL_22 0x1716 +#define SLG51000_MUXARRAY_INPUT_SEL_23 0x1717 +#define SLG51000_MUXARRAY_INPUT_SEL_24 0x1718 +#define SLG51000_MUXARRAY_INPUT_SEL_25 0x1719 +#define SLG51000_MUXARRAY_INPUT_SEL_26 0x171a +#define SLG51000_MUXARRAY_INPUT_SEL_27 0x171b +#define SLG51000_MUXARRAY_INPUT_SEL_28 0x171c +#define SLG51000_MUXARRAY_INPUT_SEL_29 0x171d +#define SLG51000_MUXARRAY_INPUT_SEL_30 0x171e +#define SLG51000_MUXARRAY_INPUT_SEL_31 0x171f +#define SLG51000_MUXARRAY_INPUT_SEL_32 0x1720 +#define SLG51000_MUXARRAY_INPUT_SEL_33 0x1721 +#define SLG51000_MUXARRAY_INPUT_SEL_34 0x1722 +#define SLG51000_MUXARRAY_INPUT_SEL_35 0x1723 +#define SLG51000_MUXARRAY_INPUT_SEL_36 0x1724 +#define SLG51000_MUXARRAY_INPUT_SEL_37 0x1725 +#define SLG51000_MUXARRAY_INPUT_SEL_38 0x1726 +#define SLG51000_MUXARRAY_INPUT_SEL_39 0x1727 +#define SLG51000_MUXARRAY_INPUT_SEL_40 0x1728 +#define SLG51000_MUXARRAY_INPUT_SEL_41 0x1729 +#define SLG51000_MUXARRAY_INPUT_SEL_42 0x172a +#define SLG51000_MUXARRAY_INPUT_SEL_43 0x172b +#define SLG51000_MUXARRAY_INPUT_SEL_44 0x172c +#define SLG51000_MUXARRAY_INPUT_SEL_45 0x172d +#define SLG51000_MUXARRAY_INPUT_SEL_46 0x172e +#define SLG51000_MUXARRAY_INPUT_SEL_47 0x172f +#define SLG51000_MUXARRAY_INPUT_SEL_48 0x1730 +#define SLG51000_MUXARRAY_INPUT_SEL_49 0x1731 +#define SLG51000_MUXARRAY_INPUT_SEL_50 0x1732 +#define SLG51000_MUXARRAY_INPUT_SEL_51 0x1733 +#define SLG51000_MUXARRAY_INPUT_SEL_52 0x1734 +#define SLG51000_MUXARRAY_INPUT_SEL_53 0x1735 +#define SLG51000_MUXARRAY_INPUT_SEL_54 0x1736 +#define SLG51000_MUXARRAY_INPUT_SEL_55 0x1737 +#define SLG51000_MUXARRAY_INPUT_SEL_56 0x1738 +#define SLG51000_MUXARRAY_INPUT_SEL_57 0x1739 +#define SLG51000_MUXARRAY_INPUT_SEL_58 0x173a +#define SLG51000_MUXARRAY_INPUT_SEL_59 0x173b +#define SLG51000_MUXARRAY_INPUT_SEL_60 0x173c +#define SLG51000_MUXARRAY_INPUT_SEL_61 0x173d +#define SLG51000_MUXARRAY_INPUT_SEL_62 0x173e +#define SLG51000_MUXARRAY_INPUT_SEL_63 0x173f +#define SLG51000_PWRSEQ_RESOURCE_EN_0 0x1900 +#define SLG51000_PWRSEQ_RESOURCE_EN_1 0x1901 +#define SLG51000_PWRSEQ_RESOURCE_EN_2 0x1902 +#define SLG51000_PWRSEQ_RESOURCE_EN_3 0x1903 +#define SLG51000_PWRSEQ_RESOURCE_EN_4 0x1904 +#define SLG51000_PWRSEQ_RESOURCE_EN_5 0x1905 +#define SLG51000_PWRSEQ_SLOT_TIME_MIN_UP0 0x1906 +#define SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN0 0x1907 +#define SLG51000_PWRSEQ_SLOT_TIME_MIN_UP1 0x1908 +#define SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN1 0x1909 +#define SLG51000_PWRSEQ_SLOT_TIME_MIN_UP2 0x190a +#define SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN2 0x190b +#define SLG51000_PWRSEQ_SLOT_TIME_MIN_UP3 0x190c +#define SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN3 0x190d +#define SLG51000_PWRSEQ_SLOT_TIME_MIN_UP4 0x190e +#define SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN4 0x190f +#define SLG51000_PWRSEQ_SLOT_TIME_MIN_UP5 0x1910 +#define SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN5 0x1911 +#define SLG51000_PWRSEQ_SLOT_TIME_MAX_CONF_A 0x1912 +#define SLG51000_PWRSEQ_SLOT_TIME_MAX_CONF_B 0x1913 +#define SLG51000_PWRSEQ_SLOT_TIME_MAX_CONF_C 0x1914 +#define SLG51000_PWRSEQ_INPUT_SENSE_CONF_A 0x1915 +#define SLG51000_PWRSEQ_INPUT_SENSE_CONF_B 0x1916 +#define SLG51000_LDO1_VSEL 0x2000 +#define SLG51000_LDO1_MINV 0x2060 +#define SLG51000_LDO1_MAXV 0x2061 +#define SLG51000_LDO1_MISC1 0x2064 +#define SLG51000_LDO1_VSEL_ACTUAL 0x2065 +#define SLG51000_LDO1_EVENT 0x20c0 +#define SLG51000_LDO1_STATUS 0x20c1 +#define SLG51000_LDO1_IRQ_MASK 0x20c2 +#define SLG51000_LDO2_VSEL 0x2200 +#define SLG51000_LDO2_MINV 0x2260 +#define SLG51000_LDO2_MAXV 0x2261 +#define SLG51000_LDO2_MISC1 0x2264 +#define SLG51000_LDO2_VSEL_ACTUAL 0x2265 +#define SLG51000_LDO2_EVENT 0x22c0 +#define SLG51000_LDO2_STATUS 0x22c1 +#define SLG51000_LDO2_IRQ_MASK 0x22c2 +#define SLG51000_LDO3_VSEL 0x2300 +#define SLG51000_LDO3_MINV 0x2360 +#define SLG51000_LDO3_MAXV 0x2361 +#define SLG51000_LDO3_CONF1 0x2364 +#define SLG51000_LDO3_CONF2 0x2365 +#define SLG51000_LDO3_VSEL_ACTUAL 0x2366 +#define SLG51000_LDO3_EVENT 0x23c0 +#define SLG51000_LDO3_STATUS 0x23c1 +#define SLG51000_LDO3_IRQ_MASK 0x23c2 +#define SLG51000_LDO4_VSEL 0x2500 +#define SLG51000_LDO4_MINV 0x2560 +#define SLG51000_LDO4_MAXV 0x2561 +#define SLG51000_LDO4_CONF1 0x2564 +#define SLG51000_LDO4_CONF2 0x2565 +#define SLG51000_LDO4_VSEL_ACTUAL 0x2566 +#define SLG51000_LDO4_EVENT 0x25c0 +#define SLG51000_LDO4_STATUS 0x25c1 +#define SLG51000_LDO4_IRQ_MASK 0x25c2 +#define SLG51000_LDO5_VSEL 0x2700 +#define SLG51000_LDO5_MINV 0x2760 +#define SLG51000_LDO5_MAXV 0x2761 +#define SLG51000_LDO5_TRIM2 0x2763 +#define SLG51000_LDO5_CONF1 0x2765 +#define SLG51000_LDO5_CONF2 0x2766 +#define SLG51000_LDO5_VSEL_ACTUAL 0x2767 +#define SLG51000_LDO5_EVENT 0x27c0 +#define SLG51000_LDO5_STATUS 0x27c1 +#define SLG51000_LDO5_IRQ_MASK 0x27c2 +#define SLG51000_LDO6_VSEL 0x2900 +#define SLG51000_LDO6_MINV 0x2960 +#define SLG51000_LDO6_MAXV 0x2961 +#define SLG51000_LDO6_TRIM2 0x2963 +#define SLG51000_LDO6_CONF1 0x2965 +#define SLG51000_LDO6_CONF2 0x2966 +#define SLG51000_LDO6_VSEL_ACTUAL 0x2967 +#define SLG51000_LDO6_EVENT 0x29c0 +#define SLG51000_LDO6_STATUS 0x29c1 +#define SLG51000_LDO6_IRQ_MASK 0x29c2 +#define SLG51000_LDO7_VSEL 0x3100 +#define SLG51000_LDO7_MINV 0x3160 +#define SLG51000_LDO7_MAXV 0x3161 +#define SLG51000_LDO7_CONF1 0x3164 +#define SLG51000_LDO7_CONF2 0x3165 +#define SLG51000_LDO7_VSEL_ACTUAL 0x3166 +#define SLG51000_LDO7_EVENT 0x31c0 +#define SLG51000_LDO7_STATUS 0x31c1 +#define SLG51000_LDO7_IRQ_MASK 0x31c2 +#define SLG51000_OTP_EVENT 0x782b +#define SLG51000_OTP_IRQ_MASK 0x782d +#define SLG51000_OTP_LOCK_OTP_PROG 0x78fe +#define SLG51000_OTP_LOCK_CTRL 0x78ff +#define SLG51000_LOCK_GLOBAL_LOCK_CTRL1 0x8000 + +/* Register Bit Fields */ + +/* SLG51000_SYSCTL_PATTERN_ID_BYTE0 = 0x1105 */ +#define SLG51000_PATTERN_ID_BYTE0_SHIFT 0 +#define SLG51000_PATTERN_ID_BYTE0_MASK (0xff << 0) + +/* SLG51000_SYSCTL_PATTERN_ID_BYTE1 = 0x1106 */ +#define SLG51000_PATTERN_ID_BYTE1_SHIFT 0 +#define SLG51000_PATTERN_ID_BYTE1_MASK (0xff << 0) + +/* SLG51000_SYSCTL_PATTERN_ID_BYTE2 = 0x1107 */ +#define SLG51000_PATTERN_ID_BYTE2_SHIFT 0 +#define SLG51000_PATTERN_ID_BYTE2_MASK (0xff << 0) + +/* SLG51000_SYSCTL_SYS_CONF_A = 0x1109 */ +#define SLG51000_I2C_ADDRESS_SHIFT 0 +#define SLG51000_I2C_ADDRESS_MASK (0x7f << 0) +#define SLG51000_I2C_DISABLE_SHIFT 7 +#define SLG51000_I2C_DISABLE_MASK (0x01 << 7) + +/* SLG51000_SYSCTL_SYS_CONF_D = 0x110c */ +#define SLG51000_CS_T_DEB_SHIFT 6 +#define SLG51000_CS_T_DEB_MASK (0x03 << 6) +#define SLG51000_I2C_CLR_MODE_SHIFT 5 +#define SLG51000_I2C_CLR_MODE_MASK (0x01 << 5) + +/* SLG51000_SYSCTL_MATRIX_CTRL_CONF_A = 0x110d */ +#define SLG51000_RESOURCE_CTRL_SHIFT 0 +#define SLG51000_RESOURCE_CTRL_MASK (0xff << 0) + +/* SLG51000_SYSCTL_MATRIX_CTRL_CONF_B = 0x110e */ +#define SLG51000_MATRIX_EVENT_SENSE_SHIFT 0 +#define SLG51000_MATRIX_EVENT_SENSE_MASK (0x07 << 0) + +/* SLG51000_SYSCTL_REFGEN_CONF_C = 0x1111 */ +#define SLG51000_REFGEN_SEL_TEMP_WARN_DEBOUNCE_SHIFT 2 +#define SLG51000_REFGEN_SEL_TEMP_WARN_DEBOUNCE_MASK (0x03 << 2) +#define SLG51000_REFGEN_SEL_TEMP_WARN_THR_SHIFT 0 +#define SLG51000_REFGEN_SEL_TEMP_WARN_THR_MASK (0x03 << 0) + +/* SLG51000_SYSCTL_UVLO_CONF_A = 0x1112 */ +#define SLG51000_VMON_UVLO_SEL_THR_SHIFT 0 +#define SLG51000_VMON_UVLO_SEL_THR_MASK (0x1f << 0) + +/* SLG51000_SYSCTL_FAULT_LOG1 = 0x1115 */ +#define SLG51000_FLT_POR_SHIFT 5 +#define SLG51000_FLT_POR_MASK (0x01 << 5) +#define SLG51000_FLT_RST_SHIFT 4 +#define SLG51000_FLT_RST_MASK (0x01 << 4) +#define SLG51000_FLT_POWER_SEQ_CRASH_REQ_SHIFT 2 +#define SLG51000_FLT_POWER_SEQ_CRASH_REQ_MASK (0x01 << 2) +#define SLG51000_FLT_OVER_TEMP_SHIFT 1 +#define SLG51000_FLT_OVER_TEMP_MASK (0x01 << 1) + +/* SLG51000_SYSCTL_EVENT = 0x1116 */ +#define SLG51000_EVT_MATRIX_SHIFT 1 +#define SLG51000_EVT_MATRIX_MASK (0x01 << 1) +#define SLG51000_EVT_HIGH_TEMP_WARN_SHIFT 0 +#define SLG51000_EVT_HIGH_TEMP_WARN_MASK (0x01 << 0) + +/* SLG51000_SYSCTL_STATUS = 0x1117 */ +#define SLG51000_STA_MATRIX_SHIFT 1 +#define SLG51000_STA_MATRIX_MASK (0x01 << 1) +#define SLG51000_STA_HIGH_TEMP_WARN_SHIFT 0 +#define SLG51000_STA_HIGH_TEMP_WARN_MASK (0x01 << 0) + +/* SLG51000_SYSCTL_IRQ_MASK = 0x1118 */ +#define SLG51000_IRQ_MATRIX_SHIFT 1 +#define SLG51000_IRQ_MATRIX_MASK (0x01 << 1) +#define SLG51000_IRQ_HIGH_TEMP_WARN_SHIFT 0 +#define SLG51000_IRQ_HIGH_TEMP_WARN_MASK (0x01 << 0) + +/* SLG51000_IO_GPIO1_CONF ~ SLG51000_IO_GPIO5_CONF = + * 0x1500, 0x1501, 0x1502, 0x1503, 0x1504 + */ +#define SLG51000_GPIO_DIR_SHIFT 7 +#define SLG51000_GPIO_DIR_MASK (0x01 << 7) +#define SLG51000_GPIO_SENS_SHIFT 5 +#define SLG51000_GPIO_SENS_MASK (0x03 << 5) +#define SLG51000_GPIO_INVERT_SHIFT 4 +#define SLG51000_GPIO_INVERT_MASK (0x01 << 4) +#define SLG51000_GPIO_BYP_SHIFT 3 +#define SLG51000_GPIO_BYP_MASK (0x01 << 3) +#define SLG51000_GPIO_T_DEB_SHIFT 1 +#define SLG51000_GPIO_T_DEB_MASK (0x03 << 1) +#define SLG51000_GPIO_LEVEL_SHIFT 0 +#define SLG51000_GPIO_LEVEL_MASK (0x01 << 0) + +/* SLG51000_IO_GPIO6_CONF = 0x1505 */ +#define SLG51000_GPIO6_SENS_SHIFT 5 +#define SLG51000_GPIO6_SENS_MASK (0x03 << 5) +#define SLG51000_GPIO6_INVERT_SHIFT 4 +#define SLG51000_GPIO6_INVERT_MASK (0x01 << 4) +#define SLG51000_GPIO6_T_DEB_SHIFT 1 +#define SLG51000_GPIO6_T_DEB_MASK (0x03 << 1) +#define SLG51000_GPIO6_LEVEL_SHIFT 0 +#define SLG51000_GPIO6_LEVEL_MASK (0x01 << 0) + +/* SLG51000_IO_GPIO_STATUS = 0x1506 */ +#define SLG51000_GPIO6_STATUS_SHIFT 5 +#define SLG51000_GPIO6_STATUS_MASK (0x01 << 5) +#define SLG51000_GPIO5_STATUS_SHIFT 4 +#define SLG51000_GPIO5_STATUS_MASK (0x01 << 4) +#define SLG51000_GPIO4_STATUS_SHIFT 3 +#define SLG51000_GPIO4_STATUS_MASK (0x01 << 3) +#define SLG51000_GPIO3_STATUS_SHIFT 2 +#define SLG51000_GPIO3_STATUS_MASK (0x01 << 2) +#define SLG51000_GPIO2_STATUS_SHIFT 1 +#define SLG51000_GPIO2_STATUS_MASK (0x01 << 1) +#define SLG51000_GPIO1_STATUS_SHIFT 0 +#define SLG51000_GPIO1_STATUS_MASK (0x01 << 0) + +/* SLG51000_LUTARRAY_LUT_VAL_0 ~ SLG51000_LUTARRAY_LUT_VAL_11 + * 0x1600, 0x1601, 0x1602, 0x1603, 0x1604, 0x1605, + * 0x1606, 0x1607, 0x1608, 0x1609, 0x160a, 0x160b + */ +#define SLG51000_LUT_VAL_SHIFT 0 +#define SLG51000_LUT_VAL_MASK (0xff << 0) + +/* SLG51000_MUXARRAY_INPUT_SEL_0 ~ SLG51000_MUXARRAY_INPUT_SEL_63 + * 0x1700, 0x1701, 0x1702, 0x1703, 0x1704, 0x1705, + * 0x1706, 0x1707, 0x1708, 0x1709, 0x170a, 0x170b, + * 0x170c, 0x170d, 0x170e, 0x170f, 0x1710, 0x1711, + * 0x1712, 0x1713, 0x1714, 0x1715, 0x1716, 0x1717, + * 0x1718, 0x1719, 0x171a, 0x171b, 0x171c, 0x171d, + * 0x171e, 0x171f, 0x1720, 0x1721, 0x1722, 0x1723, + * 0x1724, 0x1725, 0x1726, 0x1727, 0x1728, 0x1729, + * 0x173a, 0x173b, 0x173c, 0x173d, 0x173e, 0x173f, + */ +#define SLG51000_INPUT_SEL_SHIFT 0 +#define SLG51000_INPUT_SEL_MASK (0x3f << 0) + +/* SLG51000_PWRSEQ_RESOURCE_EN_0 ~ SLG51000_PWRSEQ_RESOURCE_EN_5 + * 0x1900, 0x1901, 0x1902, 0x1903, 0x1904, 0x1905 + */ +#define SLG51000_RESOURCE_EN_DOWN0_SHIFT 4 +#define SLG51000_RESOURCE_EN_DOWN0_MASK (0x07 << 4) +#define SLG51000_RESOURCE_EN_UP0_SHIFT 0 +#define SLG51000_RESOURCE_EN_UP0_MASK (0x07 << 0) + +/* SLG51000_PWRSEQ_SLOT_TIME_MIN_UP0 ~ SLG51000_PWRSEQ_SLOT_TIME_MIN_UP5 + * 0x1906, 0x1908, 0x190a, 0x190c, 0x190e, 0x1910 + */ +#define SLG51000_SLOT_TIME_MIN_UP_SHIFT 0 +#define SLG51000_SLOT_TIME_MIN_UP_MASK (0xff << 0) + +/* SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN0 ~ SLG51000_PWRSEQ_SLOT_TIME_MIN_DOWN5 + * 0x1907, 0x1909, 0x190b, 0x190d, 0x190f, 0x1911 + */ +#define SLG51000_SLOT_TIME_MIN_DOWN_SHIFT 0 +#define SLG51000_SLOT_TIME_MIN_DOWN_MASK (0xff << 0) + +/* SLG51000_PWRSEQ_SLOT_TIME_MAX_CONF_A ~ SLG51000_PWRSEQ_SLOT_TIME_MAX_CONF_C + * 0x1912, 0x1913, 0x1914 + */ +#define SLG51000_SLOT_TIME_MAX_DOWN1_SHIFT 6 +#define SLG51000_SLOT_TIME_MAX_DOWN1_MASK (0x03 << 6) +#define SLG51000_SLOT_TIME_MAX_UP1_SHIFT 4 +#define SLG51000_SLOT_TIME_MAX_UP1_MASK (0x03 << 4) +#define SLG51000_SLOT_TIME_MAX_DOWN0_SHIFT 2 +#define SLG51000_SLOT_TIME_MAX_DOWN0_MASK (0x03 << 2) +#define SLG51000_SLOT_TIME_MAX_UP0_SHIFT 0 +#define SLG51000_SLOT_TIME_MAX_UP0_MASK (0x03 << 0) + +/* SLG51000_PWRSEQ_INPUT_SENSE_CONF_A = 0x1915 */ +#define SLG51000_TRIG_UP_SENSE_SHIFT 6 +#define SLG51000_TRIG_UP_SENSE_MASK (0x01 << 6) +#define SLG51000_UP_EN_SENSE5_SHIFT 5 +#define SLG51000_UP_EN_SENSE5_MASK (0x01 << 5) +#define SLG51000_UP_EN_SENSE4_SHIFT 4 +#define SLG51000_UP_EN_SENSE4_MASK (0x01 << 4) +#define SLG51000_UP_EN_SENSE3_SHIFT 3 +#define SLG51000_UP_EN_SENSE3_MASK (0x01 << 3) +#define SLG51000_UP_EN_SENSE2_SHIFT 2 +#define SLG51000_UP_EN_SENSE2_MASK (0x01 << 2) +#define SLG51000_UP_EN_SENSE1_SHIFT 1 +#define SLG51000_UP_EN_SENSE1_MASK (0x01 << 1) +#define SLG51000_UP_EN_SENSE0_SHIFT 0 +#define SLG51000_UP_EN_SENSE0_MASK (0x01 << 0) + +/* SLG51000_PWRSEQ_INPUT_SENSE_CONF_B = 0x1916 */ +#define SLG51000_CRASH_DETECT_SENSE_SHIFT 7 +#define SLG51000_CRASH_DETECT_SENSE_MASK (0x01 << 7) +#define SLG51000_TRIG_DOWN_SENSE_SHIFT 6 +#define SLG51000_TRIG_DOWN_SENSE_MASK (0x01 << 6) +#define SLG51000_DOWN_EN_SENSE5_SHIFT 5 +#define SLG51000_DOWN_EN_SENSE5_MASK (0x01 << 5) +#define SLG51000_DOWN_EN_SENSE4_SHIFT 4 +#define SLG51000_DOWN_EN_SENSE4_MASK (0x01 << 4) +#define SLG51000_DOWN_EN_SENSE3_SHIFT 3 +#define SLG51000_DOWN_EN_SENSE3_MASK (0x01 << 3) +#define SLG51000_DOWN_EN_SENSE2_SHIFT 2 +#define SLG51000_DOWN_EN_SENSE2_MASK (0x01 << 2) +#define SLG51000_DOWN_EN_SENSE1_SHIFT 1 +#define SLG51000_DOWN_EN_SENSE1_MASK (0x01 << 1) +#define SLG51000_DOWN_EN_SENSE0_SHIFT 0 +#define SLG51000_DOWN_EN_SENSE0_MASK (0x01 << 0) + +/* SLG51000_LDO1_VSEL ~ SLG51000_LDO7_VSEL = + * 0x2000, 0x2200, 0x2300, 0x2500, 0x2700, 0x2900, 0x3100 + */ +#define SLG51000_VSEL_SHIFT 0 +#define SLG51000_VSEL_MASK (0xff << 0) + +/* SLG51000_LDO1_MINV ~ SLG51000_LDO7_MINV = + * 0x2060, 0x2260, 0x2360, 0x2560, 0x2760, 0x2960, 0x3160 + */ +#define SLG51000_MINV_SHIFT 0 +#define SLG51000_MINV_MASK (0xff << 0) + +/* SLG51000_LDO1_MAXV ~ SLG51000_LDO7_MAXV = + * 0x2061, 0x2261, 0x2361, 0x2561, 0x2761, 0x2961, 0x3161 + */ +#define SLG51000_MAXV_SHIFT 0 +#define SLG51000_MAXV_MASK (0xff << 0) + +/* SLG51000_LDO1_MISC1 = 0x2064, SLG51000_LDO2_MISC1 = 0x2264 */ +#define SLG51000_SEL_VRANGE_SHIFT 0 +#define SLG51000_SEL_VRANGE_MASK (0x01 << 0) + +/* SLG51000_LDO1_VSEL_ACTUAL ~ SLG51000_LDO7_VSEL_ACTUAL = + * 0x2065, 0x2265, 0x2366, 0x2566, 0x2767, 0x2967, 0x3166 + */ +#define SLG51000_VSEL_ACTUAL_SHIFT 0 +#define SLG51000_VSEL_ACTUAL_MASK (0xff << 0) + +/* SLG51000_LDO1_EVENT ~ SLG51000_LDO7_EVENT = + * 0x20c0, 0x22c0, 0x23c0, 0x25c0, 0x27c0, 0x29c0, 0x31c0 + */ +#define SLG51000_EVT_ILIM_FLAG_SHIFT 0 +#define SLG51000_EVT_ILIM_FLAG_MASK (0x01 << 0) +#define SLG51000_EVT_VOUT_OK_FLAG_SHIFT 1 +#define SLG51000_EVT_VOUT_OK_FLAG_MASK (0x01 << 1) + +/* SLG51000_LDO1_STATUS ~ SLG51000_LDO7_STATUS = + * 0x20c1, 0x22c1, 0x23c1, 0x25c1, 0x27c1, 0x29c1, 0x31c1 + */ +#define SLG51000_STA_ILIM_FLAG_SHIFT 0 +#define SLG51000_STA_ILIM_FLAG_MASK (0x01 << 0) +#define SLG51000_STA_VOUT_OK_FLAG_SHIFT 1 +#define SLG51000_STA_VOUT_OK_FLAG_MASK (0x01 << 1) + +/* SLG51000_LDO1_IRQ_MASK ~ SLG51000_LDO7_IRQ_MASK = + * 0x20c2, 0x22c2, 0x23c2, 0x25c2, 0x27c2, 0x29c2, 0x31c2 + */ +#define SLG51000_IRQ_ILIM_FLAG_SHIFT 0 +#define SLG51000_IRQ_ILIM_FLAG_MASK (0x01 << 0) + +/* SLG51000_LDO3_CONF1 ~ SLG51000_LDO7_CONF1 = + * 0x2364, 0x2564, 0x2765, 0x2965, 0x3164 + */ +#define SLG51000_SEL_START_ILIM_SHIFT 0 +#define SLG51000_SEL_START_ILIM_MASK (0x7f << 0) + +/* SLG51000_LDO3_CONF2 ~ SLG51000_LDO7_CONF2 = + * 0x2365, 0x2565, 0x2766, 0x2966, 0x3165 + */ +#define SLG51000_SEL_FUNC_ILIM_SHIFT 0 +#define SLG51000_SEL_FUNC_ILIM_MASK (0x7f << 0) + +/* SLG51000_LDO5_TRIM2 = 0x2763, SLG51000_LDO6_TRIM2 = 0x2963 */ +#define SLG51000_SEL_BYP_SLEW_RATE_SHIFT 2 +#define SLG51000_SEL_BYP_SLEW_RATE_MASK (0x03 << 2) +#define SLG51000_SEL_BYP_VGATE_SHIFT 1 +#define SLG51000_SEL_BYP_VGATE_MASK (0x01 << 1) +#define SLG51000_SEL_BYP_MODE_SHIFT 0 +#define SLG51000_SEL_BYP_MODE_MASK (0x01 << 0) + +/* SLG51000_OTP_EVENT = 0x782b */ +#define SLG51000_EVT_CRC_SHIFT 0 +#define SLG51000_EVT_CRC_MASK (0x01 << 0) + +/* SLG51000_OTP_IRQ_MASK = 0x782d */ +#define SLG51000_IRQ_CRC_SHIFT 0 +#define SLG51000_IRQ_CRC_MASK (0x01 << 0) + +/* SLG51000_OTP_LOCK_OTP_PROG = 0x78fe */ +#define SLG51000_LOCK_OTP_PROG_SHIFT 0 +#define SLG51000_LOCK_OTP_PROG_MASK (0x01 << 0) + +/* SLG51000_OTP_LOCK_CTRL = 0x78ff */ +#define SLG51000_LOCK_DFT_SHIFT 1 +#define SLG51000_LOCK_DFT_MASK (0x01 << 1) +#define SLG51000_LOCK_RWT_SHIFT 0 +#define SLG51000_LOCK_RWT_MASK (0x01 << 0) + +/* SLG51000_LOCK_GLOBAL_LOCK_CTRL1 = 0x8000 */ +#define SLG51000_LDO7_LOCK_SHIFT 7 +#define SLG51000_LDO7_LOCK_MASK (0x01 << 7) +#define SLG51000_LDO6_LOCK_SHIFT 6 +#define SLG51000_LDO6_LOCK_MASK (0x01 << 6) +#define SLG51000_LDO5_LOCK_SHIFT 5 +#define SLG51000_LDO5_LOCK_MASK (0x01 << 5) +#define SLG51000_LDO4_LOCK_SHIFT 4 +#define SLG51000_LDO4_LOCK_MASK (0x01 << 4) +#define SLG51000_LDO3_LOCK_SHIFT 3 +#define SLG51000_LDO3_LOCK_MASK (0x01 << 3) +#define SLG51000_LDO2_LOCK_SHIFT 2 +#define SLG51000_LDO2_LOCK_MASK (0x01 << 2) +#define SLG51000_LDO1_LOCK_SHIFT 1 +#define SLG51000_LDO1_LOCK_MASK (0x01 << 1) + +#endif /* __SLG51000_REGISTERS_H__ */ + -- cgit v1.2.3 From 662307294f27975096f0a45e1b2dc5c84a966c1b Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 20 May 2019 11:34:44 +0200 Subject: regulator: da9063: remove platform_data support There are no in-kernel users anymore, so remove this outdated interface. Signed-off-by: Wolfram Sang Reviewed-by: Simon Horman Acked-by: Steve Twiss Tested-by: Steve Twiss Reviewed-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/regulator/da9063-regulator.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index 6f9ce1a6e44d..43aa0df30346 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -683,7 +683,6 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt( static int da9063_regulator_probe(struct platform_device *pdev) { struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent); - struct da9063_pdata *da9063_pdata = dev_get_platdata(da9063->dev); struct of_regulator_match *da9063_reg_matches = NULL; struct da9063_regulators_pdata *regl_pdata; const struct da9063_dev_model *model; @@ -693,11 +692,7 @@ static int da9063_regulator_probe(struct platform_device *pdev) bool bcores_merged, bmem_bio_merged; int id, irq, n, n_regulators, ret, val; - regl_pdata = da9063_pdata ? da9063_pdata->regulators_pdata : NULL; - - if (!regl_pdata) - regl_pdata = da9063_parse_regulators_dt(pdev, - &da9063_reg_matches); + regl_pdata = da9063_parse_regulators_dt(pdev, &da9063_reg_matches); if (IS_ERR(regl_pdata) || regl_pdata->n_regulators == 0) { dev_err(&pdev->dev, -- cgit v1.2.3 From 824bd1be3ed01d67197098650d0c62b176087b11 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 20 May 2019 11:34:45 +0200 Subject: regulator: da9063: move definitions out of a header into the driver Those definitions are only used within the driver meanwhile, so put them there. Signed-off-by: Wolfram Sang Reviewed-by: Simon Horman Acked-by: Steve Twiss Tested-by: Steve Twiss Reviewed-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/regulator/da9063-regulator.c | 44 +++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index 43aa0df30346..da95197fdb4f 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -19,7 +19,6 @@ #include #include #include -#include #include @@ -28,6 +27,49 @@ REG_FIELD(_reg, __builtin_ffs((int)_mask) - 1, \ sizeof(unsigned int) * 8 - __builtin_clz((_mask)) - 1) +/* DA9063 and DA9063L regulator IDs */ +enum { + /* BUCKs */ + DA9063_ID_BCORE1, + DA9063_ID_BCORE2, + DA9063_ID_BPRO, + DA9063_ID_BMEM, + DA9063_ID_BIO, + DA9063_ID_BPERI, + + /* BCORE1 and BCORE2 in merged mode */ + DA9063_ID_BCORES_MERGED, + /* BMEM and BIO in merged mode */ + DA9063_ID_BMEM_BIO_MERGED, + /* When two BUCKs are merged, they cannot be reused separately */ + + /* LDOs on both DA9063 and DA9063L */ + DA9063_ID_LDO3, + DA9063_ID_LDO7, + DA9063_ID_LDO8, + DA9063_ID_LDO9, + DA9063_ID_LDO11, + + /* DA9063-only LDOs */ + DA9063_ID_LDO1, + DA9063_ID_LDO2, + DA9063_ID_LDO4, + DA9063_ID_LDO5, + DA9063_ID_LDO6, + DA9063_ID_LDO10, +}; + +/* Old regulator platform data */ +struct da9063_regulator_data { + int id; + struct regulator_init_data *initdata; +}; + +struct da9063_regulators_pdata { + unsigned n_regulators; + struct da9063_regulator_data *regulator_data; +}; + /* Regulator capabilities and registers description */ struct da9063_regulator_info { struct regulator_desc desc; -- cgit v1.2.3 From 973af54c5218335dbca2695fd97c20be2564438a Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 20 May 2019 11:34:46 +0200 Subject: regulator: da9063: platform_data is gone, depend on OF With OF being the only configuration possibility left, depend on it to simplify some code. Signed-off-by: Wolfram Sang Reviewed-by: Simon Horman Acked-by: Steve Twiss Tested-by: Steve Twiss Reviewed-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 2 +- drivers/regulator/da9063-regulator.c | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index b8e39109cbc6..5e3a9e6547b0 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -257,7 +257,7 @@ config REGULATOR_DA9062 config REGULATOR_DA9063 tristate "Dialog Semiconductor DA9063 regulators" - depends on MFD_DA9063 + depends on MFD_DA9063 && OF help Say y here to support the BUCKs and LDOs regulators found on DA9063 PMICs. diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c index da95197fdb4f..02f816318fba 100644 --- a/drivers/regulator/da9063-regulator.c +++ b/drivers/regulator/da9063-regulator.c @@ -634,7 +634,6 @@ static const struct regulator_init_data *da9063_get_regulator_initdata( return NULL; } -#ifdef CONFIG_OF static struct of_regulator_match da9063_matches[] = { [DA9063_ID_BCORE1] = { .name = "bcore1" }, [DA9063_ID_BCORE2] = { .name = "bcore2" }, @@ -712,15 +711,6 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt( *da9063_reg_matches = da9063_matches; return pdata; } -#else -static struct da9063_regulators_pdata *da9063_parse_regulators_dt( - struct platform_device *pdev, - struct of_regulator_match **da9063_reg_matches) -{ - *da9063_reg_matches = NULL; - return ERR_PTR(-ENODEV); -} -#endif static int da9063_regulator_probe(struct platform_device *pdev) { -- cgit v1.2.3 From 1f5f11e7370c6a55da1a37351b0cfb5f86f0cb6d Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 21 May 2019 11:04:38 +0100 Subject: regulator: arizona-ldo1: Add support for Cirrus Logic Madera codecs This adds a new driver identity "madera-ldo1" and probe function so that this driver can be used to control the LDO1 regulator on some Cirrus Logic Madera codecs. Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 8 ++-- drivers/regulator/arizona-ldo1.c | 83 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 5 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 5e3a9e6547b0..5827aace014b 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -135,12 +135,12 @@ config REGULATOR_AB8500 signal AB8500 PMIC config REGULATOR_ARIZONA_LDO1 - tristate "Wolfson Arizona class devices LDO1" - depends on MFD_ARIZONA + tristate "Cirrus Madera and Wolfson Arizona class devices LDO1" + depends on MFD_ARIZONA || MFD_MADERA depends on SND_SOC help - Support for the LDO1 regulators found on Wolfson Arizona class - devices. + Support for the LDO1 regulators found on Cirrus Logic Madera codecs + and Wolfson Microelectronic Arizona codecs. config REGULATOR_ARIZONA_MICSUPP tristate "Wolfson Arizona class devices MICSUPP" diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index e4bc7b1e5ccd..1a3d7b720f5e 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -25,6 +25,10 @@ #include #include +#include +#include +#include + struct arizona_ldo1 { struct regulator_dev *regulator; struct regmap *regmap; @@ -158,6 +162,31 @@ static const struct regulator_init_data arizona_ldo1_wm5110 = { .num_consumer_supplies = 1, }; +static const struct regulator_desc madera_ldo1 = { + .name = "LDO1", + .supply_name = "LDOVDD", + .type = REGULATOR_VOLTAGE, + .ops = &arizona_ldo1_ops, + + .vsel_reg = MADERA_LDO1_CONTROL_1, + .vsel_mask = MADERA_LDO1_VSEL_MASK, + .min_uV = 900000, + .uV_step = 25000, + .n_voltages = 13, + .enable_time = 3000, + + .owner = THIS_MODULE, +}; + +static const struct regulator_init_data madera_ldo1_default = { + .constraints = { + .min_uV = 1200000, + .max_uV = 1200000, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, +}; + static int arizona_ldo1_of_get_pdata(struct arizona_ldo1_pdata *pdata, struct regulator_config *config, const struct regulator_desc *desc, @@ -320,6 +349,32 @@ static int arizona_ldo1_remove(struct platform_device *pdev) return 0; } +static int madera_ldo1_probe(struct platform_device *pdev) +{ + struct madera *madera = dev_get_drvdata(pdev->dev.parent); + struct arizona_ldo1 *ldo1; + bool external_dcvdd; + int ret; + + ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL); + if (!ldo1) + return -ENOMEM; + + ldo1->regmap = madera->regmap; + + ldo1->init_data = madera_ldo1_default; + + ret = arizona_ldo1_common_init(pdev, ldo1, &madera_ldo1, + &madera->pdata.ldo1, + &external_dcvdd); + if (ret) + return ret; + + madera->internal_dcvdd = !external_dcvdd; + + return 0; +} + static struct platform_driver arizona_ldo1_driver = { .probe = arizona_ldo1_probe, .remove = arizona_ldo1_remove, @@ -328,10 +383,36 @@ static struct platform_driver arizona_ldo1_driver = { }, }; -module_platform_driver(arizona_ldo1_driver); +static struct platform_driver madera_ldo1_driver = { + .probe = madera_ldo1_probe, + .remove = arizona_ldo1_remove, + .driver = { + .name = "madera-ldo1", + }, +}; + +static struct platform_driver * const madera_ldo1_drivers[] = { + &arizona_ldo1_driver, + &madera_ldo1_driver, +}; + +static int __init arizona_ldo1_init(void) +{ + return platform_register_drivers(madera_ldo1_drivers, + ARRAY_SIZE(madera_ldo1_drivers)); +} +module_init(arizona_ldo1_init); + +static void __exit madera_ldo1_exit(void) +{ + platform_unregister_drivers(madera_ldo1_drivers, + ARRAY_SIZE(madera_ldo1_drivers)); +} +module_exit(madera_ldo1_exit); /* Module information */ MODULE_AUTHOR("Mark Brown "); MODULE_DESCRIPTION("Arizona LDO1 driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:arizona-ldo1"); +MODULE_ALIAS("platform:madera-ldo1"); -- cgit v1.2.3 From 7bd7916dc8ab5b056f1b53e19021e476120481c0 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 21 May 2019 11:04:39 +0100 Subject: regulator: arizona-micsupp: Add support for Cirrus Logic Madera codecs This adds a new driver identity "madera-micsupp" and probe function so that this driver can be used to control the micsupp regulator on Cirrus Logic Madera codecs. Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 7 ++-- drivers/regulator/arizona-micsupp.c | 71 ++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 4 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 5827aace014b..660f3a1717ba 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -143,11 +143,12 @@ config REGULATOR_ARIZONA_LDO1 and Wolfson Microelectronic Arizona codecs. config REGULATOR_ARIZONA_MICSUPP - tristate "Wolfson Arizona class devices MICSUPP" - depends on MFD_ARIZONA + tristate "Cirrus Madera and Wolfson Arizona class devices MICSUPP" + depends on MFD_ARIZONA || MFD_MADERA depends on SND_SOC help - Support for the MICSUPP regulators found on Wolfson Arizona class + Support for the MICSUPP regulators found on Cirrus Logic Madera codecs + and Wolfson Microelectronic Arizona codecs devices. config REGULATOR_AS3711 diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index be0d46da51a1..de6802b85e9f 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -25,6 +25,10 @@ #include #include +#include +#include +#include + #include struct arizona_micsupp { @@ -200,6 +204,28 @@ static const struct regulator_init_data arizona_micsupp_ext_default = { .num_consumer_supplies = 1, }; +static const struct regulator_desc madera_micsupp = { + .name = "MICVDD", + .supply_name = "CPVDD1", + .type = REGULATOR_VOLTAGE, + .n_voltages = 40, + .ops = &arizona_micsupp_ops, + + .vsel_reg = MADERA_LDO2_CONTROL_1, + .vsel_mask = MADERA_LDO2_VSEL_MASK, + .enable_reg = MADERA_MIC_CHARGE_PUMP_1, + .enable_mask = MADERA_CPMIC_ENA, + .bypass_reg = MADERA_MIC_CHARGE_PUMP_1, + .bypass_mask = MADERA_CPMIC_BYPASS, + + .linear_ranges = arizona_micsupp_ext_ranges, + .n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ext_ranges), + + .enable_time = 3000, + + .owner = THIS_MODULE, +}; + static int arizona_micsupp_of_get_pdata(struct arizona_micsupp_pdata *pdata, struct regulator_config *config, const struct regulator_desc *desc) @@ -316,6 +342,24 @@ static int arizona_micsupp_probe(struct platform_device *pdev) &arizona->pdata.micvdd); } +static int madera_micsupp_probe(struct platform_device *pdev) +{ + struct madera *madera = dev_get_drvdata(pdev->dev.parent); + struct arizona_micsupp *micsupp; + + micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL); + if (!micsupp) + return -ENOMEM; + + micsupp->regmap = madera->regmap; + micsupp->dapm = &madera->dapm; + micsupp->dev = madera->dev; + micsupp->init_data = arizona_micsupp_ext_default; + + return arizona_micsupp_common_init(pdev, micsupp, &madera_micsupp, + &madera->pdata.micvdd); +} + static struct platform_driver arizona_micsupp_driver = { .probe = arizona_micsupp_probe, .driver = { @@ -323,10 +367,35 @@ static struct platform_driver arizona_micsupp_driver = { }, }; -module_platform_driver(arizona_micsupp_driver); +static struct platform_driver madera_micsupp_driver = { + .probe = madera_micsupp_probe, + .driver = { + .name = "madera-micsupp", + }, +}; + +static struct platform_driver * const arizona_micsupp_drivers[] = { + &arizona_micsupp_driver, + &madera_micsupp_driver, +}; + +static int __init arizona_micsupp_init(void) +{ + return platform_register_drivers(arizona_micsupp_drivers, + ARRAY_SIZE(arizona_micsupp_drivers)); +} +module_init(arizona_micsupp_init); + +static void __exit arizona_micsupp_exit(void) +{ + platform_unregister_drivers(arizona_micsupp_drivers, + ARRAY_SIZE(arizona_micsupp_drivers)); +} +module_exit(arizona_micsupp_exit); /* Module information */ MODULE_AUTHOR("Mark Brown "); MODULE_DESCRIPTION("Arizona microphone supply driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:arizona-micsupp"); +MODULE_ALIAS("platform:madera-micsupp"); -- cgit v1.2.3 From 59dec1f0fac8107f3bffaa0051afce795e24c3e4 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Wed, 22 May 2019 18:26:29 -0700 Subject: regulator: max77650: Move max77651_SBB1_desc's declaration down Clang warns: drivers/regulator/max77650-regulator.c:32:39: warning: tentative definition of variable with internal linkage has incomplete non-array type 'struct max77650_regulator_desc' [-Wtentative-definition-incomplete-type] static struct max77650_regulator_desc max77651_SBB1_desc; ^ drivers/regulator/max77650-regulator.c:32:15: note: forward declaration of 'struct max77650_regulator_desc' static struct max77650_regulator_desc max77651_SBB1_desc; ^ 1 warning generated. Move max77651_SBB1_desc's declaration below max77650_regulator_desc's definition so this warning does not happen. Fixes: 3df4235ac41c ("regulator: max77650: Convert MAX77651 SBB1 to pickable linear range") Link: https://github.com/ClangBuiltLinux/linux/issues/491 Signed-off-by: Nathan Chancellor Reviewed-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/max77650-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/max77650-regulator.c b/drivers/regulator/max77650-regulator.c index ecf8cf7aad20..e3b28fc68cdb 100644 --- a/drivers/regulator/max77650-regulator.c +++ b/drivers/regulator/max77650-regulator.c @@ -29,8 +29,6 @@ #define MAX77650_REGULATOR_CURR_LIM_MASK GENMASK(7, 6) -static struct max77650_regulator_desc max77651_SBB1_desc; - enum { MAX77650_REGULATOR_ID_LDO = 0, MAX77650_REGULATOR_ID_SBB0, @@ -45,6 +43,8 @@ struct max77650_regulator_desc { unsigned int regB; }; +static struct max77650_regulator_desc max77651_SBB1_desc; + static const unsigned int max77651_sbb1_volt_range_sel[] = { 0x0, 0x1, 0x2, 0x3 }; -- cgit v1.2.3 From 0a33d4feea748399c9341ff054c5f29c98393d35 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 24 May 2019 18:02:46 +0800 Subject: regulator: slg51000: Constify slg51000_regl_ops and slg51000_switch_ops These regulator_ops variables never need to be modified, make them const so compiler can put them to .rodata. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/slg51000-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c index 12e21d43030b..a06a18f220e0 100644 --- a/drivers/regulator/slg51000-regulator.c +++ b/drivers/regulator/slg51000-regulator.c @@ -183,7 +183,7 @@ static const struct regmap_config slg51000_regmap_config = { .volatile_table = &slg51000_volatile_table, }; -static struct regulator_ops slg51000_regl_ops = { +static const struct regulator_ops slg51000_regl_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -193,7 +193,7 @@ static struct regulator_ops slg51000_regl_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, }; -static struct regulator_ops slg51000_switch_ops = { +static const struct regulator_ops slg51000_switch_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, -- cgit v1.2.3 From 12c574d84c8e492320a4e75b2c1157f8b61e4092 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 24 May 2019 18:02:47 +0800 Subject: regulator: slg51000: Remove unneeded regl_pdata from struct slg51000 Just use a local variable *ena_gpiod in slg51000_of_parse_cb instead. With this change, the struct slg51000_pdata can be removed. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/slg51000-regulator.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c index a06a18f220e0..04b732991d69 100644 --- a/drivers/regulator/slg51000-regulator.c +++ b/drivers/regulator/slg51000-regulator.c @@ -35,14 +35,9 @@ enum slg51000_regulators { SLG51000_MAX_REGULATORS, }; -struct slg51000_pdata { - struct gpio_desc *ena_gpiod; -}; - struct slg51000 { struct device *dev; struct regmap *regmap; - struct slg51000_pdata regl_pdata[SLG51000_MAX_REGULATORS]; struct regulator_desc *rdesc[SLG51000_MAX_REGULATORS]; struct regulator_dev *rdev[SLG51000_MAX_REGULATORS]; struct gpio_desc *cs_gpiod; @@ -204,14 +199,14 @@ static int slg51000_of_parse_cb(struct device_node *np, struct regulator_config *config) { struct slg51000 *chip = config->driver_data; - struct slg51000_pdata *rpdata = &chip->regl_pdata[desc->id]; + struct gpio_desc *ena_gpiod; enum gpiod_flags gflags = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE; - rpdata->ena_gpiod = devm_gpiod_get_from_of_node(chip->dev, np, - "enable-gpios", 0, - gflags, "gpio-en-ldo"); - if (rpdata->ena_gpiod) { - config->ena_gpiod = rpdata->ena_gpiod; + ena_gpiod = devm_gpiod_get_from_of_node(chip->dev, np, + "enable-gpios", 0, + gflags, "gpio-en-ldo"); + if (ena_gpiod) { + config->ena_gpiod = ena_gpiod; devm_gpiod_unhinge(chip->dev, config->ena_gpiod); } -- cgit v1.2.3 From cbafbd1dcc04ffe6c24225d0262b71c569631def Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Fri, 24 May 2019 18:10:34 +0300 Subject: regulator: max77620: Support Maxim 77663 Add support for Maxim 77663. Signed-off-by: Dmitry Osipenko Signed-off-by: Mark Brown --- drivers/regulator/max77620-regulator.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/max77620-regulator.c b/drivers/regulator/max77620-regulator.c index 0ad91a7f9cb9..0ec9f81fe74a 100644 --- a/drivers/regulator/max77620-regulator.c +++ b/drivers/regulator/max77620-regulator.c @@ -761,6 +761,24 @@ static struct max77620_regulator_info max20024_regs_info[MAX77620_NUM_REGS] = { RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000), }; +static struct max77620_regulator_info max77663_regs_info[MAX77620_NUM_REGS] = { + RAIL_SD(SD0, sd0, "in-sd0", SD0, 600000, 3387500, 12500, 0xFF, NONE), + RAIL_SD(SD1, sd1, "in-sd1", SD1, 800000, 1587500, 12500, 0xFF, NONE), + RAIL_SD(SD2, sd2, "in-sd2", SDX, 600000, 3787500, 12500, 0xFF, NONE), + RAIL_SD(SD3, sd3, "in-sd3", SDX, 600000, 3787500, 12500, 0xFF, NONE), + RAIL_SD(SD4, sd4, "in-sd4", SDX, 600000, 3787500, 12500, 0xFF, NONE), + + RAIL_LDO(LDO0, ldo0, "in-ldo0-1", N, 800000, 2375000, 25000), + RAIL_LDO(LDO1, ldo1, "in-ldo0-1", N, 800000, 2375000, 25000), + RAIL_LDO(LDO2, ldo2, "in-ldo2", P, 800000, 3950000, 50000), + RAIL_LDO(LDO3, ldo3, "in-ldo3-5", P, 800000, 3950000, 50000), + RAIL_LDO(LDO4, ldo4, "in-ldo4-6", P, 800000, 1587500, 12500), + RAIL_LDO(LDO5, ldo5, "in-ldo3-5", P, 800000, 3950000, 50000), + RAIL_LDO(LDO6, ldo6, "in-ldo4-6", P, 800000, 3950000, 50000), + RAIL_LDO(LDO7, ldo7, "in-ldo7-8", N, 800000, 3950000, 50000), + RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000), +}; + static int max77620_regulator_probe(struct platform_device *pdev) { struct max77620_chip *max77620_chip = dev_get_drvdata(pdev->dev.parent); @@ -785,9 +803,14 @@ static int max77620_regulator_probe(struct platform_device *pdev) case MAX77620: rinfo = max77620_regs_info; break; - default: + case MAX20024: rinfo = max20024_regs_info; break; + case MAX77663: + rinfo = max77663_regs_info; + break; + default: + return -EINVAL; } config.regmap = pmic->rmap; @@ -881,6 +904,7 @@ static const struct dev_pm_ops max77620_regulator_pm_ops = { static const struct platform_device_id max77620_regulator_devtype[] = { { .name = "max77620-pmic", }, { .name = "max20024-pmic", }, + { .name = "max77663-pmic", }, {}, }; MODULE_DEVICE_TABLE(platform, max77620_regulator_devtype); -- cgit v1.2.3 From 60b909e413dab4d131a6629dce1fb2177d3cc918 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 1 Jun 2019 01:02:52 +0200 Subject: regulator: arizona-micsupp: Delete unused include This driver uses no symbols from so just drop this include. Signed-off-by: Linus Walleij Acked-by: Charles Keepax Signed-off-by: Mark Brown --- drivers/regulator/arizona-micsupp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index de6802b85e9f..ae1a5de3e57d 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 532e9334eb38de50d75b6a0e94832ee9d9975743 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 1 Jun 2019 01:06:08 +0200 Subject: regulator: bd70528: Drop unused include This driver does not use any symbols from so just drop the include. Cc: Matti Vaittinen Signed-off-by: Linus Walleij Acked-By: Matti Vaittinen Signed-off-by: Mark Brown --- drivers/regulator/bd70528-regulator.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/bd70528-regulator.c b/drivers/regulator/bd70528-regulator.c index 30e3ed430a8a..0248a61f1006 100644 --- a/drivers/regulator/bd70528-regulator.c +++ b/drivers/regulator/bd70528-regulator.c @@ -4,7 +4,6 @@ #include #include -#include #include #include #include -- cgit v1.2.3 From 5cbb1515e75c0b8d328ddce0f5e4ff636334373c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 1 Jun 2019 01:08:51 +0200 Subject: regulator: bd718x7: Drop unused include This driver does not use any symbols from so just drop the include. Cc: Matti Vaittinen Signed-off-by: Linus Walleij Acked-By: Matti Vaittinen Signed-off-by: Mark Brown --- drivers/regulator/bd718x7-regulator.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c index fde4264da6ff..8c22cfb76173 100644 --- a/drivers/regulator/bd718x7-regulator.c +++ b/drivers/regulator/bd718x7-regulator.c @@ -4,7 +4,6 @@ #include #include -#include #include #include #include -- cgit v1.2.3 From 25a7d03dae3ac8dcc3fa00cc0ec17935eb08260d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 7 Jun 2019 13:26:40 +0200 Subject: regulator: cpcap: Spelling s/configuraion/configuration/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/regulator/cpcap-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/cpcap-regulator.c b/drivers/regulator/cpcap-regulator.c index d3284361e594..f80781d58a28 100644 --- a/drivers/regulator/cpcap-regulator.c +++ b/drivers/regulator/cpcap-regulator.c @@ -90,7 +90,7 @@ #define CPCAP_REG_OFF_MODE_SEC BIT(15) /** - * SoC specific configuraion for CPCAP regulator. There are at least three + * SoC specific configuration for CPCAP regulator. There are at least three * different SoCs each with their own parameters: omap3, omap4 and tegra2. * * The assign_reg and assign_mask seem to allow toggling between primary -- cgit v1.2.3 From 6b96092a6bfa65566dda2f5a68a559a743b8d132 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 8 Jun 2019 12:56:04 +0200 Subject: regulator: max8952: simplify getting the adapter of a client We have a dedicated pointer for that, so use it. Much easier to read and less computation involved. Signed-off-by: Wolfram Sang Signed-off-by: Mark Brown --- drivers/regulator/max8952.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index cf2a2912cb1b..451237efb359 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -192,7 +192,7 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev) static int max8952_pmic_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct i2c_adapter *adapter = client->adapter; struct max8952_platform_data *pdata = dev_get_platdata(&client->dev); struct regulator_config config = { }; struct max8952_data *max8952; -- cgit v1.2.3 From d17adf7d3f5be74bdfda89ceed7bff3910ffb6d4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 9 Jun 2019 13:05:13 +0200 Subject: regulator: max77802: Drop unused includes This driver does not use any symbols from no so just drop the includes. Cc: Javier Martinez Canillas Signed-off-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/max77802-regulator.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/max77802-regulator.c b/drivers/regulator/max77802-regulator.c index ea7b50397300..7b8ec8c0bd15 100644 --- a/drivers/regulator/max77802-regulator.c +++ b/drivers/regulator/max77802-regulator.c @@ -14,9 +14,7 @@ #include #include #include -#include #include -#include #include #include #include -- cgit v1.2.3 From 9a5ed0bac86edce4097abf7595a7de050b2f87fa Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 12 Jun 2019 09:42:22 +0200 Subject: regulator: wm831x: Convert to use GPIO descriptors This converts the Wolfson Micro WM831x DCDC converter to use a GPIO descriptor for the GPIO driving the DVS pin. There is just one (non-DT) machine in the kernel using this, and that is the Wolfson Micro (now Cirrus) Cragganmore 6410 so we patch this board to pass a descriptor table and fix up the driver accordingly. Cc: Charles Keepax Cc: Richard Fitzgerald Cc: patches@opensource.cirrus.com Signed-off-by: Linus Walleij Acked-by: Charles Keepax Signed-off-by: Mark Brown --- drivers/regulator/wm831x-dcdc.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index b422eef97b77..018dbbd96771 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include @@ -50,7 +50,7 @@ struct wm831x_dcdc { int base; struct wm831x *wm831x; struct regulator_dev *regulator; - int dvs_gpio; + struct gpio_desc *dvs_gpiod; int dvs_gpio_state; int on_vsel; int dvs_vsel; @@ -217,7 +217,7 @@ static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state) return 0; dcdc->dvs_gpio_state = state; - gpio_set_value(dcdc->dvs_gpio, state); + gpiod_set_value(dcdc->dvs_gpiod, state); /* Should wait for DVS state change to be asserted if we have * a GPIO for it, for now assume the device is configured @@ -237,10 +237,10 @@ static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev, int ret; /* If this value is already set then do a GPIO update if we can */ - if (dcdc->dvs_gpio && dcdc->on_vsel == vsel) + if (dcdc->dvs_gpiod && dcdc->on_vsel == vsel) return wm831x_buckv_set_dvs(rdev, 0); - if (dcdc->dvs_gpio && dcdc->dvs_vsel == vsel) + if (dcdc->dvs_gpiod && dcdc->dvs_vsel == vsel) return wm831x_buckv_set_dvs(rdev, 1); /* Always set the ON status to the minimum voltage */ @@ -249,7 +249,7 @@ static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev, return ret; dcdc->on_vsel = vsel; - if (!dcdc->dvs_gpio) + if (!dcdc->dvs_gpiod) return ret; /* Kick the voltage transition now */ @@ -296,7 +296,7 @@ static int wm831x_buckv_get_voltage_sel(struct regulator_dev *rdev) { struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); - if (dcdc->dvs_gpio && dcdc->dvs_gpio_state) + if (dcdc->dvs_gpiod && dcdc->dvs_gpio_state) return dcdc->dvs_vsel; else return dcdc->on_vsel; @@ -337,7 +337,7 @@ static void wm831x_buckv_dvs_init(struct platform_device *pdev, int ret; u16 ctrl; - if (!pdata || !pdata->dvs_gpio) + if (!pdata) return; /* gpiolib won't let us read the GPIO status so pick the higher @@ -345,17 +345,14 @@ static void wm831x_buckv_dvs_init(struct platform_device *pdev, */ dcdc->dvs_gpio_state = pdata->dvs_init_state; - ret = devm_gpio_request_one(&pdev->dev, pdata->dvs_gpio, - dcdc->dvs_gpio_state ? GPIOF_INIT_HIGH : 0, - "DCDC DVS"); - if (ret < 0) { - dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n", - dcdc->name, ret); + dcdc->dvs_gpiod = devm_gpiod_get(&pdev->dev, "dvs", + dcdc->dvs_gpio_state ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW); + if (IS_ERR(dcdc->dvs_gpiod)) { + dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %ld\n", + dcdc->name, PTR_ERR(dcdc->dvs_gpiod)); return; } - dcdc->dvs_gpio = pdata->dvs_gpio; - switch (pdata->dvs_control_src) { case 1: ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT; -- cgit v1.2.3 From 6f10419187d0d5fe395e2a2f2a64370961bf02a3 Mon Sep 17 00:00:00 2001 From: Anders Roxell Date: Wed, 12 Jun 2019 10:11:58 +0200 Subject: regulator: 88pm800: fix warning same module names When building with CONFIG_MFD_88PM800 and CONFIG_REGULATOR_88PM800 enabled as loadable modules, we see the following warning: warning: same module names found: drivers/regulator/88pm800.ko drivers/mfd/88pm800.ko Rework so that the file is named 88pm800-regulator. Signed-off-by: Anders Roxell Signed-off-by: Mark Brown --- drivers/regulator/88pm800-regulator.c | 289 ++++++++++++++++++++++++++++++++++ drivers/regulator/88pm800.c | 289 ---------------------------------- drivers/regulator/Makefile | 2 +- 3 files changed, 290 insertions(+), 290 deletions(-) create mode 100644 drivers/regulator/88pm800-regulator.c delete mode 100644 drivers/regulator/88pm800.c (limited to 'drivers/regulator') diff --git a/drivers/regulator/88pm800-regulator.c b/drivers/regulator/88pm800-regulator.c new file mode 100644 index 000000000000..9fd379732d18 --- /dev/null +++ b/drivers/regulator/88pm800-regulator.c @@ -0,0 +1,289 @@ +/* + * Regulators driver for Marvell 88PM800 + * + * Copyright (C) 2012 Marvell International Ltd. + * Joseph(Yossi) Hanin + * Yi Zhang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* LDO1 with DVC[0..3] */ +#define PM800_LDO1_VOUT (0x08) /* VOUT1 */ +#define PM800_LDO1_VOUT_2 (0x09) +#define PM800_LDO1_VOUT_3 (0x0A) +#define PM800_LDO2_VOUT (0x0B) +#define PM800_LDO3_VOUT (0x0C) +#define PM800_LDO4_VOUT (0x0D) +#define PM800_LDO5_VOUT (0x0E) +#define PM800_LDO6_VOUT (0x0F) +#define PM800_LDO7_VOUT (0x10) +#define PM800_LDO8_VOUT (0x11) +#define PM800_LDO9_VOUT (0x12) +#define PM800_LDO10_VOUT (0x13) +#define PM800_LDO11_VOUT (0x14) +#define PM800_LDO12_VOUT (0x15) +#define PM800_LDO13_VOUT (0x16) +#define PM800_LDO14_VOUT (0x17) +#define PM800_LDO15_VOUT (0x18) +#define PM800_LDO16_VOUT (0x19) +#define PM800_LDO17_VOUT (0x1A) +#define PM800_LDO18_VOUT (0x1B) +#define PM800_LDO19_VOUT (0x1C) + +/* BUCK1 with DVC[0..3] */ +#define PM800_BUCK1 (0x3C) +#define PM800_BUCK1_1 (0x3D) +#define PM800_BUCK1_2 (0x3E) +#define PM800_BUCK1_3 (0x3F) +#define PM800_BUCK2 (0x40) +#define PM800_BUCK3 (0x41) +#define PM800_BUCK4 (0x42) +#define PM800_BUCK4_1 (0x43) +#define PM800_BUCK4_2 (0x44) +#define PM800_BUCK4_3 (0x45) +#define PM800_BUCK5 (0x46) + +#define PM800_BUCK_ENA (0x50) +#define PM800_LDO_ENA1_1 (0x51) +#define PM800_LDO_ENA1_2 (0x52) +#define PM800_LDO_ENA1_3 (0x53) + +#define PM800_LDO_ENA2_1 (0x56) +#define PM800_LDO_ENA2_2 (0x57) +#define PM800_LDO_ENA2_3 (0x58) + +#define PM800_BUCK1_MISC1 (0x78) +#define PM800_BUCK3_MISC1 (0x7E) +#define PM800_BUCK4_MISC1 (0x81) +#define PM800_BUCK5_MISC1 (0x84) + +struct pm800_regulator_info { + struct regulator_desc desc; + int max_ua; +}; + +/* + * vreg - the buck regs string. + * ereg - the string for the enable register. + * ebit - the bit number in the enable register. + * amax - the current + * Buck has 2 kinds of voltage steps. It is easy to find voltage by ranges, + * not the constant voltage table. + * n_volt - Number of available selectors + */ +#define PM800_BUCK(match, vreg, ereg, ebit, amax, volt_ranges, n_volt) \ +{ \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(#match), \ + .regulators_node = of_match_ptr("regulators"), \ + .ops = &pm800_volt_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = PM800_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = n_volt, \ + .linear_ranges = volt_ranges, \ + .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .vsel_reg = PM800_##vreg, \ + .vsel_mask = 0x7f, \ + .enable_reg = PM800_##ereg, \ + .enable_mask = 1 << (ebit), \ + }, \ + .max_ua = (amax), \ +} + +/* + * vreg - the LDO regs string + * ereg - the string for the enable register. + * ebit - the bit number in the enable register. + * amax - the current + * volt_table - the LDO voltage table + * For all the LDOes, there are too many ranges. Using volt_table will be + * simpler and faster. + */ +#define PM800_LDO(match, vreg, ereg, ebit, amax, ldo_volt_table) \ +{ \ + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(#match), \ + .regulators_node = of_match_ptr("regulators"), \ + .ops = &pm800_volt_table_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = PM800_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(ldo_volt_table), \ + .vsel_reg = PM800_##vreg##_VOUT, \ + .vsel_mask = 0xf, \ + .enable_reg = PM800_##ereg, \ + .enable_mask = 1 << (ebit), \ + .volt_table = ldo_volt_table, \ + }, \ + .max_ua = (amax), \ +} + +/* Ranges are sorted in ascending order. */ +static const struct regulator_linear_range buck1_volt_range[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500), + REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x54, 50000), +}; + +/* BUCK 2~5 have same ranges. */ +static const struct regulator_linear_range buck2_5_volt_range[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500), + REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x72, 50000), +}; + +static const unsigned int ldo1_volt_table[] = { + 600000, 650000, 700000, 750000, 800000, 850000, 900000, 950000, + 1000000, 1050000, 1100000, 1150000, 1200000, 1300000, 1400000, 1500000, +}; + +static const unsigned int ldo2_volt_table[] = { + 1700000, 1800000, 1900000, 2000000, 2100000, 2500000, 2700000, 2800000, +}; + +/* LDO 3~17 have same voltage table. */ +static const unsigned int ldo3_17_volt_table[] = { + 1200000, 1250000, 1700000, 1800000, 1850000, 1900000, 2500000, 2600000, + 2700000, 2750000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000, +}; + +/* LDO 18~19 have same voltage table. */ +static const unsigned int ldo18_19_volt_table[] = { + 1700000, 1800000, 1900000, 2500000, 2800000, 2900000, 3100000, 3300000, +}; + +static int pm800_get_current_limit(struct regulator_dev *rdev) +{ + struct pm800_regulator_info *info = rdev_get_drvdata(rdev); + + return info->max_ua; +} + +static const struct regulator_ops pm800_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, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_current_limit = pm800_get_current_limit, +}; + +static const struct regulator_ops pm800_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, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_current_limit = pm800_get_current_limit, +}; + +/* The array is indexed by id(PM800_ID_XXX) */ +static struct pm800_regulator_info pm800_regulator_info[] = { + PM800_BUCK(buck1, BUCK1, BUCK_ENA, 0, 3000000, buck1_volt_range, 0x55), + PM800_BUCK(buck2, BUCK2, BUCK_ENA, 1, 1200000, buck2_5_volt_range, 0x73), + PM800_BUCK(buck3, BUCK3, BUCK_ENA, 2, 1200000, buck2_5_volt_range, 0x73), + PM800_BUCK(buck4, BUCK4, BUCK_ENA, 3, 1200000, buck2_5_volt_range, 0x73), + PM800_BUCK(buck5, BUCK5, BUCK_ENA, 4, 1200000, buck2_5_volt_range, 0x73), + + PM800_LDO(ldo1, LDO1, LDO_ENA1_1, 0, 200000, ldo1_volt_table), + PM800_LDO(ldo2, LDO2, LDO_ENA1_1, 1, 10000, ldo2_volt_table), + PM800_LDO(ldo3, LDO3, LDO_ENA1_1, 2, 300000, ldo3_17_volt_table), + PM800_LDO(ldo4, LDO4, LDO_ENA1_1, 3, 300000, ldo3_17_volt_table), + PM800_LDO(ldo5, LDO5, LDO_ENA1_1, 4, 300000, ldo3_17_volt_table), + PM800_LDO(ldo6, LDO6, LDO_ENA1_1, 5, 300000, ldo3_17_volt_table), + PM800_LDO(ldo7, LDO7, LDO_ENA1_1, 6, 300000, ldo3_17_volt_table), + PM800_LDO(ldo8, LDO8, LDO_ENA1_1, 7, 300000, ldo3_17_volt_table), + PM800_LDO(ldo9, LDO9, LDO_ENA1_2, 0, 300000, ldo3_17_volt_table), + PM800_LDO(ldo10, LDO10, LDO_ENA1_2, 1, 300000, ldo3_17_volt_table), + PM800_LDO(ldo11, LDO11, LDO_ENA1_2, 2, 300000, ldo3_17_volt_table), + PM800_LDO(ldo12, LDO12, LDO_ENA1_2, 3, 300000, ldo3_17_volt_table), + PM800_LDO(ldo13, LDO13, LDO_ENA1_2, 4, 300000, ldo3_17_volt_table), + PM800_LDO(ldo14, LDO14, LDO_ENA1_2, 5, 300000, ldo3_17_volt_table), + PM800_LDO(ldo15, LDO15, LDO_ENA1_2, 6, 300000, ldo3_17_volt_table), + PM800_LDO(ldo16, LDO16, LDO_ENA1_2, 7, 300000, ldo3_17_volt_table), + PM800_LDO(ldo17, LDO17, LDO_ENA1_3, 0, 300000, ldo3_17_volt_table), + PM800_LDO(ldo18, LDO18, LDO_ENA1_3, 1, 200000, ldo18_19_volt_table), + PM800_LDO(ldo19, LDO19, LDO_ENA1_3, 2, 200000, ldo18_19_volt_table), +}; + +static int pm800_regulator_probe(struct platform_device *pdev) +{ + struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct pm80x_platform_data *pdata = dev_get_platdata(pdev->dev.parent); + struct regulator_config config = { }; + struct regulator_init_data *init_data; + int i, ret; + + if (pdata && pdata->num_regulators) { + unsigned int count = 0; + + /* Check whether num_regulator is valid. */ + for (i = 0; i < ARRAY_SIZE(pdata->regulators); i++) { + if (pdata->regulators[i]) + count++; + } + if (count != pdata->num_regulators) + return -EINVAL; + } + + config.dev = chip->dev; + config.regmap = chip->subchip->regmap_power; + for (i = 0; i < PM800_ID_RG_MAX; i++) { + struct regulator_dev *regulator; + + if (pdata && pdata->num_regulators) { + init_data = pdata->regulators[i]; + if (!init_data) + continue; + + config.init_data = init_data; + } + + config.driver_data = &pm800_regulator_info[i]; + + regulator = devm_regulator_register(&pdev->dev, + &pm800_regulator_info[i].desc, &config); + if (IS_ERR(regulator)) { + ret = PTR_ERR(regulator); + dev_err(&pdev->dev, "Failed to register %s\n", + pm800_regulator_info[i].desc.name); + return ret; + } + } + + return 0; +} + +static struct platform_driver pm800_regulator_driver = { + .driver = { + .name = "88pm80x-regulator", + }, + .probe = pm800_regulator_probe, +}; + +module_platform_driver(pm800_regulator_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Joseph(Yossi) Hanin "); +MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM800 PMIC"); +MODULE_ALIAS("platform:88pm800-regulator"); diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c deleted file mode 100644 index 9fd379732d18..000000000000 --- a/drivers/regulator/88pm800.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Regulators driver for Marvell 88PM800 - * - * Copyright (C) 2012 Marvell International Ltd. - * Joseph(Yossi) Hanin - * Yi Zhang - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* LDO1 with DVC[0..3] */ -#define PM800_LDO1_VOUT (0x08) /* VOUT1 */ -#define PM800_LDO1_VOUT_2 (0x09) -#define PM800_LDO1_VOUT_3 (0x0A) -#define PM800_LDO2_VOUT (0x0B) -#define PM800_LDO3_VOUT (0x0C) -#define PM800_LDO4_VOUT (0x0D) -#define PM800_LDO5_VOUT (0x0E) -#define PM800_LDO6_VOUT (0x0F) -#define PM800_LDO7_VOUT (0x10) -#define PM800_LDO8_VOUT (0x11) -#define PM800_LDO9_VOUT (0x12) -#define PM800_LDO10_VOUT (0x13) -#define PM800_LDO11_VOUT (0x14) -#define PM800_LDO12_VOUT (0x15) -#define PM800_LDO13_VOUT (0x16) -#define PM800_LDO14_VOUT (0x17) -#define PM800_LDO15_VOUT (0x18) -#define PM800_LDO16_VOUT (0x19) -#define PM800_LDO17_VOUT (0x1A) -#define PM800_LDO18_VOUT (0x1B) -#define PM800_LDO19_VOUT (0x1C) - -/* BUCK1 with DVC[0..3] */ -#define PM800_BUCK1 (0x3C) -#define PM800_BUCK1_1 (0x3D) -#define PM800_BUCK1_2 (0x3E) -#define PM800_BUCK1_3 (0x3F) -#define PM800_BUCK2 (0x40) -#define PM800_BUCK3 (0x41) -#define PM800_BUCK4 (0x42) -#define PM800_BUCK4_1 (0x43) -#define PM800_BUCK4_2 (0x44) -#define PM800_BUCK4_3 (0x45) -#define PM800_BUCK5 (0x46) - -#define PM800_BUCK_ENA (0x50) -#define PM800_LDO_ENA1_1 (0x51) -#define PM800_LDO_ENA1_2 (0x52) -#define PM800_LDO_ENA1_3 (0x53) - -#define PM800_LDO_ENA2_1 (0x56) -#define PM800_LDO_ENA2_2 (0x57) -#define PM800_LDO_ENA2_3 (0x58) - -#define PM800_BUCK1_MISC1 (0x78) -#define PM800_BUCK3_MISC1 (0x7E) -#define PM800_BUCK4_MISC1 (0x81) -#define PM800_BUCK5_MISC1 (0x84) - -struct pm800_regulator_info { - struct regulator_desc desc; - int max_ua; -}; - -/* - * vreg - the buck regs string. - * ereg - the string for the enable register. - * ebit - the bit number in the enable register. - * amax - the current - * Buck has 2 kinds of voltage steps. It is easy to find voltage by ranges, - * not the constant voltage table. - * n_volt - Number of available selectors - */ -#define PM800_BUCK(match, vreg, ereg, ebit, amax, volt_ranges, n_volt) \ -{ \ - .desc = { \ - .name = #vreg, \ - .of_match = of_match_ptr(#match), \ - .regulators_node = of_match_ptr("regulators"), \ - .ops = &pm800_volt_range_ops, \ - .type = REGULATOR_VOLTAGE, \ - .id = PM800_ID_##vreg, \ - .owner = THIS_MODULE, \ - .n_voltages = n_volt, \ - .linear_ranges = volt_ranges, \ - .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ - .vsel_reg = PM800_##vreg, \ - .vsel_mask = 0x7f, \ - .enable_reg = PM800_##ereg, \ - .enable_mask = 1 << (ebit), \ - }, \ - .max_ua = (amax), \ -} - -/* - * vreg - the LDO regs string - * ereg - the string for the enable register. - * ebit - the bit number in the enable register. - * amax - the current - * volt_table - the LDO voltage table - * For all the LDOes, there are too many ranges. Using volt_table will be - * simpler and faster. - */ -#define PM800_LDO(match, vreg, ereg, ebit, amax, ldo_volt_table) \ -{ \ - .desc = { \ - .name = #vreg, \ - .of_match = of_match_ptr(#match), \ - .regulators_node = of_match_ptr("regulators"), \ - .ops = &pm800_volt_table_ops, \ - .type = REGULATOR_VOLTAGE, \ - .id = PM800_ID_##vreg, \ - .owner = THIS_MODULE, \ - .n_voltages = ARRAY_SIZE(ldo_volt_table), \ - .vsel_reg = PM800_##vreg##_VOUT, \ - .vsel_mask = 0xf, \ - .enable_reg = PM800_##ereg, \ - .enable_mask = 1 << (ebit), \ - .volt_table = ldo_volt_table, \ - }, \ - .max_ua = (amax), \ -} - -/* Ranges are sorted in ascending order. */ -static const struct regulator_linear_range buck1_volt_range[] = { - REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500), - REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x54, 50000), -}; - -/* BUCK 2~5 have same ranges. */ -static const struct regulator_linear_range buck2_5_volt_range[] = { - REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500), - REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x72, 50000), -}; - -static const unsigned int ldo1_volt_table[] = { - 600000, 650000, 700000, 750000, 800000, 850000, 900000, 950000, - 1000000, 1050000, 1100000, 1150000, 1200000, 1300000, 1400000, 1500000, -}; - -static const unsigned int ldo2_volt_table[] = { - 1700000, 1800000, 1900000, 2000000, 2100000, 2500000, 2700000, 2800000, -}; - -/* LDO 3~17 have same voltage table. */ -static const unsigned int ldo3_17_volt_table[] = { - 1200000, 1250000, 1700000, 1800000, 1850000, 1900000, 2500000, 2600000, - 2700000, 2750000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000, -}; - -/* LDO 18~19 have same voltage table. */ -static const unsigned int ldo18_19_volt_table[] = { - 1700000, 1800000, 1900000, 2500000, 2800000, 2900000, 3100000, 3300000, -}; - -static int pm800_get_current_limit(struct regulator_dev *rdev) -{ - struct pm800_regulator_info *info = rdev_get_drvdata(rdev); - - return info->max_ua; -} - -static const struct regulator_ops pm800_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, - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .get_current_limit = pm800_get_current_limit, -}; - -static const struct regulator_ops pm800_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, - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .get_current_limit = pm800_get_current_limit, -}; - -/* The array is indexed by id(PM800_ID_XXX) */ -static struct pm800_regulator_info pm800_regulator_info[] = { - PM800_BUCK(buck1, BUCK1, BUCK_ENA, 0, 3000000, buck1_volt_range, 0x55), - PM800_BUCK(buck2, BUCK2, BUCK_ENA, 1, 1200000, buck2_5_volt_range, 0x73), - PM800_BUCK(buck3, BUCK3, BUCK_ENA, 2, 1200000, buck2_5_volt_range, 0x73), - PM800_BUCK(buck4, BUCK4, BUCK_ENA, 3, 1200000, buck2_5_volt_range, 0x73), - PM800_BUCK(buck5, BUCK5, BUCK_ENA, 4, 1200000, buck2_5_volt_range, 0x73), - - PM800_LDO(ldo1, LDO1, LDO_ENA1_1, 0, 200000, ldo1_volt_table), - PM800_LDO(ldo2, LDO2, LDO_ENA1_1, 1, 10000, ldo2_volt_table), - PM800_LDO(ldo3, LDO3, LDO_ENA1_1, 2, 300000, ldo3_17_volt_table), - PM800_LDO(ldo4, LDO4, LDO_ENA1_1, 3, 300000, ldo3_17_volt_table), - PM800_LDO(ldo5, LDO5, LDO_ENA1_1, 4, 300000, ldo3_17_volt_table), - PM800_LDO(ldo6, LDO6, LDO_ENA1_1, 5, 300000, ldo3_17_volt_table), - PM800_LDO(ldo7, LDO7, LDO_ENA1_1, 6, 300000, ldo3_17_volt_table), - PM800_LDO(ldo8, LDO8, LDO_ENA1_1, 7, 300000, ldo3_17_volt_table), - PM800_LDO(ldo9, LDO9, LDO_ENA1_2, 0, 300000, ldo3_17_volt_table), - PM800_LDO(ldo10, LDO10, LDO_ENA1_2, 1, 300000, ldo3_17_volt_table), - PM800_LDO(ldo11, LDO11, LDO_ENA1_2, 2, 300000, ldo3_17_volt_table), - PM800_LDO(ldo12, LDO12, LDO_ENA1_2, 3, 300000, ldo3_17_volt_table), - PM800_LDO(ldo13, LDO13, LDO_ENA1_2, 4, 300000, ldo3_17_volt_table), - PM800_LDO(ldo14, LDO14, LDO_ENA1_2, 5, 300000, ldo3_17_volt_table), - PM800_LDO(ldo15, LDO15, LDO_ENA1_2, 6, 300000, ldo3_17_volt_table), - PM800_LDO(ldo16, LDO16, LDO_ENA1_2, 7, 300000, ldo3_17_volt_table), - PM800_LDO(ldo17, LDO17, LDO_ENA1_3, 0, 300000, ldo3_17_volt_table), - PM800_LDO(ldo18, LDO18, LDO_ENA1_3, 1, 200000, ldo18_19_volt_table), - PM800_LDO(ldo19, LDO19, LDO_ENA1_3, 2, 200000, ldo18_19_volt_table), -}; - -static int pm800_regulator_probe(struct platform_device *pdev) -{ - struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct pm80x_platform_data *pdata = dev_get_platdata(pdev->dev.parent); - struct regulator_config config = { }; - struct regulator_init_data *init_data; - int i, ret; - - if (pdata && pdata->num_regulators) { - unsigned int count = 0; - - /* Check whether num_regulator is valid. */ - for (i = 0; i < ARRAY_SIZE(pdata->regulators); i++) { - if (pdata->regulators[i]) - count++; - } - if (count != pdata->num_regulators) - return -EINVAL; - } - - config.dev = chip->dev; - config.regmap = chip->subchip->regmap_power; - for (i = 0; i < PM800_ID_RG_MAX; i++) { - struct regulator_dev *regulator; - - if (pdata && pdata->num_regulators) { - init_data = pdata->regulators[i]; - if (!init_data) - continue; - - config.init_data = init_data; - } - - config.driver_data = &pm800_regulator_info[i]; - - regulator = devm_regulator_register(&pdev->dev, - &pm800_regulator_info[i].desc, &config); - if (IS_ERR(regulator)) { - ret = PTR_ERR(regulator); - dev_err(&pdev->dev, "Failed to register %s\n", - pm800_regulator_info[i].desc.name); - return ret; - } - } - - return 0; -} - -static struct platform_driver pm800_regulator_driver = { - .driver = { - .name = "88pm80x-regulator", - }, - .probe = pm800_regulator_probe, -}; - -module_platform_driver(pm800_regulator_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Joseph(Yossi) Hanin "); -MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM800 PMIC"); -MODULE_ALIAS("platform:88pm800-regulator"); diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 76e78fa449a2..c15b0b613766 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o obj-$(CONFIG_REGULATOR_88PG86X) += 88pg86x.o -obj-$(CONFIG_REGULATOR_88PM800) += 88pm800.o +obj-$(CONFIG_REGULATOR_88PM800) += 88pm800-regulator.o obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o obj-$(CONFIG_REGULATOR_CPCAP) += cpcap-regulator.o obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o -- cgit v1.2.3 From fd742eaab827b47c5f2de6c1811a17075608da60 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 9 Jun 2019 13:48:12 +0200 Subject: regulator: max8952: Convert to use GPIO descriptors This finalizes the descriptor conversion of the MAX8952 driver by letting the VID0 and VID1 GPIOs be fetched from descriptors. Both VID0 and VID1 must be supplied for the VID selection to work, I add some code to preserve the semantics that if only one of the two VID gpios is supplied, it will be initialized to low. This might be a bit overzealous, but I want to preserve any implicit semantics. This is currently only used by device tree in-kernel but it is still also possible to supply the same GPIOs using a machine descriptor table if a board file is used. Ideally this should be phased over to using gpio-regulator.c that does the same thing, but it might require some refactoring and needs testing on real hardware. Cc: Tomasz Figa Cc: MyungJoo Ham Cc: Marek Szyprowski Signed-off-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/max8952.c | 62 ++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 34 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 451237efb359..8f0e4dc810f0 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -26,11 +26,9 @@ #include #include #include -#include #include #include #include -#include #include #include @@ -50,7 +48,8 @@ enum { struct max8952_data { struct i2c_client *client; struct max8952_platform_data *pdata; - + struct gpio_desc *vid0_gpiod; + struct gpio_desc *vid1_gpiod; bool vid0; bool vid1; }; @@ -100,16 +99,15 @@ static int max8952_set_voltage_sel(struct regulator_dev *rdev, { struct max8952_data *max8952 = rdev_get_drvdata(rdev); - if (!gpio_is_valid(max8952->pdata->gpio_vid0) || - !gpio_is_valid(max8952->pdata->gpio_vid1)) { + if (!max8952->vid0_gpiod || !max8952->vid1_gpiod) { /* DVS not supported */ return -EPERM; } max8952->vid0 = selector & 0x1; max8952->vid1 = (selector >> 1) & 0x1; - gpio_set_value(max8952->pdata->gpio_vid0, max8952->vid0); - gpio_set_value(max8952->pdata->gpio_vid1, max8952->vid1); + gpiod_set_value(max8952->vid0_gpiod, max8952->vid0); + gpiod_set_value(max8952->vid1_gpiod, max8952->vid1); return 0; } @@ -147,9 +145,6 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev) if (!pd) return NULL; - pd->gpio_vid0 = of_get_named_gpio(np, "max8952,vid-gpios", 0); - pd->gpio_vid1 = of_get_named_gpio(np, "max8952,vid-gpios", 1); - if (of_property_read_u32(np, "max8952,default-mode", &pd->default_mode)) dev_warn(dev, "Default mode not specified, assuming 0\n"); @@ -200,7 +195,7 @@ static int max8952_pmic_probe(struct i2c_client *client, struct gpio_desc *gpiod; enum gpiod_flags gflags; - int ret = 0, err = 0; + int ret = 0; if (client->dev.of_node) pdata = max8952_parse_dt(&client->dev); @@ -253,32 +248,31 @@ static int max8952_pmic_probe(struct i2c_client *client, max8952->vid0 = pdata->default_mode & 0x1; max8952->vid1 = (pdata->default_mode >> 1) & 0x1; - if (gpio_is_valid(pdata->gpio_vid0) && - gpio_is_valid(pdata->gpio_vid1)) { - unsigned long gpio_flags; - - gpio_flags = max8952->vid0 ? - GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; - if (devm_gpio_request_one(&client->dev, pdata->gpio_vid0, - gpio_flags, "MAX8952 VID0")) - err = 1; - - gpio_flags = max8952->vid1 ? - GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; - if (devm_gpio_request_one(&client->dev, pdata->gpio_vid1, - gpio_flags, "MAX8952 VID1")) - err = 2; - } else - err = 3; - - if (err) { + /* Fetch vid0 and vid1 GPIOs if available */ + gflags = max8952->vid0 ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; + max8952->vid0_gpiod = devm_gpiod_get_index_optional(&client->dev, + "max8952,vid", + 0, gflags); + if (IS_ERR(max8952->vid0_gpiod)) + return PTR_ERR(max8952->vid0_gpiod); + gflags = max8952->vid1 ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; + max8952->vid1_gpiod = devm_gpiod_get_index_optional(&client->dev, + "max8952,vid", + 1, gflags); + if (IS_ERR(max8952->vid1_gpiod)) + return PTR_ERR(max8952->vid1_gpiod); + + /* If either VID GPIO is missing just disable this */ + if (!max8952->vid0_gpiod || !max8952->vid1_gpiod) { dev_warn(&client->dev, "VID0/1 gpio invalid: " - "DVS not available.\n"); + "DVS not available.\n"); max8952->vid0 = 0; max8952->vid1 = 0; - /* Mark invalid */ - pdata->gpio_vid0 = -1; - pdata->gpio_vid1 = -1; + /* Make sure if we have any descriptors they get set to low */ + if (max8952->vid0_gpiod) + gpiod_set_value(max8952->vid0_gpiod, 0); + if (max8952->vid1_gpiod) + gpiod_set_value(max8952->vid1_gpiod, 0); /* Disable Pulldown of EN only */ max8952_write_reg(max8952, MAX8952_REG_CONTROL, 0x60); -- cgit v1.2.3 From 86f4ff7a0c0cd8e391ffa4dd0edb82ae0eedcc9e Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Thu, 13 Jun 2019 14:25:30 -0700 Subject: regulator: qcom_spmi: enable linear range info Signed-off-by: Jorge Ramirez-Ortiz Signed-off-by: Jeffrey Hugo Signed-off-by: Mark Brown --- drivers/regulator/qcom_spmi-regulator.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/regulator') diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index 53a61fb65642..42c429d50743 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -1744,6 +1744,7 @@ MODULE_DEVICE_TABLE(of, qcom_spmi_regulator_match); static int qcom_spmi_regulator_probe(struct platform_device *pdev) { const struct spmi_regulator_data *reg; + const struct spmi_voltage_range *range; const struct of_device_id *match; struct regulator_config config = { }; struct regulator_dev *rdev; @@ -1833,6 +1834,12 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) } } + if (vreg->set_points->count == 1) { + /* since there is only one range */ + range = vreg->set_points->range; + vreg->desc.uV_step = range->step_uV; + } + config.dev = dev; config.driver_data = vreg; config.regmap = regmap; -- cgit v1.2.3 From ba576a6232dc06605f4edfaeea9b526ba7724f84 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Thu, 13 Jun 2019 14:25:31 -0700 Subject: regulator: qcom_spmi: Refactor get_mode/set_mode spmi_regulator_common_get_mode and spmi_regulator_common_set_mode use multi-level ifs which mirror a switch statement. Refactor to use a switch statement to make the code flow more clear. Signed-off-by: Jeffrey Hugo Reviewed-by: Bjorn Andersson Signed-off-by: Mark Brown --- drivers/regulator/qcom_spmi-regulator.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index 42c429d50743..1b3383a24c9d 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -911,13 +911,16 @@ static unsigned int spmi_regulator_common_get_mode(struct regulator_dev *rdev) spmi_vreg_read(vreg, SPMI_COMMON_REG_MODE, ®, 1); - if (reg & SPMI_COMMON_MODE_HPM_MASK) - return REGULATOR_MODE_NORMAL; + reg &= SPMI_COMMON_MODE_HPM_MASK | SPMI_COMMON_MODE_AUTO_MASK; - if (reg & SPMI_COMMON_MODE_AUTO_MASK) + switch (reg) { + case SPMI_COMMON_MODE_HPM_MASK: + return REGULATOR_MODE_NORMAL; + case SPMI_COMMON_MODE_AUTO_MASK: return REGULATOR_MODE_FAST; - - return REGULATOR_MODE_IDLE; + default: + return REGULATOR_MODE_IDLE; + } } static int @@ -925,12 +928,19 @@ spmi_regulator_common_set_mode(struct regulator_dev *rdev, unsigned int mode) { struct spmi_regulator *vreg = rdev_get_drvdata(rdev); u8 mask = SPMI_COMMON_MODE_HPM_MASK | SPMI_COMMON_MODE_AUTO_MASK; - u8 val = 0; + u8 val; - if (mode == REGULATOR_MODE_NORMAL) + switch (mode) { + case REGULATOR_MODE_NORMAL: val = SPMI_COMMON_MODE_HPM_MASK; - else if (mode == REGULATOR_MODE_FAST) + break; + case REGULATOR_MODE_FAST: val = SPMI_COMMON_MODE_AUTO_MASK; + break; + default: + val = 0; + break; + } return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask); } -- cgit v1.2.3 From f2c6203fdd1197d8254073a8f3f3372b0d3d9e6b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 17 Jun 2019 18:16:52 +0100 Subject: regulator: core: Make entire header comment C++ style Makes things look more consistent. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 15 +++++++-------- drivers/regulator/helpers.c | 11 +++++------ 2 files changed, 12 insertions(+), 14 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 85f61e5dc312..9d3ed13b7f12 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1,12 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later -/* - * core.c -- Voltage/Current Regulator framework. - * - * Copyright 2007, 2008 Wolfson Microelectronics PLC. - * Copyright 2008 SlimLogic Ltd. - * - * Author: Liam Girdwood - */ +// +// core.c -- Voltage/Current Regulator framework. +// +// Copyright 2007, 2008 Wolfson Microelectronics PLC. +// Copyright 2008 SlimLogic Ltd. +// +// Author: Liam Girdwood #include #include diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index b9ae45d2d199..4986cc5064a1 100644 --- a/drivers/regulator/helpers.c +++ b/drivers/regulator/helpers.c @@ -1,10 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later -/* - * helpers.c -- Voltage/Current Regulator framework helper functions. - * - * Copyright 2007, 2008 Wolfson Microelectronics PLC. - * Copyright 2008 SlimLogic Ltd. - */ +// +// helpers.c -- Voltage/Current Regulator framework helper functions. +// +// Copyright 2007, 2008 Wolfson Microelectronics PLC. +// Copyright 2008 SlimLogic Ltd. #include #include -- cgit v1.2.3 From 42ba89c8bbd95fce16122d357456ce1bd35d31d2 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Mon, 17 Jun 2019 11:37:29 -0700 Subject: regulator: qcom_spmi: Add support for PM8005 The PM8005 is used on the msm8998 MTP. The S1 regulator is VDD_GFX, ie it needs to be on and controlled inorder to use the GPU. Add support to drive the PM8005 regulators so that we can bring up the GPU on msm8998. Signed-off-by: Jeffrey Hugo Reviewed-by: Bjorn Andersson Signed-off-by: Mark Brown --- drivers/regulator/qcom_spmi-regulator.c | 176 ++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) (limited to 'drivers/regulator') diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index 00773a485fc1..ee38b1b63a3b 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -96,6 +96,7 @@ enum spmi_regulator_logical_type { SPMI_REGULATOR_LOGICAL_TYPE_ULT_LO_SMPS, SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS, SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO, + SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS426, }; enum spmi_regulator_type { @@ -142,6 +143,7 @@ enum spmi_regulator_subtype { SPMI_REGULATOR_SUBTYPE_5V_BOOST = 0x01, SPMI_REGULATOR_SUBTYPE_FTS_CTL = 0x08, SPMI_REGULATOR_SUBTYPE_FTS2p5_CTL = 0x09, + SPMI_REGULATOR_SUBTYPE_FTS426_CTL = 0x0a, SPMI_REGULATOR_SUBTYPE_BB_2A = 0x01, SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL1 = 0x0d, SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL2 = 0x0e, @@ -162,6 +164,18 @@ enum spmi_common_regulator_registers { SPMI_COMMON_REG_STEP_CTRL = 0x61, }; +/* + * Second common register layout used by newer devices starting with ftsmps426 + * Note that some of the registers from the first common layout remain + * unchanged and their definition is not duplicated. + */ +enum spmi_ftsmps426_regulator_registers { + SPMI_FTSMPS426_REG_VOLTAGE_LSB = 0x40, + SPMI_FTSMPS426_REG_VOLTAGE_MSB = 0x41, + SPMI_FTSMPS426_REG_VOLTAGE_ULS_LSB = 0x68, + SPMI_FTSMPS426_REG_VOLTAGE_ULS_MSB = 0x69, +}; + enum spmi_vs_registers { SPMI_VS_REG_OCP = 0x4a, SPMI_VS_REG_SOFT_START = 0x4c, @@ -221,6 +235,14 @@ enum spmi_common_control_register_index { #define SPMI_COMMON_MODE_FOLLOW_HW_EN0_MASK 0x01 #define SPMI_COMMON_MODE_FOLLOW_ALL_MASK 0x1f +#define SPMI_FTSMPS426_MODE_BYPASS_MASK 3 +#define SPMI_FTSMPS426_MODE_RETENTION_MASK 4 +#define SPMI_FTSMPS426_MODE_LPM_MASK 5 +#define SPMI_FTSMPS426_MODE_AUTO_MASK 6 +#define SPMI_FTSMPS426_MODE_HPM_MASK 7 + +#define SPMI_FTSMPS426_MODE_MASK 0x07 + /* Common regulator pull down control register layout */ #define SPMI_COMMON_PULL_DOWN_ENABLE_MASK 0x80 @@ -266,6 +288,23 @@ enum spmi_common_control_register_index { #define SPMI_FTSMPS_STEP_MARGIN_NUM 4 #define SPMI_FTSMPS_STEP_MARGIN_DEN 5 +#define SPMI_FTSMPS426_STEP_CTRL_DELAY_MASK 0x03 +#define SPMI_FTSMPS426_STEP_CTRL_DELAY_SHIFT 0 + +/* Clock rate in kHz of the FTSMPS426 regulator reference clock. */ +#define SPMI_FTSMPS426_CLOCK_RATE 4800 + +/* Minimum voltage stepper delay for each step. */ +#define SPMI_FTSMPS426_STEP_DELAY 2 + +/* + * The ratio SPMI_FTSMPS426_STEP_MARGIN_NUM/SPMI_FTSMPS426_STEP_MARGIN_DEN is + * used to adjust the step rate in order to account for oscillator variance. + */ +#define SPMI_FTSMPS426_STEP_MARGIN_NUM 10 +#define SPMI_FTSMPS426_STEP_MARGIN_DEN 11 + + /* VSET value to decide the range of ULT SMPS */ #define ULT_SMPS_RANGE_SPLIT 0x60 @@ -439,6 +478,10 @@ static struct spmi_voltage_range ftsmps2p5_ranges[] = { SPMI_VOLTAGE_RANGE(1, 160000, 1360000, 2200000, 2200000, 10000), }; +static struct spmi_voltage_range ftsmps426_ranges[] = { + SPMI_VOLTAGE_RANGE(0, 0, 320000, 1352000, 1352000, 4000), +}; + static struct spmi_voltage_range boost_ranges[] = { SPMI_VOLTAGE_RANGE(0, 4000000, 4000000, 5550000, 5550000, 50000), }; @@ -472,6 +515,7 @@ static DEFINE_SPMI_SET_POINTS(ln_ldo); static DEFINE_SPMI_SET_POINTS(smps); static DEFINE_SPMI_SET_POINTS(ftsmps); static DEFINE_SPMI_SET_POINTS(ftsmps2p5); +static DEFINE_SPMI_SET_POINTS(ftsmps426); static DEFINE_SPMI_SET_POINTS(boost); static DEFINE_SPMI_SET_POINTS(boost_byp); static DEFINE_SPMI_SET_POINTS(ult_lo_smps); @@ -739,6 +783,23 @@ spmi_regulator_common_set_voltage(struct regulator_dev *rdev, unsigned selector) return spmi_vreg_write(vreg, SPMI_COMMON_REG_VOLTAGE_RANGE, buf, 2); } +static int spmi_regulator_common_list_voltage(struct regulator_dev *rdev, + unsigned selector); + +static int spmi_regulator_ftsmps426_set_voltage(struct regulator_dev *rdev, + unsigned selector) +{ + struct spmi_regulator *vreg = rdev_get_drvdata(rdev); + u8 buf[2]; + int mV; + + mV = spmi_regulator_common_list_voltage(rdev, selector) / 1000; + + buf[0] = mV & 0xff; + buf[1] = mV >> 8; + return spmi_vreg_write(vreg, SPMI_FTSMPS426_REG_VOLTAGE_LSB, buf, 2); +} + static int spmi_regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_selector, unsigned int new_selector) { @@ -770,6 +831,21 @@ static int spmi_regulator_common_get_voltage(struct regulator_dev *rdev) return spmi_hw_selector_to_sw(vreg, voltage_sel, range); } +static int spmi_regulator_ftsmps426_get_voltage(struct regulator_dev *rdev) +{ + struct spmi_regulator *vreg = rdev_get_drvdata(rdev); + const struct spmi_voltage_range *range; + u8 buf[2]; + int uV; + + spmi_vreg_read(vreg, SPMI_FTSMPS426_REG_VOLTAGE_LSB, buf, 2); + + uV = (((unsigned int)buf[1] << 8) | (unsigned int)buf[0]) * 1000; + range = vreg->set_points->range; + + return (uV - range->set_point_min_uV) / range->step_uV; +} + static int spmi_regulator_single_map_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { @@ -915,6 +991,23 @@ static unsigned int spmi_regulator_common_get_mode(struct regulator_dev *rdev) } } +static unsigned int spmi_regulator_ftsmps426_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_FTSMPS426_MODE_HPM_MASK: + return REGULATOR_MODE_NORMAL; + case SPMI_FTSMPS426_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) { @@ -937,6 +1030,30 @@ spmi_regulator_common_set_mode(struct regulator_dev *rdev, unsigned int mode) return spmi_vreg_update_bits(vreg, SPMI_COMMON_REG_MODE, val, mask); } +static int +spmi_regulator_ftsmps426_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct spmi_regulator *vreg = rdev_get_drvdata(rdev); + u8 mask = SPMI_FTSMPS426_MODE_MASK; + u8 val; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + val = SPMI_FTSMPS426_MODE_HPM_MASK; + break; + case REGULATOR_MODE_FAST: + val = SPMI_FTSMPS426_MODE_AUTO_MASK; + break; + case REGULATOR_MODE_IDLE: + val = SPMI_FTSMPS426_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) { @@ -1266,6 +1383,21 @@ static struct regulator_ops spmi_ult_ldo_ops = { .set_soft_start = spmi_regulator_common_set_soft_start, }; +static struct regulator_ops spmi_ftsmps426_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_ftsmps426_set_mode, + .get_mode = spmi_regulator_ftsmps426_get_mode, + .set_load = spmi_regulator_common_set_load, + .set_pull_down = spmi_regulator_common_set_pull_down, +}; + /* Maximum possible digital major revision value */ #define INF 0xFF @@ -1301,6 +1433,7 @@ static const struct spmi_regulator_mapping supported_regulators[] = { SPMI_VREG(BOOST, 5V_BOOST, 0, INF, BOOST, boost, boost, 0), SPMI_VREG(FTS, FTS_CTL, 0, INF, FTSMPS, ftsmps, ftsmps, 100000), SPMI_VREG(FTS, FTS2p5_CTL, 0, INF, FTSMPS, ftsmps, ftsmps2p5, 100000), + SPMI_VREG(FTS, FTS426_CTL, 0, INF, FTSMPS426, ftsmps426, ftsmps426, 100000), SPMI_VREG(BOOST_BYP, BB_2A, 0, INF, BOOST_BYP, boost, boost_byp, 0), SPMI_VREG(ULT_BUCK, ULT_HF_CTL1, 0, INF, ULT_LO_SMPS, ult_lo_smps, ult_lo_smps, 100000), @@ -1438,6 +1571,34 @@ static int spmi_regulator_init_slew_rate(struct spmi_regulator *vreg) return ret; } +static int spmi_regulator_init_slew_rate_ftsmps426(struct spmi_regulator *vreg) +{ + int ret; + u8 reg = 0; + int delay, slew_rate; + const struct spmi_voltage_range *range = &vreg->set_points->range[0]; + + ret = spmi_vreg_read(vreg, SPMI_COMMON_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; + + /* slew_rate has units of uV/us */ + slew_rate = SPMI_FTSMPS426_CLOCK_RATE * range->step_uV; + slew_rate /= 1000 * (SPMI_FTSMPS426_STEP_DELAY << delay); + slew_rate *= SPMI_FTSMPS426_STEP_MARGIN_NUM; + slew_rate /= SPMI_FTSMPS426_STEP_MARGIN_DEN; + + /* Ensure that the slew rate is greater than 0 */ + vreg->slew_rate = max(slew_rate, 1); + + return ret; +} + static int spmi_regulator_init_registers(struct spmi_regulator *vreg, const struct spmi_regulator_init_data *data) { @@ -1577,6 +1738,12 @@ static int spmi_regulator_of_parse(struct device_node *node, ret = spmi_regulator_init_slew_rate(vreg); if (ret) return ret; + break; + case SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS426: + ret = spmi_regulator_init_slew_rate_ftsmps426(vreg); + if (ret) + return ret; + break; default: break; } @@ -1733,7 +1900,16 @@ static const struct spmi_regulator_data pmi8994_regulators[] = { { } }; +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 of_device_id qcom_spmi_regulator_match[] = { + { .compatible = "qcom,pm8005-regulators", .data = &pm8005_regulators }, { .compatible = "qcom,pm8841-regulators", .data = &pm8841_regulators }, { .compatible = "qcom,pm8916-regulators", .data = &pm8916_regulators }, { .compatible = "qcom,pm8941-regulators", .data = &pm8941_regulators }, -- cgit v1.2.3 From 0211f68e626fb02d33c1e4302d907a45366a2d93 Mon Sep 17 00:00:00 2001 From: Jorge Ramirez Date: Mon, 17 Jun 2019 11:38:27 -0700 Subject: regulator: qcom_spmi: add PMS405 SPMI regulator The PMS405 has 5 HFSMPS and 13 LDO regulators, This commit adds support for one of the 5 HFSMPS regulators (s3) to the spmi regulator driver. The PMIC HFSMPS 430 regulators have 8 mV step size and a voltage control scheme consisting of two 8-bit registers defining a 16-bit voltage set point in units of millivolts S3 controls the cpu voltages (s3 is a buck regulator of type HFS430); it is therefore required so we can enable voltage scaling for safely running cpufreq. Signed-off-by: Jorge Ramirez-Ortiz Signed-off-by: Jeffrey Hugo Signed-off-by: Mark Brown --- drivers/regulator/qcom_spmi-regulator.c | 43 ++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index ee38b1b63a3b..13f83be50076 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -97,6 +97,7 @@ enum spmi_regulator_logical_type { SPMI_REGULATOR_LOGICAL_TYPE_ULT_HO_SMPS, SPMI_REGULATOR_LOGICAL_TYPE_ULT_LDO, SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS426, + SPMI_REGULATOR_LOGICAL_TYPE_HFS430, }; enum spmi_regulator_type { @@ -149,6 +150,7 @@ enum spmi_regulator_subtype { SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL2 = 0x0e, SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL3 = 0x0f, SPMI_REGULATOR_SUBTYPE_ULT_HF_CTL4 = 0x10, + SPMI_REGULATOR_SUBTYPE_HFS430 = 0x0a, }; enum spmi_common_regulator_registers { @@ -294,6 +296,8 @@ enum spmi_common_control_register_index { /* Clock rate in kHz of the FTSMPS426 regulator reference clock. */ #define SPMI_FTSMPS426_CLOCK_RATE 4800 +#define SPMI_HFS430_CLOCK_RATE 1600 + /* Minimum voltage stepper delay for each step. */ #define SPMI_FTSMPS426_STEP_DELAY 2 @@ -507,6 +511,10 @@ static struct spmi_voltage_range ult_pldo_ranges[] = { SPMI_VOLTAGE_RANGE(0, 1750000, 1750000, 3337500, 3337500, 12500), }; +static struct spmi_voltage_range hfs430_ranges[] = { + SPMI_VOLTAGE_RANGE(0, 320000, 320000, 2040000, 2040000, 8000), +}; + static DEFINE_SPMI_SET_POINTS(pldo); static DEFINE_SPMI_SET_POINTS(nldo1); static DEFINE_SPMI_SET_POINTS(nldo2); @@ -522,6 +530,7 @@ static DEFINE_SPMI_SET_POINTS(ult_lo_smps); static DEFINE_SPMI_SET_POINTS(ult_ho_smps); static DEFINE_SPMI_SET_POINTS(ult_nldo); static DEFINE_SPMI_SET_POINTS(ult_pldo); +static DEFINE_SPMI_SET_POINTS(hfs430); static inline int spmi_vreg_read(struct spmi_regulator *vreg, u16 addr, u8 *buf, int len) @@ -1398,12 +1407,26 @@ static struct regulator_ops spmi_ftsmps426_ops = { .set_pull_down = spmi_regulator_common_set_pull_down, }; +static struct regulator_ops spmi_hfs430_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_ftsmps426_set_mode, + .get_mode = spmi_regulator_ftsmps426_get_mode, +}; + /* Maximum possible digital major revision value */ #define INF 0xFF static const struct spmi_regulator_mapping supported_regulators[] = { /* type subtype dig_min dig_max ltype ops setpoints hpm_min */ SPMI_VREG(BUCK, GP_CTL, 0, INF, SMPS, smps, smps, 100000), + SPMI_VREG(BUCK, HFS430, 0, INF, HFS430, hfs430, hfs430, 10000), 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), @@ -1571,7 +1594,8 @@ static int spmi_regulator_init_slew_rate(struct spmi_regulator *vreg) return ret; } -static int spmi_regulator_init_slew_rate_ftsmps426(struct spmi_regulator *vreg) +static int spmi_regulator_init_slew_rate_ftsmps426(struct spmi_regulator *vreg, + int clock_rate) { int ret; u8 reg = 0; @@ -1588,7 +1612,7 @@ static int spmi_regulator_init_slew_rate_ftsmps426(struct spmi_regulator *vreg) delay >>= SPMI_FTSMPS426_STEP_CTRL_DELAY_SHIFT; /* slew_rate has units of uV/us */ - slew_rate = SPMI_FTSMPS426_CLOCK_RATE * range->step_uV; + slew_rate = clock_rate * range->step_uV; slew_rate /= 1000 * (SPMI_FTSMPS426_STEP_DELAY << delay); slew_rate *= SPMI_FTSMPS426_STEP_MARGIN_NUM; slew_rate /= SPMI_FTSMPS426_STEP_MARGIN_DEN; @@ -1740,7 +1764,14 @@ static int spmi_regulator_of_parse(struct device_node *node, return ret; break; case SPMI_REGULATOR_LOGICAL_TYPE_FTSMPS426: - ret = spmi_regulator_init_slew_rate_ftsmps426(vreg); + ret = spmi_regulator_init_slew_rate_ftsmps426(vreg, + SPMI_FTSMPS426_CLOCK_RATE); + if (ret) + return ret; + break; + case SPMI_REGULATOR_LOGICAL_TYPE_HFS430: + ret = spmi_regulator_init_slew_rate_ftsmps426(vreg, + SPMI_HFS430_CLOCK_RATE); if (ret) return ret; break; @@ -1908,6 +1939,11 @@ static const struct spmi_regulator_data pm8005_regulators[] = { { } }; +static const struct spmi_regulator_data pms405_regulators[] = { + { "s3", 0x1a00, "vdd_s3"}, + { } +}; + static const struct of_device_id qcom_spmi_regulator_match[] = { { .compatible = "qcom,pm8005-regulators", .data = &pm8005_regulators }, { .compatible = "qcom,pm8841-regulators", .data = &pm8841_regulators }, @@ -1915,6 +1951,7 @@ static const struct of_device_id qcom_spmi_regulator_match[] = { { .compatible = "qcom,pm8941-regulators", .data = &pm8941_regulators }, { .compatible = "qcom,pm8994-regulators", .data = &pm8994_regulators }, { .compatible = "qcom,pmi8994-regulators", .data = &pmi8994_regulators }, + { .compatible = "qcom,pms405-regulators", .data = &pms405_regulators }, { } }; MODULE_DEVICE_TABLE(of, qcom_spmi_regulator_match); -- cgit v1.2.3 From fd5d10059d5ead12dd12f05ae6d96e70d1fac3df Mon Sep 17 00:00:00 2001 From: Felix Riemann Date: Thu, 20 Jun 2019 08:45:00 +0100 Subject: regulator: da9061/62: Adjust LDO voltage selection minimum value According to the DA9061 and DA9062 datasheets the LDO voltage selection registers have a lower value of 0x02. This applies to voltage registers VLDO1_A, VLDO2_A, VLDO3_A and VLDO4_A. This linear offset of 0x02 was previously not observed by the driver, causing the LDO output voltage to be systematically lower by two steps (= 0.1V). This patch fixes the minimum linear selector offset by setting it to a value of 2 and increases the n_voltages by the same amount allowing voltages in the range 0x02 -> 0.9V to 0x38 -> 3.6V to be correctly selected. Also fixes an incorrect calculaton for the n_voltages value in the regulator LDO2. These fixes effect all LDO regulators for DA9061 and DA9062. Acked-by: Steve Twiss Tested-by: Steve Twiss Signed-off-by: Felix Riemann Signed-off-by: Steve Twiss Signed-off-by: Mark Brown --- drivers/regulator/da9062-regulator.c | 40 +++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c index a02e0488410f..2ffc64622451 100644 --- a/drivers/regulator/da9062-regulator.c +++ b/drivers/regulator/da9062-regulator.c @@ -493,12 +493,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = { .desc.ops = &da9062_ldo_ops, .desc.min_uV = (900) * 1000, .desc.uV_step = (50) * 1000, - .desc.n_voltages = ((3600) - (900))/(50) + 1, + .desc.n_voltages = ((3600) - (900))/(50) + 1 + + DA9062AA_VLDO_A_MIN_SEL, .desc.enable_reg = DA9062AA_LDO1_CONT, .desc.enable_mask = DA9062AA_LDO1_EN_MASK, .desc.vsel_reg = DA9062AA_VLDO1_A, .desc.vsel_mask = DA9062AA_VLDO1_A_MASK, - .desc.linear_min_sel = 0, + .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL, .sleep = REG_FIELD(DA9062AA_VLDO1_A, __builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1, sizeof(unsigned int) * 8 - @@ -525,12 +526,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = { .desc.ops = &da9062_ldo_ops, .desc.min_uV = (900) * 1000, .desc.uV_step = (50) * 1000, - .desc.n_voltages = ((3600) - (600))/(50) + 1, + .desc.n_voltages = ((3600) - (900))/(50) + 1 + + DA9062AA_VLDO_A_MIN_SEL, .desc.enable_reg = DA9062AA_LDO2_CONT, .desc.enable_mask = DA9062AA_LDO2_EN_MASK, .desc.vsel_reg = DA9062AA_VLDO2_A, .desc.vsel_mask = DA9062AA_VLDO2_A_MASK, - .desc.linear_min_sel = 0, + .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL, .sleep = REG_FIELD(DA9062AA_VLDO2_A, __builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1, sizeof(unsigned int) * 8 - @@ -557,12 +559,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = { .desc.ops = &da9062_ldo_ops, .desc.min_uV = (900) * 1000, .desc.uV_step = (50) * 1000, - .desc.n_voltages = ((3600) - (900))/(50) + 1, + .desc.n_voltages = ((3600) - (900))/(50) + 1 + + DA9062AA_VLDO_A_MIN_SEL, .desc.enable_reg = DA9062AA_LDO3_CONT, .desc.enable_mask = DA9062AA_LDO3_EN_MASK, .desc.vsel_reg = DA9062AA_VLDO3_A, .desc.vsel_mask = DA9062AA_VLDO3_A_MASK, - .desc.linear_min_sel = 0, + .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL, .sleep = REG_FIELD(DA9062AA_VLDO3_A, __builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1, sizeof(unsigned int) * 8 - @@ -589,12 +592,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = { .desc.ops = &da9062_ldo_ops, .desc.min_uV = (900) * 1000, .desc.uV_step = (50) * 1000, - .desc.n_voltages = ((3600) - (900))/(50) + 1, + .desc.n_voltages = ((3600) - (900))/(50) + 1 + + DA9062AA_VLDO_A_MIN_SEL, .desc.enable_reg = DA9062AA_LDO4_CONT, .desc.enable_mask = DA9062AA_LDO4_EN_MASK, .desc.vsel_reg = DA9062AA_VLDO4_A, .desc.vsel_mask = DA9062AA_VLDO4_A_MASK, - .desc.linear_min_sel = 0, + .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL, .sleep = REG_FIELD(DA9062AA_VLDO4_A, __builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1, sizeof(unsigned int) * 8 - @@ -769,12 +773,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = { .desc.ops = &da9062_ldo_ops, .desc.min_uV = (900) * 1000, .desc.uV_step = (50) * 1000, - .desc.n_voltages = ((3600) - (900))/(50) + 1, + .desc.n_voltages = ((3600) - (900))/(50) + 1 + + DA9062AA_VLDO_A_MIN_SEL, .desc.enable_reg = DA9062AA_LDO1_CONT, .desc.enable_mask = DA9062AA_LDO1_EN_MASK, .desc.vsel_reg = DA9062AA_VLDO1_A, .desc.vsel_mask = DA9062AA_VLDO1_A_MASK, - .desc.linear_min_sel = 0, + .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL, .sleep = REG_FIELD(DA9062AA_VLDO1_A, __builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1, sizeof(unsigned int) * 8 - @@ -801,12 +806,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = { .desc.ops = &da9062_ldo_ops, .desc.min_uV = (900) * 1000, .desc.uV_step = (50) * 1000, - .desc.n_voltages = ((3600) - (600))/(50) + 1, + .desc.n_voltages = ((3600) - (900))/(50) + 1 + + DA9062AA_VLDO_A_MIN_SEL, .desc.enable_reg = DA9062AA_LDO2_CONT, .desc.enable_mask = DA9062AA_LDO2_EN_MASK, .desc.vsel_reg = DA9062AA_VLDO2_A, .desc.vsel_mask = DA9062AA_VLDO2_A_MASK, - .desc.linear_min_sel = 0, + .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL, .sleep = REG_FIELD(DA9062AA_VLDO2_A, __builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1, sizeof(unsigned int) * 8 - @@ -833,12 +839,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = { .desc.ops = &da9062_ldo_ops, .desc.min_uV = (900) * 1000, .desc.uV_step = (50) * 1000, - .desc.n_voltages = ((3600) - (900))/(50) + 1, + .desc.n_voltages = ((3600) - (900))/(50) + 1 + + DA9062AA_VLDO_A_MIN_SEL, .desc.enable_reg = DA9062AA_LDO3_CONT, .desc.enable_mask = DA9062AA_LDO3_EN_MASK, .desc.vsel_reg = DA9062AA_VLDO3_A, .desc.vsel_mask = DA9062AA_VLDO3_A_MASK, - .desc.linear_min_sel = 0, + .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL, .sleep = REG_FIELD(DA9062AA_VLDO3_A, __builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1, sizeof(unsigned int) * 8 - @@ -865,12 +872,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = { .desc.ops = &da9062_ldo_ops, .desc.min_uV = (900) * 1000, .desc.uV_step = (50) * 1000, - .desc.n_voltages = ((3600) - (900))/(50) + 1, + .desc.n_voltages = ((3600) - (900))/(50) + 1 + + DA9062AA_VLDO_A_MIN_SEL, .desc.enable_reg = DA9062AA_LDO4_CONT, .desc.enable_mask = DA9062AA_LDO4_EN_MASK, .desc.vsel_reg = DA9062AA_VLDO4_A, .desc.vsel_mask = DA9062AA_VLDO4_A_MASK, - .desc.linear_min_sel = 0, + .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL, .sleep = REG_FIELD(DA9062AA_VLDO4_A, __builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1, sizeof(unsigned int) * 8 - -- cgit v1.2.3 From 61d7fdc49f03f4ec990974d1d2a8b05e64afeae4 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Wed, 19 Jun 2019 11:56:36 -0700 Subject: regulator: qcom_spmi: Fix math of spmi_regulator_set_voltage_time_sel spmi_regulator_set_voltage_time_sel() calculates the amount of delay needed as the result of setting a new voltage. Essentially this is the absolute difference of the old and new voltages, divided by the slew rate. The implementation of spmi_regulator_set_voltage_time_sel() is wrong. It attempts to calculate the difference in voltages by using the difference in selectors and multiplying by the voltage step between selectors. This ignores the possibility that the old and new selectors might be from different ranges, which have different step values. Also, the difference between the selectors may encapsulate N ranges inbetween, so a summation of each selector change from old to new would be needed. Lets avoid all of that complexity, and just get the actual voltage represented by both the old and new selector, and use those to directly compute the voltage delta. This is more straight forward, and has the side benifit of avoiding issues with regulator implementations that don't have hardware register support to get the current configured range. Fixes: e92a4047419c ("regulator: Add QCOM SPMI regulator driver") Reported-by: Bjorn Andersson Reported-by: Jorge Ramirez-Ortiz Reported-by: Mark Brown Signed-off-by: Jeffrey Hugo Reviewed-by: Bjorn Andersson Tested-by: Jorge Ramirez-Ortiz Signed-off-by: Mark Brown --- drivers/regulator/qcom_spmi-regulator.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index 13f83be50076..877df33e0246 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -813,14 +813,10 @@ static int spmi_regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_selector, unsigned int new_selector) { struct spmi_regulator *vreg = rdev_get_drvdata(rdev); - const struct spmi_voltage_range *range; int diff_uV; - range = spmi_regulator_find_range(vreg); - if (!range) - return -EINVAL; - - diff_uV = abs(new_selector - old_selector) * range->step_uV; + diff_uV = abs(spmi_regulator_common_list_voltage(rdev, new_selector) - + spmi_regulator_common_list_voltage(rdev, old_selector)); return DIV_ROUND_UP(diff_uV, vreg->slew_rate); } -- cgit v1.2.3 From b01d18232587881ae813d4a1d14c8d9a2ac36b15 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Thu, 20 Jun 2019 07:22:28 -0700 Subject: regulator: qcom_spmi: Do NULL check for lvs Low-voltage switches (lvs) don't have set_points since the voltage ranges of the output are really controlled by the inputs. This is a problem for the newly added linear range support in the probe(), as that will cause a null pointer dereference error on older platforms like msm8974 which happen to need to control some of the implemented lvs. Fix this by adding the appropriate null check. Fixes: 86f4ff7a0c0c ("regulator: qcom_spmi: enable linear range info") Reported-by: Bjorn Andersson Signed-off-by: Jeffrey Hugo Tested-by: Bjorn Andersson Signed-off-by: Mark Brown --- drivers/regulator/qcom_spmi-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/qcom_spmi-regulator.c b/drivers/regulator/qcom_spmi-regulator.c index 877df33e0246..7f51c5fc8194 100644 --- a/drivers/regulator/qcom_spmi-regulator.c +++ b/drivers/regulator/qcom_spmi-regulator.c @@ -2045,7 +2045,7 @@ static int qcom_spmi_regulator_probe(struct platform_device *pdev) } } - if (vreg->set_points->count == 1) { + if (vreg->set_points && vreg->set_points->count == 1) { /* since there is only one range */ range = vreg->set_points->range; vreg->desc.uV_step = range->step_uV; -- cgit v1.2.3 From df33799c5c3262a69acd29b7a4eb9e7cbd1b007c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 20 Jun 2019 20:35:26 +0200 Subject: regulator: s2mps11: Reduce number of rdev_get_id() calls Store the regulator ID instead of calling rdev_get_id() every time. This makes code slightly easier to read as shorter 'rdev_id' variable is used instead of full call. This can also speed things up by reducing number of calls, although effect was not measured. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 134c62db36c5..93570712eb56 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -70,10 +70,11 @@ static int s2mps11_regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int new_selector) { struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); + int rdev_id = rdev_get_id(rdev); unsigned int ramp_delay = 0; int old_volt, new_volt; - switch (rdev_get_id(rdev)) { + switch (rdev_id) { case S2MPS11_BUCK2: ramp_delay = s2mps11->ramp_delay2; break; @@ -111,9 +112,10 @@ static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); unsigned int ramp_val, ramp_shift, ramp_reg = S2MPS11_REG_RAMP_BUCK; unsigned int ramp_enable = 1, enable_shift = 0; + int rdev_id = rdev_get_id(rdev); int ret; - switch (rdev_get_id(rdev)) { + switch (rdev_id) { case S2MPS11_BUCK1: if (ramp_delay > s2mps11->ramp_delay16) s2mps11->ramp_delay16 = ramp_delay; @@ -203,9 +205,8 @@ static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) goto ramp_disable; /* Ramp delay can be enabled/disabled only for buck[2346] */ - if ((rdev_get_id(rdev) >= S2MPS11_BUCK2 && - rdev_get_id(rdev) <= S2MPS11_BUCK4) || - rdev_get_id(rdev) == S2MPS11_BUCK6) { + if ((rdev_id >= S2MPS11_BUCK2 && rdev_id <= S2MPS11_BUCK4) || + rdev_id == S2MPS11_BUCK6) { ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP, 1 << enable_shift, 1 << enable_shift); if (ret) { @@ -503,20 +504,21 @@ static const struct regulator_desc s2mps13_regulators[] = { static int s2mps14_regulator_enable(struct regulator_dev *rdev) { struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); + int rdev_id = rdev_get_id(rdev); unsigned int val; switch (s2mps11->dev_type) { case S2MPS13X: case S2MPS14X: - if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state)) + if (test_bit(rdev_id, s2mps11->suspend_state)) val = S2MPS14_ENABLE_SUSPEND; - else if (s2mps11->ext_control_gpiod[rdev_get_id(rdev)]) + else if (s2mps11->ext_control_gpiod[rdev_id]) val = S2MPS14_ENABLE_EXT_CONTROL; else val = rdev->desc->enable_mask; break; case S2MPU02: - if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state)) + if (test_bit(rdev_id, s2mps11->suspend_state)) val = S2MPU02_ENABLE_SUSPEND; else val = rdev->desc->enable_mask; @@ -570,7 +572,7 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev) if (ret < 0) return ret; - set_bit(rdev_get_id(rdev), s2mps11->suspend_state); + set_bit(rdev_id, s2mps11->suspend_state); /* * Don't enable suspend mode if regulator is already disabled because * this would effectively for a short time turn on the regulator after @@ -856,8 +858,9 @@ static int s2mps11_pmic_dt_parse(struct platform_device *pdev, static int s2mpu02_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) { unsigned int ramp_val, ramp_shift, ramp_reg; + int rdev_id = rdev_get_id(rdev); - switch (rdev_get_id(rdev)) { + switch (rdev_id) { case S2MPU02_BUCK1: ramp_shift = S2MPU02_BUCK1_RAMP_SHIFT; break; -- cgit v1.2.3 From 65d80db2ee92330269e90313c6af782036f4d23d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 20 Jun 2019 20:35:27 +0200 Subject: regulator: s2mps11: Add support for disabling S2MPS11 regulators in suspend The driver supported turning off regulators in suspend only for S2MPS14 device. However this makes also sense for S2MPS11 and can reduce the power consumption during suspend to RAM. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 210 ++++++++++++++++++++++++-------------------- 1 file changed, 115 insertions(+), 95 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 93570712eb56..9c06ecd80a90 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -34,7 +34,7 @@ struct s2mps11_info { enum sec_device_type dev_type; /* - * One bit for each S2MPS13/S2MPS14/S2MPU02 regulator whether + * One bit for each S2MPS11/S2MPS13/S2MPS14/S2MPU02 regulator whether * the suspend mode was enabled. */ DECLARE_BITMAP(suspend_state, S2MPS_REGULATOR_MAX); @@ -225,27 +225,133 @@ ramp_disable: 1 << enable_shift, 0); } +static int s2mps11_regulator_enable(struct regulator_dev *rdev) +{ + struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); + int rdev_id = rdev_get_id(rdev); + unsigned int val; + + switch (s2mps11->dev_type) { + case S2MPS11X: + if (test_bit(rdev_id, s2mps11->suspend_state)) + val = S2MPS14_ENABLE_SUSPEND; + else + val = rdev->desc->enable_mask; + break; + case S2MPS13X: + case S2MPS14X: + if (test_bit(rdev_id, s2mps11->suspend_state)) + val = S2MPS14_ENABLE_SUSPEND; + else if (s2mps11->ext_control_gpiod[rdev_id]) + val = S2MPS14_ENABLE_EXT_CONTROL; + else + val = rdev->desc->enable_mask; + break; + case S2MPU02: + if (test_bit(rdev_id, s2mps11->suspend_state)) + val = S2MPU02_ENABLE_SUSPEND; + else + val = rdev->desc->enable_mask; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, val); +} + +static int s2mps11_regulator_set_suspend_disable(struct regulator_dev *rdev) +{ + int ret; + unsigned int val, state; + struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); + int rdev_id = rdev_get_id(rdev); + + /* Below LDO should be always on or does not support suspend mode. */ + switch (s2mps11->dev_type) { + case S2MPS11X: + switch (rdev_id) { + case S2MPS11_LDO2: + case S2MPS11_LDO36: + case S2MPS11_LDO37: + case S2MPS11_LDO38: + return 0; + default: + state = S2MPS14_ENABLE_SUSPEND; + break; + } + break; + case S2MPS13X: + case S2MPS14X: + switch (rdev_id) { + case S2MPS14_LDO3: + return 0; + default: + state = S2MPS14_ENABLE_SUSPEND; + break; + } + break; + case S2MPU02: + switch (rdev_id) { + case S2MPU02_LDO13: + case S2MPU02_LDO14: + case S2MPU02_LDO15: + case S2MPU02_LDO17: + case S2MPU02_BUCK7: + state = S2MPU02_DISABLE_SUSPEND; + break; + default: + state = S2MPU02_ENABLE_SUSPEND; + break; + } + break; + default: + return -EINVAL; + } + + ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); + if (ret < 0) + return ret; + + set_bit(rdev_id, s2mps11->suspend_state); + /* + * Don't enable suspend mode if regulator is already disabled because + * this would effectively for a short time turn on the regulator after + * resuming. + * However we still want to toggle the suspend_state bit for regulator + * in case if it got enabled before suspending the system. + */ + if (!(val & rdev->desc->enable_mask)) + return 0; + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, state); +} + static const struct regulator_ops s2mps11_ldo_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, - .enable = regulator_enable_regmap, + .enable = s2mps11_regulator_enable, .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_suspend_disable = s2mps11_regulator_set_suspend_disable, }; static const struct regulator_ops s2mps11_buck_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, - .enable = regulator_enable_regmap, + .enable = s2mps11_regulator_enable, .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_time_sel = s2mps11_regulator_set_voltage_time_sel, .set_ramp_delay = s2mps11_set_ramp_delay, + .set_suspend_disable = s2mps11_regulator_set_suspend_disable, }; #define regulator_desc_s2mps11_ldo(num, step) { \ @@ -501,102 +607,16 @@ static const struct regulator_desc s2mps13_regulators[] = { regulator_desc_s2mps13_buck8_10(10, MIN_500_MV, STEP_6_25_MV, 0x10), }; -static int s2mps14_regulator_enable(struct regulator_dev *rdev) -{ - struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); - int rdev_id = rdev_get_id(rdev); - unsigned int val; - - switch (s2mps11->dev_type) { - case S2MPS13X: - case S2MPS14X: - if (test_bit(rdev_id, s2mps11->suspend_state)) - val = S2MPS14_ENABLE_SUSPEND; - else if (s2mps11->ext_control_gpiod[rdev_id]) - val = S2MPS14_ENABLE_EXT_CONTROL; - else - val = rdev->desc->enable_mask; - break; - case S2MPU02: - if (test_bit(rdev_id, s2mps11->suspend_state)) - val = S2MPU02_ENABLE_SUSPEND; - else - val = rdev->desc->enable_mask; - break; - default: - return -EINVAL; - } - - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, val); -} - -static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev) -{ - int ret; - unsigned int val, state; - struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); - int rdev_id = rdev_get_id(rdev); - - /* Below LDO should be always on or does not support suspend mode. */ - switch (s2mps11->dev_type) { - case S2MPS13X: - case S2MPS14X: - switch (rdev_id) { - case S2MPS14_LDO3: - return 0; - default: - state = S2MPS14_ENABLE_SUSPEND; - break; - } - break; - case S2MPU02: - switch (rdev_id) { - case S2MPU02_LDO13: - case S2MPU02_LDO14: - case S2MPU02_LDO15: - case S2MPU02_LDO17: - case S2MPU02_BUCK7: - state = S2MPU02_DISABLE_SUSPEND; - break; - default: - state = S2MPU02_ENABLE_SUSPEND; - break; - } - break; - default: - return -EINVAL; - } - - ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); - if (ret < 0) - return ret; - - set_bit(rdev_id, s2mps11->suspend_state); - /* - * Don't enable suspend mode if regulator is already disabled because - * this would effectively for a short time turn on the regulator after - * resuming. - * However we still want to toggle the suspend_state bit for regulator - * in case if it got enabled before suspending the system. - */ - if (!(val & rdev->desc->enable_mask)) - return 0; - - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, state); -} - static const struct regulator_ops s2mps14_reg_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, - .enable = s2mps14_regulator_enable, + .enable = s2mps11_regulator_enable, .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_time_sel = regulator_set_voltage_time_sel, - .set_suspend_disable = s2mps14_regulator_set_suspend_disable, + .set_suspend_disable = s2mps11_regulator_set_suspend_disable, }; #define regulator_desc_s2mps14_ldo(num, min, step) { \ @@ -888,24 +908,24 @@ static const struct regulator_ops s2mpu02_ldo_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, - .enable = s2mps14_regulator_enable, + .enable = s2mps11_regulator_enable, .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_time_sel = regulator_set_voltage_time_sel, - .set_suspend_disable = s2mps14_regulator_set_suspend_disable, + .set_suspend_disable = s2mps11_regulator_set_suspend_disable, }; static const struct regulator_ops s2mpu02_buck_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, - .enable = s2mps14_regulator_enable, + .enable = s2mps11_regulator_enable, .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_time_sel = regulator_set_voltage_time_sel, - .set_suspend_disable = s2mps14_regulator_set_suspend_disable, + .set_suspend_disable = s2mps11_regulator_set_suspend_disable, .set_ramp_delay = s2mpu02_set_ramp_delay, }; -- cgit v1.2.3 From 025bf37725f1929542361eef2245df30badf242e Mon Sep 17 00:00:00 2001 From: Waibel Georg Date: Thu, 20 Jun 2019 21:37:08 +0000 Subject: gpio: Fix return value mismatch of function gpiod_get_from_of_node() In case the requested gpio property is not found in the device tree, some callers of gpiod_get_from_of_node() expect a return value of NULL, others expect -ENOENT. In particular devm_fwnode_get_index_gpiod_from_child() expects -ENOENT. Currently it gets a NULL, which breaks the loop that tries all gpio_suffixes. The result is that a gpio property is not found, even though it is there. This patch changes gpiod_get_from_of_node() to return -ENOENT instead of NULL when the requested gpio property is not found in the device tree. Additionally it modifies all calling functions to properly evaluate the return value. Another approach would be to leave the return value of gpiod_get_from_of_node() as is and fix the bug in devm_fwnode_get_index_gpiod_from_child(). Other callers would still need to be reworked. The effort would be the same as with the chosen solution. Signed-off-by: Georg Waibel Reviewed-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/da9211-regulator.c | 2 ++ drivers/regulator/s2mps11.c | 4 +++- drivers/regulator/s5m8767.c | 4 +++- drivers/regulator/tps65090-regulator.c | 7 ++++--- 4 files changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index da37b4ccd834..0309823d2c72 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -289,6 +289,8 @@ static struct da9211_pdata *da9211_parse_regulators_dt( 0, GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, "da9211-enable"); + if (IS_ERR(pdata->gpiod_ren[n])) + pdata->gpiod_ren[n] = NULL; n++; } diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 9c06ecd80a90..e5a74ae40687 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -843,7 +843,9 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev, 0, GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, "s2mps11-regulator"); - if (IS_ERR(gpio[reg])) { + if (PTR_ERR(gpio[reg]) == -ENOENT) + gpio[reg] = NULL; + else if (IS_ERR(gpio[reg])) { dev_err(&pdev->dev, "Failed to get control GPIO for %d/%s\n", reg, rdata[reg].name); continue; diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index bb9d1a083299..6ca27e9d5ef7 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -574,7 +574,9 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, 0, GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, "s5m8767"); - if (IS_ERR(rdata->ext_control_gpiod)) + if (PTR_ERR(rdata->ext_control_gpiod) == -ENOENT) + rdata->ext_control_gpiod = NULL; + else if (IS_ERR(rdata->ext_control_gpiod)) return PTR_ERR(rdata->ext_control_gpiod); rdata->id = i; diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index ca39b3d55123..10ea4b5a0f55 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c @@ -371,11 +371,12 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data( "dcdc-ext-control-gpios", 0, gflags, "tps65090"); - if (IS_ERR(rpdata->gpiod)) - return ERR_CAST(rpdata->gpiod); - if (!rpdata->gpiod) + if (PTR_ERR(rpdata->gpiod) == -ENOENT) { dev_err(&pdev->dev, "could not find DCDC external control GPIO\n"); + rpdata->gpiod = NULL; + } else if (IS_ERR(rpdata->gpiod)) + return ERR_CAST(rpdata->gpiod); } if (of_property_read_u32(tps65090_matches[idx].of_node, -- cgit v1.2.3 From 4e210fbeee8e2f0eb04761c624fcccc8401eba4c Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Mon, 1 Jul 2019 10:14:23 +0200 Subject: regulator: add support for the stm32-booster Add support for the 3.3V booster regulator embedded in stm32h7 and stm32mp1 devices, that can be used to supply ADC analog input switches. This regulator is supplied by vdda. It's controlled by using SYSCFG: - STM32H7 has a unique register to set/clear the booster enable bit - STM32MP1 has separate set and clear registers to configure it. Signed-off-by: Fabrice Gasnier Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 11 ++++ drivers/regulator/Makefile | 1 + drivers/regulator/stm32-booster.c | 132 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 drivers/regulator/stm32-booster.c (limited to 'drivers/regulator') diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 0e7d425ba9b1..1e590ecf1a9d 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -839,6 +839,17 @@ config REGULATOR_SLG51000 The SLG51000 is seven compact and customizable low dropout regulators. +config REGULATOR_STM32_BOOSTER + tristate "STMicroelectronics STM32 BOOSTER" + depends on ARCH_STM32 || COMPILE_TEST + help + This driver supports internal booster (3V3) embedded in some + STMicroelectronics STM32 chips. It can be used to supply ADC analog + input switches when vdda supply is below 2.7V. + + This driver can also be built as a module. If so, the module + will be called stm32-booster. + config REGULATOR_STM32_VREFBUF tristate "STMicroelectronics STM32 VREFBUF" depends on ARCH_STM32 || COMPILE_TEST diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index c15b0b613766..eef73b5a35a4 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -105,6 +105,7 @@ obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o obj-$(CONFIG_REGULATOR_SLG51000) += slg51000-regulator.o +obj-$(CONFIG_REGULATOR_STM32_BOOSTER) += stm32-booster.o obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o diff --git a/drivers/regulator/stm32-booster.c b/drivers/regulator/stm32-booster.c new file mode 100644 index 000000000000..2a897666c650 --- /dev/null +++ b/drivers/regulator/stm32-booster.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) STMicroelectronics 2019 +// Author(s): Fabrice Gasnier . + +#include +#include +#include +#include +#include +#include +#include + +/* STM32H7 SYSCFG register */ +#define STM32H7_SYSCFG_PMCR 0x04 +#define STM32H7_SYSCFG_BOOSTE_MASK BIT(8) + +/* STM32MP1 SYSCFG has set and clear registers */ +#define STM32MP1_SYSCFG_PMCSETR 0x04 +#define STM32MP1_SYSCFG_PMCCLRR 0x44 +#define STM32MP1_SYSCFG_EN_BOOSTER_MASK BIT(8) + +static const struct regulator_ops stm32h7_booster_ops = { + .list_voltage = regulator_list_voltage_linear, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const struct regulator_desc stm32h7_booster_desc = { + .name = "booster", + .supply_name = "vdda", + .n_voltages = 1, + .type = REGULATOR_VOLTAGE, + .min_uV = 3300000, + .fixed_uV = 3300000, + .ramp_delay = 66000, /* up to 50us to stabilize */ + .ops = &stm32h7_booster_ops, + .enable_reg = STM32H7_SYSCFG_PMCR, + .enable_mask = STM32H7_SYSCFG_BOOSTE_MASK, + .owner = THIS_MODULE, +}; + +static int stm32mp1_booster_enable(struct regulator_dev *rdev) +{ + return regmap_write(rdev->regmap, STM32MP1_SYSCFG_PMCSETR, + STM32MP1_SYSCFG_EN_BOOSTER_MASK); +} + +static int stm32mp1_booster_disable(struct regulator_dev *rdev) +{ + return regmap_write(rdev->regmap, STM32MP1_SYSCFG_PMCCLRR, + STM32MP1_SYSCFG_EN_BOOSTER_MASK); +} + +static const struct regulator_ops stm32mp1_booster_ops = { + .list_voltage = regulator_list_voltage_linear, + .enable = stm32mp1_booster_enable, + .disable = stm32mp1_booster_disable, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const struct regulator_desc stm32mp1_booster_desc = { + .name = "booster", + .supply_name = "vdda", + .n_voltages = 1, + .type = REGULATOR_VOLTAGE, + .min_uV = 3300000, + .fixed_uV = 3300000, + .ramp_delay = 66000, + .ops = &stm32mp1_booster_ops, + .enable_reg = STM32MP1_SYSCFG_PMCSETR, + .enable_mask = STM32MP1_SYSCFG_EN_BOOSTER_MASK, + .owner = THIS_MODULE, +}; + +static int stm32_booster_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = pdev->dev.of_node; + struct regulator_config config = { }; + const struct regulator_desc *desc; + struct regulator_dev *rdev; + struct regmap *regmap; + int ret; + + regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + desc = (const struct regulator_desc *) + of_match_device(dev->driver->of_match_table, dev)->data; + + config.regmap = regmap; + config.dev = dev; + config.of_node = np; + config.init_data = of_get_regulator_init_data(dev, np, desc); + + rdev = devm_regulator_register(dev, desc, &config); + if (IS_ERR(rdev)) { + ret = PTR_ERR(rdev); + dev_err(dev, "register failed with error %d\n", ret); + return ret; + } + + return 0; +} + +static const struct of_device_id stm32_booster_of_match[] = { + { + .compatible = "st,stm32h7-booster", + .data = (void *)&stm32h7_booster_desc + }, { + .compatible = "st,stm32mp1-booster", + .data = (void *)&stm32mp1_booster_desc + }, { + }, +}; +MODULE_DEVICE_TABLE(of, stm32_booster_of_match); + +static struct platform_driver stm32_booster_driver = { + .probe = stm32_booster_probe, + .driver = { + .name = "stm32-booster", + .of_match_table = of_match_ptr(stm32_booster_of_match), + }, +}; +module_platform_driver(stm32_booster_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Fabrice Gasnier "); +MODULE_DESCRIPTION("STMicroelectronics STM32 booster regulator driver"); +MODULE_ALIAS("platform:stm32-booster"); -- cgit v1.2.3 From a3c7c029c3da01645f2db1bf7737668d17c2c78a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 3 Jul 2019 09:20:09 +0100 Subject: regulator: max77620: remove redundant assignment to variable ret The variable ret is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190703082009.18779-1-colin.king@canonical.com Signed-off-by: Mark Brown --- drivers/regulator/max77620-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/max77620-regulator.c b/drivers/regulator/max77620-regulator.c index 2ae2d319321b..8d9731e4052b 100644 --- a/drivers/regulator/max77620-regulator.c +++ b/drivers/regulator/max77620-regulator.c @@ -467,7 +467,7 @@ static int max77620_regulator_is_enabled(struct regulator_dev *rdev) { struct max77620_regulator *pmic = rdev_get_drvdata(rdev); int id = rdev_get_id(rdev); - int ret = 1; + int ret; if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE) return 1; -- cgit v1.2.3 From ba2bf340ade89e71c53273ea115c7872865782c1 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 3 Jul 2019 10:48:49 +0200 Subject: regulator: max77650: add MODULE_ALIAS() Define a MODULE_ALIAS() in the regulator sub-driver for max77650 so that the appropriate module gets loaded together with the core mfd driver. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20190703084849.9668-1-brgl@bgdev.pl Signed-off-by: Mark Brown --- drivers/regulator/max77650-regulator.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/regulator') diff --git a/drivers/regulator/max77650-regulator.c b/drivers/regulator/max77650-regulator.c index e3b28fc68cdb..b79fe93c8edb 100644 --- a/drivers/regulator/max77650-regulator.c +++ b/drivers/regulator/max77650-regulator.c @@ -452,3 +452,4 @@ module_platform_driver(max77650_regulator_driver); MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver"); MODULE_AUTHOR("Bartosz Golaszewski "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:max77650-regulator"); -- cgit v1.2.3 From 2da8d9473e20a2f6645dcb0cea4848a2c1e83af9 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 3 Jul 2019 18:10:34 +0200 Subject: regulator: implement selector stepping Some regulators require that the requested voltage be reached gradually by setting all or some of the intermediate values. Implement a new field in the regulator description struct that allows users to specify the number of selectors by which the regulator API should step when ramping the voltage up/down. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20190703161035.31808-2-brgl@bgdev.pl Signed-off-by: Mark Brown --- drivers/regulator/core.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'drivers/regulator') diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 9d3ed13b7f12..df82e2a8442a 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3106,6 +3106,66 @@ static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, return ret; } +static int _regulator_set_voltage_sel_step(struct regulator_dev *rdev, + int uV, int new_selector) +{ + const struct regulator_ops *ops = rdev->desc->ops; + int diff, old_sel, curr_sel, ret; + + /* Stepping is only needed if the regulator is enabled. */ + if (!_regulator_is_enabled(rdev)) + goto final_set; + + if (!ops->get_voltage_sel) + return -EINVAL; + + old_sel = ops->get_voltage_sel(rdev); + if (old_sel < 0) + return old_sel; + + diff = new_selector - old_sel; + if (diff == 0) + return 0; /* No change needed. */ + + if (diff > 0) { + /* Stepping up. */ + for (curr_sel = old_sel + rdev->desc->vsel_step; + curr_sel < new_selector; + curr_sel += rdev->desc->vsel_step) { + /* + * Call the callback directly instead of using + * _regulator_call_set_voltage_sel() as we don't + * want to notify anyone yet. Same in the branch + * below. + */ + ret = ops->set_voltage_sel(rdev, curr_sel); + if (ret) + goto try_revert; + } + } else { + /* Stepping down. */ + for (curr_sel = old_sel - rdev->desc->vsel_step; + curr_sel > new_selector; + curr_sel -= rdev->desc->vsel_step) { + ret = ops->set_voltage_sel(rdev, curr_sel); + if (ret) + goto try_revert; + } + } + +final_set: + /* The final selector will trigger the notifiers. */ + return _regulator_call_set_voltage_sel(rdev, uV, new_selector); + +try_revert: + /* + * At least try to return to the previous voltage if setting a new + * one failed. + */ + (void)ops->set_voltage_sel(rdev, old_sel); + return ret; +} + static int _regulator_set_voltage_time(struct regulator_dev *rdev, int old_uV, int new_uV) { @@ -3179,6 +3239,9 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, selector = ret; if (old_selector == selector) ret = 0; + else if (rdev->desc->vsel_step) + ret = _regulator_set_voltage_sel_step( + rdev, best_val, selector); else ret = _regulator_call_set_voltage_sel( rdev, best_val, selector); -- cgit v1.2.3 From 3c7577d442a76c2015dd765497395fb394b78051 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 3 Jul 2019 18:10:35 +0200 Subject: regulator: max77650: use vsel_step Use the new vsel_step field in the regulator description to instruct the regulator API on the required voltage ramping. Switch to using the generic regmap helpers for voltage setting and remove the old set_voltage callback that handcoded the selector stepping. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20190703161035.31808-3-brgl@bgdev.pl Signed-off-by: Mark Brown --- drivers/regulator/max77650-regulator.c | 73 +++++----------------------------- 1 file changed, 9 insertions(+), 64 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/max77650-regulator.c b/drivers/regulator/max77650-regulator.c index b79fe93c8edb..e57fc9197d62 100644 --- a/drivers/regulator/max77650-regulator.c +++ b/drivers/regulator/max77650-regulator.c @@ -108,67 +108,6 @@ static int max77650_regulator_disable(struct regulator_dev *rdev) MAX77650_REGULATOR_DISABLED); } -static int max77650_regulator_set_voltage_sel(struct regulator_dev *rdev, - unsigned int sel) -{ - struct max77650_regulator_desc *rdesc = rdev_get_drvdata(rdev); - int rv = 0, curr, diff; - bool ascending; - - /* - * If the regulator is disabled, we can program the desired - * voltage right away. - */ - if (!max77650_regulator_is_enabled(rdev)) { - if (rdesc == &max77651_SBB1_desc) - return regulator_set_voltage_sel_pickable_regmap(rdev, - sel); - else - return regulator_set_voltage_sel_regmap(rdev, sel); - } - - /* - * Otherwise we need to manually ramp the output voltage up/down - * one step at a time. - */ - - if (rdesc == &max77651_SBB1_desc) - curr = regulator_get_voltage_sel_pickable_regmap(rdev); - else - curr = regulator_get_voltage_sel_regmap(rdev); - - if (curr < 0) - return curr; - - diff = curr - sel; - if (diff == 0) - return 0; /* Already there. */ - else if (diff > 0) - ascending = false; - else - ascending = true; - - /* - * Make sure we'll get to the right voltage and break the loop even if - * the selector equals 0. - */ - for (ascending ? curr++ : curr--;; ascending ? curr++ : curr--) { - if (rdesc == &max77651_SBB1_desc) - rv = regulator_set_voltage_sel_pickable_regmap(rdev, - curr); - else - rv = regulator_set_voltage_sel_regmap(rdev, curr); - - if (rv) - return rv; - - if (curr == sel) - break; - } - - return 0; -} - static const struct regulator_ops max77650_regulator_LDO_ops = { .is_enabled = max77650_regulator_is_enabled, .enable = max77650_regulator_enable, @@ -176,7 +115,7 @@ static const struct regulator_ops max77650_regulator_LDO_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = max77650_regulator_set_voltage_sel, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_active_discharge = regulator_set_active_discharge_regmap, }; @@ -187,7 +126,7 @@ static const struct regulator_ops max77650_regulator_SBB_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = max77650_regulator_set_voltage_sel, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_current_limit = regulator_get_current_limit_regmap, .set_current_limit = regulator_set_current_limit_regmap, .set_active_discharge = regulator_set_active_discharge_regmap, @@ -200,7 +139,7 @@ static const struct regulator_ops max77651_SBB1_regulator_ops = { .disable = max77650_regulator_disable, .list_voltage = regulator_list_voltage_pickable_linear_range, .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, - .set_voltage_sel = max77650_regulator_set_voltage_sel, + .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap, .get_current_limit = regulator_get_current_limit_regmap, .set_current_limit = regulator_set_current_limit_regmap, .set_active_discharge = regulator_set_active_discharge_regmap, @@ -217,6 +156,7 @@ static struct max77650_regulator_desc max77650_LDO_desc = { .min_uV = 1350000, .uV_step = 12500, .n_voltages = 128, + .vsel_step = 1, .vsel_mask = MAX77650_REGULATOR_V_LDO_MASK, .vsel_reg = MAX77650_REG_CNFG_LDO_A, .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, @@ -242,6 +182,7 @@ static struct max77650_regulator_desc max77650_SBB0_desc = { .min_uV = 800000, .uV_step = 25000, .n_voltages = 64, + .vsel_step = 1, .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, .vsel_reg = MAX77650_REG_CNFG_SBB0_A, .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, @@ -271,6 +212,7 @@ static struct max77650_regulator_desc max77650_SBB1_desc = { .min_uV = 800000, .uV_step = 12500, .n_voltages = 64, + .vsel_step = 1, .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, .vsel_reg = MAX77650_REG_CNFG_SBB1_A, .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, @@ -301,6 +243,7 @@ static struct max77650_regulator_desc max77651_SBB1_desc = { .linear_ranges = max77651_sbb1_volt_ranges, .n_linear_ranges = ARRAY_SIZE(max77651_sbb1_volt_ranges), .n_voltages = 58, + .vsel_step = 1, .vsel_range_mask = MAX77651_REGULATOR_V_SBB1_RANGE_MASK, .vsel_range_reg = MAX77650_REG_CNFG_SBB1_A, .vsel_mask = MAX77651_REGULATOR_V_SBB1_MASK, @@ -332,6 +275,7 @@ static struct max77650_regulator_desc max77650_SBB2_desc = { .min_uV = 800000, .uV_step = 50000, .n_voltages = 64, + .vsel_step = 1, .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, .vsel_reg = MAX77650_REG_CNFG_SBB2_A, .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, @@ -361,6 +305,7 @@ static struct max77650_regulator_desc max77651_SBB2_desc = { .min_uV = 2400000, .uV_step = 50000, .n_voltages = 64, + .vsel_step = 1, .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK, .vsel_reg = MAX77650_REG_CNFG_SBB2_A, .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED, -- cgit v1.2.3