Commit 5fb565b6 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'regulator/for-5.8' into regulator-linus

parents cc580454 0b0c0bd8
......@@ -73,6 +73,8 @@ number as described in MAX8998 datasheet.
- ESAFEOUT1: (ldo19)
- ESAFEOUT2: (ld020)
- CHARGER: main battery charger current control
Standard regulator bindings are used inside regulator subnodes. Check
Documentation/devicetree/bindings/regulator/regulator.txt
for more details.
......@@ -113,5 +115,11 @@ Example:
regulator-always-on;
regulator-boot-on;
};
charger_reg: CHARGER {
regulator-name = "CHARGER";
regulator-min-microamp = <90000>;
regulator-max-microamp = <800000>;
};
};
};
Anatop Voltage regulators
Required properties:
- compatible: Must be "fsl,anatop-regulator"
- regulator-name: A string used as a descriptive name for regulator outputs
- anatop-reg-offset: Anatop MFD register offset
- anatop-vol-bit-shift: Bit shift for the register
- anatop-vol-bit-width: Number of bits used in the register
- anatop-min-bit-val: Minimum value of this register
- anatop-min-voltage: Minimum voltage of this regulator
- anatop-max-voltage: Maximum voltage of this regulator
Optional properties:
- anatop-delay-reg-offset: Anatop MFD step time register offset
- anatop-delay-bit-shift: Bit shift for the step time register
- anatop-delay-bit-width: Number of bits used in the step time register
- vin-supply: The supply for this regulator
- anatop-enable-bit: Regulator enable bit offset
Any property defined as part of the core regulator
binding, defined in regulator.txt, can also be used.
Example:
regulator-vddpu {
compatible = "fsl,anatop-regulator";
regulator-name = "vddpu";
regulator-min-microvolt = <725000>;
regulator-max-microvolt = <1300000>;
regulator-always-on;
anatop-reg-offset = <0x140>;
anatop-vol-bit-shift = <9>;
anatop-vol-bit-width = <5>;
anatop-delay-reg-offset = <0x170>;
anatop-delay-bit-shift = <24>;
anatop-delay-bit-width = <2>;
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1300000>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/anatop-regulator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale Anatop Voltage Regulators
maintainers:
- Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
allOf:
- $ref: "regulator.yaml#"
properties:
compatible:
const: fsl,anatop-regulator
regulator-name: true
anatop-reg-offset:
$ref: '/schemas/types.yaml#/definitions/uint32'
description: u32 value representing the anatop MFD register offset.
anatop-vol-bit-shift:
$ref: '/schemas/types.yaml#/definitions/uint32'
description: u32 value representing the bit shift for the register.
anatop-vol-bit-width:
$ref: '/schemas/types.yaml#/definitions/uint32'
description: u32 value representing the number of bits used in the register.
anatop-min-bit-val:
$ref: '/schemas/types.yaml#/definitions/uint32'
description: u32 value representing the minimum value of this register.
anatop-min-voltage:
$ref: '/schemas/types.yaml#/definitions/uint32'
description: u32 value representing the minimum voltage of this regulator.
anatop-max-voltage:
$ref: '/schemas/types.yaml#/definitions/uint32'
description: u32 value representing the maximum voltage of this regulator.
anatop-delay-reg-offset:
$ref: '/schemas/types.yaml#/definitions/uint32'
description: u32 value representing the anatop MFD step time register offset.
anatop-delay-bit-shift:
$ref: '/schemas/types.yaml#/definitions/uint32'
description: u32 value representing the bit shift for the step time register.
anatop-delay-bit-width:
$ref: '/schemas/types.yaml#/definitions/uint32'
description: u32 value representing the number of bits used in the step time register.
anatop-enable-bit:
$ref: '/schemas/types.yaml#/definitions/uint32'
description: u32 value representing regulator enable bit offset.
vin-supply:
$ref: '/schemas/types.yaml#/definitions/phandle'
description: input supply phandle.
required:
- compatible
- regulator-name
- anatop-reg-offset
- anatop-vol-bit-shift
- anatop-vol-bit-width
- anatop-min-bit-val
- anatop-min-voltage
- anatop-max-voltage
unevaluatedProperties: false
examples:
- |
regulator-vddpu {
compatible = "fsl,anatop-regulator";
regulator-name = "vddpu";
regulator-min-microvolt = <725000>;
regulator-max-microvolt = <1300000>;
regulator-always-on;
anatop-reg-offset = <0x140>;
anatop-vol-bit-shift = <9>;
anatop-vol-bit-width = <5>;
anatop-delay-reg-offset = <0x170>;
anatop-delay-bit-shift = <24>;
anatop-delay-bit-width = <2>;
anatop-min-bit-val = <1>;
anatop-min-voltage = <725000>;
anatop-max-voltage = <1300000>;
};
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/maxim,max77826.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim Integrated MAX77826 PMIC
maintainers:
- Iskren Chernev <iskren.chernev@gmail.com>
properties:
$nodename:
pattern: "pmic@[0-9a-f]{1,2}"
compatible:
enum:
- maxim,max77826
reg:
maxItems: 1
regulators:
type: object
allOf:
- $ref: regulator.yaml#
description: |
list of regulators provided by this controller, must be named
after their hardware counterparts LDO[1-15], BUCK and BUCKBOOST
patternProperties:
"^LDO([1-9]|1[0-5])$":
type: object
allOf:
- $ref: regulator.yaml#
"^BUCK|BUCKBOOST$":
type: object
allOf:
- $ref: regulator.yaml#
additionalProperties: false
required:
- compatible
- reg
- regulators
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@69 {
compatible = "maxim,max77826";
reg = <0x69>;
regulators {
LDO2 {
regulator-min-microvolt = <650000>;
regulator-max-microvolt = <3587500>;
};
};
};
};
...
......@@ -9725,6 +9725,13 @@ F: drivers/lightnvm/
F: include/linux/lightnvm.h
F: include/uapi/linux/lightnvm.h
LINEAR RANGES HELPERS
M: Mark Brown <broonie@kernel.org>
R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
F: lib/linear_ranges.c
F: lib/test_linear_ranges.c
F: include/linux/linear_range.h
LINUX FOR POWER MACINTOSH
M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
L: linuxppc-dev@lists.ozlabs.org
......
......@@ -335,14 +335,14 @@ static int bd70528_get_present(struct bd70528_psy *bdpsy, int *val)
return 0;
}
struct linear_range {
struct bd70528_linear_range {
int min;
int step;
int vals;
int low_sel;
};
static const struct linear_range current_limit_ranges[] = {
static const struct bd70528_linear_range current_limit_ranges[] = {
{
.min = 5,
.step = 1,
......@@ -374,7 +374,7 @@ static const struct linear_range current_limit_ranges[] = {
* voltage for low temperatures. The driver currently only reads
* the charge current at room temperature. We do set both though.
*/
static const struct linear_range warm_charge_curr[] = {
static const struct bd70528_linear_range warm_charge_curr[] = {
{
.min = 10,
.step = 10,
......@@ -398,7 +398,7 @@ static const struct linear_range warm_charge_curr[] = {
#define MAX_WARM_CHG_CURR_SEL 0x1f
#define MIN_CHG_CURR_SEL 0x0
static int find_value_for_selector_low(const struct linear_range *r,
static int find_value_for_selector_low(const struct bd70528_linear_range *r,
int selectors, unsigned int sel,
unsigned int *val)
{
......@@ -420,7 +420,7 @@ static int find_value_for_selector_low(const struct linear_range *r,
* I guess it is enough if we use voltage/current which is closest (below)
* the requested?
*/
static int find_selector_for_value_low(const struct linear_range *r,
static int find_selector_for_value_low(const struct bd70528_linear_range *r,
int selectors, unsigned int val,
unsigned int *sel, bool *found)
{
......
......@@ -11,13 +11,13 @@ static const struct regulator_ops pg86x_ops = {
.list_voltage = regulator_list_voltage_linear_range,
};
static const struct regulator_linear_range pg86x_buck1_ranges[] = {
static const struct linear_range pg86x_buck1_ranges[] = {
REGULATOR_LINEAR_RANGE( 0, 0, 10, 0),
REGULATOR_LINEAR_RANGE(1000000, 11, 34, 25000),
REGULATOR_LINEAR_RANGE(1600000, 35, 47, 50000),
};
static const struct regulator_linear_range pg86x_buck2_ranges[] = {
static const struct linear_range pg86x_buck2_ranges[] = {
REGULATOR_LINEAR_RANGE( 0, 0, 15, 0),
REGULATOR_LINEAR_RANGE(1000000, 16, 39, 25000),
REGULATOR_LINEAR_RANGE(1600000, 40, 52, 50000),
......
......@@ -134,13 +134,13 @@ struct pm800_regulator_info {
}
/* Ranges are sorted in ascending order. */
static const struct regulator_linear_range buck1_volt_range[] = {
static const struct 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[] = {
static const struct linear_range buck2_5_volt_range[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500),
REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x72, 50000),
};
......
# SPDX-License-Identifier: GPL-2.0-only
menuconfig REGULATOR
bool "Voltage and Current Regulator Support"
select LINEAR_RANGES
help
Generic Voltage and Current Regulator support.
......@@ -585,6 +586,16 @@ config REGULATOR_MAX77802
Exynos5420/Exynos5800 SoCs to control various voltages.
It includes support for control of voltage and ramp speed.
config REGULATOR_MAX77826
tristate "Maxim 77826 regulator"
depends on I2C
select REGMAP_I2C
help
This driver controls a Maxim 77826 regulator via I2C bus.
The regulator include 15 LDOs, BUCK and BUCK BOOST regulator.
It includes support for control of output voltage. This
regulator is found on the Samsung Galaxy S5 (klte) smartphone.
config REGULATOR_MC13XXX_CORE
tristate
......
......@@ -74,6 +74,7 @@ obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
obj-$(CONFIG_REGULATOR_MAX77686) += max77686-regulator.o
obj-$(CONFIG_REGULATOR_MAX77693) += max77693-regulator.o
obj-$(CONFIG_REGULATOR_MAX77802) += max77802-regulator.o
obj-$(CONFIG_REGULATOR_MAX77826) += max77826-regulator.o
obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
......
......@@ -139,17 +139,6 @@ static const unsigned int ldo_vintcore_voltages[] = {
1350000,
};
static const unsigned int ldo_sdio_voltages[] = {
1160000,
1050000,
1100000,
1500000,
1800000,
2200000,
2910000,
3050000,
};
static const unsigned int fixed_1200000_voltage[] = {
1200000,
};
......@@ -166,10 +155,6 @@ static const unsigned int fixed_2050000_voltage[] = {
2050000,
};
static const unsigned int fixed_3300000_voltage[] = {
3300000,
};
static const unsigned int ldo_vana_voltages[] = {
1050000,
1075000,
......@@ -192,13 +177,6 @@ static const unsigned int ldo_vaudio_voltages[] = {
2600000, /* Duplicated in Vaudio and IsoUicc Control register. */
};
static const unsigned int ldo_vdmic_voltages[] = {
1800000,
1900000,
2000000,
2850000,
};
static DEFINE_MUTEX(shared_mode_mutex);
static struct ab8500_shared_mode ldo_anamic1_shared;
static struct ab8500_shared_mode ldo_anamic2_shared;
......
......@@ -220,13 +220,13 @@ static const struct regmap_config act8865_regmap_config = {
.val_bits = 8,
};
static const struct regulator_linear_range act8865_voltage_ranges[] = {
static const struct linear_range act8865_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000),
REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000),
REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
};
static const struct regulator_linear_range act8600_sudcdc_voltage_ranges[] = {
static const struct linear_range act8600_sudcdc_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(3000000, 0, 63, 0),
REGULATOR_LINEAR_RANGE(3000000, 64, 159, 100000),
REGULATOR_LINEAR_RANGE(12600000, 160, 191, 200000),
......
......@@ -73,7 +73,7 @@ struct act8945a_pmic {
u32 op_mode[ACT8945A_ID_MAX];
};
static const struct regulator_linear_range act8945a_voltage_ranges[] = {
static const struct linear_range act8945a_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000),
REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000),
REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
......
......@@ -87,7 +87,7 @@ static const struct regulator_ops arizona_ldo1_hc_ops = {
.set_bypass = regulator_set_bypass_regmap,
};
static const struct regulator_linear_range arizona_ldo1_hc_ranges[] = {
static const struct linear_range arizona_ldo1_hc_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 0x6, 50000),
REGULATOR_LINEAR_RANGE(1800000, 0x7, 0x7, 0),
};
......
......@@ -125,7 +125,7 @@ static const struct regulator_ops arizona_micsupp_ops = {
.set_bypass = arizona_micsupp_set_bypass,
};
static const struct regulator_linear_range arizona_micsupp_ranges[] = {
static const struct linear_range arizona_micsupp_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 0x1e, 50000),
REGULATOR_LINEAR_RANGE(3300000, 0x1f, 0x1f, 0),
};
......@@ -152,7 +152,7 @@ static const struct regulator_desc arizona_micsupp = {
.owner = THIS_MODULE,
};
static const struct regulator_linear_range arizona_micsupp_ext_ranges[] = {
static const struct linear_range arizona_micsupp_ext_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 0x14, 25000),
REGULATOR_LINEAR_RANGE(1500000, 0x15, 0x27, 100000),
};
......
......@@ -103,18 +103,18 @@ static const struct regulator_ops as3711_dldo_ops = {
.map_voltage = regulator_map_voltage_linear_range,
};
static const struct regulator_linear_range as3711_sd_ranges[] = {
static const struct linear_range as3711_sd_ranges[] = {
REGULATOR_LINEAR_RANGE(612500, 0x1, 0x40, 12500),
REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000),
REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7f, 50000),
};
static const struct regulator_linear_range as3711_aldo_ranges[] = {
static const struct linear_range as3711_aldo_ranges[] = {
REGULATOR_LINEAR_RANGE(1200000, 0, 0xf, 50000),
REGULATOR_LINEAR_RANGE(1800000, 0x10, 0x1f, 100000),
};
static const struct regulator_linear_range as3711_dldo_ranges[] = {
static const struct linear_range as3711_dldo_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 0x10, 50000),
REGULATOR_LINEAR_RANGE(1750000, 0x20, 0x3f, 50000),
};
......
......@@ -389,7 +389,7 @@ static const struct regulator_ops as3722_ldo6_extcntrl_ops = {
.set_bypass = regulator_set_bypass_regmap,
};
static const struct regulator_linear_range as3722_ldo_ranges[] = {
static const struct linear_range as3722_ldo_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x00, 0x00, 0),
REGULATOR_LINEAR_RANGE(825000, 0x01, 0x24, 25000),
REGULATOR_LINEAR_RANGE(1725000, 0x40, 0x7F, 25000),
......@@ -487,7 +487,7 @@ static bool as3722_sd0_is_low_voltage(struct as3722_regulators *as3722_regs)
return false;
}
static const struct regulator_linear_range as3722_sd2345_ranges[] = {
static const struct linear_range as3722_sd2345_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x00, 0x00, 0),
REGULATOR_LINEAR_RANGE(612500, 0x01, 0x40, 12500),
REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000),
......
......@@ -510,7 +510,7 @@ static const struct regulator_ops axp20x_ops_sw = {
.is_enabled = regulator_is_enabled_regmap,
};
static const struct regulator_linear_range axp20x_ldo4_ranges[] = {
static const struct linear_range axp20x_ldo4_ranges[] = {
REGULATOR_LINEAR_RANGE(1250000,
AXP20X_LDO4_V_OUT_1250mV_START,
AXP20X_LDO4_V_OUT_1250mV_END,
......@@ -638,7 +638,7 @@ static const struct regulator_desc axp22x_drivevbus_regulator = {
};
/* DCDC ranges shared with AXP813 */
static const struct regulator_linear_range axp803_dcdc234_ranges[] = {
static const struct linear_range axp803_dcdc234_ranges[] = {
REGULATOR_LINEAR_RANGE(500000,
AXP803_DCDC234_500mV_START,
AXP803_DCDC234_500mV_END,
......@@ -649,7 +649,7 @@ static const struct regulator_linear_range axp803_dcdc234_ranges[] = {
20000),
};
static const struct regulator_linear_range axp803_dcdc5_ranges[] = {
static const struct linear_range axp803_dcdc5_ranges[] = {
REGULATOR_LINEAR_RANGE(800000,
AXP803_DCDC5_800mV_START,
AXP803_DCDC5_800mV_END,
......@@ -660,7 +660,7 @@ static const struct regulator_linear_range axp803_dcdc5_ranges[] = {
20000),
};
static const struct regulator_linear_range axp803_dcdc6_ranges[] = {
static const struct linear_range axp803_dcdc6_ranges[] = {
REGULATOR_LINEAR_RANGE(600000,
AXP803_DCDC6_600mV_START,
AXP803_DCDC6_600mV_END,
......@@ -672,7 +672,7 @@ static const struct regulator_linear_range axp803_dcdc6_ranges[] = {
};
/* AXP806's CLDO2 and AXP809's DLDO1 share the same range */
static const struct regulator_linear_range axp803_dldo2_ranges[] = {
static const struct linear_range axp803_dldo2_ranges[] = {
REGULATOR_LINEAR_RANGE(700000,
AXP803_DLDO2_700mV_START,
AXP803_DLDO2_700mV_END,
......@@ -758,7 +758,7 @@ static const struct regulator_desc axp803_regulators[] = {
AXP_DESC_FIXED(AXP803, RTC_LDO, "rtc-ldo", "ips", 3000),
};
static const struct regulator_linear_range axp806_dcdca_ranges[] = {
static const struct linear_range axp806_dcdca_ranges[] = {
REGULATOR_LINEAR_RANGE(600000,
AXP806_DCDCA_600mV_START,
AXP806_DCDCA_600mV_END,
......@@ -769,7 +769,7 @@ static const struct regulator_linear_range axp806_dcdca_ranges[] = {
20000),
};
static const struct regulator_linear_range axp806_dcdcd_ranges[] = {
static const struct linear_range axp806_dcdcd_ranges[] = {
REGULATOR_LINEAR_RANGE(600000,
AXP806_DCDCD_600mV_START,
AXP806_DCDCD_600mV_END,
......@@ -834,7 +834,7 @@ static const struct regulator_desc axp806_regulators[] = {
AXP806_PWR_OUT_CTRL2, AXP806_PWR_OUT_SW_MASK),
};
static const struct regulator_linear_range axp809_dcdc4_ranges[] = {
static const struct linear_range axp809_dcdc4_ranges[] = {
REGULATOR_LINEAR_RANGE(600000,
AXP809_DCDC4_600mV_START,
AXP809_DCDC4_600mV_END,
......
......@@ -116,14 +116,14 @@ static const unsigned int ldo_vbus[] = {
};
/* DCDC group CSR: supported voltages in microvolts */
static const struct regulator_linear_range dcdc_csr_ranges[] = {
static const struct linear_range dcdc_csr_ranges[] = {
REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
REGULATOR_LINEAR_RANGE(1360000, 51, 55, 20000),
REGULATOR_LINEAR_RANGE(900000, 56, 63, 0),
};
/* DCDC group IOSR1: supported voltages in microvolts */
static const struct regulator_linear_range dcdc_iosr1_ranges[] = {
static const struct linear_range dcdc_iosr1_ranges[] = {
REGULATOR_LINEAR_RANGE(860000, 2, 51, 10000),
REGULATOR_LINEAR_RANGE(1500000, 52, 52, 0),
REGULATOR_LINEAR_RANGE(1800000, 53, 53, 0),
......@@ -131,7 +131,7 @@ static const struct regulator_linear_range dcdc_iosr1_ranges[] = {
};
/* DCDC group SDSR1: supported voltages in microvolts */
static const struct regulator_linear_range dcdc_sdsr1_ranges[] = {
static const struct linear_range dcdc_sdsr1_ranges[] = {
REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
REGULATOR_LINEAR_RANGE(1340000, 51, 51, 0),
REGULATOR_LINEAR_RANGE(900000, 52, 63, 0),
......@@ -143,7 +143,7 @@ struct bcm590xx_info {
u8 n_voltages;
const unsigned int *volt_table;
u8 n_linear_ranges;
const struct regulator_linear_range *linear_ranges;
const struct linear_range *linear_ranges;
};
#define BCM590XX_REG_TABLE(_name, _table) \
......
......@@ -20,22 +20,22 @@
#define BUCK_RAMPRATE_125MV 1
#define BUCK_RAMP_MAX 250
static const struct regulator_linear_range bd70528_buck1_volts[] = {
static const struct linear_range bd70528_buck1_volts[] = {
REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 600000),
REGULATOR_LINEAR_RANGE(2750000, 0x2, 0xf, 50000),
};
static const struct regulator_linear_range bd70528_buck2_volts[] = {
static const struct linear_range bd70528_buck2_volts[] = {
REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 300000),
REGULATOR_LINEAR_RANGE(1550000, 0x2, 0xd, 50000),
REGULATOR_LINEAR_RANGE(3000000, 0xe, 0xf, 300000),
};
static const struct regulator_linear_range bd70528_buck3_volts[] = {
static const struct linear_range bd70528_buck3_volts[] = {
REGULATOR_LINEAR_RANGE(800000, 0x00, 0xd, 50000),
REGULATOR_LINEAR_RANGE(1800000, 0xe, 0xf, 0),
};
/* All LDOs have same voltage ranges */
static const struct regulator_linear_range bd70528_ldo_volts[] = {
static const struct linear_range bd70528_ldo_volts[] = {
REGULATOR_LINEAR_RANGE(1650000, 0x0, 0x07, 50000),
REGULATOR_LINEAR_RANGE(2100000, 0x8, 0x0f, 100000),
REGULATOR_LINEAR_RANGE(2850000, 0x10, 0x19, 50000),
......
......@@ -65,27 +65,27 @@ static const struct reg_init buck7_inits[] = {
},
};
static const struct regulator_linear_range bd71828_buck1267_volts[] = {
static const struct linear_range bd71828_buck1267_volts[] = {
REGULATOR_LINEAR_RANGE(500000, 0x00, 0xef, 6250),
REGULATOR_LINEAR_RANGE(2000000, 0xf0, 0xff, 0),
};
static const struct regulator_linear_range bd71828_buck3_volts[] = {
static const struct linear_range bd71828_buck3_volts[] = {
REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x0f, 50000),
REGULATOR_LINEAR_RANGE(2000000, 0x10, 0x1f, 0),
};
static const struct regulator_linear_range bd71828_buck4_volts[] = {
static const struct linear_range bd71828_buck4_volts[] = {
REGULATOR_LINEAR_RANGE(1000000, 0x00, 0x1f, 25000),
REGULATOR_LINEAR_RANGE(1800000, 0x20, 0x3f, 0),
};
static const struct regulator_linear_range bd71828_buck5_volts[] = {
static const struct linear_range bd71828_buck5_volts[] = {
REGULATOR_LINEAR_RANGE(2500000, 0x00, 0x0f, 50000),
REGULATOR_LINEAR_RANGE(3300000, 0x10, 0x1f, 0),
};
static const struct regulator_linear_range bd71828_ldo_volts[] = {
static const struct linear_range bd71828_ldo_volts[] = {
REGULATOR_LINEAR_RANGE(800000, 0x00, 0x31, 50000),
REGULATOR_LINEAR_RANGE(3300000, 0x32, 0x3f, 0),
};
......
This diff is collapsed.
......@@ -3642,36 +3642,19 @@ static int regulator_get_optimal_voltage(struct regulator_dev *rdev,
return done;
}
static int regulator_balance_voltage(struct regulator_dev *rdev,
suspend_state_t state)
int regulator_do_balance_voltage(struct regulator_dev *rdev,
suspend_state_t state, bool skip_coupled)
{
struct regulator_dev **c_rdevs;
struct regulator_dev *best_rdev;
struct coupling_desc *c_desc = &rdev->coupling_desc;
struct regulator_coupler *coupler = c_desc->coupler;
int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev;
unsigned int delta, best_delta;
unsigned long c_rdev_done = 0;
bool best_c_rdev_done;
c_rdevs = c_desc->coupled_rdevs;
n_coupled = c_desc->n_coupled;
/*
* If system is in a state other than PM_SUSPEND_ON, don't check
* other coupled regulators.
*/
if (state != PM_SUSPEND_ON)
n_coupled = 1;
if (c_desc->n_resolved < n_coupled) {
rdev_err(rdev, "Not all coupled regulators registered\n");
return -EPERM;
}
/* Invoke custom balancer for customized couplers */
if (coupler && coupler->balance_voltage)
return coupler->balance_voltage(coupler, rdev, state);
n_coupled = skip_coupled ? 1 : c_desc->n_coupled;
/*
* Find the best possible voltage change on each loop. Leave the loop
......@@ -3742,6 +3725,32 @@ static int regulator_balance_voltage(struct regulator_dev *rdev,
return ret;
}
static int regulator_balance_voltage(struct regulator_dev *rdev,
suspend_state_t state)
{
struct coupling_desc *c_desc = &rdev->coupling_desc;
struct regulator_coupler *coupler = c_desc->coupler;
bool skip_coupled = false;
/*
* If system is in a state other than PM_SUSPEND_ON, don't check
* other coupled regulators.
*/
if (state != PM_SUSPEND_ON)
skip_coupled = true;
if (c_desc->n_resolved < c_desc->n_coupled) {
rdev_err(rdev, "Not all coupled regulators registered\n");
return -EPERM;
}
/* Invoke custom balancer for customized couplers */
if (coupler && coupler->balance_voltage)
return coupler->balance_voltage(coupler, rdev, state);
return regulator_do_balance_voltage(rdev, state, skip_coupled);
}
/**
* regulator_set_voltage - set regulator output voltage
* @regulator: regulator source
......@@ -4312,6 +4321,7 @@ EXPORT_SYMBOL_GPL(regulator_set_load);
int regulator_allow_bypass(struct regulator *regulator, bool enable)
{
struct regulator_dev *rdev = regulator->rdev;
const char *name = rdev_get_name(rdev);
int ret = 0;
if (!rdev->desc->ops->set_bypass)
......@@ -4326,18 +4336,26 @@ int regulator_allow_bypass(struct regulator *regulator, bool enable)
rdev->bypass_count++;
if (rdev->bypass_count == rdev->open_count) {
trace_regulator_bypass_enable(name);
ret = rdev->desc->ops->set_bypass(rdev, enable);
if (ret != 0)
rdev->bypass_count--;
else
trace_regulator_bypass_enable_complete(name);
}
} else if (!enable && regulator->bypass) {
rdev->bypass_count--;
if (rdev->bypass_count != rdev->open_count) {
trace_regulator_bypass_disable(name);
ret = rdev->desc->ops->set_bypass(rdev, enable);
if (ret != 0)
rdev->bypass_count++;
else
trace_regulator_bypass_disable_complete(name);
}
}
......@@ -5496,6 +5514,7 @@ static void regulator_summary_show_subtree(struct seq_file *s,
seq_printf(s, "%*s%-*s ",
(level + 1) * 3 + 1, "",
30 - (level + 1) * 3,
consumer->supply_name ? consumer->supply_name :
consumer->dev ? dev_name(consumer->dev) : "deviceless");
switch (rdev->desc->type) {
......
......@@ -248,7 +248,7 @@ static int da9034_set_dvc_voltage_sel(struct regulator_dev *rdev,
return ret;
}
static const struct regulator_linear_range da9034_ldo12_ranges[] = {
static const struct linear_range da9034_ldo12_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 50000),
REGULATOR_LINEAR_RANGE(2700000, 8, 15, 50000),
};
......
......@@ -181,7 +181,7 @@ static int db8500_regulator_switch_disable(struct regulator_dev *rdev)
goto out;
}
info->is_enabled = 0;
info->is_enabled = false;
out:
return ret;
}
......
......@@ -131,10 +131,11 @@ int regulator_get_voltage_sel_pickable_regmap(struct regulator_dev *rdev)
unsigned int r_val;
int range;
unsigned int val;
int ret, i;
unsigned int voltages_in_range = 0;
int ret;
unsigned int voltages = 0;
const struct linear_range *r = rdev->desc->linear_ranges;
if (!rdev->desc->linear_ranges)
if (!r)
return -EINVAL;
ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
......@@ -152,11 +153,9 @@ int regulator_get_voltage_sel_pickable_regmap(struct regulator_dev *rdev)
if (range < 0)
return -EINVAL;
for (i = 0; i < range; i++)
voltages_in_range += (rdev->desc->linear_ranges[i].max_sel -
rdev->desc->linear_ranges[i].min_sel) + 1;
voltages = linear_range_values_in_range_array(r, range);
return val + voltages_in_range;
return val + voltages;
}
EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_pickable_regmap);
......@@ -179,8 +178,11 @@ int regulator_set_voltage_sel_pickable_regmap(struct regulator_dev *rdev,
unsigned int voltages_in_range = 0;
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
voltages_in_range = (rdev->desc->linear_ranges[i].max_sel -
rdev->desc->linear_ranges[i].min_sel) + 1;
const struct linear_range *r;
r = &rdev->desc->linear_ranges[i];
voltages_in_range = linear_range_values_in_range(r);
if (sel < voltages_in_range)
break;
sel -= voltages_in_range;
......@@ -405,8 +407,10 @@ EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
const struct regulator_linear_range *range;
const struct linear_range *range;
int ret = -EINVAL;
unsigned int sel;
bool found;
int voltage, i;
if (!rdev->desc->n_linear_ranges) {
......@@ -415,35 +419,19 @@ int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
}
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
int linear_max_uV;
range = &rdev->desc->linear_ranges[i];
linear_max_uV = range->min_uV +
(range->max_sel - range->min_sel) * range->uV_step;
if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV))
ret = linear_range_get_selector_high(range, min_uV, &sel,
&found);
if (ret)
continue;
if (min_uV <= range->min_uV)
min_uV = range->min_uV;
/* range->uV_step == 0 means fixed voltage range */
if (range->uV_step == 0) {
ret = 0;
} else {
ret = DIV_ROUND_UP(min_uV - range->min_uV,
range->uV_step);
if (ret < 0)
return ret;
}
ret += range->min_sel;
ret = sel;
/*
* Map back into a voltage to verify we're still in bounds.
* If we are not, then continue checking rest of the ranges.
*/
voltage = rdev->desc->ops->list_voltage(rdev, ret);
voltage = rdev->desc->ops->list_voltage(rdev, sel);
if (voltage >= min_uV && voltage <= max_uV)
break;
}
......@@ -468,7 +456,7 @@ EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range);
int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
const struct regulator_linear_range *range;
const struct linear_range *range;
int ret = -EINVAL;
int voltage, i;
unsigned int selector = 0;
......@@ -480,30 +468,25 @@ int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev,
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
int linear_max_uV;
bool found;
unsigned int sel;
range = &rdev->desc->linear_ranges[i];
linear_max_uV = range->min_uV +
(range->max_sel - range->min_sel) * range->uV_step;
linear_max_uV = linear_range_get_max_value(range);
if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV)) {
selector += (range->max_sel - range->min_sel + 1);
if (!(min_uV <= linear_max_uV && max_uV >= range->min)) {
selector += linear_range_values_in_range(range);
continue;
}
if (min_uV <= range->min_uV)
min_uV = range->min_uV;
/* range->uV_step == 0 means fixed voltage range */
if (range->uV_step == 0) {
ret = 0;
} else {
ret = DIV_ROUND_UP(min_uV - range->min_uV,
range->uV_step);
if (ret < 0)
return ret;
ret = linear_range_get_selector_high(range, min_uV, &sel,
&found);
if (ret) {
selector += linear_range_values_in_range(range);
continue;
}
ret += selector;
ret = selector + sel;
voltage = rdev->desc->ops->list_voltage(rdev, ret);
......@@ -513,7 +496,7 @@ int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev,
* exit but retry until we have checked all ranges.
*/
if (voltage < min_uV || voltage > max_uV)
selector += (range->max_sel - range->min_sel + 1);
selector += linear_range_values_in_range(range);
else
break;
}
......@@ -561,7 +544,7 @@ EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev,
unsigned int selector)
{
const struct regulator_linear_range *range;
const struct linear_range *range;
int i;
unsigned int all_sels = 0;
......@@ -571,18 +554,28 @@ int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev,
}
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
unsigned int sels_in_range;
unsigned int sel_indexes;
range = &rdev->desc->linear_ranges[i];
sels_in_range = range->max_sel - range->min_sel;
sel_indexes = linear_range_values_in_range(range) - 1;
if (all_sels + sels_in_range >= selector) {
if (all_sels + sel_indexes >= selector) {
selector -= all_sels;
return range->min_uV + (range->uV_step * selector);
/*
* As we see here, pickable ranges work only as
* long as the first selector for each pickable
* range is 0, and the each subsequent range for
* this 'pick' follow immediately at next unused
* selector (Eg. there is no gaps between ranges).
* I think this is fine but it probably should be
* documented. OTOH, whole pickable range stuff
* might benefit from some documentation
*/
return range->min + (range->step * selector);
}
all_sels += (sels_in_range + 1);
all_sels += (sel_indexes + 1);
}
return -EINVAL;
......@@ -604,27 +597,18 @@ EXPORT_SYMBOL_GPL(regulator_list_voltage_pickable_linear_range);
int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc,
unsigned int selector)
{
const struct regulator_linear_range *range;
int i;
unsigned int val;
int ret;
if (!desc->n_linear_ranges) {
BUG_ON(!desc->n_linear_ranges);
return -EINVAL;
}
for (i = 0; i < desc->n_linear_ranges; i++) {
range = &desc->linear_ranges[i];
if (!(selector >= range->min_sel &&
selector <= range->max_sel))
continue;
selector -= range->min_sel;
return range->min_uV + (range->uV_step * selector);
}
ret = linear_range_get_value_array(desc->linear_ranges,
desc->n_linear_ranges, selector,
&val);
if (ret)
return ret;
return -EINVAL;
return val;
}
EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear_range);
......
......@@ -87,7 +87,7 @@ static const unsigned int ldo_8_voltages[] = {
};
/* Ranges are sorted in ascending order. */
static const struct regulator_linear_range ldo_audio_volt_range[] = {
static const struct linear_range ldo_audio_volt_range[] = {
REGULATOR_LINEAR_RANGE(2800000, 0, 3, 50000),
REGULATOR_LINEAR_RANGE(3000000, 4, 7, 100000),
};
......@@ -195,7 +195,7 @@ static const struct regulator_ops hi6421_buck345_ops;
* _id - LDO id name string
* _match - of match name string
* n_volt - number of votages available
* volt_ranges - array of regulator_linear_range
* volt_ranges - array of linear_range
* vstep - voltage increase in each linear step in uV
* vreg - voltage select register
* vmask - voltage select mask
......
......@@ -36,7 +36,7 @@ static const struct regulator_ops lochnagar_micvdd_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};
static const struct regulator_linear_range lochnagar_micvdd_ranges[] = {
static const struct linear_range lochnagar_micvdd_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 0xC, 50000),
REGULATOR_LINEAR_RANGE(1700000, 0xD, 0x1F, 100000),
};
......@@ -97,7 +97,7 @@ static const struct regulator_ops lochnagar_vddcore_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};
static const struct regulator_linear_range lochnagar_vddcore_ranges[] = {
static const struct linear_range lochnagar_vddcore_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0x8, 0x41, 12500),
};
......
......@@ -54,14 +54,14 @@ struct lp873x_regulator {
static const struct lp873x_regulator regulators[];
static const struct regulator_linear_range buck0_buck1_ranges[] = {
static const struct linear_range buck0_buck1_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x13, 0),
REGULATOR_LINEAR_RANGE(700000, 0x14, 0x17, 10000),
REGULATOR_LINEAR_RANGE(735000, 0x18, 0x9d, 5000),
REGULATOR_LINEAR_RANGE(1420000, 0x9e, 0xff, 20000),
};
static const struct regulator_linear_range ldo0_ldo1_ranges[] = {
static const struct linear_range ldo0_ldo1_ranges[] = {
REGULATOR_LINEAR_RANGE(800000, 0x0, 0x19, 100000),
};
......
......@@ -46,7 +46,7 @@ struct lp87565_regulator {
static const struct lp87565_regulator regulators[];
static const struct regulator_linear_range buck0_1_2_3_ranges[] = {
static const struct linear_range buck0_1_2_3_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0xA, 0x17, 10000),
REGULATOR_LINEAR_RANGE(735000, 0x18, 0x9d, 5000),
REGULATOR_LINEAR_RANGE(1420000, 0x9e, 0xff, 20000),
......
......@@ -92,7 +92,7 @@ struct lp8788_buck {
};
/* BUCK 1 ~ 4 voltage ranges */
static const struct regulator_linear_range buck_volt_ranges[] = {
static const struct linear_range buck_volt_ranges[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0, 0),
REGULATOR_LINEAR_RANGE(800000, 1, 25, 50000),
};
......
......@@ -49,7 +49,7 @@ static const unsigned int max77651_sbb1_volt_range_sel[] = {
0x0, 0x1, 0x2, 0x3
};
static const struct regulator_linear_range max77651_sbb1_volt_ranges[] = {
static const struct linear_range max77651_sbb1_volt_ranges[] = {
/* range index 0 */
REGULATOR_LINEAR_RANGE(2400000, 0x00, 0x0f, 50000),
/* range index 1 */
......
// SPDX-License-Identifier: GPL-2.0-or-later
//
// max77826-regulator.c - regulator driver for Maxim MAX77826
//
// Author: Iskren Chernev <iskren.chernev@gmail.com>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
enum max77826_registers {
MAX77826_REG_INT_SRC = 0x00,
MAX77826_REG_SYS_INT,
MAX77826_REG_INT1,
MAX77826_REG_INT2,
MAX77826_REG_BB_INT,
MAX77826_REG_INT_SRC_M,
MAX77826_REG_TOPSYS_INT_M,
MAX77826_REG_INT1_M,
MAX77826_REG_INT2_M,
MAX77826_REG_BB_INT_M,
MAX77826_REG_TOPSYS_STAT,
MAX77826_REG_STAT1,
MAX77826_REG_STAT2,
MAX77826_REG_BB_STAT,
/* 0x0E - 0x0F: Reserved */
MAX77826_REG_LDO_OPMD1 = 0x10,
MAX77826_REG_LDO_OPMD2,
MAX77826_REG_LDO_OPMD3,
MAX77826_REG_LDO_OPMD4,
MAX77826_REG_B_BB_OPMD,
/* 0x15 - 0x1F: Reserved */
MAX77826_REG_LDO1_CFG = 0x20,
MAX77826_REG_LDO2_CFG,
MAX77826_REG_LDO3_CFG,
MAX77826_REG_LDO4_CFG,
MAX77826_REG_LDO5_CFG,
MAX77826_REG_LDO6_CFG,
MAX77826_REG_LDO7_CFG,
MAX77826_REG_LDO8_CFG,
MAX77826_REG_LDO9_CFG,
MAX77826_REG_LDO10_CFG,
MAX77826_REG_LDO11_CFG,
MAX77826_REG_LDO12_CFG,
MAX77826_REG_LDO13_CFG,
MAX77826_REG_LDO14_CFG,
MAX77826_REG_LDO15_CFG,
/* 0x2F: Reserved */
MAX77826_REG_BUCK_CFG = 0x30,
MAX77826_REG_BUCK_VOUT,
MAX77826_REG_BB_CFG,
MAX77826_REG_BB_VOUT,
/* 0x34 - 0x3F: Reserved */
MAX77826_REG_BUCK_SS_FREQ = 0x40,
MAX77826_REG_UVLO_FALL,
/* 0x42 - 0xCE: Reserved */
MAX77826_REG_DEVICE_ID = 0xCF,
};
enum max77826_regulators {
MAX77826_LDO1 = 0,
MAX77826_LDO2,
MAX77826_LDO3,
MAX77826_LDO4,
MAX77826_LDO5,
MAX77826_LDO6,
MAX77826_LDO7,
MAX77826_LDO8,
MAX77826_LDO9,
MAX77826_LDO10,
MAX77826_LDO11,
MAX77826_LDO12,
MAX77826_LDO13,
MAX77826_LDO14,
MAX77826_LDO15,
MAX77826_BUCK,
MAX77826_BUCKBOOST,
MAX77826_MAX_REGULATORS,
};
#define MAX77826_MASK_LDO 0x7f
#define MAX77826_MASK_BUCK 0xff
#define MAX77826_MASK_BUCKBOOST 0x7f
#define MAX77826_BUCK_RAMP_DELAY 12500
/* values in mV */
/* for LDO1-3 */
#define MAX77826_NMOS_LDO_VOLT_MIN 600000
#define MAX77826_NMOS_LDO_VOLT_MAX 2187500
#define MAX77826_NMOS_LDO_VOLT_STEP 12500
/* for LDO4-15 */
#define MAX77826_PMOS_LDO_VOLT_MIN 800000
#define MAX77826_PMOS_LDO_VOLT_MAX 3975000
#define MAX77826_PMOS_LDO_VOLT_STEP 25000
/* for BUCK */
#define MAX77826_BUCK_VOLT_MIN 500000
#define MAX77826_BUCK_VOLT_MAX 1800000
#define MAX77826_BUCK_VOLT_STEP 6250
/* for BUCKBOOST */
#define MAX77826_BUCKBOOST_VOLT_MIN 2600000
#define MAX77826_BUCKBOOST_VOLT_MAX 4187500
#define MAX77826_BUCKBOOST_VOLT_STEP 12500
#define MAX77826_VOLT_RANGE(_type) \
((MAX77826_ ## _type ## _VOLT_MAX - \
MAX77826_ ## _type ## _VOLT_MIN) / \
MAX77826_ ## _type ## _VOLT_STEP + 1)
#define MAX77826_LDO(_id, _type) \
[MAX77826_LDO ## _id] = { \
.id = MAX77826_LDO ## _id, \
.name = "LDO"#_id, \
.of_match = of_match_ptr("LDO"#_id), \
.regulators_node = "regulators", \
.ops = &max77826_most_ops, \
.min_uV = MAX77826_ ## _type ## _LDO_VOLT_MIN, \
.uV_step = MAX77826_ ## _type ## _LDO_VOLT_STEP, \
.n_voltages = MAX77826_VOLT_RANGE(_type ## _LDO), \
.enable_reg = MAX77826_REG_LDO_OPMD1 + (_id - 1) / 4, \
.enable_mask = BIT(((_id - 1) % 4) * 2 + 1), \
.vsel_reg = MAX77826_REG_LDO1_CFG + (_id - 1), \
.vsel_mask = MAX77826_MASK_LDO, \
.owner = THIS_MODULE, \
}
#define MAX77826_BUCK(_idx, _id, _ops) \
[MAX77826_ ## _id] = { \
.id = MAX77826_ ## _id, \
.name = #_id, \
.of_match = of_match_ptr(#_id), \
.regulators_node = "regulators", \
.ops = &_ops, \
.min_uV = MAX77826_ ## _id ## _VOLT_MIN, \
.uV_step = MAX77826_ ## _id ## _VOLT_STEP, \
.n_voltages = MAX77826_VOLT_RANGE(_id), \
.enable_reg = MAX77826_REG_B_BB_OPMD, \
.enable_mask = BIT(_idx * 2 + 1), \
.vsel_reg = MAX77826_REG_BUCK_VOUT + _idx * 2, \
.vsel_mask = MAX77826_MASK_ ## _id, \
.owner = THIS_MODULE, \
}
struct max77826_regulator_info {
struct regmap *regmap;
struct regulator_desc *rdesc;
};
static const struct regmap_config max77826_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX77826_REG_DEVICE_ID,
};
static int max77826_set_voltage_time_sel(struct regulator_dev *,
unsigned int old_selector,
unsigned int new_selector);
static const struct regulator_ops max77826_most_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 const struct regulator_ops max77826_buck_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,
.set_voltage_time_sel = max77826_set_voltage_time_sel,
};
static struct regulator_desc max77826_regulators_desc[] = {
MAX77826_LDO(1, NMOS),
MAX77826_LDO(2, NMOS),
MAX77826_LDO(3, NMOS),
MAX77826_LDO(4, PMOS),
MAX77826_LDO(5, PMOS),
MAX77826_LDO(6, PMOS),
MAX77826_LDO(7, PMOS),
MAX77826_LDO(8, PMOS),
MAX77826_LDO(9, PMOS),
MAX77826_LDO(10, PMOS),
MAX77826_LDO(11, PMOS),
MAX77826_LDO(12, PMOS),
MAX77826_LDO(13, PMOS),
MAX77826_LDO(14, PMOS),
MAX77826_LDO(15, PMOS),
MAX77826_BUCK(0, BUCK, max77826_buck_ops),
MAX77826_BUCK(1, BUCKBOOST, max77826_most_ops),
};
static int max77826_set_voltage_time_sel(struct regulator_dev *rdev,
unsigned int old_selector,
unsigned int new_selector)
{
if (new_selector > old_selector) {
return DIV_ROUND_UP(MAX77826_BUCK_VOLT_STEP *
(new_selector - old_selector),
MAX77826_BUCK_RAMP_DELAY);
}
return 0;
}
static int max77826_read_device_id(struct regmap *regmap, struct device *dev)
{
unsigned int device_id;
int res;
res = regmap_read(regmap, MAX77826_REG_DEVICE_ID, &device_id);
if (!res)
dev_dbg(dev, "DEVICE_ID: 0x%x\n", device_id);
return res;
}
static int max77826_i2c_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct max77826_regulator_info *info;
struct regulator_config config = {};
struct regulator_dev *rdev;
struct regmap *regmap;
int i;
info = devm_kzalloc(dev, sizeof(struct max77826_regulator_info),
GFP_KERNEL);
if (!info)
return -ENOMEM;
info->rdesc = max77826_regulators_desc;
regmap = devm_regmap_init_i2c(client, &max77826_regmap_config);
if (IS_ERR(regmap)) {
dev_err(dev, "Failed to allocate regmap!\n");
return PTR_ERR(regmap);
}
info->regmap = regmap;
i2c_set_clientdata(client, info);
config.dev = dev;
config.regmap = regmap;
config.driver_data = info;
for (i = 0; i < MAX77826_MAX_REGULATORS; i++) {
rdev = devm_regulator_register(dev,
&max77826_regulators_desc[i],
&config);
if (IS_ERR(rdev)) {
dev_err(dev, "Failed to register regulator!\n");
return PTR_ERR(rdev);
}
}
return max77826_read_device_id(regmap, dev);
}
static const struct of_device_id max77826_of_match[] = {
{ .compatible = "maxim,max77826" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, max77826_of_match);
static const struct i2c_device_id max77826_id[] = {
{ "max77826-regulator" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, max77826_id);
static struct i2c_driver max77826_regulator_driver = {
.driver = {
.name = "max77826",
.of_match_table = of_match_ptr(max77826_of_match),
},
.probe_new = max77826_i2c_probe,
.id_table = max77826_id,
};
module_i2c_driver(max77826_regulator_driver);
MODULE_AUTHOR("Iskren Chernev <iskren.chernev@gmail.com>");
MODULE_DESCRIPTION("MAX77826 PMIC regulator driver");
MODULE_LICENSE("GPL");
......@@ -33,6 +33,10 @@ struct max8998_data {
unsigned int buck2_idx;
};
static const unsigned int charger_current_table[] = {
90000, 380000, 475000, 550000, 570000, 600000, 700000, 800000,
};
static int max8998_get_enable_register(struct regulator_dev *rdev,
int *reg, int *shift)
{
......@@ -63,6 +67,10 @@ static int max8998_get_enable_register(struct regulator_dev *rdev,
*reg = MAX8998_REG_CHGR2;
*shift = 7 - (ldo - MAX8998_ESAFEOUT1);
break;
case MAX8998_CHARGER:
*reg = MAX8998_REG_CHGR2;
*shift = 0;
break;
default:
return -EINVAL;
}
......@@ -88,6 +96,11 @@ static int max8998_ldo_is_enabled(struct regulator_dev *rdev)
return val & (1 << shift);
}
static int max8998_ldo_is_enabled_inverted(struct regulator_dev *rdev)
{
return (!max8998_ldo_is_enabled(rdev));
}
static int max8998_ldo_enable(struct regulator_dev *rdev)
{
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
......@@ -358,6 +371,74 @@ static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev,
return 0;
}
static int max8998_set_current_limit(struct regulator_dev *rdev,
int min_uA, int max_uA)
{
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
struct i2c_client *i2c = max8998->iodev->i2c;
unsigned int n_currents = rdev->desc->n_current_limits;
int i, sel = -1;
if (n_currents == 0)
return -EINVAL;
if (rdev->desc->curr_table) {
const unsigned int *curr_table = rdev->desc->curr_table;
bool ascend = curr_table[n_currents - 1] > curr_table[0];
/* search for closest to maximum */
if (ascend) {
for (i = n_currents - 1; i >= 0; i--) {
if (min_uA <= curr_table[i] &&
curr_table[i] <= max_uA) {
sel = i;
break;
}
}
} else {
for (i = 0; i < n_currents; i++) {
if (min_uA <= curr_table[i] &&
curr_table[i] <= max_uA) {
sel = i;
break;
}
}
}
}
if (sel < 0)
return -EINVAL;
sel <<= ffs(rdev->desc->csel_mask) - 1;
return max8998_update_reg(i2c, rdev->desc->csel_reg,
sel, rdev->desc->csel_mask);
}
int max8998_get_current_limit(struct regulator_dev *rdev)
{
struct max8998_data *max8998 = rdev_get_drvdata(rdev);
struct i2c_client *i2c = max8998->iodev->i2c;
u8 val;
int ret;
ret = max8998_read_reg(i2c, rdev->desc->csel_reg, &val);
if (ret != 0)
return ret;
val &= rdev->desc->csel_mask;
val >>= ffs(rdev->desc->csel_mask) - 1;
if (rdev->desc->curr_table) {
if (val >= rdev->desc->n_current_limits)
return -EINVAL;
return rdev->desc->curr_table[val];
}
return -EINVAL;
}
static const struct regulator_ops max8998_ldo_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
......@@ -379,6 +460,15 @@ static const struct regulator_ops max8998_buck_ops = {
.set_voltage_time_sel = max8998_set_voltage_buck_time_sel,
};
static const struct regulator_ops max8998_charger_ops = {
.set_current_limit = max8998_set_current_limit,
.get_current_limit = max8998_get_current_limit,
.is_enabled = max8998_ldo_is_enabled_inverted,
/* Swapped as register is inverted */
.enable = max8998_ldo_disable,
.disable = max8998_ldo_enable,
};
static const struct regulator_ops max8998_others_ops = {
.is_enabled = max8998_ldo_is_enabled,
.enable = max8998_ldo_enable,
......@@ -397,6 +487,19 @@ static const struct regulator_ops max8998_others_ops = {
.owner = THIS_MODULE, \
}
#define MAX8998_CURRENT_REG(_name, _ops, _table, _reg, _mask) \
{ \
.name = #_name, \
.id = MAX8998_##_name, \
.ops = _ops, \
.curr_table = _table, \
.n_current_limits = ARRAY_SIZE(_table), \
.csel_reg = _reg, \
.csel_mask = _mask, \
.type = REGULATOR_CURRENT, \
.owner = THIS_MODULE, \
}
#define MAX8998_OTHERS_REG(_name, _id) \
{ \
.name = #_name, \
......@@ -432,6 +535,8 @@ static const struct regulator_desc regulators[] = {
MAX8998_OTHERS_REG(ENVICHG, MAX8998_ENVICHG),
MAX8998_OTHERS_REG(ESAFEOUT1, MAX8998_ESAFEOUT1),
MAX8998_OTHERS_REG(ESAFEOUT2, MAX8998_ESAFEOUT2),
MAX8998_CURRENT_REG(CHARGER, &max8998_charger_ops,
charger_current_table, MAX8998_REG_CHGR1, 0x7),
};
static int max8998_pmic_dt_parse_dvs_gpio(struct max8998_dev *iodev,
......
......@@ -391,11 +391,11 @@ static const struct of_device_id mcp16502_ids[] = {
};
MODULE_DEVICE_TABLE(of, mcp16502_ids);
static const struct regulator_linear_range b1l12_ranges[] = {
static const struct linear_range b1l12_ranges[] = {
REGULATOR_LINEAR_RANGE(1200000, VDD_LOW_SEL, VDD_HIGH_SEL, 50000),
};
static const struct regulator_linear_range b234_ranges[] = {
static const struct linear_range b234_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, VDD_LOW_SEL, VDD_HIGH_SEL, 25000),
};
......
......@@ -73,7 +73,7 @@ static int mp8859_get_voltage_sel(struct regulator_dev *rdev)
return val;
}
static const struct regulator_linear_range mp8859_dcdc_ranges[] = {
static const struct linear_range mp8859_dcdc_ranges[] = {
REGULATOR_LINEAR_RANGE(0, VOL_MIN_IDX, VOL_MAX_IDX, 10000),
};
......
......@@ -102,15 +102,15 @@ struct mt6323_regulator_info {
.modeset_mask = _modeset_mask, \
}
static const struct regulator_linear_range buck_volt_range1[] = {
static const struct linear_range buck_volt_range1[] = {
REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
};
static const struct regulator_linear_range buck_volt_range2[] = {
static const struct linear_range buck_volt_range2[] = {
REGULATOR_LINEAR_RANGE(1400000, 0, 0x7f, 12500),
};
static const struct regulator_linear_range buck_volt_range3[] = {
static const struct linear_range buck_volt_range3[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
};
......
......@@ -137,19 +137,19 @@ struct mt6358_regulator_info {
.qi = BIT(15), \
}
static const struct regulator_linear_range buck_volt_range1[] = {
static const struct linear_range buck_volt_range1[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 6250),
};
static const struct regulator_linear_range buck_volt_range2[] = {
static const struct linear_range buck_volt_range2[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 12500),
};
static const struct regulator_linear_range buck_volt_range3[] = {
static const struct linear_range buck_volt_range3[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
};
static const struct regulator_linear_range buck_volt_range4[] = {
static const struct linear_range buck_volt_range4[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 0x7f, 12500),
};
......
......@@ -152,15 +152,15 @@ struct mt6380_regulator_info {
.modeset_mask = _modeset_mask, \
}
static const struct regulator_linear_range buck_volt_range1[] = {
static const struct linear_range buck_volt_range1[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 0xfe, 6250),
};
static const struct regulator_linear_range buck_volt_range2[] = {
static const struct linear_range buck_volt_range2[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 0xfe, 6250),
};
static const struct regulator_linear_range buck_volt_range3[] = {
static const struct linear_range buck_volt_range3[] = {
REGULATOR_LINEAR_RANGE(1200000, 0, 0x3c, 25000),
};
......
......@@ -102,15 +102,15 @@ struct mt6397_regulator_info {
.qi = BIT(15), \
}
static const struct regulator_linear_range buck_volt_range1[] = {
static const struct linear_range buck_volt_range1[] = {
REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
};
static const struct regulator_linear_range buck_volt_range2[] = {
static const struct linear_range buck_volt_range2[] = {
REGULATOR_LINEAR_RANGE(800000, 0, 0x7f, 6250),
};
static const struct regulator_linear_range buck_volt_range3[] = {
static const struct linear_range buck_volt_range3[] = {
REGULATOR_LINEAR_RANGE(1500000, 0, 0x1f, 20000),
};
......
......@@ -22,14 +22,14 @@
#include <linux/of_platform.h>
#include <linux/regulator/of_regulator.h>
static const struct regulator_linear_range smps_low_ranges[] = {
static const struct linear_range smps_low_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(500000, 0x1, 0x6, 0),
REGULATOR_LINEAR_RANGE(510000, 0x7, 0x79, 10000),
REGULATOR_LINEAR_RANGE(1650000, 0x7A, 0x7f, 0),
};
static const struct regulator_linear_range smps_high_ranges[] = {
static const struct linear_range smps_high_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(1000000, 0x1, 0x6, 0),
REGULATOR_LINEAR_RANGE(1020000, 0x7, 0x79, 20000),
......
......@@ -86,7 +86,7 @@ enum rpmh_regulator_type {
struct rpmh_vreg_hw_data {
enum rpmh_regulator_type regulator_type;
const struct regulator_ops *ops;
const struct regulator_linear_range voltage_range;
const struct linear_range voltage_range;
int n_voltages;
int hpm_min_load_uA;
const int *pmic_mode_map;
......
......@@ -148,41 +148,41 @@ static const struct rpm_reg_parts rpm8960_ncp_parts = {
/*
* Physically available PMIC regulator voltage ranges
*/
static const struct regulator_linear_range pldo_ranges[] = {
static const struct linear_range pldo_ranges[] = {
REGULATOR_LINEAR_RANGE( 750000, 0, 59, 12500),
REGULATOR_LINEAR_RANGE(1500000, 60, 123, 25000),
REGULATOR_LINEAR_RANGE(3100000, 124, 160, 50000),
};
static const struct regulator_linear_range nldo_ranges[] = {
static const struct linear_range nldo_ranges[] = {
REGULATOR_LINEAR_RANGE( 750000, 0, 63, 12500),
};
static const struct regulator_linear_range nldo1200_ranges[] = {
static const struct linear_range nldo1200_ranges[] = {
REGULATOR_LINEAR_RANGE( 375000, 0, 59, 6250),
REGULATOR_LINEAR_RANGE( 750000, 60, 123, 12500),
};
static const struct regulator_linear_range smps_ranges[] = {
static const struct linear_range smps_ranges[] = {
REGULATOR_LINEAR_RANGE( 375000, 0, 29, 12500),
REGULATOR_LINEAR_RANGE( 750000, 30, 89, 12500),
REGULATOR_LINEAR_RANGE(1500000, 90, 153, 25000),
};
static const struct regulator_linear_range ftsmps_ranges[] = {
static const struct linear_range ftsmps_ranges[] = {
REGULATOR_LINEAR_RANGE( 350000, 0, 6, 50000),
REGULATOR_LINEAR_RANGE( 700000, 7, 63, 12500),
REGULATOR_LINEAR_RANGE(1500000, 64, 100, 50000),
};
static const struct regulator_linear_range smb208_ranges[] = {
static const struct linear_range smb208_ranges[] = {
REGULATOR_LINEAR_RANGE( 375000, 0, 29, 12500),
REGULATOR_LINEAR_RANGE( 750000, 30, 89, 12500),
REGULATOR_LINEAR_RANGE(1500000, 90, 153, 25000),
REGULATOR_LINEAR_RANGE(3100000, 154, 234, 25000),
};
static const struct regulator_linear_range ncp_ranges[] = {
static const struct linear_range ncp_ranges[] = {
REGULATOR_LINEAR_RANGE(1500000, 0, 31, 50000),
};
......@@ -604,16 +604,6 @@ static const struct qcom_rpm_reg pm8921_smps = {
.supports_force_mode_bypass = false,
};
static const struct qcom_rpm_reg pm8921_ftsmps = {
.desc.linear_ranges = ftsmps_ranges,
.desc.n_linear_ranges = ARRAY_SIZE(ftsmps_ranges),
.desc.n_voltages = 101,
.desc.ops = &uV_ops,
.parts = &rpm8960_smps_parts,
.supports_force_mode_auto = true,
.supports_force_mode_bypass = false,
};
static const struct qcom_rpm_reg pm8921_ncp = {
.desc.linear_ranges = ncp_ranges,
.desc.n_linear_ranges = ARRAY_SIZE(ncp_ranges),
......
This diff is collapsed.
......@@ -165,14 +165,14 @@ static const int rk808_buck_config_regs[] = {
RK808_BUCK4_CONFIG_REG,
};
static const struct regulator_linear_range rk808_ldo3_voltage_ranges[] = {
static const struct linear_range rk808_ldo3_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(800000, 0, 13, 100000),
REGULATOR_LINEAR_RANGE(2500000, 15, 15, 0),
};
#define RK809_BUCK5_SEL_CNT (8)
static const struct regulator_linear_range rk809_buck5_voltage_ranges[] = {
static const struct linear_range rk809_buck5_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(1500000, 0, 0, 0),
REGULATOR_LINEAR_RANGE(1800000, 1, 3, 200000),
REGULATOR_LINEAR_RANGE(2800000, 4, 5, 200000),
......@@ -201,14 +201,14 @@ static const struct regulator_linear_range rk809_buck5_voltage_ranges[] = {
#define RK817_BUCK1_SEL_CNT (RK817_BUCK1_SEL0 + RK817_BUCK1_SEL1 + 1)
#define RK817_BUCK3_SEL_CNT (RK817_BUCK1_SEL0 + RK817_BUCK3_SEL1 + 1)
static const struct regulator_linear_range rk817_buck1_voltage_ranges[] = {
static const struct linear_range rk817_buck1_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN0, 0,
RK817_BUCK1_SEL0, RK817_BUCK1_STP0),
REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN1, RK817_BUCK1_SEL0 + 1,
RK817_BUCK1_SEL_CNT, RK817_BUCK1_STP1),
};
static const struct regulator_linear_range rk817_buck3_voltage_ranges[] = {
static const struct linear_range rk817_buck3_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN0, 0,
RK817_BUCK1_SEL0, RK817_BUCK1_STP0),
REGULATOR_LINEAR_RANGE(RK817_BUCK1_MIN1, RK817_BUCK1_SEL0 + 1,
......@@ -665,7 +665,7 @@ static const struct regulator_ops rk808_switch_ops = {
.set_suspend_disable = rk808_set_suspend_disable,
};
static const struct regulator_linear_range rk805_buck_1_2_voltage_ranges[] = {
static const struct linear_range rk805_buck_1_2_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(712500, 0, 59, 12500),
REGULATOR_LINEAR_RANGE(1800000, 60, 62, 200000),
REGULATOR_LINEAR_RANGE(2300000, 63, 63, 0),
......
......@@ -749,37 +749,37 @@ static const struct regulator_ops s2mps15_reg_buck_ops = {
}
/* voltage range for s2mps15 LDO 3, 5, 15, 16, 18, 20, 23 and 27 */
static const struct regulator_linear_range s2mps15_ldo_voltage_ranges1[] = {
static const struct linear_range s2mps15_ldo_voltage_ranges1[] = {
REGULATOR_LINEAR_RANGE(1000000, 0xc, 0x38, 25000),
};
/* voltage range for s2mps15 LDO 2, 6, 14, 17, 19, 21, 24 and 25 */
static const struct regulator_linear_range s2mps15_ldo_voltage_ranges2[] = {
static const struct linear_range s2mps15_ldo_voltage_ranges2[] = {
REGULATOR_LINEAR_RANGE(1800000, 0x0, 0x3f, 25000),
};
/* voltage range for s2mps15 LDO 4, 11, 12, 13, 22 and 26 */
static const struct regulator_linear_range s2mps15_ldo_voltage_ranges3[] = {
static const struct linear_range s2mps15_ldo_voltage_ranges3[] = {
REGULATOR_LINEAR_RANGE(700000, 0x0, 0x34, 12500),
};
/* voltage range for s2mps15 LDO 7, 8, 9 and 10 */
static const struct regulator_linear_range s2mps15_ldo_voltage_ranges4[] = {
static const struct linear_range s2mps15_ldo_voltage_ranges4[] = {
REGULATOR_LINEAR_RANGE(700000, 0x10, 0x20, 25000),
};
/* voltage range for s2mps15 LDO 1 */
static const struct regulator_linear_range s2mps15_ldo_voltage_ranges5[] = {
static const struct linear_range s2mps15_ldo_voltage_ranges5[] = {
REGULATOR_LINEAR_RANGE(500000, 0x0, 0x20, 12500),
};
/* voltage range for s2mps15 BUCK 1, 2, 3, 4, 5, 6 and 7 */
static const struct regulator_linear_range s2mps15_buck_voltage_ranges1[] = {
static const struct linear_range s2mps15_buck_voltage_ranges1[] = {
REGULATOR_LINEAR_RANGE(500000, 0x20, 0xc0, 6250),
};
/* voltage range for s2mps15 BUCK 8, 9 and 10 */
static const struct regulator_linear_range s2mps15_buck_voltage_ranges2[] = {
static const struct linear_range s2mps15_buck_voltage_ranges2[] = {
REGULATOR_LINEAR_RANGE(1000000, 0x20, 0x78, 12500),
};
......
......@@ -32,7 +32,7 @@ static const struct regulator_ops sky81452_reg_ops = {
.is_enabled = regulator_is_enabled_regmap,
};
static const struct regulator_linear_range sky81452_reg_ranges[] = {
static const struct linear_range sky81452_reg_ranges[] = {
REGULATOR_LINEAR_RANGE(4500000, 0, 14, 250000),
REGULATOR_LINEAR_RANGE(9000000, 15, 31, 1000000),
};
......
......@@ -57,13 +57,13 @@ enum {
/* Ramp delay worst case is (2250uV/uS) */
#define PMIC_RAMP_DELAY 2200
static const struct regulator_linear_range buck1_ranges[] = {
static const struct linear_range buck1_ranges[] = {
REGULATOR_LINEAR_RANGE(725000, 0, 4, 0),
REGULATOR_LINEAR_RANGE(725000, 5, 36, 25000),
REGULATOR_LINEAR_RANGE(1500000, 37, 63, 0),
};
static const struct regulator_linear_range buck2_ranges[] = {
static const struct linear_range buck2_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 17, 0),
REGULATOR_LINEAR_RANGE(1050000, 18, 19, 0),
REGULATOR_LINEAR_RANGE(1100000, 20, 21, 0),
......@@ -77,7 +77,7 @@ static const struct regulator_linear_range buck2_ranges[] = {
REGULATOR_LINEAR_RANGE(1500000, 36, 63, 0),
};
static const struct regulator_linear_range buck3_ranges[] = {
static const struct linear_range buck3_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 19, 0),
REGULATOR_LINEAR_RANGE(1100000, 20, 23, 0),
REGULATOR_LINEAR_RANGE(1200000, 24, 27, 0),
......@@ -87,7 +87,7 @@ static const struct regulator_linear_range buck3_ranges[] = {
REGULATOR_LINEAR_RANGE(3400000, 56, 63, 0),
};
static const struct regulator_linear_range buck4_ranges[] = {
static const struct linear_range buck4_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 27, 25000),
REGULATOR_LINEAR_RANGE(1300000, 28, 29, 0),
REGULATOR_LINEAR_RANGE(1350000, 30, 31, 0),
......@@ -97,19 +97,19 @@ static const struct regulator_linear_range buck4_ranges[] = {
REGULATOR_LINEAR_RANGE(3900000, 61, 63, 0),
};
static const struct regulator_linear_range ldo1_ranges[] = {
static const struct linear_range ldo1_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
};
static const struct regulator_linear_range ldo2_ranges[] = {
static const struct linear_range ldo2_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0),
};
static const struct regulator_linear_range ldo3_ranges[] = {
static const struct linear_range ldo3_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 30, 0),
......@@ -117,13 +117,13 @@ static const struct regulator_linear_range ldo3_ranges[] = {
REGULATOR_LINEAR_RANGE(500000, 31, 31, 0),
};
static const struct regulator_linear_range ldo5_ranges[] = {
static const struct linear_range ldo5_ranges[] = {
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 0),
REGULATOR_LINEAR_RANGE(1700000, 8, 30, 100000),
REGULATOR_LINEAR_RANGE(3900000, 31, 31, 0),
};
static const struct regulator_linear_range ldo6_ranges[] = {
static const struct linear_range ldo6_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 24, 100000),
REGULATOR_LINEAR_RANGE(3300000, 25, 31, 0),
};
......
......@@ -71,23 +71,23 @@ struct tps65086_regulator {
unsigned int decay_mask;
};
static const struct regulator_linear_range tps65086_10mv_ranges[] = {
static const struct linear_range tps65086_10mv_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(410000, 0x1, 0x7F, 10000),
};
static const struct regulator_linear_range tps65086_buck126_25mv_ranges[] = {
static const struct linear_range tps65086_buck126_25mv_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(1000000, 0x1, 0x18, 0),
REGULATOR_LINEAR_RANGE(1025000, 0x19, 0x7F, 25000),
};
static const struct regulator_linear_range tps65086_buck345_25mv_ranges[] = {
static const struct linear_range tps65086_buck345_25mv_ranges[] = {
REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(425000, 0x1, 0x7F, 25000),
};
static const struct regulator_linear_range tps65086_ldoa1_ranges[] = {
static const struct linear_range tps65086_ldoa1_ranges[] = {
REGULATOR_LINEAR_RANGE(1350000, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(1500000, 0x1, 0x7, 100000),
REGULATOR_LINEAR_RANGE(2300000, 0x8, 0xB, 100000),
......@@ -95,7 +95,7 @@ static const struct regulator_linear_range tps65086_ldoa1_ranges[] = {
REGULATOR_LINEAR_RANGE(3300000, 0xE, 0xE, 0),
};
static const struct regulator_linear_range tps65086_ldoa23_ranges[] = {
static const struct linear_range tps65086_ldoa23_ranges[] = {
REGULATOR_LINEAR_RANGE(700000, 0x0, 0xD, 50000),
REGULATOR_LINEAR_RANGE(1400000, 0xE, 0xF, 100000),
};
......
......@@ -56,14 +56,14 @@ static const unsigned int LDO1_VSEL_table[] = {
2800000, 3000000, 3100000, 3300000,
};
static const struct regulator_linear_range tps65217_uv1_ranges[] = {
static const struct linear_range tps65217_uv1_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 24, 25000),
REGULATOR_LINEAR_RANGE(1550000, 25, 52, 50000),
REGULATOR_LINEAR_RANGE(3000000, 53, 55, 100000),
REGULATOR_LINEAR_RANGE(3300000, 56, 63, 0),
};
static const struct regulator_linear_range tps65217_uv2_ranges[] = {
static const struct linear_range tps65217_uv2_ranges[] = {
REGULATOR_LINEAR_RANGE(1500000, 0, 8, 50000),
REGULATOR_LINEAR_RANGE(2000000, 9, 13, 100000),
REGULATOR_LINEAR_RANGE(2450000, 14, 31, 50000),
......
......@@ -56,17 +56,17 @@
.bypass_mask = _sm, \
} \
static const struct regulator_linear_range dcdc1_dcdc2_ranges[] = {
static const struct linear_range dcdc1_dcdc2_ranges[] = {
REGULATOR_LINEAR_RANGE(850000, 0x0, 0x32, 10000),
REGULATOR_LINEAR_RANGE(1375000, 0x33, 0x3f, 25000),
};
static const struct regulator_linear_range ldo1_dcdc3_ranges[] = {
static const struct linear_range ldo1_dcdc3_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0x0, 0x1a, 25000),
REGULATOR_LINEAR_RANGE(1600000, 0x1b, 0x3f, 50000),
};
static const struct regulator_linear_range dcdc4_ranges[] = {
static const struct linear_range dcdc4_ranges[] = {
REGULATOR_LINEAR_RANGE(1175000, 0x0, 0xf, 25000),
REGULATOR_LINEAR_RANGE(1600000, 0x10, 0x34, 50000),
};
......
......@@ -46,11 +46,11 @@ enum tps65912_regulators { DCDC1, DCDC2, DCDC3, DCDC4, LDO1, LDO2, LDO3,
.n_linear_ranges = ARRAY_SIZE(_lr), \
}
static const struct regulator_linear_range tps65912_dcdc_ranges[] = {
static const struct linear_range tps65912_dcdc_ranges[] = {
REGULATOR_LINEAR_RANGE(500000, 0x0, 0x3f, 50000),
};
static const struct regulator_linear_range tps65912_ldo_ranges[] = {
static const struct linear_range tps65912_ldo_ranges[] = {
REGULATOR_LINEAR_RANGE(800000, 0x0, 0x20, 25000),
REGULATOR_LINEAR_RANGE(1650000, 0x21, 0x3c, 50000),
REGULATOR_LINEAR_RANGE(3100000, 0x3d, 0x3f, 100000),
......
......@@ -271,7 +271,7 @@ static int tps80031_vbus_is_enabled(struct regulator_dev *rdev)
{
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps80031_dev(rdev);
int ret = -EIO;
int ret;
uint8_t ctrl1 = 0;
uint8_t ctrl3 = 0;
......@@ -322,7 +322,7 @@ static int tps80031_vbus_disable(struct regulator_dev *rdev)
{
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
struct device *parent = to_tps80031_dev(rdev);
int ret = 0;
int ret;
if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
......@@ -530,7 +530,8 @@ static int tps80031_regulator_config(struct device *parent,
case TPS80031_REGULATOR_LDOUSB:
if (ri->config_flags & (TPS80031_USBLDO_INPUT_VSYS |
TPS80031_USBLDO_INPUT_PMID)) {
unsigned val = 0;
unsigned val;
if (ri->config_flags & TPS80031_USBLDO_INPUT_VSYS)
val = MISC2_LDOUSB_IN_VSYS;
else
......
......@@ -360,12 +360,12 @@ static const u16 VINTANA2_VSEL_table[] = {
};
/* 600mV to 1450mV in 12.5 mV steps */
static const struct regulator_linear_range VDD1_ranges[] = {
static const struct linear_range VDD1_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 68, 12500)
};
/* 600mV to 1450mV in 12.5 mV steps, everything above = 1500mV */
static const struct regulator_linear_range VDD2_ranges[] = {
static const struct linear_range VDD2_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 68, 12500),
REGULATOR_LINEAR_RANGE(1500000, 69, 69, 12500)
};
......
......@@ -495,7 +495,7 @@ static const struct regulator_ops twlsmps_ops = {
};
/*----------------------------------------------------------------------*/
static const struct regulator_linear_range twl6030ldo_linear_range[] = {
static const struct linear_range twl6030ldo_linear_range[] = {
REGULATOR_LINEAR_RANGE(0, 0, 0, 0),
REGULATOR_LINEAR_RANGE(1000000, 1, 24, 100000),
REGULATOR_LINEAR_RANGE(2750000, 31, 31, 0),
......
......@@ -204,7 +204,7 @@ static irqreturn_t wm831x_dcdc_oc_irq(int irq, void *data)
* BUCKV specifics
*/
static const struct regulator_linear_range wm831x_buckv_ranges[] = {
static const struct linear_range wm831x_buckv_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0, 0x7, 0),
REGULATOR_LINEAR_RANGE(600000, 0x8, 0x68, 12500),
};
......
......@@ -59,7 +59,7 @@ static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data)
* General purpose LDOs
*/
static const struct regulator_linear_range wm831x_gp_ldo_ranges[] = {
static const struct linear_range wm831x_gp_ldo_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),
REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),
};
......@@ -312,7 +312,7 @@ static struct platform_driver wm831x_gp_ldo_driver = {
* Analogue LDOs
*/
static const struct regulator_linear_range wm831x_aldo_ranges[] = {
static const struct linear_range wm831x_aldo_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 12, 50000),
REGULATOR_LINEAR_RANGE(1700000, 13, 31, 100000),
};
......
......@@ -470,7 +470,7 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
return 0;
}
static const struct regulator_linear_range wm8350_ldo_ranges[] = {
static const struct linear_range wm8350_ldo_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 15, 50000),
REGULATOR_LINEAR_RANGE(1800000, 16, 31, 100000),
};
......
......@@ -13,7 +13,7 @@
#include <linux/regulator/driver.h>
#include <linux/mfd/wm8400-private.h>
static const struct regulator_linear_range wm8400_ldo_ranges[] = {
static const struct linear_range wm8400_ldo_ranges[] = {
REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),
REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),
};
......
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2020 ROHM Semiconductors */
#ifndef LINEAR_RANGE_H
#define LINEAR_RANGE_H
#include <linux/types.h>
/**
* struct linear_range - table of selector - value pairs
*
* Define a lookup-table for range of values. Intended to help when looking
* for a register value matching certaing physical measure (like voltage).
* Usable when increment of one in register always results a constant increment
* of the physical measure (like voltage).
*
* @min: Lowest value in range
* @min_sel: Lowest selector for range
* @max_sel: Highest selector for range
* @step: Value step size
*/
struct linear_range {
unsigned int min;
unsigned int min_sel;
unsigned int max_sel;
unsigned int step;
};
unsigned int linear_range_values_in_range(const struct linear_range *r);
unsigned int linear_range_values_in_range_array(const struct linear_range *r,
int ranges);
unsigned int linear_range_get_max_value(const struct linear_range *r);
int linear_range_get_value(const struct linear_range *r, unsigned int selector,
unsigned int *val);
int linear_range_get_value_array(const struct linear_range *r, int ranges,
unsigned int selector, unsigned int *val);
int linear_range_get_selector_low(const struct linear_range *r,
unsigned int val, unsigned int *selector,
bool *found);
int linear_range_get_selector_high(const struct linear_range *r,
unsigned int val, unsigned int *selector,
bool *found);
int linear_range_get_selector_low_array(const struct linear_range *r,
int ranges, unsigned int val,
unsigned int *selector, bool *found);
#endif
......@@ -39,6 +39,7 @@ enum {
MAX8998_ENVICHG,
MAX8998_ESAFEOUT1,
MAX8998_ESAFEOUT2,
MAX8998_CHARGER,
};
/**
......
......@@ -62,6 +62,8 @@ int regulator_get_voltage_rdev(struct regulator_dev *rdev);
int regulator_set_voltage_rdev(struct regulator_dev *rdev,
int min_uV, int max_uV,
suspend_state_t state);
int regulator_do_balance_voltage(struct regulator_dev *rdev,
suspend_state_t state, bool skip_coupled);
#else
static inline int regulator_coupler_register(struct regulator_coupler *coupler)
{
......@@ -92,6 +94,12 @@ static inline int regulator_set_voltage_rdev(struct regulator_dev *rdev,
{
return -EINVAL;
}
static inline int regulator_do_balance_voltage(struct regulator_dev *rdev,
suspend_state_t state,
bool skip_coupled)
{
return -EINVAL;
}
#endif
#endif
......@@ -13,6 +13,7 @@
#define __LINUX_REGULATOR_DRIVER_H_
#include <linux/device.h>
#include <linux/linear_range.h>
#include <linux/notifier.h>
#include <linux/regulator/consumer.h>
#include <linux/ww_mutex.h>
......@@ -39,31 +40,13 @@ enum regulator_status {
REGULATOR_STATUS_UNDEFINED,
};
/**
* struct regulator_linear_range - specify linear voltage ranges
*
* Specify a range of voltages for regulator_map_linear_range() and
* regulator_list_linear_range().
*
* @min_uV: Lowest voltage in range
* @min_sel: Lowest selector for range
* @max_sel: Highest selector for range
* @uV_step: Step size
*/
struct regulator_linear_range {
unsigned int min_uV;
unsigned int min_sel;
unsigned int max_sel;
unsigned int uV_step;
};
/* Initialize struct regulator_linear_range */
/* Initialize struct linear_range for regulators */
#define REGULATOR_LINEAR_RANGE(_min_uV, _min_sel, _max_sel, _step_uV) \
{ \
.min_uV = _min_uV, \
.min = _min_uV, \
.min_sel = _min_sel, \
.max_sel = _max_sel, \
.uV_step = _step_uV, \
.step = _step_uV, \
}
/**
......@@ -348,7 +331,7 @@ struct regulator_desc {
unsigned int ramp_delay;
int min_dropout_uV;
const struct regulator_linear_range *linear_ranges;
const struct linear_range *linear_ranges;
const unsigned int *linear_range_selectors;
int n_linear_ranges;
......
......@@ -70,6 +70,38 @@ DEFINE_EVENT(regulator_basic, regulator_disable_complete,
);
DEFINE_EVENT(regulator_basic, regulator_bypass_enable,
TP_PROTO(const char *name),
TP_ARGS(name)
);
DEFINE_EVENT(regulator_basic, regulator_bypass_enable_complete,
TP_PROTO(const char *name),
TP_ARGS(name)
);
DEFINE_EVENT(regulator_basic, regulator_bypass_disable,
TP_PROTO(const char *name),
TP_ARGS(name)
);
DEFINE_EVENT(regulator_basic, regulator_bypass_disable_complete,
TP_PROTO(const char *name),
TP_ARGS(name)
);
/*
* Events that take a range of numerical values, mostly for voltages
* and so on.
......
......@@ -19,6 +19,9 @@ config RAID6_PQ_BENCHMARK
Benchmark all available RAID6 PQ functions on init and choose the
fastest one.
config LINEAR_RANGES
tristate
config PACKING
bool "Generic bitfield packing and unpacking"
default n
......
......@@ -2092,6 +2092,18 @@ config LIST_KUNIT_TEST
If unsure, say N.
config LINEAR_RANGES_TEST
tristate "KUnit test for linear_ranges"
depends on KUNIT
select LINEAR_RANGES
help
This builds the linear_ranges unit test, which runs on boot.
Tests the linear_ranges logic correctness.
For more information on KUnit and unit tests in general please refer
to the KUnit documentation in Documentation/dev-tools/kunit/.
If unsure, say N.
config TEST_UDELAY
tristate "udelay test driver"
help
......
......@@ -125,6 +125,7 @@ obj-$(CONFIG_DEBUG_LIST) += list_debug.o
obj-$(CONFIG_DEBUG_OBJECTS) += debugobjects.o
obj-$(CONFIG_BITREVERSE) += bitrev.o
obj-$(CONFIG_LINEAR_RANGES) += linear_ranges.o
obj-$(CONFIG_PACKING) += packing.o
obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
obj-$(CONFIG_CRC16) += crc16.o
......@@ -309,3 +310,4 @@ obj-$(CONFIG_OBJAGG) += objagg.o
# KUnit tests
obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o
obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o
// SPDX-License-Identifier: GPL-2.0
/*
* helpers to map values in a linear range to range index
*
* Original idea borrowed from regulator framework
*
* It might be useful if we could support also inversely proportional ranges?
* Copyright 2020 ROHM Semiconductors
*/
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/linear_range.h>
#include <linux/module.h>
/**
* linear_range_values_in_range - return the amount of values in a range
* @r: pointer to linear range where values are counted
*
* Compute the amount of values in range pointed by @r. Note, values can
* be all equal - range with selectors 0,...,2 with step 0 still contains
* 3 values even though they are all equal.
*
* Return: the amount of values in range pointed by @r
*/
unsigned int linear_range_values_in_range(const struct linear_range *r)
{
if (!r)
return 0;
return r->max_sel - r->min_sel + 1;
}
EXPORT_SYMBOL_GPL(linear_range_values_in_range);
/**
* linear_range_values_in_range_array - return the amount of values in ranges
* @r: pointer to array of linear ranges where values are counted
* @ranges: amount of ranges we include in computation.
*
* Compute the amount of values in ranges pointed by @r. Note, values can
* be all equal - range with selectors 0,...,2 with step 0 still contains
* 3 values even though they are all equal.
*
* Return: the amount of values in first @ranges ranges pointed by @r
*/
unsigned int linear_range_values_in_range_array(const struct linear_range *r,
int ranges)
{
int i, values_in_range = 0;
for (i = 0; i < ranges; i++) {
int values;
values = linear_range_values_in_range(&r[i]);
if (!values)
return values;
values_in_range += values;
}
return values_in_range;
}
EXPORT_SYMBOL_GPL(linear_range_values_in_range_array);
/**
* linear_range_get_max_value - return the largest value in a range
* @r: pointer to linear range where value is looked from
*
* Return: the largest value in the given range
*/
unsigned int linear_range_get_max_value(const struct linear_range *r)
{
return r->min + (r->max_sel - r->min_sel) * r->step;
}
EXPORT_SYMBOL_GPL(linear_range_get_max_value);
/**
* linear_range_get_value - fetch a value from given range
* @r: pointer to linear range where value is looked from
* @selector: selector for which the value is searched
* @val: address where found value is updated
*
* Search given ranges for value which matches given selector.
*
* Return: 0 on success, -EINVAL given selector is not found from any of the
* ranges.
*/
int linear_range_get_value(const struct linear_range *r, unsigned int selector,
unsigned int *val)
{
if (r->min_sel > selector || r->max_sel < selector)
return -EINVAL;
*val = r->min + (selector - r->min_sel) * r->step;
return 0;
}
EXPORT_SYMBOL_GPL(linear_range_get_value);
/**
* linear_range_get_value_array - fetch a value from array of ranges
* @r: pointer to array of linear ranges where value is looked from
* @ranges: amount of ranges in an array
* @selector: selector for which the value is searched
* @val: address where found value is updated
*
* Search through an array of ranges for value which matches given selector.
*
* Return: 0 on success, -EINVAL given selector is not found from any of the
* ranges.
*/
int linear_range_get_value_array(const struct linear_range *r, int ranges,
unsigned int selector, unsigned int *val)
{
int i;
for (i = 0; i < ranges; i++)
if (r[i].min_sel <= selector && r[i].max_sel >= selector)
return linear_range_get_value(&r[i], selector, val);
return -EINVAL;
}
EXPORT_SYMBOL_GPL(linear_range_get_value_array);
/**
* linear_range_get_selector_low - return linear range selector for value
* @r: pointer to linear range where selector is looked from
* @val: value for which the selector is searched
* @selector: address where found selector value is updated
* @found: flag to indicate that given value was in the range
*
* Return selector which which range value is closest match for given
* input value. Value is matching if it is equal or smaller than given
* value. If given value is in the range, then @found is set true.
*
* Return: 0 on success, -EINVAL if range is invalid or does not contain
* value smaller or equal to given value
*/
int linear_range_get_selector_low(const struct linear_range *r,
unsigned int val, unsigned int *selector,
bool *found)
{
*found = false;
if (r->min > val)
return -EINVAL;
if (linear_range_get_max_value(r) < val) {
*selector = r->max_sel;
return 0;
}
*found = true;
if (r->step == 0)
*selector = r->min_sel;
else
*selector = (val - r->min) / r->step + r->min_sel;
return 0;
}
EXPORT_SYMBOL_GPL(linear_range_get_selector_low);
/**
* linear_range_get_selector_low_array - return linear range selector for value
* @r: pointer to array of linear ranges where selector is looked from
* @ranges: amount of ranges to scan from array
* @val: value for which the selector is searched
* @selector: address where found selector value is updated
* @found: flag to indicate that given value was in the range
*
* Scan array of ranges for selector which which range value matches given
* input value. Value is matching if it is equal or smaller than given
* value. If given value is found to be in a range scanning is stopped and
* @found is set true. If a range with values smaller than given value is found
* but the range max is being smaller than given value, then the ranges
* biggest selector is updated to @selector but scanning ranges is continued
* and @found is set to false.
*
* Return: 0 on success, -EINVAL if range array is invalid or does not contain
* range with a value smaller or equal to given value
*/
int linear_range_get_selector_low_array(const struct linear_range *r,
int ranges, unsigned int val,
unsigned int *selector, bool *found)
{
int i;
int ret = -EINVAL;
for (i = 0; i < ranges; i++) {
int tmpret;
tmpret = linear_range_get_selector_low(&r[i], val, selector,
found);
if (!tmpret)
ret = 0;
if (*found)
break;
}
return ret;
}
EXPORT_SYMBOL_GPL(linear_range_get_selector_low_array);
/**
* linear_range_get_selector_high - return linear range selector for value
* @r: pointer to linear range where selector is looked from
* @val: value for which the selector is searched
* @selector: address where found selector value is updated
* @found: flag to indicate that given value was in the range
*
* Return selector which which range value is closest match for given
* input value. Value is matching if it is equal or higher than given
* value. If given value is in the range, then @found is set true.
*
* Return: 0 on success, -EINVAL if range is invalid or does not contain
* value greater or equal to given value
*/
int linear_range_get_selector_high(const struct linear_range *r,
unsigned int val, unsigned int *selector,
bool *found)
{
*found = false;
if (linear_range_get_max_value(r) < val)
return -EINVAL;
if (r->min > val) {
*selector = r->min_sel;
return 0;
}
*found = true;
if (r->step == 0)
*selector = r->max_sel;
else
*selector = DIV_ROUND_UP(val - r->min, r->step) + r->min_sel;
return 0;
}
EXPORT_SYMBOL_GPL(linear_range_get_selector_high);
MODULE_DESCRIPTION("linear-ranges helper");
MODULE_LICENSE("GPL");
// SPDX-License-Identifier: GPL-2.0
/*
* KUnit test for the linear_ranges helper.
*
* Copyright (C) 2020, ROHM Semiconductors.
* Author: Matti Vaittinen <matti.vaittien@fi.rohmeurope.com>
*/
#include <kunit/test.h>
#include <linux/linear_range.h>
/* First things first. I deeply dislike unit-tests. I have seen all the hell
* breaking loose when people who think the unit tests are "the silver bullet"
* to kill bugs get to decide how a company should implement testing strategy...
*
* Believe me, it may get _really_ ridiculous. It is tempting to think that
* walking through all the possible execution branches will nail down 100% of
* bugs. This may lead to ideas about demands to get certain % of "test
* coverage" - measured as line coverage. And that is one of the worst things
* you can do.
*
* Ask people to provide line coverage and they do. I've seen clever tools
* which generate test cases to test the existing functions - and by default
* these tools expect code to be correct and just generate checks which are
* passing when ran against current code-base. Run this generator and you'll get
* tests that do not test code is correct but just verify nothing changes.
* Problem is that testing working code is pointless. And if it is not
* working, your test must not assume it is working. You won't catch any bugs
* by such tests. What you can do is to generate a huge amount of tests.
* Especially if you were are asked to proivde 100% line-coverage x_x. So what
* does these tests - which are not finding any bugs now - do?
*
* They add inertia to every future development. I think it was Terry Pratchet
* who wrote someone having same impact as thick syrup has to chronometre.
* Excessive amount of unit-tests have this effect to development. If you do
* actually find _any_ bug from code in such environment and try fixing it...
* ...chances are you also need to fix the test cases. In sunny day you fix one
* test. But I've done refactoring which resulted 500+ broken tests (which had
* really zero value other than proving to managers that we do do "quality")...
*
* After this being said - there are situations where UTs can be handy. If you
* have algorithms which take some input and should produce output - then you
* can implement few, carefully selected simple UT-cases which test this. I've
* previously used this for example for netlink and device-tree data parsing
* functions. Feed some data examples to functions and verify the output is as
* expected. I am not covering all the cases but I will see the logic should be
* working.
*
* Here we also do some minor testing. I don't want to go through all branches
* or test more or less obvious things - but I want to see the main logic is
* working. And I definitely don't want to add 500+ test cases that break when
* some simple fix is done x_x. So - let's only add few, well selected tests
* which ensure as much logic is good as possible.
*/
/*
* Test Range 1:
* selectors: 2 3 4 5 6
* values (5): 10 20 30 40 50
*
* Test Range 2:
* selectors: 7 8 9 10
* values (4): 100 150 200 250
*/
#define RANGE1_MIN 10
#define RANGE1_MIN_SEL 2
#define RANGE1_STEP 10
/* 2, 3, 4, 5, 6 */
static const unsigned int range1_sels[] = { RANGE1_MIN_SEL, RANGE1_MIN_SEL + 1,
RANGE1_MIN_SEL + 2,
RANGE1_MIN_SEL + 3,
RANGE1_MIN_SEL + 4 };
/* 10, 20, 30, 40, 50 */
static const unsigned int range1_vals[] = { RANGE1_MIN, RANGE1_MIN +
RANGE1_STEP,
RANGE1_MIN + RANGE1_STEP * 2,
RANGE1_MIN + RANGE1_STEP * 3,
RANGE1_MIN + RANGE1_STEP * 4 };
#define RANGE2_MIN 100
#define RANGE2_MIN_SEL 7
#define RANGE2_STEP 50
/* 7, 8, 9, 10 */
static const unsigned int range2_sels[] = { RANGE2_MIN_SEL, RANGE2_MIN_SEL + 1,
RANGE2_MIN_SEL + 2,
RANGE2_MIN_SEL + 3 };
/* 100, 150, 200, 250 */
static const unsigned int range2_vals[] = { RANGE2_MIN, RANGE2_MIN +
RANGE2_STEP,
RANGE2_MIN + RANGE2_STEP * 2,
RANGE2_MIN + RANGE2_STEP * 3 };
#define RANGE1_NUM_VALS (ARRAY_SIZE(range1_vals))
#define RANGE2_NUM_VALS (ARRAY_SIZE(range2_vals))
#define RANGE_NUM_VALS (RANGE1_NUM_VALS + RANGE2_NUM_VALS)
#define RANGE1_MAX_SEL (RANGE1_MIN_SEL + RANGE1_NUM_VALS - 1)
#define RANGE1_MAX_VAL (range1_vals[RANGE1_NUM_VALS - 1])
#define RANGE2_MAX_SEL (RANGE2_MIN_SEL + RANGE2_NUM_VALS - 1)
#define RANGE2_MAX_VAL (range2_vals[RANGE2_NUM_VALS - 1])
#define SMALLEST_SEL RANGE1_MIN_SEL
#define SMALLEST_VAL RANGE1_MIN
static struct linear_range testr[] = {
{
.min = RANGE1_MIN,
.min_sel = RANGE1_MIN_SEL,
.max_sel = RANGE1_MAX_SEL,
.step = RANGE1_STEP,
}, {
.min = RANGE2_MIN,
.min_sel = RANGE2_MIN_SEL,
.max_sel = RANGE2_MAX_SEL,
.step = RANGE2_STEP
},
};
static void range_test_get_value(struct kunit *test)
{
int ret, i;
unsigned int sel, val;
for (i = 0; i < RANGE1_NUM_VALS; i++) {
sel = range1_sels[i];
ret = linear_range_get_value_array(&testr[0], 2, sel, &val);
KUNIT_EXPECT_EQ(test, 0, ret);
KUNIT_EXPECT_EQ(test, val, range1_vals[i]);
}
for (i = 0; i < RANGE2_NUM_VALS; i++) {
sel = range2_sels[i];
ret = linear_range_get_value_array(&testr[0], 2, sel, &val);
KUNIT_EXPECT_EQ(test, 0, ret);
KUNIT_EXPECT_EQ(test, val, range2_vals[i]);
}
ret = linear_range_get_value_array(&testr[0], 2, sel + 1, &val);
KUNIT_EXPECT_NE(test, 0, ret);
}
static void range_test_get_selector_high(struct kunit *test)
{
int ret, i;
unsigned int sel;
bool found;
for (i = 0; i < RANGE1_NUM_VALS; i++) {
ret = linear_range_get_selector_high(&testr[0], range1_vals[i],
&sel, &found);
KUNIT_EXPECT_EQ(test, 0, ret);
KUNIT_EXPECT_EQ(test, sel, range1_sels[i]);
KUNIT_EXPECT_TRUE(test, found);
}
ret = linear_range_get_selector_high(&testr[0], RANGE1_MAX_VAL + 1,
&sel, &found);
KUNIT_EXPECT_LE(test, ret, 0);
ret = linear_range_get_selector_high(&testr[0], RANGE1_MIN - 1,
&sel, &found);
KUNIT_EXPECT_EQ(test, 0, ret);
KUNIT_EXPECT_FALSE(test, found);
KUNIT_EXPECT_EQ(test, sel, range1_sels[0]);
}
static void range_test_get_value_amount(struct kunit *test)
{
int ret;
ret = linear_range_values_in_range_array(&testr[0], 2);
KUNIT_EXPECT_EQ(test, (int)RANGE_NUM_VALS, ret);
}
static void range_test_get_selector_low(struct kunit *test)
{
int i, ret;
unsigned int sel;
bool found;
for (i = 0; i < RANGE1_NUM_VALS; i++) {
ret = linear_range_get_selector_low_array(&testr[0], 2,
range1_vals[i], &sel,
&found);
KUNIT_EXPECT_EQ(test, 0, ret);
KUNIT_EXPECT_EQ(test, sel, range1_sels[i]);
KUNIT_EXPECT_TRUE(test, found);
}
for (i = 0; i < RANGE2_NUM_VALS; i++) {
ret = linear_range_get_selector_low_array(&testr[0], 2,
range2_vals[i], &sel,
&found);
KUNIT_EXPECT_EQ(test, 0, ret);
KUNIT_EXPECT_EQ(test, sel, range2_sels[i]);
KUNIT_EXPECT_TRUE(test, found);
}
/*
* Seek value greater than range max => get_selector_*_low should
* return Ok - but set found to false as value is not in range
*/
ret = linear_range_get_selector_low_array(&testr[0], 2,
range2_vals[RANGE2_NUM_VALS - 1] + 1,
&sel, &found);
KUNIT_EXPECT_EQ(test, 0, ret);
KUNIT_EXPECT_EQ(test, sel, range2_sels[RANGE2_NUM_VALS - 1]);
KUNIT_EXPECT_FALSE(test, found);
}
static struct kunit_case range_test_cases[] = {
KUNIT_CASE(range_test_get_value_amount),
KUNIT_CASE(range_test_get_selector_high),
KUNIT_CASE(range_test_get_selector_low),
KUNIT_CASE(range_test_get_value),
{},
};
static struct kunit_suite range_test_module = {
.name = "linear-ranges-test",
.test_cases = range_test_cases,
};
kunit_test_suites(&range_test_module);
MODULE_LICENSE("GPL");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment