Skip to contentSkip to conversation

Add gpio based voltage switching regulator

RFC In review Heiko Stübner 2 participants 5 messages Sep 26, 2011 – Sep 30, 2011 Voltage and current regulator framework

lore
Share & tools
lore
#0 lore raw

RFC 1/1 Add gpio based voltage switching regulator

This patch adds support for regulators that can switch between two voltage levels by setting a gpio.

An example such a regulator is the TI-tps65024x regulator family. They contain 4 fixed and 1 runtime-switchable voltage regulators. The switch can be used by a cpufreq driver to set the core voltage on some SoCs, for example the S3C2416/2450.

Handling of set_voltage calls with a range that fits neither the low nor the high voltage is determined by the inbetween_high option. When set to 1 the high voltage is used, on 0 the low voltage is used and on -EINVAL an error is returned, disallowing the usage of the voltage range.

---
I'm not hung up on the "inbetween handling", in fact at the moment it seems to not belong there. But I'm not sure on how to handle frequency tables like

	[0] = { 1000000, 1150000 },
	[1] = { 1150000, 1250000 },
	[2] = { 1250000, 1350000 },

I.e. the middle value should use the voltage in 2 for switch regulators, but the defined value for more intelligent ones.

 drivers/regulator/Kconfig        |    8 +
 drivers/regulator/Makefile       |    1 +
 drivers/regulator/switch.c       |  320 ++++++++++++++++++++++++++++++++++++++
 include/linux/regulator/switch.h |   65 ++++++++
 4 files changed, 394 insertions(+), 0 deletions(-)
drivers/regulator/Kconfig +8 -0
index c7fd2c0..8510d8c 100644
@@ -45,6 +45,14 @@ config REGULATOR_FIXED_VOLTAGE
 	  useful for systems which use a combination of software
 	  managed regulators and simple non-configurable regulators.
 
+config REGULATOR_SWITCHED_VOLTAGE
+	tristate "Switched voltage regulator support"
+	help
+	  This driver provides support for regulators that can switch
+	  between two voltages by setting a gpio,
+	  useful for systems which use a combination of software
+	  managed regulators and simple non-configurable regulators.
+
 config REGULATOR_VIRTUAL_CONSUMER
 	tristate "Virtual regulator consumer support"
 	help
drivers/regulator/Makefile +1 -0
index 040d5aa..5a8f4ee 100644
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_REGULATOR) += core.o dummy.o
 obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
+obj-$(CONFIG_REGULATOR_SWITCHED_VOLTAGE) += switch.o
 obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
 obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
 
drivers/regulator/switch.c new file +320 -0

320 lines not on this page · raw message

include/linux/regulator/switch.h new file +65 -0

65 lines not on this page · raw message

Signature · 1 line
tg: (c6a389f..) topic/drivers/reg-switch (depends on: master)
#1 lore raw
Quoted 2 lines · Heiko Stübner

This patch adds support for regulators that can switch between two voltage levels by setting a gpio.

This really should be scalable beyond two voltages, or at least prepared for that possibility.

Quoted 5 lines

Handling of set_voltage calls with a range that fits neither the low nor the high voltage is determined by the inbetween_high option. When set to 1 the high voltage is used, on 0 the low voltage is used and on -EINVAL an error is returned, disallowing the usage of the voltage range.

No, don't do this. If you can't set the requested voltage then fail. This is not in the least bit driver specific.

Quoted 8 lines

I'm not hung up on the "inbetween handling", in fact at the moment it seems to not belong there. But I'm not sure on how to handle frequency tables like

	[0] = { 1000000, 1150000 },
	[1] = { 1150000, 1250000 },
	[2] = { 1250000, 1350000 },

I.e. the middle value should use the voltage in 2 for switch regulators, but the defined value for more intelligent ones.

I'm afraid I can't parse this, sorry.

drivers/regulator/switch.c line 2

Quoted 3 lines
drivers/regulator/switch.c new file +2 -0
@@ -0,0 +1,320 @@
+/*
+ * switched.c

This needs a better name.

Otherwise this looks good, the main thing is the ability to support more voltages.

#2 lore raw

Hi Mark,

thanks for your comments.

Am Montag, 26. September 2011, 14:51:55 schrieb Mark Brown:

Quoted 6 lines · Heiko Stübner
Quoted 2 lines

This patch adds support for regulators that can switch between two voltage levels by setting a gpio.

This really should be scalable beyond two voltages, or at least prepared for that possibility.

I think I've come up with a solution for this but would like to make sure I'm on the right track. So my general idea is to define the platform_data like

static struct switched_voltage_config es600_dcdc3 = { [...]

	.switch_gpios = {
		GPIO1, /* bit 0 in matrix */
		GPIO2, /* bit 1 in matrix */
	},
	.nr_switch_gpios = 2,
	.switch_matrix = {
		{ .microvolts = 1000000, .gpio_state = (0 << 1) | (0 << 0) },
		{ .microvolts = 1100000, .gpio_state = (0 << 1) | (1 << 0) },
		{ .microvolts = 1200000, .gpio_state = (1 << 1) | (0 << 0) },
		{ .microvolts = 1300000, .gpio_state = (1 << 1) | (1 << 0) },
	},
	.nr_switch_matrix = 4,

[...]
};

i.e. each voltage keeps the target gpio state in a bit-field which makes the mapping current_state -> voltage in get_voltage very easy.

set_voltage would then look like

	gpio_state = get_gpio_state_for_voltage(microvolts);
	for(ptr = 0; ptr < nr_switch_gpios; ptr++) {
		state = ( gpio_state & (1 << ptr) ) >> ptr;
		gpio_set_value(switch_gpios[ptr], state);
	}

i.e. simply extracting the target setting from the bitfield for each gpio.

If using integers for the state, this would scale up to 16 gpios and voltage-permutations thereof.

Reasonable?

Quoted 8 lines
Quoted 5 lines

Handling of set_voltage calls with a range that fits neither the low nor the high voltage is determined by the inbetween_high option. When set to 1 the high voltage is used, on 0 the low voltage is used and on -EINVAL an error is returned, disallowing the usage of the voltage range.

No, don't do this. If you can't set the requested voltage then fail. This is not in the least bit driver specific.

ok

Quoted 5 lines

drivers/regulator/switch.c line 2

Quoted 3 lines
drivers/regulator/switch.c new file +2 -0
@@ -0,0 +1,320 @@
+/*
+ * switched.c

This needs a better name.

"gpio-regulator"?

I'm quite open to suggestions :-)

Quoted 2 lines

Otherwise this looks good, the main thing is the ability to support more voltages.

Heiko

#3 lore raw
Quoted 5 lines · Heiko Stübner
	.switch_gpios = {
		GPIO1, /* bit 0 in matrix */
		GPIO2, /* bit 1 in matrix */
	},
	.nr_switch_gpios = 2,

This seems like a good plan.

Quoted 4 lines
Quoted 1 line

This needs a better name.

"gpio-regulator"?

I'm quite open to suggestions :-)

That would be better, yes.

#4 lore raw

RFC v2 1/1 Add gpio-regulator driver

As suggested by Mark Brown, I created a more generalised gpio-regulator driver.

It is definitly not finished - it just implements my idea and compiles - real world testing and fixing follows this weekend. If possible I'd just like to make sure I'm on the right track this time :-) .

As the mechanisms of setting gpio states don't change with the regulator type it is also possible to use it as a current regulator.
Therefore it could replace i.e. the bq24022/bq2407x driver later on.

Platform data for the 3 gpio controlled regulators I know of could look like:

struct gpio_regulator_config bq24022 = {
	.supply_name = "bq24022",

	.gpios = {
		GPIO_ISET2,
	},
	.nr_gpios = 1,

	.gpio_states = {
		{ .value = 100000, gpios = (0 << 0) },
		{ .value = 500000, gpios = (1 << 0) },
	},
	.nr_gpio_states = 2,
	.state_at_boot = (0 << 0),
	.type = REGULATOR_CURRENT,
};
struct gpio_regulator_config bq24075 = {
	.supply_name = "bq24075",

	.gpios = {
		GPIO_EN1,
		GPIO_EN2,
	},
	.nr_gpios = 2,

	.gpio_states = {
		{ .value = 100000, gpios = (0 << 1) | (0 << 0) },
		{ .value = 500000, gpios = (0 << 1) | (1 << 0) },
		{ .value = 975000, gpios = (1 << 1) | (0 << 0) },
	},
	.nr_gpio_states = 3,
	.state_at_boot = (0 << 1)|(0 << 0),
	.type = REGULATOR_CURRENT,
};
struct gpio_regulator_config tps650240 = {
	.supply_name = "tps650240-dcdc3",

	.gpios = {
		GPIO_DEFDCDC3,
	},
	.nr_gpios = 1,

	.gpio_states = {
		{ .value = 1000000, gpios = (0 << 0) },
		{ .value = 1300000, gpios = (1 << 0) },
	},
	.nr_gpio_states = 2,
	.state_at_boot = (1 << 0),
	.type = REGULATOR_VOLTAGE,
};

Comments?

---
 drivers/regulator/Kconfig                |    6 +
 drivers/regulator/Makefile               |    1 +
 drivers/regulator/gpio-regulator.c       |  361 ++++++++++++++++++++++++++++++
 include/linux/regulator/gpio-regulator.h |   84 +++++++
 4 files changed, 452 insertions(+), 0 deletions(-)
 create mode 100644 drivers/regulator/gpio-regulator.c
 create mode 100644 include/linux/regulator/gpio-regulator.h
drivers/regulator/Kconfig +6 -0
index 8510d8c..57e2ccc 100644
@@ -72,6 +72,12 @@ config REGULATOR_USERSPACE_CONSUMER
 
           If unsure, say no.
 
+config REGULATOR_GPIO
+	tristate "gpio regulator support"
+	help
+	  This driver provides support for regulators that can be
+	  controlled by setting gpios.
+
 config REGULATOR_BQ24022
 	tristate "TI bq24022 Dual Input 1-Cell Li-Ion Charger IC"
 	help
drivers/regulator/Makefile +1 -0
index 5a8f4ee..44dcac3 100644
@@ -9,6 +9,7 @@ obj-$(CONFIG_REGULATOR_SWITCHED_VOLTAGE) += switch.o
 obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
 obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
 
+obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
 obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
 obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
 obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
drivers/regulator/gpio-regulator.c new file +363 -0

363 lines not on this page · raw message

include/linux/regulator/gpio-regulator.h new file +84 -0

84 lines not on this page · raw message

Signature · 1 line
1.7.5.4