linux-mediatek.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 00/10] Support ROHM BD99954 charger IC
@ 2020-03-31 12:20 Matti Vaittinen
  2020-03-31 12:23 ` [PATCH v7 03/10] lib: add linear ranges helpers Matti Vaittinen
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Matti Vaittinen @ 2020-03-31 12:20 UTC (permalink / raw)
  To: matti.vaittinen, mazziesaccount
  Cc: Mark Rutland, Milo Kim, Andrei Stefanescu, Rafael J. Wysocki,
	Tony Lindgren, Linus Walleij, Brendan Higgins, Liam Girdwood,
	Masahiro Yamada, devicetree, linux-omap, mikko.mutanen,
	Vincenzo Frascino, Dan Williams, linux-samsung-soc,
	Andy Shevchenko, Uwe Kleine-König, linux-pm,
	Krzysztof Kozlowski, Ard Biesheuvel, Bartosz Golaszewski,
	Chen-Yu Tsai, Andy Gross, markus.laine, linux-arm-msm,
	Borislav Petkov, Petr Mladek, Mikhail Zaslonko, Charles Keepax,
	Arnd Bergmann, Bartlomiej Zolnierkiewicz, Gary Hook,
	Richard Fitzgerald, Rob Herring, linux-mediatek, David Gow,
	Shuah Khan, Matthias Brugger, Thomas Gleixner, Bjorn Andersson,
	linux-arm-kernel, Support Opensource, Sangbeom Kim,
	Greg Kroah-Hartman, Randy Dunlap, GitAuthor: Matti Vaittinen,
	Sebastian Reichel, linux-kernel, Tal Gilboa, Changbin Du,
	Mark Brown, Masami Hiramatsu, patches, Andrew Morton,
	Vladimir Oltean, David S. Miller

Support ROHM BD99954 Battery Management IC

ROHM BD99954 is a Battery Management IC for 1-4 cell Lithium-Ion
secondary battery. BD99954 is intended to be used in space-constraint
equipment such as Low profile Notebook PC, Tablets and other
applications.

Series extracts a "linear ranges" helper out of the regulator
framework. Linear ranges helper is intended to help converting
real-world values to register values when conversion is linear. I
suspect this is useful also for power subsystem and possibly for clk.

This version of series introduces new battry DT binding entries and
adds the parsing in power_supply_get_battery_info().

Changelog v7:
 General:
   - rebased on top of v5.6
 bd99954 driver:
   - fixed bunch of styling issues spotted by Andy Shevchenko
   - dropped ACPI table as ACPI properties are not supported at this
     version of driver.
   - added few acks

Changelog v6:
 generic:
   - rebased on top of 5.6-rc7.
 linear ranges:
   - moved to lib as requested by Greg KH
   - EXPORT_SYMBOL => EXPORT_SYMBOL_GPL
   - licence GPL-2.0, not later
   - added KUnit test for linear ranges

Changelog v5:
 generic:
   - rebased on top of 5.6-rc6.
 DT-bindings:
   - Dropped -charger extension from compatible and removed wildcard x.
 regulators:
   - squashed the regulator changes in one patch.
 power-supply KConfig:
   - fixed indentiation
   - dropped unnecessary 'default N' from BD99954.

Changelog v4:
 generic:
   - rebase and drop RFC.
 DT-bindings:
   - add I2C node address-cells and size-cells to fix yaml check errors
   - uncomment multipleOf:
 bd70528:
   - add patch which renames driver internal linear_range struct to
     avoid collision when regulator/driver.h (which gets included from
     rohm generic header) introduces the linear_range struct.
 regulators:
   - rebase to v5.6-rc2 and convert also the two newly introduced
     drivers to use linear_range struct instead of
     regulator_linear_range.
 linear_ranges:
   - Fix kerneldoc.

Changelog RFC-v3:
 DT-bindings:
   - fix the BD99954 binding (the *-microvolt Vs. *-microvolts issue is
     still there. Not sure which one is correct)
   - renabe tricklecharge-* binding to trickle-charge-* as suggested by
     Rob.
 - drop the linear-ranges helper which was written for BD70528 and
   extract the linear-range code from regulator framework instead.
 - refactor regulator framework to utilize extracted linear-ranges
   code.
 - change the struct regulator_linear_range to linear_range from
   regulator drivers.
 - refactor BD70528 to use regulator framework originated
   linear-ranges code.
 - change BD99954 to use linear-ranges code from regulator framework

Changelog RFC-v2:
 DT-bindings:
   - Used the battery parameters described in battery.txt
   - Added few new parameters to battery.txt
   - Added ASCII art charging profile chart for BD99954 to explain
     states and limits.
 Linear ranges:
   - Fixed division by zero error from linear-ranges code if step 0 is
     used.
 Power-supply core:
   - Added parsing of new battery parameters.
 BD99954 driver:
   - converted to use battery parameters from battery node
   - Added step 0 ranges for reg values which do not change voltage
   - added dt-node to psy-config

Patch 1:
	DT binding docs for the new battery parameters
Patch 2:
	BD99954 charger DT binding docs
Patch 3:
	Linear ranges helpers
Patch 4:
	Test for linear ranges helpers
Patch 5:
	Rename driver internal struct linear_range from bd70528-power
Patch 6:
	Use linear-ranges helpers in regulator framework and
	convert regulator drivers to use new linear_range struct.
Patch 7:
	Use linear-ranges helpers in bd70528 driver
Patch 8:
	Parsing of new battery parameters
Patch 9:
	ROHM BD99954 charger IC driver
Patch 10:
	Fix Kconfig help text indentiation for other entries as well.

---

Matti Vaittinen (10):
  dt-bindings: battery: add new battery parameters
  dt_bindings: ROHM BD99954 Charger
  lib: add linear ranges helpers
  lib/test_linear_ranges: add a test for the 'linear_ranges'
  power: supply: bd70528: rename linear_range to avoid collision
  regulator: use linear_ranges helper
  power: supply: bd70528: use linear ranges
  power: supply: add battery parameters
  power: supply: Support ROHM bd99954 charger
  power: supply: Fix Kconfig help text indentiation

 .../bindings/power/supply/battery.txt         |    6 +
 .../bindings/power/supply/rohm,bd99954.yaml   |  155 +++
 drivers/power/supply/Kconfig                  |   34 +-
 drivers/power/supply/Makefile                 |    1 +
 drivers/power/supply/bd70528-charger.c        |  140 +-
 drivers/power/supply/bd99954-charger.c        | 1149 +++++++++++++++++
 drivers/power/supply/power_supply_core.c      |    8 +
 drivers/regulator/88pg86x.c                   |    4 +-
 drivers/regulator/88pm800-regulator.c         |    4 +-
 drivers/regulator/Kconfig                     |    1 +
 drivers/regulator/act8865-regulator.c         |    4 +-
 drivers/regulator/act8945a-regulator.c        |    2 +-
 drivers/regulator/arizona-ldo1.c              |    2 +-
 drivers/regulator/arizona-micsupp.c           |    4 +-
 drivers/regulator/as3711-regulator.c          |    6 +-
 drivers/regulator/as3722-regulator.c          |    4 +-
 drivers/regulator/axp20x-regulator.c          |   16 +-
 drivers/regulator/bcm590xx-regulator.c        |    8 +-
 drivers/regulator/bd70528-regulator.c         |    8 +-
 drivers/regulator/bd71828-regulator.c         |   10 +-
 drivers/regulator/bd718x7-regulator.c         |   26 +-
 drivers/regulator/da903x.c                    |    2 +-
 drivers/regulator/helpers.c                   |  130 +-
 drivers/regulator/hi6421-regulator.c          |    4 +-
 drivers/regulator/lochnagar-regulator.c       |    4 +-
 drivers/regulator/lp873x-regulator.c          |    4 +-
 drivers/regulator/lp87565-regulator.c         |    2 +-
 drivers/regulator/lp8788-buck.c               |    2 +-
 drivers/regulator/max77650-regulator.c        |    2 +-
 drivers/regulator/mcp16502.c                  |    4 +-
 drivers/regulator/mp8859.c                    |    2 +-
 drivers/regulator/mt6323-regulator.c          |    6 +-
 drivers/regulator/mt6358-regulator.c          |    8 +-
 drivers/regulator/mt6380-regulator.c          |    6 +-
 drivers/regulator/mt6397-regulator.c          |    6 +-
 drivers/regulator/palmas-regulator.c          |    4 +-
 drivers/regulator/qcom-rpmh-regulator.c       |    2 +-
 drivers/regulator/qcom_rpm-regulator.c        |   14 +-
 drivers/regulator/qcom_smd-regulator.c        |   70 +-
 drivers/regulator/rk808-regulator.c           |   10 +-
 drivers/regulator/s2mps11.c                   |   14 +-
 drivers/regulator/sky81452-regulator.c        |    2 +-
 drivers/regulator/stpmic1_regulator.c         |   18 +-
 drivers/regulator/tps65086-regulator.c        |   10 +-
 drivers/regulator/tps65217-regulator.c        |    4 +-
 drivers/regulator/tps65218-regulator.c        |    6 +-
 drivers/regulator/tps65912-regulator.c        |    4 +-
 drivers/regulator/twl-regulator.c             |    4 +-
 drivers/regulator/twl6030-regulator.c         |    2 +-
 drivers/regulator/wm831x-dcdc.c               |    2 +-
 drivers/regulator/wm831x-ldo.c                |    4 +-
 drivers/regulator/wm8350-regulator.c          |    2 +-
 drivers/regulator/wm8400-regulator.c          |    2 +-
 include/linux/linear_range.h                  |   48 +
 include/linux/power/bd99954-charger.h         | 1075 +++++++++++++++
 include/linux/power_supply.h                  |    4 +
 include/linux/regulator/driver.h              |   27 +-
 lib/Kconfig                                   |    3 +
 lib/Kconfig.debug                             |   11 +
 lib/Makefile                                  |    2 +
 lib/linear_ranges.c                           |  246 ++++
 lib/test_linear_ranges.c                      |  228 ++++
 62 files changed, 3236 insertions(+), 356 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/power/supply/rohm,bd99954.yaml
 create mode 100644 drivers/power/supply/bd99954-charger.c
 create mode 100644 include/linux/linear_range.h
 create mode 100644 include/linux/power/bd99954-charger.h
 create mode 100644 lib/linear_ranges.c
 create mode 100644 lib/test_linear_ranges.c


base-commit: 7111951b8d4973bda27ff663f2cf18b663d15b48
-- 
2.21.0


-- 
Matti Vaittinen, Linux device drivers
ROHM Semiconductors, Finland SWDC
Kiviharjunlenkki 1E
90220 OULU
FINLAND

~~~ "I don't think so," said Rene Descartes. Just then he vanished ~~~
Simon says - in Latin please.
~~~ "non cogito me" dixit Rene Descarte, deinde evanescavit ~~~
Thanks to Simon Glass for the translation =] 

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v7 03/10] lib: add linear ranges helpers
  2020-03-31 12:20 [PATCH v7 00/10] Support ROHM BD99954 charger IC Matti Vaittinen
@ 2020-03-31 12:23 ` Matti Vaittinen
  2020-03-31 14:05   ` Andy Shevchenko
  2020-03-31 12:24 ` [PATCH v7 00/10] Support ROHM BD99954 charger IC Ard Biesheuvel
  2020-03-31 12:25 ` [PATCH v7 06/10] regulator: use linear_ranges helper Matti Vaittinen
  2 siblings, 1 reply; 13+ messages in thread
From: Matti Vaittinen @ 2020-03-31 12:23 UTC (permalink / raw)
  To: matti.vaittinen, mazziesaccount
  Cc: Mark Rutland, Milo Kim, Andrei Stefanescu, Rafael J. Wysocki,
	Tony Lindgren, Linus Walleij, Brendan Higgins, Bjorn Andersson,
	Masahiro Yamada, devicetree, mikko.mutanen, Vincenzo Frascino,
	Dan Williams, Gary Hook, linux-samsung-soc, linux-omap,
	Herbert Xu, linux-pm, Chen-Yu Tsai, Krzysztof Kozlowski,
	Ard Biesheuvel, Bartosz Golaszewski, Andy Shevchenko, Andy Gross,
	markus.laine, linux-arm-msm, Borislav Petkov, Petr Mladek,
	Mikhail Zaslonko, Charles Keepax, Arnd Bergmann,
	Bartlomiej Zolnierkiewicz, Liam Girdwood, Richard Fitzgerald,
	Rob Herring, linux-mediatek, David Gow, Shuah Khan,
	Matthias Brugger, Thomas Gleixner, Andy Shevchenko,
	linux-arm-kernel, Support Opensource, Sangbeom Kim,
	Greg Kroah-Hartman, Randy Dunlap, GitAuthor: Matti Vaittinen,
	Sebastian Reichel, linux-kernel, Tal Gilboa, Changbin Du,
	Mark Brown, Uwe Kleine-König, Masami Hiramatsu, patches,
	Andrew Morton, Vladimir Oltean, David S. Miller

Many devices have control registers which control some measurable
property. Often a register contains control field so that change in
this field causes linear change in the controlled property. It is not
a rare case that user wants to give 'meaningful' control values and
driver needs to convert them to register field values. Even more
often user wants to 'see' the currently set value - again in
meaningful units - and driver needs to convert the values it reads
from register to these meaningful units. Examples of this include:

- regulators, voltage/current configurations
- power, voltage/current configurations
- clk(?) NCOs

and maybe others I can't think of right now.

Provide a linear_range helper which can do conversion from user value
to register value 'selector'.

The idea here is stolen from regulator framework and patches refactoring
the regulator helpers to use this are following.

Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
---

No changes since v6

 include/linux/linear_range.h |  48 +++++++
 lib/Kconfig                  |   3 +
 lib/Makefile                 |   1 +
 lib/linear_ranges.c          | 246 +++++++++++++++++++++++++++++++++++
 4 files changed, 298 insertions(+)
 create mode 100644 include/linux/linear_range.h
 create mode 100644 lib/linear_ranges.c

diff --git a/include/linux/linear_range.h b/include/linux/linear_range.h
new file mode 100644
index 000000000000..17b5943727d5
--- /dev/null
+++ b/include/linux/linear_range.h
@@ -0,0 +1,48 @@
+/* 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
diff --git a/lib/Kconfig b/lib/Kconfig
index bc7e56370129..411ab2d2d800 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -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
diff --git a/lib/Makefile b/lib/Makefile
index 611872c06926..18c3d313872e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -122,6 +122,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
diff --git a/lib/linear_ranges.c b/lib/linear_ranges.c
new file mode 100644
index 000000000000..52246325f9a9
--- /dev/null
+++ b/lib/linear_ranges.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * linear_ranges.c -- 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>
+
+/**
+ * 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)
+		*found = true;
+
+	if (!r->step)
+		*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 scannins 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) {
+		*found = true;
+	} else {
+		*selector = r->min_sel;
+		return 0;
+	}
+
+	if (!r->step)
+		*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);
-- 
2.21.0


-- 
Matti Vaittinen, Linux device drivers
ROHM Semiconductors, Finland SWDC
Kiviharjunlenkki 1E
90220 OULU
FINLAND

~~~ "I don't think so," said Rene Descartes. Just then he vanished ~~~
Simon says - in Latin please.
~~~ "non cogito me" dixit Rene Descarte, deinde evanescavit ~~~
Thanks to Simon Glass for the translation =] 

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v7 00/10] Support ROHM BD99954 charger IC
  2020-03-31 12:20 [PATCH v7 00/10] Support ROHM BD99954 charger IC Matti Vaittinen
  2020-03-31 12:23 ` [PATCH v7 03/10] lib: add linear ranges helpers Matti Vaittinen
@ 2020-03-31 12:24 ` Ard Biesheuvel
  2020-03-31 14:02   ` Vaittinen, Matti
  2020-03-31 12:25 ` [PATCH v7 06/10] regulator: use linear_ranges helper Matti Vaittinen
  2 siblings, 1 reply; 13+ messages in thread
From: Ard Biesheuvel @ 2020-03-31 12:24 UTC (permalink / raw)
  To: Matti Vaittinen
  Cc: Mark Rutland, Milo Kim, Andrei Stefanescu, Rafael J. Wysocki,
	Tony Lindgren, Linus Walleij, Brendan Higgins, Liam Girdwood,
	Masahiro Yamada, devicetree, linux-omap, mikko.mutanen,
	Vincenzo Frascino, Dan Williams, linux-samsung-soc,
	Andy Shevchenko, Uwe Kleine-König,
	Bartlomiej Zolnierkiewicz, Krzysztof Kozlowski,
	Bartosz Golaszewski, Chen-Yu Tsai, Andy Gross, markus.laine,
	linux-arm-msm, Borislav Petkov, Petr Mladek, Mikhail Zaslonko,
	Charles Keepax, Arnd Bergmann, mazziesaccount, Gary Hook,
	Richard Fitzgerald, Rob Herring, linux-mediatek, David Gow,
	Shuah Khan, Matthias Brugger, Thomas Gleixner, Bjorn Andersson,
	Linux ARM, Support Opensource, Sangbeom Kim, Greg Kroah-Hartman,
	linux-pm, Randy Dunlap, Sebastian Reichel,
	Linux Kernel Mailing List, Tal Gilboa, Changbin Du, Mark Brown,
	Masami Hiramatsu, patches, Andrew Morton, Vladimir Oltean,
	David S. Miller

Hello Matti,

On Tue, 31 Mar 2020 at 14:20, Matti Vaittinen
<matti.vaittinen@fi.rohmeurope.com> wrote:
>
> Support ROHM BD99954 Battery Management IC
>
> ROHM BD99954 is a Battery Management IC for 1-4 cell Lithium-Ion
> secondary battery. BD99954 is intended to be used in space-constraint
> equipment such as Low profile Notebook PC, Tablets and other
> applications.
>

Is it *really* necessary to cc this to 50 different people?

In the future, please trim down the cc list and keep it to the mailing
list, maintainers and reviewers of the affected subsystem.


> Series extracts a "linear ranges" helper out of the regulator
> framework. Linear ranges helper is intended to help converting
> real-world values to register values when conversion is linear. I
> suspect this is useful also for power subsystem and possibly for clk.
>
> This version of series introduces new battry DT binding entries and
> adds the parsing in power_supply_get_battery_info().
>
> Changelog v7:
>  General:
>    - rebased on top of v5.6
>  bd99954 driver:
>    - fixed bunch of styling issues spotted by Andy Shevchenko
>    - dropped ACPI table as ACPI properties are not supported at this
>      version of driver.
>    - added few acks
>
> Changelog v6:
>  generic:
>    - rebased on top of 5.6-rc7.
>  linear ranges:
>    - moved to lib as requested by Greg KH
>    - EXPORT_SYMBOL => EXPORT_SYMBOL_GPL
>    - licence GPL-2.0, not later
>    - added KUnit test for linear ranges
>
> Changelog v5:
>  generic:
>    - rebased on top of 5.6-rc6.
>  DT-bindings:
>    - Dropped -charger extension from compatible and removed wildcard x.
>  regulators:
>    - squashed the regulator changes in one patch.
>  power-supply KConfig:
>    - fixed indentiation
>    - dropped unnecessary 'default N' from BD99954.
>
> Changelog v4:
>  generic:
>    - rebase and drop RFC.
>  DT-bindings:
>    - add I2C node address-cells and size-cells to fix yaml check errors
>    - uncomment multipleOf:
>  bd70528:
>    - add patch which renames driver internal linear_range struct to
>      avoid collision when regulator/driver.h (which gets included from
>      rohm generic header) introduces the linear_range struct.
>  regulators:
>    - rebase to v5.6-rc2 and convert also the two newly introduced
>      drivers to use linear_range struct instead of
>      regulator_linear_range.
>  linear_ranges:
>    - Fix kerneldoc.
>
> Changelog RFC-v3:
>  DT-bindings:
>    - fix the BD99954 binding (the *-microvolt Vs. *-microvolts issue is
>      still there. Not sure which one is correct)
>    - renabe tricklecharge-* binding to trickle-charge-* as suggested by
>      Rob.
>  - drop the linear-ranges helper which was written for BD70528 and
>    extract the linear-range code from regulator framework instead.
>  - refactor regulator framework to utilize extracted linear-ranges
>    code.
>  - change the struct regulator_linear_range to linear_range from
>    regulator drivers.
>  - refactor BD70528 to use regulator framework originated
>    linear-ranges code.
>  - change BD99954 to use linear-ranges code from regulator framework
>
> Changelog RFC-v2:
>  DT-bindings:
>    - Used the battery parameters described in battery.txt
>    - Added few new parameters to battery.txt
>    - Added ASCII art charging profile chart for BD99954 to explain
>      states and limits.
>  Linear ranges:
>    - Fixed division by zero error from linear-ranges code if step 0 is
>      used.
>  Power-supply core:
>    - Added parsing of new battery parameters.
>  BD99954 driver:
>    - converted to use battery parameters from battery node
>    - Added step 0 ranges for reg values which do not change voltage
>    - added dt-node to psy-config
>
> Patch 1:
>         DT binding docs for the new battery parameters
> Patch 2:
>         BD99954 charger DT binding docs
> Patch 3:
>         Linear ranges helpers
> Patch 4:
>         Test for linear ranges helpers
> Patch 5:
>         Rename driver internal struct linear_range from bd70528-power
> Patch 6:
>         Use linear-ranges helpers in regulator framework and
>         convert regulator drivers to use new linear_range struct.
> Patch 7:
>         Use linear-ranges helpers in bd70528 driver
> Patch 8:
>         Parsing of new battery parameters
> Patch 9:
>         ROHM BD99954 charger IC driver
> Patch 10:
>         Fix Kconfig help text indentiation for other entries as well.
>
> ---
>
> Matti Vaittinen (10):
>   dt-bindings: battery: add new battery parameters
>   dt_bindings: ROHM BD99954 Charger
>   lib: add linear ranges helpers
>   lib/test_linear_ranges: add a test for the 'linear_ranges'
>   power: supply: bd70528: rename linear_range to avoid collision
>   regulator: use linear_ranges helper
>   power: supply: bd70528: use linear ranges
>   power: supply: add battery parameters
>   power: supply: Support ROHM bd99954 charger
>   power: supply: Fix Kconfig help text indentiation
>
>  .../bindings/power/supply/battery.txt         |    6 +
>  .../bindings/power/supply/rohm,bd99954.yaml   |  155 +++
>  drivers/power/supply/Kconfig                  |   34 +-
>  drivers/power/supply/Makefile                 |    1 +
>  drivers/power/supply/bd70528-charger.c        |  140 +-
>  drivers/power/supply/bd99954-charger.c        | 1149 +++++++++++++++++
>  drivers/power/supply/power_supply_core.c      |    8 +
>  drivers/regulator/88pg86x.c                   |    4 +-
>  drivers/regulator/88pm800-regulator.c         |    4 +-
>  drivers/regulator/Kconfig                     |    1 +
>  drivers/regulator/act8865-regulator.c         |    4 +-
>  drivers/regulator/act8945a-regulator.c        |    2 +-
>  drivers/regulator/arizona-ldo1.c              |    2 +-
>  drivers/regulator/arizona-micsupp.c           |    4 +-
>  drivers/regulator/as3711-regulator.c          |    6 +-
>  drivers/regulator/as3722-regulator.c          |    4 +-
>  drivers/regulator/axp20x-regulator.c          |   16 +-
>  drivers/regulator/bcm590xx-regulator.c        |    8 +-
>  drivers/regulator/bd70528-regulator.c         |    8 +-
>  drivers/regulator/bd71828-regulator.c         |   10 +-
>  drivers/regulator/bd718x7-regulator.c         |   26 +-
>  drivers/regulator/da903x.c                    |    2 +-
>  drivers/regulator/helpers.c                   |  130 +-
>  drivers/regulator/hi6421-regulator.c          |    4 +-
>  drivers/regulator/lochnagar-regulator.c       |    4 +-
>  drivers/regulator/lp873x-regulator.c          |    4 +-
>  drivers/regulator/lp87565-regulator.c         |    2 +-
>  drivers/regulator/lp8788-buck.c               |    2 +-
>  drivers/regulator/max77650-regulator.c        |    2 +-
>  drivers/regulator/mcp16502.c                  |    4 +-
>  drivers/regulator/mp8859.c                    |    2 +-
>  drivers/regulator/mt6323-regulator.c          |    6 +-
>  drivers/regulator/mt6358-regulator.c          |    8 +-
>  drivers/regulator/mt6380-regulator.c          |    6 +-
>  drivers/regulator/mt6397-regulator.c          |    6 +-
>  drivers/regulator/palmas-regulator.c          |    4 +-
>  drivers/regulator/qcom-rpmh-regulator.c       |    2 +-
>  drivers/regulator/qcom_rpm-regulator.c        |   14 +-
>  drivers/regulator/qcom_smd-regulator.c        |   70 +-
>  drivers/regulator/rk808-regulator.c           |   10 +-
>  drivers/regulator/s2mps11.c                   |   14 +-
>  drivers/regulator/sky81452-regulator.c        |    2 +-
>  drivers/regulator/stpmic1_regulator.c         |   18 +-
>  drivers/regulator/tps65086-regulator.c        |   10 +-
>  drivers/regulator/tps65217-regulator.c        |    4 +-
>  drivers/regulator/tps65218-regulator.c        |    6 +-
>  drivers/regulator/tps65912-regulator.c        |    4 +-
>  drivers/regulator/twl-regulator.c             |    4 +-
>  drivers/regulator/twl6030-regulator.c         |    2 +-
>  drivers/regulator/wm831x-dcdc.c               |    2 +-
>  drivers/regulator/wm831x-ldo.c                |    4 +-
>  drivers/regulator/wm8350-regulator.c          |    2 +-
>  drivers/regulator/wm8400-regulator.c          |    2 +-
>  include/linux/linear_range.h                  |   48 +
>  include/linux/power/bd99954-charger.h         | 1075 +++++++++++++++
>  include/linux/power_supply.h                  |    4 +
>  include/linux/regulator/driver.h              |   27 +-
>  lib/Kconfig                                   |    3 +
>  lib/Kconfig.debug                             |   11 +
>  lib/Makefile                                  |    2 +
>  lib/linear_ranges.c                           |  246 ++++
>  lib/test_linear_ranges.c                      |  228 ++++
>  62 files changed, 3236 insertions(+), 356 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/power/supply/rohm,bd99954.yaml
>  create mode 100644 drivers/power/supply/bd99954-charger.c
>  create mode 100644 include/linux/linear_range.h
>  create mode 100644 include/linux/power/bd99954-charger.h
>  create mode 100644 lib/linear_ranges.c
>  create mode 100644 lib/test_linear_ranges.c
>
>
> base-commit: 7111951b8d4973bda27ff663f2cf18b663d15b48
> --
> 2.21.0
>
>
> --
> Matti Vaittinen, Linux device drivers
> ROHM Semiconductors, Finland SWDC
> Kiviharjunlenkki 1E
> 90220 OULU
> FINLAND
>
> ~~~ "I don't think so," said Rene Descartes. Just then he vanished ~~~
> Simon says - in Latin please.
> ~~~ "non cogito me" dixit Rene Descarte, deinde evanescavit ~~~
> Thanks to Simon Glass for the translation =]

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v7 06/10] regulator: use linear_ranges helper
  2020-03-31 12:20 [PATCH v7 00/10] Support ROHM BD99954 charger IC Matti Vaittinen
  2020-03-31 12:23 ` [PATCH v7 03/10] lib: add linear ranges helpers Matti Vaittinen
  2020-03-31 12:24 ` [PATCH v7 00/10] Support ROHM BD99954 charger IC Ard Biesheuvel
@ 2020-03-31 12:25 ` Matti Vaittinen
  2020-04-01 10:17   ` Mark Brown
  2 siblings, 1 reply; 13+ messages in thread
From: Matti Vaittinen @ 2020-03-31 12:25 UTC (permalink / raw)
  To: matti.vaittinen, mazziesaccount
  Cc: Mark Rutland, Milo Kim, Andrei Stefanescu, Rafael J. Wysocki,
	Tony Lindgren, Linus Walleij, Brendan Higgins, Bjorn Andersson,
	Masahiro Yamada, devicetree, mikko.mutanen, Vincenzo Frascino,
	Dan Williams, Gary Hook, linux-samsung-soc, linux-omap,
	Herbert Xu, linux-pm, Chen-Yu Tsai, Krzysztof Kozlowski,
	Ard Biesheuvel, Bartosz Golaszewski, Andy Shevchenko, Andy Gross,
	markus.laine, linux-arm-msm, Borislav Petkov, Petr Mladek,
	Mikhail Zaslonko, Charles Keepax, Arnd Bergmann,
	Bartlomiej Zolnierkiewicz, Liam Girdwood, Richard Fitzgerald,
	Rob Herring, linux-mediatek, David Gow, Shuah Khan,
	Matthias Brugger, Thomas Gleixner, Andy Shevchenko,
	linux-arm-kernel, Support Opensource, Sangbeom Kim,
	Greg Kroah-Hartman, Randy Dunlap, GitAuthor: Matti Vaittinen,
	Sebastian Reichel, linux-kernel, Tal Gilboa, Changbin Du,
	Mark Brown, Uwe Kleine-König, Masami Hiramatsu, patches,
	Andrew Morton, Vladimir Oltean, David S. Miller

Change the regulator helpers to use common linear_ranges code.

Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Acked-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---

No changes since v6 (rebased on v5.6)

 drivers/regulator/88pg86x.c             |   4 +-
 drivers/regulator/88pm800-regulator.c   |   4 +-
 drivers/regulator/Kconfig               |   1 +
 drivers/regulator/act8865-regulator.c   |   4 +-
 drivers/regulator/act8945a-regulator.c  |   2 +-
 drivers/regulator/arizona-ldo1.c        |   2 +-
 drivers/regulator/arizona-micsupp.c     |   4 +-
 drivers/regulator/as3711-regulator.c    |   6 +-
 drivers/regulator/as3722-regulator.c    |   4 +-
 drivers/regulator/axp20x-regulator.c    |  16 +--
 drivers/regulator/bcm590xx-regulator.c  |   8 +-
 drivers/regulator/bd70528-regulator.c   |   8 +-
 drivers/regulator/bd71828-regulator.c   |  10 +-
 drivers/regulator/bd718x7-regulator.c   |  26 ++---
 drivers/regulator/da903x.c              |   2 +-
 drivers/regulator/helpers.c             | 130 +++++++++++-------------
 drivers/regulator/hi6421-regulator.c    |   4 +-
 drivers/regulator/lochnagar-regulator.c |   4 +-
 drivers/regulator/lp873x-regulator.c    |   4 +-
 drivers/regulator/lp87565-regulator.c   |   2 +-
 drivers/regulator/lp8788-buck.c         |   2 +-
 drivers/regulator/max77650-regulator.c  |   2 +-
 drivers/regulator/mcp16502.c            |   4 +-
 drivers/regulator/mp8859.c              |   2 +-
 drivers/regulator/mt6323-regulator.c    |   6 +-
 drivers/regulator/mt6358-regulator.c    |   8 +-
 drivers/regulator/mt6380-regulator.c    |   6 +-
 drivers/regulator/mt6397-regulator.c    |   6 +-
 drivers/regulator/palmas-regulator.c    |   4 +-
 drivers/regulator/qcom-rpmh-regulator.c |   2 +-
 drivers/regulator/qcom_rpm-regulator.c  |  14 +--
 drivers/regulator/qcom_smd-regulator.c  |  70 ++++++-------
 drivers/regulator/rk808-regulator.c     |  10 +-
 drivers/regulator/s2mps11.c             |  14 +--
 drivers/regulator/sky81452-regulator.c  |   2 +-
 drivers/regulator/stpmic1_regulator.c   |  18 ++--
 drivers/regulator/tps65086-regulator.c  |  10 +-
 drivers/regulator/tps65217-regulator.c  |   4 +-
 drivers/regulator/tps65218-regulator.c  |   6 +-
 drivers/regulator/tps65912-regulator.c  |   4 +-
 drivers/regulator/twl-regulator.c       |   4 +-
 drivers/regulator/twl6030-regulator.c   |   2 +-
 drivers/regulator/wm831x-dcdc.c         |   2 +-
 drivers/regulator/wm831x-ldo.c          |   4 +-
 drivers/regulator/wm8350-regulator.c    |   2 +-
 drivers/regulator/wm8400-regulator.c    |   2 +-
 include/linux/regulator/driver.h        |  27 +----
 47 files changed, 225 insertions(+), 257 deletions(-)

diff --git a/drivers/regulator/88pg86x.c b/drivers/regulator/88pg86x.c
index d5ef55c81185..71cfa2c5de5e 100644
--- a/drivers/regulator/88pg86x.c
+++ b/drivers/regulator/88pg86x.c
@@ -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),
diff --git a/drivers/regulator/88pm800-regulator.c b/drivers/regulator/88pm800-regulator.c
index 69ae25886181..d08ee81ed1ac 100644
--- a/drivers/regulator/88pm800-regulator.c
+++ b/drivers/regulator/88pm800-regulator.c
@@ -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),
 };
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 074a2ef55943..1fd2fe2b0c7a 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1,6 +1,7 @@
 # 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.
 
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c
index 0fa97f934df4..19b9742c9ecc 100644
--- a/drivers/regulator/act8865-regulator.c
+++ b/drivers/regulator/act8865-regulator.c
@@ -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),
diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c
index d2f804dbc785..6a62f946ccae 100644
--- a/drivers/regulator/act8945a-regulator.c
+++ b/drivers/regulator/act8945a-regulator.c
@@ -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),
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index 1a3d7b720f5e..ade0bef4569d 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -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),
 };
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c
index ae1a5de3e57d..f6cfd3f6f0dd 100644
--- a/drivers/regulator/arizona-micsupp.c
+++ b/drivers/regulator/arizona-micsupp.c
@@ -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),
 };
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
index ece88103f2fd..b6b9206969ae 100644
--- a/drivers/regulator/as3711-regulator.c
+++ b/drivers/regulator/as3711-regulator.c
@@ -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),
 };
diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c
index bd5d0bacb08d..33ca197860b3 100644
--- a/drivers/regulator/as3722-regulator.c
+++ b/drivers/regulator/as3722-regulator.c
@@ -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),
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 16f0c8570036..7b3dc37130f3 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -512,7 +512,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,
@@ -640,7 +640,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,
@@ -651,7 +651,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,
@@ -662,7 +662,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,
@@ -674,7 +674,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,
@@ -760,7 +760,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,
@@ -771,7 +771,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,
@@ -836,7 +836,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,
diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index 8c98c3f07660..65e23fc5f9c3 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -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) \
diff --git a/drivers/regulator/bd70528-regulator.c b/drivers/regulator/bd70528-regulator.c
index 5bf8a2dc5fe7..d44adf7e875a 100644
--- a/drivers/regulator/bd70528-regulator.c
+++ b/drivers/regulator/bd70528-regulator.c
@@ -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),
diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c
index b2fa17be4988..85c0b9000963 100644
--- a/drivers/regulator/bd71828-regulator.c
+++ b/drivers/regulator/bd71828-regulator.c
@@ -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),
 };
diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c
index cf3872837abc..819573610ee2 100644
--- a/drivers/regulator/bd718x7-regulator.c
+++ b/drivers/regulator/bd718x7-regulator.c
@@ -152,7 +152,7 @@ static const struct regulator_ops bd718xx_dvs_buck_regulator_ops = {
  * BD71847 BUCK1/2
  * 0.70 to 1.30V (10mV step)
  */
-static const struct regulator_linear_range bd718xx_dvs_buck_volts[] = {
+static const struct linear_range bd718xx_dvs_buck_volts[] = {
 	REGULATOR_LINEAR_RANGE(700000, 0x00, 0x3C, 10000),
 	REGULATOR_LINEAR_RANGE(1300000, 0x3D, 0x3F, 0),
 };
@@ -163,7 +163,7 @@ static const struct regulator_linear_range bd718xx_dvs_buck_volts[] = {
  * and
  * 0.675 to 1.325 (range 1)
  */
-static const struct regulator_linear_range bd71837_buck5_volts[] = {
+static const struct linear_range bd71837_buck5_volts[] = {
 	/* Ranges when VOLT_SEL bit is 0 */
 	REGULATOR_LINEAR_RANGE(700000, 0x00, 0x03, 100000),
 	REGULATOR_LINEAR_RANGE(1050000, 0x04, 0x05, 50000),
@@ -185,7 +185,7 @@ static const unsigned int bd71837_buck5_volt_range_sel[] = {
 /*
  * BD71847 BUCK3
  */
-static const struct regulator_linear_range bd71847_buck3_volts[] = {
+static const struct linear_range bd71847_buck3_volts[] = {
 	/* Ranges when VOLT_SEL bits are 00 */
 	REGULATOR_LINEAR_RANGE(700000, 0x00, 0x03, 100000),
 	REGULATOR_LINEAR_RANGE(1050000, 0x04, 0x05, 50000),
@@ -202,7 +202,7 @@ static const unsigned int bd71847_buck3_volt_range_sel[] = {
 	0x0, 0x0, 0x0, 0x40, 0x80, 0x80, 0x80
 };
 
-static const struct regulator_linear_range bd71847_buck4_volts[] = {
+static const struct linear_range bd71847_buck4_volts[] = {
 	REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000),
 	REGULATOR_LINEAR_RANGE(2600000, 0x00, 0x03, 100000),
 };
@@ -213,7 +213,7 @@ static const unsigned int bd71847_buck4_volt_range_sel[] = { 0x0, 0x40 };
  * BUCK6
  * 3.0V to 3.3V (step 100mV)
  */
-static const struct regulator_linear_range bd71837_buck6_volts[] = {
+static const struct linear_range bd71837_buck6_volts[] = {
 	REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000),
 };
 
@@ -237,7 +237,7 @@ static const unsigned int bd718xx_3rd_nodvs_buck_volts[] = {
  * BUCK8
  * 0.8V to 1.40V (step 10mV)
  */
-static const struct regulator_linear_range bd718xx_4th_nodvs_buck_volts[] = {
+static const struct linear_range bd718xx_4th_nodvs_buck_volts[] = {
 	REGULATOR_LINEAR_RANGE(800000, 0x00, 0x3C, 10000),
 };
 
@@ -245,7 +245,7 @@ static const struct regulator_linear_range bd718xx_4th_nodvs_buck_volts[] = {
  * LDO1
  * 3.0 to 3.3V (100mV step)
  */
-static const struct regulator_linear_range bd718xx_ldo1_volts[] = {
+static const struct linear_range bd718xx_ldo1_volts[] = {
 	REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000),
 	REGULATOR_LINEAR_RANGE(1600000, 0x00, 0x03, 100000),
 };
@@ -264,7 +264,7 @@ static const unsigned int ldo_2_volts[] = {
  * LDO3
  * 1.8 to 3.3V (100mV step)
  */
-static const struct regulator_linear_range bd718xx_ldo3_volts[] = {
+static const struct linear_range bd718xx_ldo3_volts[] = {
 	REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
 };
 
@@ -272,7 +272,7 @@ static const struct regulator_linear_range bd718xx_ldo3_volts[] = {
  * LDO4
  * 0.9 to 1.8V (100mV step)
  */
-static const struct regulator_linear_range bd718xx_ldo4_volts[] = {
+static const struct linear_range bd718xx_ldo4_volts[] = {
 	REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000),
 };
 
@@ -280,7 +280,7 @@ static const struct regulator_linear_range bd718xx_ldo4_volts[] = {
  * LDO5 for BD71837
  * 1.8 to 3.3V (100mV step)
  */
-static const struct regulator_linear_range bd71837_ldo5_volts[] = {
+static const struct linear_range bd71837_ldo5_volts[] = {
 	REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
 };
 
@@ -288,7 +288,7 @@ static const struct regulator_linear_range bd71837_ldo5_volts[] = {
  * LDO5 for BD71837
  * 1.8 to 3.3V (100mV step)
  */
-static const struct regulator_linear_range bd71847_ldo5_volts[] = {
+static const struct linear_range bd71847_ldo5_volts[] = {
 	REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
 	REGULATOR_LINEAR_RANGE(800000, 0x00, 0x0F, 100000),
 };
@@ -299,7 +299,7 @@ static const unsigned int bd71847_ldo5_volt_range_sel[] = { 0x0, 0x20 };
  * LDO6
  * 0.9 to 1.8V (100mV step)
  */
-static const struct regulator_linear_range bd718xx_ldo6_volts[] = {
+static const struct linear_range bd718xx_ldo6_volts[] = {
 	REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000),
 };
 
@@ -307,7 +307,7 @@ static const struct regulator_linear_range bd718xx_ldo6_volts[] = {
  * LDO7
  * 1.8 to 3.3V (100mV step)
  */
-static const struct regulator_linear_range bd71837_ldo7_volts[] = {
+static const struct linear_range bd71837_ldo7_volts[] = {
 	REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
 };
 
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
index 5493c3a86426..770e694824ac 100644
--- a/drivers/regulator/da903x.c
+++ b/drivers/regulator/da903x.c
@@ -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),
 };
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index bb16c465426e..e970e9d2f8be 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -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;
-
-	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;
+	unsigned int val;
+	int ret;
 
-		selector -= range->min_sel;
+	BUG_ON(!desc->n_linear_ranges);
 
-		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);
 
diff --git a/drivers/regulator/hi6421-regulator.c b/drivers/regulator/hi6421-regulator.c
index 5ac3d7c29725..66219d8dfc1a 100644
--- a/drivers/regulator/hi6421-regulator.c
+++ b/drivers/regulator/hi6421-regulator.c
@@ -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
diff --git a/drivers/regulator/lochnagar-regulator.c b/drivers/regulator/lochnagar-regulator.c
index 9b05e03ba830..5ea3e4141684 100644
--- a/drivers/regulator/lochnagar-regulator.c
+++ b/drivers/regulator/lochnagar-regulator.c
@@ -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),
 };
 
diff --git a/drivers/regulator/lp873x-regulator.c b/drivers/regulator/lp873x-regulator.c
index b55de293ca7a..fe049b67e7d5 100644
--- a/drivers/regulator/lp873x-regulator.c
+++ b/drivers/regulator/lp873x-regulator.c
@@ -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),
 };
 
diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c
index 4ae12ac1f4c6..5d525dacf959 100644
--- a/drivers/regulator/lp87565-regulator.c
+++ b/drivers/regulator/lp87565-regulator.c
@@ -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),
diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
index 222502a29658..74b7b496b12d 100644
--- a/drivers/regulator/lp8788-buck.c
+++ b/drivers/regulator/lp8788-buck.c
@@ -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),
 };
diff --git a/drivers/regulator/max77650-regulator.c b/drivers/regulator/max77650-regulator.c
index ac89a412f665..ca08f94a368d 100644
--- a/drivers/regulator/max77650-regulator.c
+++ b/drivers/regulator/max77650-regulator.c
@@ -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 */
diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c
index e5a02711cb46..6d0ad74935b3 100644
--- a/drivers/regulator/mcp16502.c
+++ b/drivers/regulator/mcp16502.c
@@ -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),
 };
 
diff --git a/drivers/regulator/mp8859.c b/drivers/regulator/mp8859.c
index 1d26b506ee5b..a9b9fc77cbc3 100644
--- a/drivers/regulator/mp8859.c
+++ b/drivers/regulator/mp8859.c
@@ -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),
 };
 
diff --git a/drivers/regulator/mt6323-regulator.c b/drivers/regulator/mt6323-regulator.c
index 893ea190788a..ff9016170db3 100644
--- a/drivers/regulator/mt6323-regulator.c
+++ b/drivers/regulator/mt6323-regulator.c
@@ -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),
 };
 
diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c
index ba42682e06f3..13cb6ac9a892 100644
--- a/drivers/regulator/mt6358-regulator.c
+++ b/drivers/regulator/mt6358-regulator.c
@@ -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),
 };
 
diff --git a/drivers/regulator/mt6380-regulator.c b/drivers/regulator/mt6380-regulator.c
index b6aed090b5e0..9efd8710a6f3 100644
--- a/drivers/regulator/mt6380-regulator.c
+++ b/drivers/regulator/mt6380-regulator.c
@@ -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),
 };
 
diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c
index fd9ed864a0c1..269c2a6028e8 100644
--- a/drivers/regulator/mt6397-regulator.c
+++ b/drivers/regulator/mt6397-regulator.c
@@ -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),
 };
 
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index 31325912d311..337dd614695e 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -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),
diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c
index c86ad40015ce..953c7fba8d9d 100644
--- a/drivers/regulator/qcom-rpmh-regulator.c
+++ b/drivers/regulator/qcom-rpmh-regulator.c
@@ -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;
diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c
index 7407cd5a1b74..c15cceeebe45 100644
--- a/drivers/regulator/qcom_rpm-regulator.c
+++ b/drivers/regulator/qcom_rpm-regulator.c
@@ -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),
 };
 
diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c
index fff8d5fdef6a..34b5c62265a9 100644
--- a/drivers/regulator/qcom_smd-regulator.c
+++ b/drivers/regulator/qcom_smd-regulator.c
@@ -199,7 +199,7 @@ static const struct regulator_ops rpm_bob_ops = {
 };
 
 static const struct regulator_desc pma8084_hfsmps = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(375000,  0,  95, 12500),
 		REGULATOR_LINEAR_RANGE(1550000, 96, 158, 25000),
 	},
@@ -209,7 +209,7 @@ static const struct regulator_desc pma8084_hfsmps = {
 };
 
 static const struct regulator_desc pma8084_ftsmps = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(350000,  0, 184, 5000),
 		REGULATOR_LINEAR_RANGE(1280000, 185, 261, 10000),
 	},
@@ -219,7 +219,7 @@ static const struct regulator_desc pma8084_ftsmps = {
 };
 
 static const struct regulator_desc pma8084_pldo = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE( 750000,  0,  63, 12500),
 		REGULATOR_LINEAR_RANGE(1550000, 64, 126, 25000),
 		REGULATOR_LINEAR_RANGE(3100000, 127, 163, 50000),
@@ -230,7 +230,7 @@ static const struct regulator_desc pma8084_pldo = {
 };
 
 static const struct regulator_desc pma8084_nldo = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(750000, 0, 63, 12500),
 	},
 	.n_linear_ranges = 1,
@@ -243,7 +243,7 @@ static const struct regulator_desc pma8084_switch = {
 };
 
 static const struct regulator_desc pm8x41_hfsmps = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE( 375000,  0,  95, 12500),
 		REGULATOR_LINEAR_RANGE(1575000, 96, 158, 25000),
 	},
@@ -253,7 +253,7 @@ static const struct regulator_desc pm8x41_hfsmps = {
 };
 
 static const struct regulator_desc pm8841_ftsmps = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(350000,  0, 184, 5000),
 		REGULATOR_LINEAR_RANGE(1280000, 185, 261, 10000),
 	},
@@ -263,7 +263,7 @@ static const struct regulator_desc pm8841_ftsmps = {
 };
 
 static const struct regulator_desc pm8941_boost = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(4000000, 0, 30, 50000),
 	},
 	.n_linear_ranges = 1,
@@ -272,7 +272,7 @@ static const struct regulator_desc pm8941_boost = {
 };
 
 static const struct regulator_desc pm8941_pldo = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE( 750000,  0,  63, 12500),
 		REGULATOR_LINEAR_RANGE(1550000, 64, 126, 25000),
 		REGULATOR_LINEAR_RANGE(3100000, 127, 163, 50000),
@@ -283,7 +283,7 @@ static const struct regulator_desc pm8941_pldo = {
 };
 
 static const struct regulator_desc pm8941_nldo = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(750000, 0, 63, 12500),
 	},
 	.n_linear_ranges = 1,
@@ -302,7 +302,7 @@ static const struct regulator_desc pm8941_switch = {
 };
 
 static const struct regulator_desc pm8916_pldo = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(750000, 0, 208, 12500),
 	},
 	.n_linear_ranges = 1,
@@ -311,7 +311,7 @@ static const struct regulator_desc pm8916_pldo = {
 };
 
 static const struct regulator_desc pm8916_nldo = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(375000, 0, 93, 12500),
 	},
 	.n_linear_ranges = 1,
@@ -320,7 +320,7 @@ static const struct regulator_desc pm8916_nldo = {
 };
 
 static const struct regulator_desc pm8916_buck_lvo_smps = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(375000, 0, 95, 12500),
 		REGULATOR_LINEAR_RANGE(750000, 96, 127, 25000),
 	},
@@ -330,7 +330,7 @@ static const struct regulator_desc pm8916_buck_lvo_smps = {
 };
 
 static const struct regulator_desc pm8916_buck_hvo_smps = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(1550000, 0, 31, 25000),
 	},
 	.n_linear_ranges = 1,
@@ -339,7 +339,7 @@ static const struct regulator_desc pm8916_buck_hvo_smps = {
 };
 
 static const struct regulator_desc pm8950_hfsmps = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(375000, 0, 95, 12500),
 		REGULATOR_LINEAR_RANGE(1550000, 96, 127, 25000),
 	},
@@ -349,7 +349,7 @@ static const struct regulator_desc pm8950_hfsmps = {
 };
 
 static const struct regulator_desc pm8950_ftsmps2p5 = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(80000, 0, 255, 5000),
 		REGULATOR_LINEAR_RANGE(160000, 256, 460, 10000),
 	},
@@ -359,7 +359,7 @@ static const struct regulator_desc pm8950_ftsmps2p5 = {
 };
 
 static const struct regulator_desc pm8950_ult_nldo = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(375000, 0, 202, 12500),
 	},
 	.n_linear_ranges = 1,
@@ -368,7 +368,7 @@ static const struct regulator_desc pm8950_ult_nldo = {
 };
 
 static const struct regulator_desc pm8950_ult_pldo = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(1750000, 0, 127, 12500),
 	},
 	.n_linear_ranges = 1,
@@ -377,7 +377,7 @@ static const struct regulator_desc pm8950_ult_pldo = {
 };
 
 static const struct regulator_desc pm8950_pldo_lv = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(1500000, 0, 16, 25000),
 	},
 	.n_linear_ranges = 1,
@@ -386,7 +386,7 @@ static const struct regulator_desc pm8950_pldo_lv = {
 };
 
 static const struct regulator_desc pm8950_pldo = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(975000, 0, 164, 12500),
 	},
 	.n_linear_ranges = 1,
@@ -396,7 +396,7 @@ static const struct regulator_desc pm8950_pldo = {
 
 
 static const struct regulator_desc pm8994_hfsmps = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE( 375000,  0,  95, 12500),
 		REGULATOR_LINEAR_RANGE(1550000, 96, 158, 25000),
 	},
@@ -406,7 +406,7 @@ static const struct regulator_desc pm8994_hfsmps = {
 };
 
 static const struct regulator_desc pm8994_ftsmps = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(350000,  0, 199, 5000),
 		REGULATOR_LINEAR_RANGE(700000, 200, 349, 10000),
 	},
@@ -416,7 +416,7 @@ static const struct regulator_desc pm8994_ftsmps = {
 };
 
 static const struct regulator_desc pm8994_nldo = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(750000, 0, 63, 12500),
 	},
 	.n_linear_ranges = 1,
@@ -425,7 +425,7 @@ static const struct regulator_desc pm8994_nldo = {
 };
 
 static const struct regulator_desc pm8994_pldo = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE( 750000,  0,  63, 12500),
 		REGULATOR_LINEAR_RANGE(1550000, 64, 126, 25000),
 		REGULATOR_LINEAR_RANGE(3100000, 127, 163, 50000),
@@ -446,7 +446,7 @@ static const struct regulator_desc pm8994_lnldo = {
 };
 
 static const struct regulator_desc pm8998_ftsmps = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(320000, 0, 258, 4000),
 	},
 	.n_linear_ranges = 1,
@@ -455,7 +455,7 @@ static const struct regulator_desc pm8998_ftsmps = {
 };
 
 static const struct regulator_desc pm8998_hfsmps = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000),
 	},
 	.n_linear_ranges = 1,
@@ -464,7 +464,7 @@ static const struct regulator_desc pm8998_hfsmps = {
 };
 
 static const struct regulator_desc pm8998_nldo = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(312000, 0, 127, 8000),
 	},
 	.n_linear_ranges = 1,
@@ -473,7 +473,7 @@ static const struct regulator_desc pm8998_nldo = {
 };
 
 static const struct regulator_desc pm8998_pldo = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(1664000, 0, 255, 8000),
 	},
 	.n_linear_ranges = 1,
@@ -482,7 +482,7 @@ static const struct regulator_desc pm8998_pldo = {
 };
 
 static const struct regulator_desc pm8998_pldo_lv = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(1256000, 0, 127, 8000),
 	},
 	.n_linear_ranges = 1,
@@ -495,7 +495,7 @@ static const struct regulator_desc pm8998_switch = {
 };
 
 static const struct regulator_desc pmi8998_bob = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(1824000, 0, 83, 32000),
 	},
 	.n_linear_ranges = 1,
@@ -504,7 +504,7 @@ static const struct regulator_desc pmi8998_bob = {
 };
 
 static const struct regulator_desc pms405_hfsmps3 = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000),
 	},
 	.n_linear_ranges = 1,
@@ -513,7 +513,7 @@ static const struct regulator_desc pms405_hfsmps3 = {
 };
 
 static const struct regulator_desc pms405_nldo300 = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(312000, 0, 127, 8000),
 	},
 	.n_linear_ranges = 1,
@@ -522,7 +522,7 @@ static const struct regulator_desc pms405_nldo300 = {
 };
 
 static const struct regulator_desc pms405_nldo1200 = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(312000, 0, 127, 8000),
 	},
 	.n_linear_ranges = 1,
@@ -531,7 +531,7 @@ static const struct regulator_desc pms405_nldo1200 = {
 };
 
 static const struct regulator_desc pms405_pldo50 = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(1664000, 0, 128, 16000),
 	},
 	.n_linear_ranges = 1,
@@ -540,7 +540,7 @@ static const struct regulator_desc pms405_pldo50 = {
 };
 
 static const struct regulator_desc pms405_pldo150 = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(1664000, 0, 128, 16000),
 	},
 	.n_linear_ranges = 1,
@@ -549,7 +549,7 @@ static const struct regulator_desc pms405_pldo150 = {
 };
 
 static const struct regulator_desc pms405_pldo600 = {
-	.linear_ranges = (struct regulator_linear_range[]) {
+	.linear_ranges = (struct linear_range[]) {
 		REGULATOR_LINEAR_RANGE(1256000, 0, 98, 8000),
 	},
 	.n_linear_ranges = 1,
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index 31f79fda3238..e926c1a85846 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -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),
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 23d288278957..33cf84bce05a 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -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),
 };
 
diff --git a/drivers/regulator/sky81452-regulator.c b/drivers/regulator/sky81452-regulator.c
index 177dede82a61..37658affe072 100644
--- a/drivers/regulator/sky81452-regulator.c
+++ b/drivers/regulator/sky81452-regulator.c
@@ -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),
 };
diff --git a/drivers/regulator/stpmic1_regulator.c b/drivers/regulator/stpmic1_regulator.c
index f3d7d007ecbb..adc9973d1b2f 100644
--- a/drivers/regulator/stpmic1_regulator.c
+++ b/drivers/regulator/stpmic1_regulator.c
@@ -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),
 };
diff --git a/drivers/regulator/tps65086-regulator.c b/drivers/regulator/tps65086-regulator.c
index 5a5e9b5bf4be..9910e949373c 100644
--- a/drivers/regulator/tps65086-regulator.c
+++ b/drivers/regulator/tps65086-regulator.c
@@ -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),
 };
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
index 67ba78da77ec..d27dbbafcf72 100644
--- a/drivers/regulator/tps65217-regulator.c
+++ b/drivers/regulator/tps65217-regulator.c
@@ -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),
diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c
index b72035610013..05d13f807918 100644
--- a/drivers/regulator/tps65218-regulator.c
+++ b/drivers/regulator/tps65218-regulator.c
@@ -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),
 };
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
index 276faeddc370..15c79931ea89 100644
--- a/drivers/regulator/tps65912-regulator.c
+++ b/drivers/regulator/tps65912-regulator.c
@@ -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),
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 866b4dd01da9..4a51cfea45ac 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -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)
 };
diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c
index b8100c3cedad..f7db250a7583 100644
--- a/drivers/regulator/twl6030-regulator.c
+++ b/drivers/regulator/twl6030-regulator.c
@@ -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),
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 018dbbd96771..ad2203d11a88 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -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),
 };
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index 56754686c982..7b6cf4810cb7 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -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),
 };
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 56d6168a888d..ae5f0e7fce8b 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -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),
 };
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
index 6f331b51e479..4cb1fbb59722 100644
--- a/drivers/regulator/wm8400-regulator.c
+++ b/drivers/regulator/wm8400-regulator.c
@@ -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),
 };
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 9a911bb5fb61..7a3982da8868 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -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;
-- 
2.21.0


-- 
Matti Vaittinen, Linux device drivers
ROHM Semiconductors, Finland SWDC
Kiviharjunlenkki 1E
90220 OULU
FINLAND

~~~ "I don't think so," said Rene Descartes. Just then he vanished ~~~
Simon says - in Latin please.
~~~ "non cogito me" dixit Rene Descarte, deinde evanescavit ~~~
Thanks to Simon Glass for the translation =] 

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v7 00/10] Support ROHM BD99954 charger IC
  2020-03-31 12:24 ` [PATCH v7 00/10] Support ROHM BD99954 charger IC Ard Biesheuvel
@ 2020-03-31 14:02   ` Vaittinen, Matti
  2020-03-31 14:21     ` andriy.shevchenko
  0 siblings, 1 reply; 13+ messages in thread
From: Vaittinen, Matti @ 2020-03-31 14:02 UTC (permalink / raw)
  To: ardb
  Cc: mark.rutland, milo.kim, andrei.stefanescu, rafael, tony,
	linus.walleij, Gary.Hook, linux-kernel, yamada.masahiro,
	devicetree, linux-omap, Mutanen,  Mikko, vincenzo.frascino,
	dan.j.williams, linux-samsung-soc, uwe, b.zolnierkie, krzk,
	bgolaszewski, wens, agross, Laine, Markus, linux-arm-msm, bp,
	pmladek, zaslonko, ckeepax, arnd, linux-pm, brendanhiggins, rf,
	broonie, linux-mediatek, sre, davidgow, skhan, matthias.bgg,
	tglx, andriy.shevchenko, linux-arm-kernel, support.opensource,
	sbkim73, patches, rdunlap, lgirdwood, talgi, changbin.du,
	robh+dt, bjorn.andersson, mhiramat, gregkh, akpm, olteanv, davem,
	mazziesaccount


On Tue, 2020-03-31 at 14:24 +0200, Ard Biesheuvel wrote:
> Hello Matti,
> 
> On Tue, 31 Mar 2020 at 14:20, Matti Vaittinen
> <matti.vaittinen@fi.rohmeurope.com> wrote:
> > Support ROHM BD99954 Battery Management IC
> > 
> > ROHM BD99954 is a Battery Management IC for 1-4 cell Lithium-Ion
> > secondary battery. BD99954 is intended to be used in space-
> > constraint
> > equipment such as Low profile Notebook PC, Tablets and other
> > applications.
> > 
> 
> Is it *really* necessary to cc this to 50 different people?
> 
> In the future, please trim down the cc list and keep it to the
> mailing
> list, maintainers and reviewers of the affected subsystem.

Sorry Ard (and others). This is the list get_maintainers.pl gave for
the series. Partially the large amount of receivers is caused by the
regulator framework change which impacted bunch of individual drivers.
Please, see the amount changed files from summary below. In addition to
that the linear_range code has been drifting from one place to other
during the review iterations until it settled to /lib. For example Greg
gave me some comments while linear_ranges was still heading to
drivers/base - so I did not drop Greg off from new revisions of the
series even if it was no longer changing drivers/base

It's hard for me to decide who of the fellows are relevant and who are
not. I know email flood is annoying and thus I did not send all of the
patches in the series to everyone. And - personally I do like receiving
whole series if I have been added in one patch. But I admit my mailbox
is not as crowded as it used to be so maybe that is why it is not so
annoying for me to delete mails.

Anyways, I will drop everyone who asks to be dropped from subsequent
patches but other than that - I guess it's better to accidentally
include someone who needs to press delete - than drop someone who
want's to have a say on changes.

> >  .../bindings/power/supply/battery.txt         |    6 +
> >  .../bindings/power/supply/rohm,bd99954.yaml   |  155 +++
> >  drivers/power/supply/Kconfig                  |   34 +-
> >  drivers/power/supply/Makefile                 |    1 +
> >  drivers/power/supply/bd70528-charger.c        |  140 +-
> >  drivers/power/supply/bd99954-charger.c        | 1149
> > +++++++++++++++++
> >  drivers/power/supply/power_supply_core.c      |    8 +
> >  drivers/regulator/88pg86x.c                   |    4 +-
> >  drivers/regulator/88pm800-regulator.c         |    4 +-
> >  drivers/regulator/Kconfig                     |    1 +
> >  drivers/regulator/act8865-regulator.c         |    4 +-
> >  drivers/regulator/act8945a-regulator.c        |    2 +-
> >  drivers/regulator/arizona-ldo1.c              |    2 +-
> >  drivers/regulator/arizona-micsupp.c           |    4 +-
> >  drivers/regulator/as3711-regulator.c          |    6 +-
> >  drivers/regulator/as3722-regulator.c          |    4 +-
> >  drivers/regulator/axp20x-regulator.c          |   16 +-
> >  drivers/regulator/bcm590xx-regulator.c        |    8 +-
> >  drivers/regulator/bd70528-regulator.c         |    8 +-
> >  drivers/regulator/bd71828-regulator.c         |   10 +-
> >  drivers/regulator/bd718x7-regulator.c         |   26 +-
> >  drivers/regulator/da903x.c                    |    2 +-
> >  drivers/regulator/helpers.c                   |  130 +-
> >  drivers/regulator/hi6421-regulator.c          |    4 +-
> >  drivers/regulator/lochnagar-regulator.c       |    4 +-
> >  drivers/regulator/lp873x-regulator.c          |    4 +-
> >  drivers/regulator/lp87565-regulator.c         |    2 +-
> >  drivers/regulator/lp8788-buck.c               |    2 +-
> >  drivers/regulator/max77650-regulator.c        |    2 +-
> >  drivers/regulator/mcp16502.c                  |    4 +-
> >  drivers/regulator/mp8859.c                    |    2 +-
> >  drivers/regulator/mt6323-regulator.c          |    6 +-
> >  drivers/regulator/mt6358-regulator.c          |    8 +-
> >  drivers/regulator/mt6380-regulator.c          |    6 +-
> >  drivers/regulator/mt6397-regulator.c          |    6 +-
> >  drivers/regulator/palmas-regulator.c          |    4 +-
> >  drivers/regulator/qcom-rpmh-regulator.c       |    2 +-
> >  drivers/regulator/qcom_rpm-regulator.c        |   14 +-
> >  drivers/regulator/qcom_smd-regulator.c        |   70 +-
> >  drivers/regulator/rk808-regulator.c           |   10 +-
> >  drivers/regulator/s2mps11.c                   |   14 +-
> >  drivers/regulator/sky81452-regulator.c        |    2 +-
> >  drivers/regulator/stpmic1_regulator.c         |   18 +-
> >  drivers/regulator/tps65086-regulator.c        |   10 +-
> >  drivers/regulator/tps65217-regulator.c        |    4 +-
> >  drivers/regulator/tps65218-regulator.c        |    6 +-
> >  drivers/regulator/tps65912-regulator.c        |    4 +-
> >  drivers/regulator/twl-regulator.c             |    4 +-
> >  drivers/regulator/twl6030-regulator.c         |    2 +-
> >  drivers/regulator/wm831x-dcdc.c               |    2 +-
> >  drivers/regulator/wm831x-ldo.c                |    4 +-
> >  drivers/regulator/wm8350-regulator.c          |    2 +-
> >  drivers/regulator/wm8400-regulator.c          |    2 +-
> >  include/linux/linear_range.h                  |   48 +
> >  include/linux/power/bd99954-charger.h         | 1075
> > +++++++++++++++
> >  include/linux/power_supply.h                  |    4 +
> >  include/linux/regulator/driver.h              |   27 +-
> >  lib/Kconfig                                   |    3 +
> >  lib/Kconfig.debug                             |   11 +
> >  lib/Makefile                                  |    2 +
> >  lib/linear_ranges.c                           |  246 ++++
> >  lib/test_linear_ranges.c                      |  228 ++++
> >  62 files changed, 3236 insertions(+), 356 deletions(-)
> >  create mode 100644
> > Documentation/devicetree/bindings/power/supply/rohm,bd99954.yaml
> >  create mode 100644 drivers/power/supply/bd99954-charger.c
> >  create mode 100644 include/linux/linear_range.h
> >  create mode 100644 include/linux/power/bd99954-charger.h
> >  create mode 100644 lib/linear_ranges.c
> >  create mode 100644 lib/test_linear_ranges.c
> > 
> > 

Best Regards
	Matti

> > 
> > 
> > --
> > Matti Vaittinen, Linux device drivers
> > ROHM Semiconductors, Finland SWDC
> > Kiviharjunlenkki 1E
> > 90220 OULU
> > FINLAND
> > 
> > ~~~ "I don't think so," said Rene Descartes. Just then he vanished
> > ~~~
> > Simon says - in Latin please.
> > ~~~ "non cogito me" dixit Rene Descarte, deinde evanescavit ~~~
> > Thanks to Simon Glass for the translation =]

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v7 03/10] lib: add linear ranges helpers
  2020-03-31 12:23 ` [PATCH v7 03/10] lib: add linear ranges helpers Matti Vaittinen
@ 2020-03-31 14:05   ` Andy Shevchenko
  2020-04-01 10:09     ` [SPF Softfail] " Vaittinen, Matti
  0 siblings, 1 reply; 13+ messages in thread
From: Andy Shevchenko @ 2020-03-31 14:05 UTC (permalink / raw)
  To: Matti Vaittinen
  Cc: Mark Rutland, Milo Kim, Andrei Stefanescu, Rafael J. Wysocki,
	Tony Lindgren, Linus Walleij, Brendan Higgins, Liam Girdwood,
	Masahiro Yamada, devicetree, mikko.mutanen, Vincenzo Frascino,
	Dan Williams, linux-samsung-soc, linux-omap, Herbert Xu,
	Bartlomiej Zolnierkiewicz, Krzysztof Kozlowski, Ard Biesheuvel,
	Bartosz Golaszewski, Chen-Yu Tsai, Andy Gross, markus.laine,
	linux-arm-msm, Borislav Petkov, Petr Mladek, Mikhail Zaslonko,
	Charles Keepax, Arnd Bergmann, mazziesaccount, Gary Hook,
	Richard Fitzgerald, Rob Herring, linux-mediatek, David Gow,
	Shuah Khan, Matthias Brugger, Thomas Gleixner, Bjorn Andersson,
	linux-arm-kernel, Support Opensource, Sangbeom Kim,
	Greg Kroah-Hartman, linux-pm, Randy Dunlap, Sebastian Reichel,
	linux-kernel, Tal Gilboa, Changbin Du, Mark Brown,
	Uwe Kleine-König, Masami Hiramatsu, patches, Andrew Morton,
	Vladimir Oltean, David S. Miller

On Tue, Mar 31, 2020 at 03:23:03PM +0300, Matti Vaittinen wrote:
> Many devices have control registers which control some measurable
> property. Often a register contains control field so that change in
> this field causes linear change in the controlled property. It is not
> a rare case that user wants to give 'meaningful' control values and
> driver needs to convert them to register field values. Even more
> often user wants to 'see' the currently set value - again in
> meaningful units - and driver needs to convert the values it reads
> from register to these meaningful units. Examples of this include:
> 
> - regulators, voltage/current configurations
> - power, voltage/current configurations
> - clk(?) NCOs
> 
> and maybe others I can't think of right now.
> 
> Provide a linear_range helper which can do conversion from user value
> to register value 'selector'.
> 
> The idea here is stolen from regulator framework and patches refactoring
> the regulator helpers to use this are following.

...

> +/*
> + * linear_ranges.c -- helpers to map values in a linear range to range index

File name inside file can bring an unnecessary churn in the future in case we
would like to rename it (by some reason). So, better to remove.

> + *
> + * Original idea borrowed from regulator framework
> + *

> + * It might be useful if we could support also inversely proportional ranges?

Looks like remark that should not be here, rather in commit message or even in cover letter.

> + * Copyright 2020 ROHM Semiconductors
> + */

...

> +/**
> + * linear_range_get_value - fetch a value from given range

> + *

This blank line is not needed. Can we drop them everywhere?

> + * @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_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)
> +		*found = true;

As far as I can see this is a bit different from _high counterpart. So, if we
even not found the range we still check r->step. Can we make them symmetrical
(to some extend)?

> +	if (!r->step)

Why not positive conditional?

> +		*selector = r->min_sel;
> +	else
> +		*selector = (val - r->min) / r->step + r->min_sel;

> +	return 0;
> +}

...

> +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;
> +}

Can we refactor this?

	int i;
	int ret = -EINVAL;

	for (i = 0; i < ranges; i++) {
		ret = linear_range_get_selector_low(&r[i], val, selector, found);
		if (*found)
			break;
	}

	return break;

This will unshadow the error code returned by the loop body.

Or if ranges is guaranteed to be always positive number, convert this to do {} while.

...

> +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) {
> +		*found = true;
> +	} else {
> +		*selector = r->min_sel;
> +		return 0;
> +	}

	if (r->min > val) {
		*selector = r->min_sel;
		return 0;
	}

	...see below...

> +	if (!r->step)

Positive conditional?

> +		*selector = r->max_sel;
> +	else
> +		*selector = DIV_ROUND_UP(val - r->min, r->step) + r->min_sel;


	*found = true;

> +	return 0;
> +}

-- 
With Best Regards,
Andy Shevchenko



_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v7 00/10] Support ROHM BD99954 charger IC
  2020-03-31 14:02   ` Vaittinen, Matti
@ 2020-03-31 14:21     ` andriy.shevchenko
  0 siblings, 0 replies; 13+ messages in thread
From: andriy.shevchenko @ 2020-03-31 14:21 UTC (permalink / raw)
  To: Vaittinen, Matti
  Cc: mark.rutland, milo.kim, andrei.stefanescu, devicetree, tony,
	linus.walleij, Gary.Hook, linux-kernel, yamada.masahiro,
	linux-omap, Mutanen, Mikko, vincenzo.frascino, ardb,
	linux-samsung-soc, uwe, rafael, krzk, bgolaszewski, wens, agross,
	Laine, Markus, linux-arm-msm, bp, pmladek, zaslonko, ckeepax,
	arnd, linux-pm, brendanhiggins, dan.j.williams, rf, broonie,
	linux-mediatek, sre, davidgow, skhan, matthias.bgg, tglx,
	bjorn.andersson, linux-arm-kernel, support.opensource, sbkim73,
	patches, rdunlap, lgirdwood, talgi, changbin.du, b.zolnierkie,
	robh+dt, mhiramat, gregkh, akpm, olteanv, davem, mazziesaccount

On Tue, Mar 31, 2020 at 02:02:55PM +0000, Vaittinen, Matti wrote:
> 
> On Tue, 2020-03-31 at 14:24 +0200, Ard Biesheuvel wrote:
> > Hello Matti,
> > 
> > On Tue, 31 Mar 2020 at 14:20, Matti Vaittinen
> > <matti.vaittinen@fi.rohmeurope.com> wrote:
> > > Support ROHM BD99954 Battery Management IC
> > > 
> > > ROHM BD99954 is a Battery Management IC for 1-4 cell Lithium-Ion
> > > secondary battery. BD99954 is intended to be used in space-
> > > constraint
> > > equipment such as Low profile Notebook PC, Tablets and other
> > > applications.
> > > 
> > 
> > Is it *really* necessary to cc this to 50 different people?
> > 
> > In the future, please trim down the cc list and keep it to the
> > mailing
> > list, maintainers and reviewers of the affected subsystem.
> 
> Sorry Ard (and others). This is the list get_maintainers.pl gave for
> the series. Partially the large amount of receivers is caused by the
> regulator framework change which impacted bunch of individual drivers.
> Please, see the amount changed files from summary below. In addition to
> that the linear_range code has been drifting from one place to other
> during the review iterations until it settled to /lib. For example Greg
> gave me some comments while linear_ranges was still heading to
> drivers/base - so I did not drop Greg off from new revisions of the
> series even if it was no longer changing drivers/base

I'm wondering if the command line I usually use gives you such amount of recipients.

	scripts/get_maintainer.pl --git --git-min-percent=67 ...


-- 
With Best Regards,
Andy Shevchenko



_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [SPF Softfail] Re: [PATCH v7 03/10] lib: add linear ranges helpers
  2020-03-31 14:05   ` Andy Shevchenko
@ 2020-04-01 10:09     ` Vaittinen, Matti
  2020-04-01 12:39       ` Andy Shevchenko
  0 siblings, 1 reply; 13+ messages in thread
From: Vaittinen, Matti @ 2020-04-01 10:09 UTC (permalink / raw)
  To: andy.shevchenko
  Cc: mark.rutland, milo.kim, andrei.stefanescu, rafael, tony,
	linus.walleij, brendanhiggins, linux-kernel, yamada.masahiro,
	linux-omap, vincenzo.frascino, tglx, linux-samsung-soc, herbert,
	b.zolnierkie, krzk, bgolaszewski, wens, agross, Laine, Markus,
	bp, devicetree, zaslonko, ckeepax, arnd, linux-pm, linux-arm-msm,
	rf, broonie, linux-mediatek, sre, davidgow, skhan, matthias.bgg,
	dan.j.williams, bjorn.andersson, linux-arm-kernel,
	support.opensource, sbkim73, patches, rdunlap, lgirdwood, talgi,
	Mutanen,  Mikko, robh+dt, uwe, mhiramat, gregkh, akpm, olteanv,
	davem, mazziesaccount

Hello Andy,

Thanks for the review again. I'll send v8 later this week :) 

On Tue, 2020-03-31 at 17:05 +0300, Andy Shevchenko wrote:
> On Tue, Mar 31, 2020 at 03:23:03PM +0300, Matti Vaittinen wrote:
> > Many devices have control registers which control some measurable
> > property. Often a register contains control field so that change in
> > this field causes linear change in the controlled property. It is
> > not
> > a rare case that user wants to give 'meaningful' control values and
> > driver needs to convert them to register field values. Even more
> > often user wants to 'see' the currently set value - again in
> > meaningful units - and driver needs to convert the values it reads
> > from register to these meaningful units. Examples of this include:
> > 
> > - regulators, voltage/current configurations
> > - power, voltage/current configurations
> > - clk(?) NCOs
> > 
> > and maybe others I can't think of right now.
> > 
> > Provide a linear_range helper which can do conversion from user
> > value
> > to register value 'selector'.
> > 
> > The idea here is stolen from regulator framework and patches
> > refactoring
> > the regulator helpers to use this are following.
> 
> ...
> 
> > +/*
> > + * linear_ranges.c -- helpers to map values in a linear range to
> > range index
> 
> File name inside file can bring an unnecessary churn in the future in
> case we
> would like to rename it (by some reason). So, better to remove.

Agree.

> > + *
> > + * Original idea borrowed from regulator framework
> > + *
> > + * It might be useful if we could support also inversely
> > proportional ranges?
> 
> Looks like remark that should not be here, rather in commit message
> or even in cover letter.

I think this is a good place so that anyone who opens this file will
see what could be done to improve this. No one is looking at the old
commit messages unless they face some problems. And cover letters fade
away even faster - although the cover letter and commit messages may
catch some attention during the patch submissions.

So maybe you would agree with me if I added this also in cover letter
and commit message :)

> 
> > + * Copyright 2020 ROHM Semiconductors
> > + */
> 
> ...
> 
> > +/**
> > + * linear_range_get_value - fetch a value from given range
> > + *
> 
> This blank line is not needed. Can we drop them everywhere?

Yep. We can. I see that is recommended way in Documentation/doc-
guide/kernel-doc.rst. (Although for my eye it looks clearer with the
empty line)

> 
> > + * @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_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)
> > +		*found = true;
> 
> As far as I can see this is a bit different from _high counterpart. 

Yes. Because the logic is different. _low accepts selector for a
closest value which is smaller or equal to given. _high accepts
selector for a closest value which is higher or equal to given. This
mean that both the _high and _low accept also input value which is not
in the range - _low accepts input which is higher than range, _high
accepts input which is lower than the range.

Both functions bail out right away if input is not "acceptable". 

_low if:
+	if (r->min > val)
> > +		return -EINVAL;

_high if:
+	if (linear_range_get_max_value(r) < val)
> > +		return -EINVAL;
> > 

After this check, if the input is within the other end of range, then
we can set found to true.

for _low:
> > +	if (linear_range_get_max_value(r) >= val)
> > +		*found = true;

for _high:
> > +	if (r->min <= val) {
> > +		*found = true;
> > 

And I agree with your later comment - inversing this check for makes
the function cleaner.

> So, if we
> even not found the range we still check r->step. Can we make them
> symmetrical
> (to some extend)?

Yes we can. For _low we can do:

if (linear_range_get_max_value(r) < val) {
	*selector = r->max_sel;
	return 0;
}

if (!r->step)
	*selector = r->max_sel;
else
	*selector = DIV_ROUND_UP(val - r->min, r->step) + r - min_sel;
*found = true;
 
return 0;
 


> 
> > +	if (!r->step)
> 
> Why not positive conditional?

because we really want to test if step is zero. I can write it as
if (r->step == 0) if that is preferred. But we definitely want to chek
if r->step is zero and handle it as exception case. (We want to protect
from division by zero - and in that case all selectors are Ok as range
is constant)


> > +		*selector = r->min_sel;
> > +	else
> > +		*selector = (val - r->min) / r->step + r->min_sel;
> > +	return 0;
> > +}
> 
> ...
> 
> > +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;
> > +}
> 
> Can we refactor this?
> 
> 	int i;
> 	int ret = -EINVAL;
> 
> 	for (i = 0; i < ranges; i++) {
> 		ret = linear_range_get_selector_low(&r[i], val,
> selector, found);
> 		if (*found)
> 			break;
> 	}
> 
> 	return break;
> 
> This will unshadow the error code returned by the loop body.

What is the return break; doing here? I don't understand the syntax.
And we want the logic to be such that we return zero from this function
if _any_ of the calls to linear_range_get_selector_low returned zero.
(Even if further calls would return non-zero value). But we wan't to
keep looking for better (in-range) match if *found is not true.


> Or if ranges is guaranteed to be always positive number, convert this
> to do {} while.

I don't see the benefit :/

> 
> ...
> 
> > +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) {
> > +		*found = true;
> > +	} else {
> > +		*selector = r->min_sel;
> > +		return 0;
> > +	}
> 
> 	if (r->min > val) {
> 		*selector = r->min_sel;
> 		return 0;
> 	}

I agree. Inversing this condition makes it cleaner.


Best Regards
	Matti
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v7 06/10] regulator: use linear_ranges helper
  2020-03-31 12:25 ` [PATCH v7 06/10] regulator: use linear_ranges helper Matti Vaittinen
@ 2020-04-01 10:17   ` Mark Brown
  0 siblings, 0 replies; 13+ messages in thread
From: Mark Brown @ 2020-04-01 10:17 UTC (permalink / raw)
  To: Matti Vaittinen
  Cc: Mark Rutland, Milo Kim, Andrei Stefanescu, Rafael J. Wysocki,
	Tony Lindgren, Linus Walleij, Brendan Higgins, Liam Girdwood,
	Masahiro Yamada, devicetree, linux-omap, mikko.mutanen,
	Vincenzo Frascino, Dan Williams, linux-samsung-soc,
	Andy Shevchenko, Herbert Xu, Bartlomiej Zolnierkiewicz,
	Chen-Yu Tsai, Krzysztof Kozlowski, Ard Biesheuvel,
	Bartosz Golaszewski, Andy Shevchenko, Andy Gross, markus.laine,
	linux-arm-msm, Borislav Petkov, Petr Mladek, Mikhail Zaslonko,
	Charles Keepax, Arnd Bergmann, mazziesaccount, Gary Hook,
	Richard Fitzgerald, Rob Herring, linux-mediatek, David Gow,
	Shuah Khan, Matthias Brugger, Thomas Gleixner, Bjorn Andersson,
	linux-arm-kernel, Support Opensource, Sangbeom Kim,
	Greg Kroah-Hartman, linux-pm, Randy Dunlap, Sebastian Reichel,
	linux-kernel, Tal Gilboa, Changbin Du, Uwe Kleine-König,
	Masami Hiramatsu, patches, Andrew Morton, Vladimir Oltean,
	David S. Miller


[-- Attachment #1.1: Type: text/plain, Size: 176 bytes --]

On Tue, Mar 31, 2020 at 03:25:30PM +0300, Matti Vaittinen wrote:

> Change the regulator helpers to use common linear_ranges code.

Reviwed-by: Mark Brown <broonie@kernel.org>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 170 bytes --]

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [SPF Softfail] Re: [PATCH v7 03/10] lib: add linear ranges helpers
  2020-04-01 10:09     ` [SPF Softfail] " Vaittinen, Matti
@ 2020-04-01 12:39       ` Andy Shevchenko
  2020-04-01 13:18         ` Vaittinen, Matti
  0 siblings, 1 reply; 13+ messages in thread
From: Andy Shevchenko @ 2020-04-01 12:39 UTC (permalink / raw)
  To: Vaittinen, Matti
  Cc: mark.rutland, milo.kim, andrei.stefanescu, rafael, tony,
	linus.walleij, brendanhiggins, linux-kernel, yamada.masahiro,
	linux-omap, vincenzo.frascino, tglx, linux-samsung-soc, herbert,
	b.zolnierkie, krzk, bgolaszewski, wens, agross, Laine, Markus,
	bp, devicetree, zaslonko, ckeepax, arnd, linux-pm, linux-arm-msm,
	rf, broonie, linux-mediatek, sre, davidgow, skhan, matthias.bgg,
	dan.j.williams, bjorn.andersson, linux-arm-kernel,
	support.opensource, sbkim73, patches, rdunlap, lgirdwood, talgi,
	Mutanen, Mikko, robh+dt, uwe, mhiramat, gregkh, akpm, olteanv,
	davem, mazziesaccount

On Wed, Apr 1, 2020 at 1:09 PM Vaittinen, Matti
<Matti.Vaittinen@fi.rohmeurope.com> wrote:
> On Tue, 2020-03-31 at 17:05 +0300, Andy Shevchenko wrote:
> > On Tue, Mar 31, 2020 at 03:23:03PM +0300, Matti Vaittinen wrote:

...

> > > + * It might be useful if we could support also inversely
> > > proportional ranges?
> >
> > Looks like remark that should not be here, rather in commit message
> > or even in cover letter.
>
> I think this is a good place so that anyone who opens this file will
> see what could be done to improve this. No one is looking at the old
> commit messages unless they face some problems. And cover letters fade
> away even faster - although the cover letter and commit messages may
> catch some attention during the patch submissions.
>
> So maybe you would agree with me if I added this also in cover letter
> and commit message :)

OK

...

> > > +int linear_range_get_selector_low(const struct linear_range *r,
> > > +                             unsigned int val, unsigned int
> > > *selector,
> > > +                             bool *found)

> > As far as I can see this is a bit different from _high counterpart.
>
> Yes. Because the logic is different. _low accepts selector for a
> closest value which is smaller or equal to given. _high accepts
> selector for a closest value which is higher or equal to given. This
> mean that both the _high and _low accept also input value which is not
> in the range - _low accepts input which is higher than range, _high
> accepts input which is lower than the range.

Thanks for elaboration.

> > > +   if (!r->step)
> >
> > Why not positive conditional?
>
> because we really want to test if step is zero.

> I can write it as
> if (r->step == 0) if that is preferred.

Yes, please. Then we will see that 0 has special meaning here.

>  But we definitely want to chek
> if r->step is zero and handle it as exception case. (We want to protect
> from division by zero - and in that case all selectors are Ok as range
> is constant)
>
>
> > > +           *selector = r->min_sel;
> > > +   else
> > > +           *selector = (val - r->min) / r->step + r->min_sel;
> > > +   return 0;
> > > +}

...

> > > +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;
> > > +}
> >
> > Can we refactor this?
> >
> >       int i;
> >       int ret = -EINVAL;
> >
> >       for (i = 0; i < ranges; i++) {
> >               ret = linear_range_get_selector_low(&r[i], val,
> > selector, found);
> >               if (*found)
> >                       break;
> >       }
> >
> >       return break;
> >
> > This will unshadow the error code returned by the loop body.
>
> What is the return break; doing here? I don't understand the syntax.

Typo. return ret; should be.

> And we want the logic to be such that we return zero from this function
> if _any_ of the calls to linear_range_get_selector_low returned zero.
> (Even if further calls would return non-zero value). But we wan't to
> keep looking for better (in-range) match if *found is not true.

won't or want to? I'm confused with the last.
Is this logic described in the description? Sorry, I forgot, although
I had read it.
If no, perhaps it needs to be added either to description or as a
comment to the loop.

> > Or if ranges is guaranteed to be always positive number, convert this
> > to do {} while.
>
> I don't see the benefit :/

I see.
 do {
   ret = ...
 } while (++i < ranges && *found == false);

much better to read.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [SPF Softfail] Re: [PATCH v7 03/10] lib: add linear ranges helpers
  2020-04-01 12:39       ` Andy Shevchenko
@ 2020-04-01 13:18         ` Vaittinen, Matti
  2020-04-01 14:42           ` Andy Shevchenko
  0 siblings, 1 reply; 13+ messages in thread
From: Vaittinen, Matti @ 2020-04-01 13:18 UTC (permalink / raw)
  To: andy.shevchenko
  Cc: mark.rutland, milo.kim, andrei.stefanescu, rafael, tony,
	linus.walleij, brendanhiggins, linux-kernel, yamada.masahiro,
	linux-omap, vincenzo.frascino, tglx, linux-samsung-soc, herbert,
	b.zolnierkie, krzk, bgolaszewski, wens, agross, Laine, Markus,
	bp, devicetree, zaslonko, ckeepax, arnd, linux-pm, linux-arm-msm,
	rf, broonie, linux-mediatek, sre, davidgow, skhan, matthias.bgg,
	dan.j.williams, bjorn.andersson, linux-arm-kernel,
	support.opensource, sbkim73, patches, rdunlap, lgirdwood, talgi,
	Mutanen, Mikko, robh+dt, uwe, mhiramat, gregkh, akpm, olteanv,
	davem, mazziesaccount


On Wed, 2020-04-01 at 15:39 +0300, Andy Shevchenko wrote:
> On Wed, Apr 1, 2020 at 1:09 PM Vaittinen, Matti
> <Matti.Vaittinen@fi.rohmeurope.com> wrote:
> > On Tue, 2020-03-31 at 17:05 +0300, Andy Shevchenko wrote:
> > > On Tue, Mar 31, 2020 at 03:23:03PM +0300, Matti Vaittinen wrote:
> > > > +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;
> > > > +}
> > > 
> > > Can we refactor this?
> > > 
> > >       int i;
> > >       int ret = -EINVAL;
> > > 
> > >       for (i = 0; i < ranges; i++) {
> > >               ret = linear_range_get_selector_low(&r[i], val,
> > > selector, found);
> > >               if (*found)
> > >                       break;
> > >       }
> > > 
> > >       return break;
> > > 
> > > This will unshadow the error code returned by the loop body.
> > 
> > What is the return break; doing here? I don't understand the
> > syntax.
> 
> Typo. return ret; should be.
> 
> > And we want the logic to be such that we return zero from this
> > function
> > if _any_ of the calls to linear_range_get_selector_low returned
> > zero.
> > (Even if further calls would return non-zero value). But we wan't
> > to
> > keep looking for better (in-range) match if *found is not true.
> 
> won't or want to? I'm confused with the last.

want :) Typo here too.

> Is this logic described in the description? Sorry, I forgot, although
> I had read it.

 * 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 scannins 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.

I think it is but I am open to all suggestions how to improve doc!

> > > Or if ranges is guaranteed to be always positive number, convert
> > > this
> > > to do {} while.
> > 
> > I don't see the benefit :/
> 
> I see.
>  do {
>    ret = ...
>  } while (++i < ranges && *found == false);
> 
> much better to read.

Huh?
Compared to:
for (i = 0; i < ranges; i++) {
	ret = ...
}

I wouldn't say so.

As I explained, we need to have "temporary" return value in any case
because we need to return 0 if any of the calls to
linear_range_get_selector_low() returned 0. Return value 0 from
linear_range_get_selector_low() means we found "matching" value (lower
than input) and selector was updated (although input value was not in
range).


Br,
	Matti Vaittinen
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [SPF Softfail] Re: [PATCH v7 03/10] lib: add linear ranges helpers
  2020-04-01 13:18         ` Vaittinen, Matti
@ 2020-04-01 14:42           ` Andy Shevchenko
  2020-04-02  4:03             ` Vaittinen, Matti
  0 siblings, 1 reply; 13+ messages in thread
From: Andy Shevchenko @ 2020-04-01 14:42 UTC (permalink / raw)
  To: Vaittinen, Matti
  Cc: mark.rutland, milo.kim, andrei.stefanescu, rafael, tony,
	linus.walleij, brendanhiggins, linux-kernel, yamada.masahiro,
	linux-omap, vincenzo.frascino, tglx, linux-samsung-soc, herbert,
	b.zolnierkie, krzk, bgolaszewski, wens, agross, Laine, Markus,
	bp, devicetree, zaslonko, ckeepax, arnd, linux-pm, linux-arm-msm,
	rf, broonie, linux-mediatek, sre, davidgow, skhan, matthias.bgg,
	dan.j.williams, bjorn.andersson, linux-arm-kernel,
	support.opensource, sbkim73, patches, rdunlap, lgirdwood, talgi,
	Mutanen, Mikko, robh+dt, uwe, mhiramat, gregkh, akpm, olteanv,
	davem, mazziesaccount

On Wed, Apr 1, 2020 at 4:18 PM Vaittinen, Matti
<Matti.Vaittinen@fi.rohmeurope.com> wrote:
> On Wed, 2020-04-01 at 15:39 +0300, Andy Shevchenko wrote:
> > On Wed, Apr 1, 2020 at 1:09 PM Vaittinen, Matti
> > <Matti.Vaittinen@fi.rohmeurope.com> wrote:
> > > On Tue, 2020-03-31 at 17:05 +0300, Andy Shevchenko wrote:
> > > > On Tue, Mar 31, 2020 at 03:23:03PM +0300, Matti Vaittinen wrote:
> > > > > +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;
> > > > > +}

Looked again at the code of the callee.
So, *found becomes true if and only if the return is 0 (or other way
around if you prefer).
Now I'm wondering why you need 'found' at all?

It means above may be as simple as

      int i;
      int ret = -EINVAL;

      for (i = 0; i < ranges; i++) {
               ret = linear_range_get_selector_low(&r[i], val, selector, found);
               if (*found)
                       break;
      }

      return ret;

or assuming 'found' will gone

  int i
  int ret = -EINVAL;

  for (i = 0; i < ranges && ret; i++) {
      ret = linear_range_get_selector_low(&r[i], val, selector);
  }
  return ret;

...

>  * value. If given value is found to be in a range scannins is

> I think it is but I am open to all suggestions how to improve doc!

Thanks. At least fix a typo: scannins -> scannings

...

> Compared to:
> for (i = 0; i < ranges; i++) {
>         ret = ...
> }
>
> I wouldn't say so.
>
> As I explained, we need to have "temporary" return value in any case
> because we need to return 0 if any of the calls to
> linear_range_get_selector_low() returned 0. Return value 0 from
> linear_range_get_selector_low() means we found "matching" value (lower
> than input) and selector was updated (although input value was not in
> range).

See above.

--
With Best Regards,
Andy Shevchenko

_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [SPF Softfail] Re: [PATCH v7 03/10] lib: add linear ranges helpers
  2020-04-01 14:42           ` Andy Shevchenko
@ 2020-04-02  4:03             ` Vaittinen, Matti
  0 siblings, 0 replies; 13+ messages in thread
From: Vaittinen, Matti @ 2020-04-02  4:03 UTC (permalink / raw)
  To: andy.shevchenko
  Cc: mark.rutland, milo.kim, andrei.stefanescu, rafael, tony,
	linus.walleij, brendanhiggins, linux-kernel, yamada.masahiro,
	linux-omap, vincenzo.frascino, tglx, linux-samsung-soc, herbert,
	b.zolnierkie, krzk, bgolaszewski, wens, agross, Laine, Markus,
	bp, devicetree, zaslonko, ckeepax, arnd, linux-pm, linux-arm-msm,
	rf, broonie, linux-mediatek, sre, davidgow, skhan, matthias.bgg,
	dan.j.williams, bjorn.andersson, linux-arm-kernel,
	support.opensource, sbkim73, patches, rdunlap, lgirdwood, talgi,
	Mutanen, Mikko, robh+dt, uwe, mhiramat, gregkh, akpm, olteanv,
	davem, mazziesaccount

Hello Andy,

On Wed, 2020-04-01 at 17:42 +0300, Andy Shevchenko wrote:
> On Wed, Apr 1, 2020 at 4:18 PM Vaittinen, Matti
> <Matti.Vaittinen@fi.rohmeurope.com> wrote:
> > On Wed, 2020-04-01 at 15:39 +0300, Andy Shevchenko wrote:
> > > On Wed, Apr 1, 2020 at 1:09 PM Vaittinen, Matti
> > > <Matti.Vaittinen@fi.rohmeurope.com> wrote:
> > > > On Tue, 2020-03-31 at 17:05 +0300, Andy Shevchenko wrote:
> > > > > On Tue, Mar 31, 2020 at 03:23:03PM +0300, Matti Vaittinen
> > > > > wrote:
> > > > > > +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;
> > > > > > +}
> 
> Looked again at the code of the callee.
> So, *found becomes true if and only if the return is 0

Yes. If found is true, then ret is 0.

>  (or other way
> around if you prefer).

No. Not other way around. Ret can be 0 and found false. This is what we
need to handle. Ret means we found range value smaller than given
input. Found means also the given input was in range.

> Now I'm wondering why you need 'found' at all?

To separate case where given input was in range.

> It means above may be as simple as
> 
>       int i;
>       int ret = -EINVAL;
> 
>       for (i = 0; i < ranges; i++) {
>                ret = linear_range_get_selector_low(&r[i], val,
> selector, found);
>                if (*found)
>                        break;
>       }

No. It can't. Here we get wrong return value if one of the calls to
linear_range_get_selector_low() return zero with found being false and
subsequent calls return non zero ret. Then we actually found lower-
than-given-input value from one of the ranges and updated the selector
(that would be usable for example for regulator voltage control) but
end up returning non zero ret as the subsequent calls to
linear_range_get_selector_low() do overwrite the ret.

OTOH, we should not stop for first range having zero ret if found is
false because some of the ranges may have range where given input is
in-range (and this is considered better value).

> 
>       return ret;
> 
> or assuming 'found' will gone

No. We should not drop the 'found'.

> 
>   int i
>   int ret = -EINVAL;
> 
>   for (i = 0; i < ranges && ret; i++) {
>       ret = linear_range_get_selector_low(&r[i], val, selector);
>   }
>   return ret;
> 
> ...
> 
> >  * value. If given value is found to be in a range scannins is
> > I think it is but I am open to all suggestions how to improve doc!
> 
> Thanks. At least fix a typo: scannins -> scannings
> 

Thanks :) I'll fix it

> ...
> 
> > Compared to:
> > for (i = 0; i < ranges; i++) {
> >         ret = ...
> > }
> > 
> > I wouldn't say so.
> > 
> > As I explained, we need to have "temporary" return value in any
> > case
> > because we need to return 0 if any of the calls to
> > linear_range_get_selector_low() returned 0. Return value 0 from
> > linear_range_get_selector_low() means we found "matching" value
> > (lower
> > than input) and selector was updated (although input value was not
> > in
> > range).
> 
> See above.


Best Regards
	--Matti
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2020-04-02  4:03 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-31 12:20 [PATCH v7 00/10] Support ROHM BD99954 charger IC Matti Vaittinen
2020-03-31 12:23 ` [PATCH v7 03/10] lib: add linear ranges helpers Matti Vaittinen
2020-03-31 14:05   ` Andy Shevchenko
2020-04-01 10:09     ` [SPF Softfail] " Vaittinen, Matti
2020-04-01 12:39       ` Andy Shevchenko
2020-04-01 13:18         ` Vaittinen, Matti
2020-04-01 14:42           ` Andy Shevchenko
2020-04-02  4:03             ` Vaittinen, Matti
2020-03-31 12:24 ` [PATCH v7 00/10] Support ROHM BD99954 charger IC Ard Biesheuvel
2020-03-31 14:02   ` Vaittinen, Matti
2020-03-31 14:21     ` andriy.shevchenko
2020-03-31 12:25 ` [PATCH v7 06/10] regulator: use linear_ranges helper Matti Vaittinen
2020-04-01 10:17   ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).