Skip to contentSkip to conversation

regulator: Add GPIO enable control to fixed voltage regulator driver

PATCH Superseded Roger Quadros 2 participants 3 messages Aug 4, 2009 – Aug 5, 2009 Voltage and current regulator framework

lore
Share & tools
lore
#0 lore raw

PATCH v5 1/1 regulator: Add GPIO enable control to fixed voltage regulator driver

From: Roger Quadros <[email protected]>

Now fixed regulators that have their enable pin connected to a GPIO line can use the fixed regulator driver for regulator enable/disable control. The GPIO number and polarity information is passed through platform data. GPIO enable control is achieved using gpiolib.

---
 drivers/regulator/fixed.c       |   88 ++++++++++++++++++++++++++++++++++++++-
 include/linux/regulator/fixed.h |   21 +++++++++
 2 files changed, 107 insertions(+), 2 deletions(-)
drivers/regulator/fixed.c +86 -2
index cdc674f..205fb60 100644
@@ -5,6 +5,9 @@
  *
  * Author: Mark Brown <[email protected]>
  *
+ * Copyright (c) 2009 Nokia Corporation
+ * Roger Quadros <[email protected]>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
@@ -20,20 +23,45 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/fixed.h>
+#include <linux/gpio.h>
 
 struct fixed_voltage_data {
 	struct regulator_desc desc;
 	struct regulator_dev *dev;
 	int microvolts;
+	int gpio;
+	unsigned enable_high:1;
+	unsigned is_enabled:1;
 };
 
 static int fixed_voltage_is_enabled(struct regulator_dev *dev)
 {
-	return 1;
+	struct fixed_voltage_data *data = rdev_get_drvdata(dev);
+
+	return data->is_enabled;
 }
 
 static int fixed_voltage_enable(struct regulator_dev *dev)
 {
+	struct fixed_voltage_data *data = rdev_get_drvdata(dev);
+
+	if (gpio_is_valid(data->gpio)) {
+		gpio_set_value_cansleep(data->gpio, data->enable_high);
+		data->is_enabled = 1;
+	}
+
+	return 0;
+}
+
+static int fixed_voltage_disable(struct regulator_dev *dev)
+{
+	struct fixed_voltage_data *data = rdev_get_drvdata(dev);
+
+	if (gpio_is_valid(data->gpio)) {
+		gpio_set_value_cansleep(data->gpio, !data->enable_high);
+		data->is_enabled = 0;
+	}
+
 	return 0;
 }
 
@@ -58,6 +86,7 @@ static int fixed_voltage_list_voltage(struct regulator_dev *dev,
 static struct regulator_ops fixed_voltage_ops = {
 	.is_enabled = fixed_voltage_is_enabled,
 	.enable = fixed_voltage_enable,
+	.disable = fixed_voltage_disable,
 	.get_voltage = fixed_voltage_get_voltage,
 	.list_voltage = fixed_voltage_list_voltage,
 };
@@ -85,12 +114,61 @@ static int regulator_fixed_voltage_probe(struct platform_device *pdev)
 	drvdata->desc.n_voltages = 1;
 
 	drvdata->microvolts = config->microvolts;
+	drvdata->gpio = config->gpio;
+
+	if (gpio_is_valid(config->gpio)) {
+		drvdata->enable_high = config->enable_high;
+
+		/* FIXME: Remove below print warning
+		 *
+		 * config->gpio must be set to -EINVAL by platform code if
+		 * GPIO control is not required. However, early adopters
+		 * not requiring GPIO control may forget to initialize
+		 * config->gpio to -EINVAL. This will cause GPIO 0 to be used
+		 * for GPIO control.
+		 *
+		 * This warning will be removed once there are a couple of users
+		 * for this driver.
+		 */
+		if (!config->gpio)
+			dev_warn(&pdev->dev,
+				"using GPIO 0 for regulator enable control\n");
+
+		ret = gpio_request(config->gpio, config->supply_name);
+		if (ret) {
+			dev_err(&pdev->dev,
+			   "Could not obtain regulator enable GPIO %d: %d\n",
+							config->gpio, ret);
+			goto err_name;
+		}
+
+		/* set output direction without changing state
+		 * to prevent glitch
+		 */
+		drvdata->is_enabled = config->enabled_at_boot;
+		ret = drvdata->is_enabled ?
+				config->enable_high : !config->enable_high;
+
+		ret = gpio_direction_output(config->gpio, ret);
+		if (ret) {
+			dev_err(&pdev->dev,
+			   "Could not configure regulator enable GPIO %d direction: %d\n",
+							config->gpio, ret);
+			goto err_gpio;
+		}
+
+	} else {
+		/* Regulator without GPIO control is considered
+		 * always enabled
+		 */
+		drvdata->is_enabled = 1;
+	}
 
 	drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
 					  config->init_data, drvdata);
 	if (IS_ERR(drvdata->dev)) {
 		ret = PTR_ERR(drvdata->dev);
-		goto err_name;
+		goto err_gpio;
 	}
 
 	platform_set_drvdata(pdev, drvdata);
@@ -100,6 +178,9 @@ static int regulator_fixed_voltage_probe(struct platform_device *pdev)
 
 	return 0;
 
+err_gpio:
+	if (gpio_is_valid(config->gpio))
+		gpio_free(config->gpio);
 err_name:
 	kfree(drvdata->desc.name);
 err:
@@ -115,6 +196,9 @@ static int regulator_fixed_voltage_remove(struct platform_device *pdev)
 	kfree(drvdata->desc.name);
 	kfree(drvdata);
 
+	if (gpio_is_valid(drvdata->gpio))
+		gpio_free(drvdata->gpio);
+
 	return 0;
 }
 
include/linux/regulator/fixed.h +21 -0
index 91b4da3..bd75b18 100644
@@ -16,9 +16,30 @@
 
 struct regulator_init_data;
 
+/**
+ * struct fixed_voltage_config - fixed_voltage_config structure
+ * @supply_name:	Name of the regulator supply
+ * @microvolts:		Output voltage of regulator
+ * @gpio:		GPIO to use for enable control
+ * 			set to -EINVAL if not used
+ * @enable_high:	Polarity of enable GPIO
+ *			1 = Active high, 0 = Active low
+ * @enabled_at_boot:	Whether regulator has been enabled at
+ * 			boot or not. 1 = Yes, 0 = No
+ * 			This is used to keep the regulator at
+ * 			the default state
+ * @init_data:		regulator_init_data
+ *
+ * This structure contains fixed voltage regulator configuration
+ * information that must be passed by platform code to the fixed
+ * voltage regulator driver.
+ */
 struct fixed_voltage_config {
 	const char *supply_name;
 	int microvolts;
+	int gpio;
+	unsigned enable_high:1;
+	unsigned enabled_at_boot:1;
 	struct regulator_init_data *init_data;
 };
 
Signature · 1 line
1.5.6.3
Acked-by on v5 1/1
#1 lore raw
Quoted 8 lines · Roger Quadros

From: Roger Quadros <[email protected]>

Now fixed regulators that have their enable pin connected to a GPIO line can use the fixed regulator driver for regulator enable/disable control. The GPIO number and polarity information is passed through platform data. GPIO enable control is achieved using gpiolib.

Looks good, thanks for taking the time to do this and fixing up the review comments.

A couple of small notes that I don't see as blocking merge:

drivers/regulator/fixed.c static int regulator_fixed_voltage_probe(struct platform_device *pdev) · line 131

Quoted 11 lines
drivers/regulator/fixed.c +11 -0
+
+		/* FIXME: Remove below print warning
+		 *
+		 * config->gpio must be set to -EINVAL by platform code if
+		 * GPIO control is not required. However, early adopters
+		 * not requiring GPIO control may forget to initialize
+		 * config->gpio to -EINVAL. This will cause GPIO 0 to be used
+		 * for GPIO control.
+		 *
+		 * This warning will be removed once there are a couple of users
+		 * for this driver.

Probably just for 2.6.33 or something; the point here is that this is an incompatible change in the platform data which we can get away with here due to the fact that there aren't any current users.

drivers/regulator/fixed.c static int regulator_fixed_voltage_probe(struct platform_device *pdev) · line 150

Quoted 3 lines
drivers/regulator/fixed.c +3 -0
+		drvdata->is_enabled = config->enabled_at_boot;
+		ret = drvdata->is_enabled ?
+				config->enable_high : !config->enable_high;

Might be more legible without the ternery operator but no point spinning the patch for that.

#2 lore raw
Quoted 33 lines · Mark Brown
Quoted 8 lines · Roger Quadros

From: Roger Quadros <[email protected]>

Now fixed regulators that have their enable pin connected to a GPIO line can use the fixed regulator driver for regulator enable/disable control. The GPIO number and polarity information is passed through platform data. GPIO enable control is achieved using gpiolib.

Looks good, thanks for taking the time to do this and fixing up the review comments.

A couple of small notes that I don't see as blocking merge:

Quoted 11 lines

+
+             /* FIXME: Remove below print warning
+              *
+              * config->gpio must be set to -EINVAL by platform code if
+              * GPIO control is not required. However, early adopters
+              * not requiring GPIO control may forget to initialize
+              * config->gpio to -EINVAL. This will cause GPIO 0 to be used
+              * for GPIO control.
+              *
+              * This warning will be removed once there are a couple of users
+              * for this driver.

Probably just for 2.6.33 or something; the point here is that this is an incompatible change in the platform data which we can get away with here due to the fact that there aren't any current users.

Quoted 7 lines
Quoted 3 lines

+             drvdata->is_enabled = config->enabled_at_boot;
+             ret = drvdata->is_enabled ?
+                             config->enable_high : !config->enable_high;

Might be more legible without the ternery operator but no point spinning the patch for that.

Thank you all for review.

As reported by Liam, the patch does not apply on latest
git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6.git#for-next
Seems it moved on in the last 2 days when from which I based my patch on.

I will regenerate the patch against latest HEAD and resend.

cheers,
-roger