linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/6] regulator: core: Allow regulators to provide a voltage to selector mapping
@ 2012-05-09 23:47 Mark Brown
  2012-05-09 23:47 ` [PATCH 2/6] regulator: core: Allow drivers to set simple linear voltage maps as data Mark Brown
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Mark Brown @ 2012-05-09 23:47 UTC (permalink / raw)
  To: Liam Girdwood
  Cc: Yadwinder Singh, Graeme Gregory, linux-kernel, patches, Mark Brown

In order to allow more drivers to factor things out into data allow
drivers to provide a mapping function to convert voltages into selectors.
This allows any driver to use set_voltage_sel(). The existing mapping
based on iterating over list_voltage() is provided as an operation which
can be assigned to the new map_voltage() function though for ease of
transition it is treated as the default.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 drivers/regulator/core.c         |   82 +++++++++++++++++++++++++-------------
 include/linux/regulator/driver.h |    4 ++
 2 files changed, 59 insertions(+), 27 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index f899af5..2633310 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1967,14 +1967,54 @@ int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel)
 }
 EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap);
 
+/**
+ * regulator_map_voltage_iterate - map_voltage() based on list_voltage()
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers implementing set_voltage_sel() and list_voltage() can use
+ * this as their map_voltage() operation.  It will find a suitable
+ * voltage by calling list_voltage() until it gets something in bounds
+ * for the requested voltages.
+ */
+int regulator_map_voltage_iterate(struct regulator_dev *rdev,
+				  int min_uV, int max_uV)
+{
+	int best_val = INT_MAX;
+	int selector = 0;
+	int i, ret;
+
+	/* Find the smallest voltage that falls within the specified
+	 * range.
+	 */
+	for (i = 0; i < rdev->desc->n_voltages; i++) {
+		ret = rdev->desc->ops->list_voltage(rdev, i);
+		if (ret < 0)
+			continue;
+
+		if (ret < best_val && ret >= min_uV && ret <= max_uV) {
+			best_val = ret;
+			selector = i;
+		}
+	}
+
+	if (best_val != INT_MAX)
+		return selector;
+	else
+		return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
+
 static int _regulator_do_set_voltage(struct regulator_dev *rdev,
 				     int min_uV, int max_uV)
 {
 	int ret;
 	int delay = 0;
+	int best_val;
 	unsigned int selector;
 	int old_selector = -1;
-	int best_val = INT_MAX;
 
 	trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
 
@@ -1995,39 +2035,27 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
 	if (rdev->desc->ops->set_voltage) {
 		ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
 						   &selector);
-
-		if (rdev->desc->ops->list_voltage)
-			best_val = rdev->desc->ops->list_voltage(rdev,
-								 selector);
-		else
-			best_val = -1;
 	} else if (rdev->desc->ops->set_voltage_sel) {
-		int i;
-
-		selector = 0;
-
-		/* Find the smallest voltage that falls within the specified
-		 * range.
-		 */
-		for (i = 0; i < rdev->desc->n_voltages; i++) {
-			ret = rdev->desc->ops->list_voltage(rdev, i);
-			if (ret < 0)
-				continue;
+		if (rdev->desc->ops->map_voltage)
+			ret = rdev->desc->ops->map_voltage(rdev, min_uV,
+							   max_uV);
+		else
+			ret = regulator_map_voltage_iterate(rdev, min_uV,
+							    max_uV);
 
-			if (ret < best_val && ret >= min_uV && ret <= max_uV) {
-				best_val = ret;
-				selector = i;
-			}
+		if (ret >= 0) {
+			selector = ret;
+			ret = rdev->desc->ops->set_voltage_sel(rdev, ret);
 		}
-
-		if (best_val != INT_MAX)
-			ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
-		else
-			ret = -EINVAL;
 	} else {
 		ret = -EINVAL;
 	}
 
+	if (rdev->desc->ops->list_voltage)
+		best_val = rdev->desc->ops->list_voltage(rdev, selector);
+	else
+		best_val = -1;
+
 	/* Call set_voltage_time_sel if successfully obtained old_selector */
 	if (ret == 0 && old_selector >= 0 &&
 	    rdev->desc->ops->set_voltage_time_sel) {
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 8160bc8..13aa852 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -46,6 +46,7 @@ enum regulator_status {
  *               The driver should select the voltage closest to min_uV.
  * @set_voltage_sel: Set the voltage for the regulator using the specified
  *                   selector.
+ * @map_voltage: Convert a voltage into a selector
  * @get_voltage: Return the currently configured voltage for the regulator.
  * @get_voltage_sel: Return the currently configured voltage selector for the
  *                   regulator.
@@ -91,6 +92,7 @@ struct regulator_ops {
 	/* get/set regulator voltage */
 	int (*set_voltage) (struct regulator_dev *, int min_uV, int max_uV,
 			    unsigned *selector);
+	int (*map_voltage)(struct regulator_dev *, int min_uV, int max_uV);
 	int (*set_voltage_sel) (struct regulator_dev *, unsigned selector);
 	int (*get_voltage) (struct regulator_dev *);
 	int (*get_voltage_sel) (struct regulator_dev *);
@@ -260,6 +262,8 @@ int rdev_get_id(struct regulator_dev *rdev);
 
 int regulator_mode_to_status(unsigned int);
 
+int regulator_map_voltage_iterate(struct regulator_dev *rdev,
+				  int min_uV, int max_uV);
 int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev);
 int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel);
 int regulator_is_enabled_regmap(struct regulator_dev *rdev);
-- 
1.7.10


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

* [PATCH 2/6] regulator: core: Allow drivers to set simple linear voltage maps as data
  2012-05-09 23:47 [PATCH 1/6] regulator: core: Allow regulators to provide a voltage to selector mapping Mark Brown
@ 2012-05-09 23:47 ` Mark Brown
  2012-05-09 23:47 ` [PATCH 3/6] regulator: wm831x: Convert to regulator_list_voltage_linear() Mark Brown
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2012-05-09 23:47 UTC (permalink / raw)
  To: Liam Girdwood
  Cc: Yadwinder Singh, Graeme Gregory, linux-kernel, patches, Mark Brown

A lot of regulator hardware maps selectors on to voltages with a simple
linear mapping function

    selector = base + (selector * step size)

Provide off the shelf list_voltage() and map_voltage() operations which
use new min_uV and uV_step members in the regulator_desc to implement
this function.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 drivers/regulator/core.c         |   53 ++++++++++++++++++++++++++++++++++++++
 include/linux/regulator/driver.h |   15 +++++++++--
 2 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 2633310..a3cfaea 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1860,6 +1860,26 @@ int regulator_count_voltages(struct regulator *regulator)
 EXPORT_SYMBOL_GPL(regulator_count_voltages);
 
 /**
+ * regulator_list_voltage_linear - List voltages with simple calculation
+ *
+ * @rdev: Regulator device
+ * @selector: Selector to convert into a voltage
+ *
+ * Regulators with a simple linear mapping between voltages and
+ * selectors can set min_uV and uV_step in the regulator descriptor
+ * and then use this function as their list_voltage() operation,
+ */
+int regulator_list_voltage_linear(struct regulator_dev *rdev,
+				  unsigned int selector)
+{
+	if (selector >= rdev->desc->n_voltages)
+		return -EINVAL;
+
+	return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
+}
+EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
+
+/**
  * regulator_list_voltage - enumerate supported voltages
  * @regulator: regulator source
  * @selector: identify voltage to list
@@ -2007,6 +2027,39 @@ int regulator_map_voltage_iterate(struct regulator_dev *rdev,
 }
 EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
 
+/**
+ * regulator_map_voltage_linear - map_voltage() for simple linear mappings
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers providing min_uV and uV_step in their regulator_desc can
+ * use this as their map_voltage() operation.
+ */
+int regulator_map_voltage_linear(struct regulator_dev *rdev,
+				 int min_uV, int max_uV)
+{
+	int ret, voltage;
+
+	if (!rdev->desc->uV_step) {
+		BUG_ON(!rdev->desc->uV_step);
+		return -EINVAL;
+	}
+
+	ret = (min_uV - rdev->desc->min_uV) / rdev->desc->uV_step;
+	if (ret < 0)
+		return ret;
+
+	/* Map back into a voltage to verify we're still in bounds */
+	voltage = rdev->desc->ops->list_voltage(rdev, ret);
+	if (voltage < min_uV || voltage > max_uV)
+		return -EINVAL;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
+
 static int _regulator_do_set_voltage(struct regulator_dev *rdev,
 				     int min_uV, int max_uV)
 {
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 13aa852..b0432cc 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -161,12 +161,16 @@ enum regulator_type {
  * @name: Identifying name for the regulator.
  * @supply_name: Identifying the regulator supply
  * @id: Numerical identifier for the regulator.
- * @n_voltages: Number of selectors available for ops.list_voltage().
  * @ops: Regulator operations table.
  * @irq: Interrupt number for the regulator.
  * @type: Indicates if the regulator is a voltage or current regulator.
  * @owner: Module providing the regulator, used for refcounting.
-
+ *
+ * @n_voltages: Number of selectors available for ops.list_voltage().
+ *
+ * @min_uV: Voltage given by the lowest selector (if linear mapping)
+ * @uV_step: Voltage increase with each selector (if linear mapping)
+ *
  * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_
  * @vsel_mask: Mask for register bitfield used for selector
  * @enable_reg: Register for control when using regmap enable/disable ops
@@ -182,6 +186,9 @@ struct regulator_desc {
 	enum regulator_type type;
 	struct module *owner;
 
+	unsigned int min_uV;
+	unsigned int uV_step;
+
 	unsigned int vsel_reg;
 	unsigned int vsel_mask;
 	unsigned int enable_reg;
@@ -262,6 +269,10 @@ int rdev_get_id(struct regulator_dev *rdev);
 
 int regulator_mode_to_status(unsigned int);
 
+int regulator_list_voltage_linear(struct regulator_dev *rdev,
+				  unsigned int selector);
+int regulator_map_voltage_linear(struct regulator_dev *rdev,
+				  int min_uV, int max_uV);
 int regulator_map_voltage_iterate(struct regulator_dev *rdev,
 				  int min_uV, int max_uV);
 int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev);
-- 
1.7.10


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

* [PATCH 3/6] regulator: wm831x: Convert to regulator_list_voltage_linear()
  2012-05-09 23:47 [PATCH 1/6] regulator: core: Allow regulators to provide a voltage to selector mapping Mark Brown
  2012-05-09 23:47 ` [PATCH 2/6] regulator: core: Allow drivers to set simple linear voltage maps as data Mark Brown
@ 2012-05-09 23:47 ` Mark Brown
  2012-05-09 23:47 ` [PATCH 4/6] regulator: wm8350: Convert DCDCs to set_voltage_sel() and linear voltages Mark Brown
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2012-05-09 23:47 UTC (permalink / raw)
  To: Liam Girdwood
  Cc: Yadwinder Singh, Graeme Gregory, linux-kernel, patches, Mark Brown

Only the alive LDOs can actually use this as all the other regulators have
two linear ranges.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 drivers/regulator/wm831x-ldo.c |   15 ++++-----------
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index 5bf793d..74ee686 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -630,15 +630,6 @@ static struct platform_driver wm831x_aldo_driver = {
 
 #define WM831X_ALIVE_LDO_MAX_SELECTOR 0xf
 
-static int wm831x_alive_ldo_list_voltage(struct regulator_dev *rdev,
-				      unsigned int selector)
-{
-	/* 0.8-1.55V in 50mV steps */
-	if (selector <= WM831X_ALIVE_LDO_MAX_SELECTOR)
-		return 800000 + (selector * 50000);
-	return -EINVAL;
-}
-
 static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev,
 					    int reg,
 					    int min_uV, int max_uV,
@@ -650,7 +641,7 @@ static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev,
 
 	vsel = (min_uV - 800000) / 50000;
 
-	ret = wm831x_alive_ldo_list_voltage(rdev, vsel);
+	ret = regulator_list_voltage_linear(rdev, vsel);
 	if (ret < 0)
 		return ret;
 	if (ret < min_uV || ret > max_uV)
@@ -700,7 +691,7 @@ static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
 }
 
 static struct regulator_ops wm831x_alive_ldo_ops = {
-	.list_voltage = wm831x_alive_ldo_list_voltage,
+	.list_voltage = regulator_list_voltage_linear,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 	.set_voltage = wm831x_alive_ldo_set_voltage,
 	.set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage,
@@ -765,6 +756,8 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
 	ldo->desc.vsel_mask = WM831X_LDO11_ON_VSEL_MASK;
 	ldo->desc.enable_reg = WM831X_LDO_ENABLE;
 	ldo->desc.enable_mask = 1 << id;
+	ldo->desc.min_uV = 800000;
+	ldo->desc.uV_step = 50000;
 
 	config.dev = pdev->dev.parent;
 	config.init_data = pdata->ldo[id];
-- 
1.7.10


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

* [PATCH 4/6] regulator: wm8350: Convert DCDCs to set_voltage_sel() and linear voltages
  2012-05-09 23:47 [PATCH 1/6] regulator: core: Allow regulators to provide a voltage to selector mapping Mark Brown
  2012-05-09 23:47 ` [PATCH 2/6] regulator: core: Allow drivers to set simple linear voltage maps as data Mark Brown
  2012-05-09 23:47 ` [PATCH 3/6] regulator: wm831x: Convert to regulator_list_voltage_linear() Mark Brown
@ 2012-05-09 23:47 ` Mark Brown
  2012-05-09 23:47 ` [PATCH 5/6] regulator: wm8350: Convert LDOs to set_voltage_sel() Mark Brown
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2012-05-09 23:47 UTC (permalink / raw)
  To: Liam Girdwood
  Cc: Yadwinder Singh, Graeme Gregory, linux-kernel, patches, Mark Brown

The WM8350 DCDCs have a simple linear mapping from selectors to voltages
so can be converted very simply to use the new infrastructure for a nice
reduction in code size.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 drivers/regulator/wm8350-regulator.c |   64 +++++-----------------------------
 1 file changed, 8 insertions(+), 56 deletions(-)

diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 12ecaec..a618284 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -359,60 +359,6 @@ int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
 }
 EXPORT_SYMBOL_GPL(wm8350_isink_set_flash);
 
-static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV,
-				   int max_uV, unsigned *selector)
-{
-	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-	int volt_reg, dcdc = rdev_get_id(rdev), mV,
-		min_mV = min_uV / 1000, max_mV = max_uV / 1000;
-	u16 val;
-
-	if (min_mV < 850 || min_mV > 4025)
-		return -EINVAL;
-	if (max_mV < 850 || max_mV > 4025)
-		return -EINVAL;
-
-	/* step size is 25mV */
-	mV = (min_mV - 826) / 25;
-	if (wm8350_dcdc_val_to_mvolts(mV) > max_mV)
-		return -EINVAL;
-	BUG_ON(wm8350_dcdc_val_to_mvolts(mV) < min_mV);
-
-	switch (dcdc) {
-	case WM8350_DCDC_1:
-		volt_reg = WM8350_DCDC1_CONTROL;
-		break;
-	case WM8350_DCDC_3:
-		volt_reg = WM8350_DCDC3_CONTROL;
-		break;
-	case WM8350_DCDC_4:
-		volt_reg = WM8350_DCDC4_CONTROL;
-		break;
-	case WM8350_DCDC_6:
-		volt_reg = WM8350_DCDC6_CONTROL;
-		break;
-	case WM8350_DCDC_2:
-	case WM8350_DCDC_5:
-	default:
-		return -EINVAL;
-	}
-
-	*selector = mV;
-
-	/* all DCDCs have same mV bits */
-	val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
-	wm8350_reg_write(wm8350, volt_reg, val | mV);
-	return 0;
-}
-
-static int wm8350_dcdc_list_voltage(struct regulator_dev *rdev,
-				    unsigned selector)
-{
-	if (selector > WM8350_DCDC_MAX_VSEL)
-		return -EINVAL;
-	return wm8350_dcdc_val_to_mvolts(selector) * 1000;
-}
-
 static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 {
 	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
@@ -1087,9 +1033,9 @@ static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev,
 }
 
 static struct regulator_ops wm8350_dcdc_ops = {
-	.set_voltage = wm8350_dcdc_set_voltage,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
-	.list_voltage = wm8350_dcdc_list_voltage,
+	.list_voltage = regulator_list_voltage_linear,
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
 	.is_enabled = regulator_is_enabled_regmap,
@@ -1140,6 +1086,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
 		.irq = WM8350_IRQ_UV_DC1,
 		.type = REGULATOR_VOLTAGE,
 		.n_voltages = WM8350_DCDC_MAX_VSEL + 1,
+		.min_uV = 850000,
+		.uV_step = 25000,
 		.vsel_reg = WM8350_DCDC1_CONTROL,
 		.vsel_mask = WM8350_DC1_VSEL_MASK,
 		.enable_reg = WM8350_DCDC_LDO_REQUESTED,
@@ -1163,6 +1111,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
 		.irq = WM8350_IRQ_UV_DC3,
 		.type = REGULATOR_VOLTAGE,
 		.n_voltages = WM8350_DCDC_MAX_VSEL + 1,
+		.min_uV = 850000,
+		.uV_step = 25000,
 		.vsel_reg = WM8350_DCDC3_CONTROL,
 		.vsel_mask = WM8350_DC3_VSEL_MASK,
 		.enable_reg = WM8350_DCDC_LDO_REQUESTED,
@@ -1199,6 +1149,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
 		.irq = WM8350_IRQ_UV_DC6,
 		.type = REGULATOR_VOLTAGE,
 		.n_voltages = WM8350_DCDC_MAX_VSEL + 1,
+		.min_uV = 850000,
+		.uV_step = 25000,
 		.vsel_reg = WM8350_DCDC6_CONTROL,
 		.vsel_mask = WM8350_DC6_VSEL_MASK,
 		.enable_reg = WM8350_DCDC_LDO_REQUESTED,
-- 
1.7.10


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

* [PATCH 5/6] regulator: wm8350: Convert LDOs to set_voltage_sel()
  2012-05-09 23:47 [PATCH 1/6] regulator: core: Allow regulators to provide a voltage to selector mapping Mark Brown
                   ` (2 preceding siblings ...)
  2012-05-09 23:47 ` [PATCH 4/6] regulator: wm8350: Convert DCDCs to set_voltage_sel() and linear voltages Mark Brown
@ 2012-05-09 23:47 ` Mark Brown
  2012-05-09 23:47 ` [PATCH 6/6] regulator: wm8400: Modernise driver Mark Brown
  2012-05-10  9:23 ` [PATCH 1/6] regulator: core: Allow regulators to provide a voltage to selector mapping Liam Girdwood
  5 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2012-05-09 23:47 UTC (permalink / raw)
  To: Liam Girdwood
  Cc: Yadwinder Singh, Graeme Gregory, linux-kernel, patches, Mark Brown

Since there are two linear ranges for the LDO voltages provide a voltage
mapping function and then use regulator_set_voltage_sel_regmap().

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 drivers/regulator/wm8350-regulator.c |   38 +++++++---------------------------
 1 file changed, 8 insertions(+), 30 deletions(-)

diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index a618284..9efca21 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -671,13 +671,12 @@ static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev)
 	return 0;
 }
 
-static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV,
-				  int max_uV, unsigned *selector)
+static int wm8350_ldo_map_voltage(struct regulator_dev *rdev, int min_uV,
+				  int max_uV)
 {
-	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-	int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000,
-		max_mV = max_uV / 1000;
-	u16 val;
+	int mV;
+	int min_mV = min_uV / 1000;
+	int max_mV = max_uV / 1000;
 
 	if (min_mV < 900 || min_mV > 3300)
 		return -EINVAL;
@@ -698,29 +697,7 @@ static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV,
 		BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
 	}
 
-	switch (ldo) {
-	case WM8350_LDO_1:
-		volt_reg = WM8350_LDO1_CONTROL;
-		break;
-	case WM8350_LDO_2:
-		volt_reg = WM8350_LDO2_CONTROL;
-		break;
-	case WM8350_LDO_3:
-		volt_reg = WM8350_LDO3_CONTROL;
-		break;
-	case WM8350_LDO_4:
-		volt_reg = WM8350_LDO4_CONTROL;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	*selector = mV;
-
-	/* all LDOs have same mV bits */
-	val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
-	wm8350_reg_write(wm8350, volt_reg, val | mV);
-	return 0;
+	return mV;
 }
 
 static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
@@ -1057,7 +1034,8 @@ static struct regulator_ops wm8350_dcdc2_5_ops = {
 };
 
 static struct regulator_ops wm8350_ldo_ops = {
-	.set_voltage = wm8350_ldo_set_voltage,
+	.map_voltage = wm8350_ldo_map_voltage,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 	.list_voltage = wm8350_ldo_list_voltage,
 	.enable = regulator_enable_regmap,
-- 
1.7.10


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

* [PATCH 6/6] regulator: wm8400: Modernise driver
  2012-05-09 23:47 [PATCH 1/6] regulator: core: Allow regulators to provide a voltage to selector mapping Mark Brown
                   ` (3 preceding siblings ...)
  2012-05-09 23:47 ` [PATCH 5/6] regulator: wm8350: Convert LDOs to set_voltage_sel() Mark Brown
@ 2012-05-09 23:47 ` Mark Brown
  2012-05-10  9:23 ` [PATCH 1/6] regulator: core: Allow regulators to provide a voltage to selector mapping Liam Girdwood
  5 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2012-05-09 23:47 UTC (permalink / raw)
  To: Liam Girdwood
  Cc: Yadwinder Singh, Graeme Gregory, linux-kernel, patches, Mark Brown

Update the driver to use all the regmap based helpers, saving a nice chunk
of code (especially for the DCDCs).

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 drivers/regulator/wm8400-regulator.c |  169 +++++++++-------------------------
 1 file changed, 44 insertions(+), 125 deletions(-)

diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
index 4408b78..69a2b7c 100644
--- a/drivers/regulator/wm8400-regulator.c
+++ b/drivers/regulator/wm8400-regulator.c
@@ -19,31 +19,6 @@
 #include <linux/regulator/driver.h>
 #include <linux/mfd/wm8400-private.h>
 
-static int wm8400_ldo_is_enabled(struct regulator_dev *dev)
-{
-	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
-	u16 val;
-
-	val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
-	return (val & WM8400_LDO1_ENA) != 0;
-}
-
-static int wm8400_ldo_enable(struct regulator_dev *dev)
-{
-	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
-
-	return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
-			       WM8400_LDO1_ENA, WM8400_LDO1_ENA);
-}
-
-static int wm8400_ldo_disable(struct regulator_dev *dev)
-{
-	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
-
-	return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
-			       WM8400_LDO1_ENA, 0);
-}
-
 static int wm8400_ldo_list_voltage(struct regulator_dev *dev,
 				   unsigned selector)
 {
@@ -56,21 +31,9 @@ static int wm8400_ldo_list_voltage(struct regulator_dev *dev,
 		return 1600000 + ((selector - 14) * 100000);
 }
 
-static int wm8400_ldo_get_voltage_sel(struct regulator_dev *dev)
+static int wm8400_ldo_map_voltage(struct regulator_dev *dev,
+				  int min_uV, int max_uV)
 {
-	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
-	u16 val;
-
-	val = wm8400_reg_read(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev));
-	val &= WM8400_LDO1_VSEL_MASK;
-
-	return val;
-}
-
-static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
-				  int min_uV, int max_uV, unsigned *selector)
-{
-	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
 	u16 val;
 
 	if (min_uV < 900000 || min_uV > 3300000)
@@ -94,92 +57,19 @@ static int wm8400_ldo_set_voltage(struct regulator_dev *dev,
 		val += 0xf;
 	}
 
-	*selector = val;
-
-	return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev),
-			       WM8400_LDO1_VSEL_MASK, val);
+	return val;
 }
 
 static struct regulator_ops wm8400_ldo_ops = {
-	.is_enabled = wm8400_ldo_is_enabled,
-	.enable = wm8400_ldo_enable,
-	.disable = wm8400_ldo_disable,
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
 	.list_voltage = wm8400_ldo_list_voltage,
-	.get_voltage_sel = wm8400_ldo_get_voltage_sel,
-	.set_voltage = wm8400_ldo_set_voltage,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.map_voltage = wm8400_ldo_map_voltage,
 };
 
-static int wm8400_dcdc_is_enabled(struct regulator_dev *dev)
-{
-	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
-	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
-	u16 val;
-
-	val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
-	return (val & WM8400_DC1_ENA) != 0;
-}
-
-static int wm8400_dcdc_enable(struct regulator_dev *dev)
-{
-	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
-	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
-
-	return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
-			       WM8400_DC1_ENA, WM8400_DC1_ENA);
-}
-
-static int wm8400_dcdc_disable(struct regulator_dev *dev)
-{
-	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
-	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
-
-	return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
-			       WM8400_DC1_ENA, 0);
-}
-
-static int wm8400_dcdc_list_voltage(struct regulator_dev *dev,
-				    unsigned selector)
-{
-	if (selector > WM8400_DC1_VSEL_MASK)
-		return -EINVAL;
-
-	return 850000 + (selector * 25000);
-}
-
-static int wm8400_dcdc_get_voltage_sel(struct regulator_dev *dev)
-{
-	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
-	u16 val;
-	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
-
-	val = wm8400_reg_read(wm8400, WM8400_DCDC1_CONTROL_1 + offset);
-	val &= WM8400_DC1_VSEL_MASK;
-
-	return val;
-}
-
-static int wm8400_dcdc_set_voltage(struct regulator_dev *dev,
-				   int min_uV, int max_uV, unsigned *selector)
-{
-	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
-	u16 val;
-	int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
-
-	if (min_uV < 850000)
-		return -EINVAL;
-
-	val = DIV_ROUND_UP(min_uV - 850000, 25000);
-
-	if (850000 + (25000 * val) > max_uV)
-		return -EINVAL;
-	BUG_ON(850000 + (25000 * val) < min_uV);
-
-	*selector = val;
-
-	return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset,
-			       WM8400_DC1_VSEL_MASK, val);
-}
-
 static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev)
 {
 	struct wm8400 *wm8400 = rdev_get_drvdata(dev);
@@ -258,12 +148,12 @@ static unsigned int wm8400_dcdc_get_optimum_mode(struct regulator_dev *dev,
 }
 
 static struct regulator_ops wm8400_dcdc_ops = {
-	.is_enabled = wm8400_dcdc_is_enabled,
-	.enable = wm8400_dcdc_enable,
-	.disable = wm8400_dcdc_disable,
-	.list_voltage = wm8400_dcdc_list_voltage,
-	.get_voltage_sel = wm8400_dcdc_get_voltage_sel,
-	.set_voltage = wm8400_dcdc_set_voltage,
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.list_voltage = regulator_list_voltage_linear,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 	.get_mode = wm8400_dcdc_get_mode,
 	.set_mode = wm8400_dcdc_set_mode,
 	.get_optimum_mode = wm8400_dcdc_get_optimum_mode,
@@ -274,7 +164,11 @@ static struct regulator_desc regulators[] = {
 		.name = "LDO1",
 		.id = WM8400_LDO1,
 		.ops = &wm8400_ldo_ops,
+		.enable_reg = WM8400_LDO1_CONTROL,
+		.enable_mask = WM8400_LDO1_ENA,
 		.n_voltages = WM8400_LDO1_VSEL_MASK + 1,
+		.vsel_reg = WM8400_LDO1_CONTROL,
+		.vsel_mask = WM8400_LDO1_VSEL_MASK,
 		.type = REGULATOR_VOLTAGE,
 		.owner = THIS_MODULE,
 	},
@@ -282,15 +176,23 @@ static struct regulator_desc regulators[] = {
 		.name = "LDO2",
 		.id = WM8400_LDO2,
 		.ops = &wm8400_ldo_ops,
+		.enable_reg = WM8400_LDO2_CONTROL,
+		.enable_mask = WM8400_LDO2_ENA,
 		.n_voltages = WM8400_LDO2_VSEL_MASK + 1,
 		.type = REGULATOR_VOLTAGE,
+		.vsel_reg = WM8400_LDO2_CONTROL,
+		.vsel_mask = WM8400_LDO2_VSEL_MASK,
 		.owner = THIS_MODULE,
 	},
 	{
 		.name = "LDO3",
 		.id = WM8400_LDO3,
 		.ops = &wm8400_ldo_ops,
+		.enable_reg = WM8400_LDO3_CONTROL,
+		.enable_mask = WM8400_LDO3_ENA,
 		.n_voltages = WM8400_LDO3_VSEL_MASK + 1,
+		.vsel_reg = WM8400_LDO3_CONTROL,
+		.vsel_mask = WM8400_LDO3_VSEL_MASK,
 		.type = REGULATOR_VOLTAGE,
 		.owner = THIS_MODULE,
 	},
@@ -298,7 +200,11 @@ static struct regulator_desc regulators[] = {
 		.name = "LDO4",
 		.id = WM8400_LDO4,
 		.ops = &wm8400_ldo_ops,
+		.enable_reg = WM8400_LDO4_CONTROL,
+		.enable_mask = WM8400_LDO4_ENA,
 		.n_voltages = WM8400_LDO4_VSEL_MASK + 1,
+		.vsel_reg = WM8400_LDO4_CONTROL,
+		.vsel_mask = WM8400_LDO4_VSEL_MASK,
 		.type = REGULATOR_VOLTAGE,
 		.owner = THIS_MODULE,
 	},
@@ -306,7 +212,13 @@ static struct regulator_desc regulators[] = {
 		.name = "DCDC1",
 		.id = WM8400_DCDC1,
 		.ops = &wm8400_dcdc_ops,
+		.enable_reg = WM8400_DCDC1_CONTROL_1,
+		.enable_mask = WM8400_DC1_ENA_MASK,
 		.n_voltages = WM8400_DC1_VSEL_MASK + 1,
+		.vsel_reg = WM8400_DCDC1_CONTROL_1,
+		.vsel_mask = WM8400_DC1_VSEL_MASK,
+		.min_uV = 850000,
+		.uV_step = 25000,
 		.type = REGULATOR_VOLTAGE,
 		.owner = THIS_MODULE,
 	},
@@ -314,7 +226,13 @@ static struct regulator_desc regulators[] = {
 		.name = "DCDC2",
 		.id = WM8400_DCDC2,
 		.ops = &wm8400_dcdc_ops,
+		.enable_reg = WM8400_DCDC2_CONTROL_1,
+		.enable_mask = WM8400_DC1_ENA_MASK,
 		.n_voltages = WM8400_DC2_VSEL_MASK + 1,
+		.vsel_reg = WM8400_DCDC2_CONTROL_1,
+		.vsel_mask = WM8400_DC2_VSEL_MASK,
+		.min_uV = 850000,
+		.uV_step = 25000,
 		.type = REGULATOR_VOLTAGE,
 		.owner = THIS_MODULE,
 	},
@@ -329,6 +247,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
 	config.dev = &pdev->dev;
 	config.init_data = pdev->dev.platform_data;
 	config.driver_data = wm8400;
+	config.regmap = wm8400->regmap;
 
 	rdev = regulator_register(&regulators[pdev->id], &config);
 	if (IS_ERR(rdev))
-- 
1.7.10


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

* Re: [PATCH 1/6] regulator: core: Allow regulators to provide a voltage to selector mapping
  2012-05-09 23:47 [PATCH 1/6] regulator: core: Allow regulators to provide a voltage to selector mapping Mark Brown
                   ` (4 preceding siblings ...)
  2012-05-09 23:47 ` [PATCH 6/6] regulator: wm8400: Modernise driver Mark Brown
@ 2012-05-10  9:23 ` Liam Girdwood
  5 siblings, 0 replies; 7+ messages in thread
From: Liam Girdwood @ 2012-05-10  9:23 UTC (permalink / raw)
  To: Mark Brown; +Cc: Yadwinder Singh, Graeme Gregory, linux-kernel, patches

On Thu, 2012-05-10 at 00:47 +0100, Mark Brown wrote:
> In order to allow more drivers to factor things out into data allow
> drivers to provide a mapping function to convert voltages into selectors.
> This allows any driver to use set_voltage_sel(). The existing mapping
> based on iterating over list_voltage() is provided as an operation which
> can be assigned to the new map_voltage() function though for ease of
> transition it is treated as the default.
> 
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> ---

All

Acked-by: Liam Girdwood <lrg@ti.com>


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

end of thread, other threads:[~2012-05-10  9:23 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-09 23:47 [PATCH 1/6] regulator: core: Allow regulators to provide a voltage to selector mapping Mark Brown
2012-05-09 23:47 ` [PATCH 2/6] regulator: core: Allow drivers to set simple linear voltage maps as data Mark Brown
2012-05-09 23:47 ` [PATCH 3/6] regulator: wm831x: Convert to regulator_list_voltage_linear() Mark Brown
2012-05-09 23:47 ` [PATCH 4/6] regulator: wm8350: Convert DCDCs to set_voltage_sel() and linear voltages Mark Brown
2012-05-09 23:47 ` [PATCH 5/6] regulator: wm8350: Convert LDOs to set_voltage_sel() Mark Brown
2012-05-09 23:47 ` [PATCH 6/6] regulator: wm8400: Modernise driver Mark Brown
2012-05-10  9:23 ` [PATCH 1/6] regulator: core: Allow regulators to provide a voltage to selector mapping Liam Girdwood

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).