diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-01 18:06:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-01 18:06:20 -0400 |
commit | f3c3f0670501fee130f22193369249deea8cc630 (patch) | |
tree | 27ae58e4f338d571be93a7557ae7de48de10a947 | |
parent | c18ae42aa5b3473c00f51b6937d0c00bdb6ce2d2 (diff) | |
parent | 0151546fb34e92494acd65ed84a603c2a4a90168 (diff) |
Merge branch 'for-linus' of git://opensource.wolfsonmicro.com/regulator
* 'for-linus' of git://opensource.wolfsonmicro.com/regulator: (22 commits)
regulator: Constify constraints name
regulator: Fix possible nullpointer dereference in regulator_enable()
regulator: gpio-regulator add dependency on GENERIC_GPIO
regulator: Add module.h include to gpio-regulator
regulator: Add driver for gpio-controlled regulators
regulator: remove duplicate REG_CTRL2 defines in tps65023
regulator: Clarify documentation for regulator-regulator supplies
regulator: Fix some bitrot in the machine driver documentation
regulator: tps65023: Added support for the similiar TPS65020 chip
regulator: tps65023: Setting correct core regulator for tps65021
regulator: tps65023: Set missing bit for update core-voltage
regulator: tps65023: Fixes i2c configuration issues
regulator: Add debugfs file showing the supply map table
regulator: tps6586x: add SMx slew rate setting
regulator: tps65023: Fixes i2c configuration issues
regulator: tps6507x: Remove num_voltages array
regulator: max8952: removed unused mutex.
regulator: fix regulator/consumer.h kernel-doc warning
regulator: Ensure enough enable time for max8649
regulator: 88pm8607: Fix off-by-one value range checking in the case of no id is matched
...
-rw-r--r-- | Documentation/power/regulator/machine.txt | 19 | ||||
-rw-r--r-- | drivers/regulator/88pm8607.c | 2 | ||||
-rw-r--r-- | drivers/regulator/Kconfig | 10 | ||||
-rw-r--r-- | drivers/regulator/Makefile | 1 | ||||
-rw-r--r-- | drivers/regulator/aat2870-regulator.c | 1 | ||||
-rw-r--r-- | drivers/regulator/core.c | 43 | ||||
-rw-r--r-- | drivers/regulator/gpio-regulator.c | 358 | ||||
-rw-r--r-- | drivers/regulator/max8649.c | 2 | ||||
-rw-r--r-- | drivers/regulator/max8952.c | 3 | ||||
-rw-r--r-- | drivers/regulator/tps65023-regulator.c | 183 | ||||
-rw-r--r-- | drivers/regulator/tps6507x-regulator.c | 8 | ||||
-rw-r--r-- | drivers/regulator/tps6586x-regulator.c | 32 | ||||
-rw-r--r-- | drivers/regulator/tps65912-regulator.c | 2 | ||||
-rw-r--r-- | include/linux/mfd/tps6586x.h | 16 | ||||
-rw-r--r-- | include/linux/regulator/gpio-regulator.h | 87 | ||||
-rw-r--r-- | include/linux/regulator/machine.h | 2 |
16 files changed, 721 insertions, 48 deletions
diff --git a/Documentation/power/regulator/machine.txt b/Documentation/power/regulator/machine.txt index b42419b52e44..ce63af0a8e35 100644 --- a/Documentation/power/regulator/machine.txt +++ b/Documentation/power/regulator/machine.txt | |||
@@ -16,7 +16,7 @@ initialisation code by creating a struct regulator_consumer_supply for | |||
16 | each regulator. | 16 | each regulator. |
17 | 17 | ||
18 | struct regulator_consumer_supply { | 18 | struct regulator_consumer_supply { |
19 | struct device *dev; /* consumer */ | 19 | const char *dev_name; /* consumer dev_name() */ |
20 | const char *supply; /* consumer supply - e.g. "vcc" */ | 20 | const char *supply; /* consumer supply - e.g. "vcc" */ |
21 | }; | 21 | }; |
22 | 22 | ||
@@ -24,13 +24,13 @@ e.g. for the machine above | |||
24 | 24 | ||
25 | static struct regulator_consumer_supply regulator1_consumers[] = { | 25 | static struct regulator_consumer_supply regulator1_consumers[] = { |
26 | { | 26 | { |
27 | .dev = &platform_consumerB_device.dev, | 27 | .dev_name = "dev_name(consumer B)", |
28 | .supply = "Vcc", | 28 | .supply = "Vcc", |
29 | },}; | 29 | },}; |
30 | 30 | ||
31 | static struct regulator_consumer_supply regulator2_consumers[] = { | 31 | static struct regulator_consumer_supply regulator2_consumers[] = { |
32 | { | 32 | { |
33 | .dev = &platform_consumerA_device.dev, | 33 | .dev = "dev_name(consumer A"), |
34 | .supply = "Vcc", | 34 | .supply = "Vcc", |
35 | },}; | 35 | },}; |
36 | 36 | ||
@@ -43,6 +43,7 @@ to their supply regulator :- | |||
43 | 43 | ||
44 | static struct regulator_init_data regulator1_data = { | 44 | static struct regulator_init_data regulator1_data = { |
45 | .constraints = { | 45 | .constraints = { |
46 | .name = "Regulator-1", | ||
46 | .min_uV = 3300000, | 47 | .min_uV = 3300000, |
47 | .max_uV = 3300000, | 48 | .max_uV = 3300000, |
48 | .valid_modes_mask = REGULATOR_MODE_NORMAL, | 49 | .valid_modes_mask = REGULATOR_MODE_NORMAL, |
@@ -51,13 +52,19 @@ static struct regulator_init_data regulator1_data = { | |||
51 | .consumer_supplies = regulator1_consumers, | 52 | .consumer_supplies = regulator1_consumers, |
52 | }; | 53 | }; |
53 | 54 | ||
55 | The name field should be set to something that is usefully descriptive | ||
56 | for the board for configuration of supplies for other regulators and | ||
57 | for use in logging and other diagnostic output. Normally the name | ||
58 | used for the supply rail in the schematic is a good choice. If no | ||
59 | name is provided then the subsystem will choose one. | ||
60 | |||
54 | Regulator-1 supplies power to Regulator-2. This relationship must be registered | 61 | Regulator-1 supplies power to Regulator-2. This relationship must be registered |
55 | with the core so that Regulator-1 is also enabled when Consumer A enables its | 62 | with the core so that Regulator-1 is also enabled when Consumer A enables its |
56 | supply (Regulator-2). The supply regulator is set by the supply_regulator | 63 | supply (Regulator-2). The supply regulator is set by the supply_regulator |
57 | field below:- | 64 | field below and co:- |
58 | 65 | ||
59 | static struct regulator_init_data regulator2_data = { | 66 | static struct regulator_init_data regulator2_data = { |
60 | .supply_regulator = "regulator_name", | 67 | .supply_regulator = "Regulator-1", |
61 | .constraints = { | 68 | .constraints = { |
62 | .min_uV = 1800000, | 69 | .min_uV = 1800000, |
63 | .max_uV = 2000000, | 70 | .max_uV = 2000000, |
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index d63fddb0fbb0..e821b2159b4b 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c | |||
@@ -412,7 +412,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev) | |||
412 | if (info->desc.id == res->start) | 412 | if (info->desc.id == res->start) |
413 | break; | 413 | break; |
414 | } | 414 | } |
415 | if ((i < 0) || (i > PM8607_ID_RG_MAX)) { | 415 | if (i == ARRAY_SIZE(pm8607_regulator_info)) { |
416 | dev_err(&pdev->dev, "Failed to find regulator %llu\n", | 416 | dev_err(&pdev->dev, "Failed to find regulator %llu\n", |
417 | (unsigned long long)res->start); | 417 | (unsigned long long)res->start); |
418 | return -EINVAL; | 418 | return -EINVAL; |
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index c7fd2c0e3f2b..9713b1b860cb 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -64,6 +64,16 @@ config REGULATOR_USERSPACE_CONSUMER | |||
64 | 64 | ||
65 | If unsure, say no. | 65 | If unsure, say no. |
66 | 66 | ||
67 | config REGULATOR_GPIO | ||
68 | tristate "GPIO regulator support" | ||
69 | depends on GENERIC_GPIO | ||
70 | help | ||
71 | This driver provides support for regulators that can be | ||
72 | controlled via gpios. | ||
73 | It is capable of supporting current and voltage regulators | ||
74 | and the platform has to provide a mapping of GPIO-states | ||
75 | to target volts/amps. | ||
76 | |||
67 | config REGULATOR_BQ24022 | 77 | config REGULATOR_BQ24022 |
68 | tristate "TI bq24022 Dual Input 1-Cell Li-Ion Charger IC" | 78 | tristate "TI bq24022 Dual Input 1-Cell Li-Ion Charger IC" |
69 | help | 79 | help |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 040d5aa63535..93a6318f5328 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o | |||
8 | obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o | 8 | obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o |
9 | obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o | 9 | obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o |
10 | 10 | ||
11 | obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o | ||
11 | obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o | 12 | obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o |
12 | obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o | 13 | obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o |
13 | obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o | 14 | obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o |
diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index cd4104542f0d..5abeb3ac3e8d 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
25 | #include <linux/module.h> | ||
25 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
26 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
27 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 9e4c123c4028..67fa2a3297ad 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -1425,7 +1425,7 @@ int regulator_enable(struct regulator *regulator) | |||
1425 | ret = _regulator_enable(rdev); | 1425 | ret = _regulator_enable(rdev); |
1426 | mutex_unlock(&rdev->mutex); | 1426 | mutex_unlock(&rdev->mutex); |
1427 | 1427 | ||
1428 | if (ret != 0) | 1428 | if (ret != 0 && rdev->supply) |
1429 | regulator_disable(rdev->supply); | 1429 | regulator_disable(rdev->supply); |
1430 | 1430 | ||
1431 | return ret; | 1431 | return ret; |
@@ -2971,6 +2971,43 @@ void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) | |||
2971 | } | 2971 | } |
2972 | EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); | 2972 | EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); |
2973 | 2973 | ||
2974 | #ifdef CONFIG_DEBUG_FS | ||
2975 | static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, | ||
2976 | size_t count, loff_t *ppos) | ||
2977 | { | ||
2978 | char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
2979 | ssize_t len, ret = 0; | ||
2980 | struct regulator_map *map; | ||
2981 | |||
2982 | if (!buf) | ||
2983 | return -ENOMEM; | ||
2984 | |||
2985 | list_for_each_entry(map, ®ulator_map_list, list) { | ||
2986 | len = snprintf(buf + ret, PAGE_SIZE - ret, | ||
2987 | "%s -> %s.%s\n", | ||
2988 | rdev_get_name(map->regulator), map->dev_name, | ||
2989 | map->supply); | ||
2990 | if (len >= 0) | ||
2991 | ret += len; | ||
2992 | if (ret > PAGE_SIZE) { | ||
2993 | ret = PAGE_SIZE; | ||
2994 | break; | ||
2995 | } | ||
2996 | } | ||
2997 | |||
2998 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); | ||
2999 | |||
3000 | kfree(buf); | ||
3001 | |||
3002 | return ret; | ||
3003 | } | ||
3004 | |||
3005 | static const struct file_operations supply_map_fops = { | ||
3006 | .read = supply_map_read_file, | ||
3007 | .llseek = default_llseek, | ||
3008 | }; | ||
3009 | #endif | ||
3010 | |||
2974 | static int __init regulator_init(void) | 3011 | static int __init regulator_init(void) |
2975 | { | 3012 | { |
2976 | int ret; | 3013 | int ret; |
@@ -2983,6 +3020,10 @@ static int __init regulator_init(void) | |||
2983 | pr_warn("regulator: Failed to create debugfs directory\n"); | 3020 | pr_warn("regulator: Failed to create debugfs directory\n"); |
2984 | debugfs_root = NULL; | 3021 | debugfs_root = NULL; |
2985 | } | 3022 | } |
3023 | |||
3024 | if (IS_ERR(debugfs_create_file("supply_map", 0444, debugfs_root, | ||
3025 | NULL, &supply_map_fops))) | ||
3026 | pr_warn("regulator: Failed to create supplies debugfs\n"); | ||
2986 | #endif | 3027 | #endif |
2987 | 3028 | ||
2988 | regulator_dummy_init(); | 3029 | regulator_dummy_init(); |
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c new file mode 100644 index 000000000000..f0acf52498bd --- /dev/null +++ b/drivers/regulator/gpio-regulator.c | |||
@@ -0,0 +1,358 @@ | |||
1 | /* | ||
2 | * gpio-regulator.c | ||
3 | * | ||
4 | * Copyright 2011 Heiko Stuebner <heiko@sntech.de> | ||
5 | * | ||
6 | * based on fixed.c | ||
7 | * | ||
8 | * Copyright 2008 Wolfson Microelectronics PLC. | ||
9 | * | ||
10 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
11 | * | ||
12 | * Copyright (c) 2009 Nokia Corporation | ||
13 | * Roger Quadros <ext-roger.quadros@nokia.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License as | ||
17 | * published by the Free Software Foundation; either version 2 of the | ||
18 | * License, or (at your option) any later version. | ||
19 | * | ||
20 | * This is useful for systems with mixed controllable and | ||
21 | * non-controllable regulators, as well as for allowing testing on | ||
22 | * systems with no controllable regulators. | ||
23 | */ | ||
24 | |||
25 | #include <linux/err.h> | ||
26 | #include <linux/mutex.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/regulator/driver.h> | ||
30 | #include <linux/regulator/machine.h> | ||
31 | #include <linux/regulator/gpio-regulator.h> | ||
32 | #include <linux/gpio.h> | ||
33 | #include <linux/delay.h> | ||
34 | #include <linux/slab.h> | ||
35 | |||
36 | struct gpio_regulator_data { | ||
37 | struct regulator_desc desc; | ||
38 | struct regulator_dev *dev; | ||
39 | |||
40 | int enable_gpio; | ||
41 | bool enable_high; | ||
42 | bool is_enabled; | ||
43 | unsigned startup_delay; | ||
44 | |||
45 | struct gpio *gpios; | ||
46 | int nr_gpios; | ||
47 | |||
48 | struct gpio_regulator_state *states; | ||
49 | int nr_states; | ||
50 | |||
51 | int state; | ||
52 | }; | ||
53 | |||
54 | static int gpio_regulator_is_enabled(struct regulator_dev *dev) | ||
55 | { | ||
56 | struct gpio_regulator_data *data = rdev_get_drvdata(dev); | ||
57 | |||
58 | return data->is_enabled; | ||
59 | } | ||
60 | |||
61 | static int gpio_regulator_enable(struct regulator_dev *dev) | ||
62 | { | ||
63 | struct gpio_regulator_data *data = rdev_get_drvdata(dev); | ||
64 | |||
65 | if (gpio_is_valid(data->enable_gpio)) { | ||
66 | gpio_set_value_cansleep(data->enable_gpio, data->enable_high); | ||
67 | data->is_enabled = true; | ||
68 | } | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int gpio_regulator_disable(struct regulator_dev *dev) | ||
74 | { | ||
75 | struct gpio_regulator_data *data = rdev_get_drvdata(dev); | ||
76 | |||
77 | if (gpio_is_valid(data->enable_gpio)) { | ||
78 | gpio_set_value_cansleep(data->enable_gpio, !data->enable_high); | ||
79 | data->is_enabled = false; | ||
80 | } | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static int gpio_regulator_enable_time(struct regulator_dev *dev) | ||
86 | { | ||
87 | struct gpio_regulator_data *data = rdev_get_drvdata(dev); | ||
88 | |||
89 | return data->startup_delay; | ||
90 | } | ||
91 | |||
92 | static int gpio_regulator_get_value(struct regulator_dev *dev) | ||
93 | { | ||
94 | struct gpio_regulator_data *data = rdev_get_drvdata(dev); | ||
95 | int ptr; | ||
96 | |||
97 | for (ptr = 0; ptr < data->nr_states; ptr++) | ||
98 | if (data->states[ptr].gpios == data->state) | ||
99 | return data->states[ptr].value; | ||
100 | |||
101 | return -EINVAL; | ||
102 | } | ||
103 | |||
104 | static int gpio_regulator_set_value(struct regulator_dev *dev, | ||
105 | int min, int max) | ||
106 | { | ||
107 | struct gpio_regulator_data *data = rdev_get_drvdata(dev); | ||
108 | int ptr, target, state; | ||
109 | |||
110 | target = -1; | ||
111 | for (ptr = 0; ptr < data->nr_states; ptr++) | ||
112 | if (data->states[ptr].value >= min && | ||
113 | data->states[ptr].value <= max) | ||
114 | target = data->states[ptr].gpios; | ||
115 | |||
116 | if (target < 0) | ||
117 | return -EINVAL; | ||
118 | |||
119 | for (ptr = 0; ptr < data->nr_gpios; ptr++) { | ||
120 | state = (target & (1 << ptr)) >> ptr; | ||
121 | gpio_set_value(data->gpios[ptr].gpio, state); | ||
122 | } | ||
123 | data->state = target; | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static int gpio_regulator_set_voltage(struct regulator_dev *dev, | ||
129 | int min_uV, int max_uV, | ||
130 | unsigned *selector) | ||
131 | { | ||
132 | return gpio_regulator_set_value(dev, min_uV, max_uV); | ||
133 | } | ||
134 | |||
135 | static int gpio_regulator_list_voltage(struct regulator_dev *dev, | ||
136 | unsigned selector) | ||
137 | { | ||
138 | struct gpio_regulator_data *data = rdev_get_drvdata(dev); | ||
139 | |||
140 | if (selector >= data->nr_states) | ||
141 | return -EINVAL; | ||
142 | |||
143 | return data->states[selector].value; | ||
144 | } | ||
145 | |||
146 | static int gpio_regulator_set_current_limit(struct regulator_dev *dev, | ||
147 | int min_uA, int max_uA) | ||
148 | { | ||
149 | return gpio_regulator_set_value(dev, min_uA, max_uA); | ||
150 | } | ||
151 | |||
152 | static struct regulator_ops gpio_regulator_voltage_ops = { | ||
153 | .is_enabled = gpio_regulator_is_enabled, | ||
154 | .enable = gpio_regulator_enable, | ||
155 | .disable = gpio_regulator_disable, | ||
156 | .enable_time = gpio_regulator_enable_time, | ||
157 | .get_voltage = gpio_regulator_get_value, | ||
158 | .set_voltage = gpio_regulator_set_voltage, | ||
159 | .list_voltage = gpio_regulator_list_voltage, | ||
160 | }; | ||
161 | |||
162 | static struct regulator_ops gpio_regulator_current_ops = { | ||
163 | .is_enabled = gpio_regulator_is_enabled, | ||
164 | .enable = gpio_regulator_enable, | ||
165 | .disable = gpio_regulator_disable, | ||
166 | .enable_time = gpio_regulator_enable_time, | ||
167 | .get_current_limit = gpio_regulator_get_value, | ||
168 | .set_current_limit = gpio_regulator_set_current_limit, | ||
169 | }; | ||
170 | |||
171 | static int __devinit gpio_regulator_probe(struct platform_device *pdev) | ||
172 | { | ||
173 | struct gpio_regulator_config *config = pdev->dev.platform_data; | ||
174 | struct gpio_regulator_data *drvdata; | ||
175 | int ptr, ret, state; | ||
176 | |||
177 | drvdata = kzalloc(sizeof(struct gpio_regulator_data), GFP_KERNEL); | ||
178 | if (drvdata == NULL) { | ||
179 | dev_err(&pdev->dev, "Failed to allocate device data\n"); | ||
180 | return -ENOMEM; | ||
181 | } | ||
182 | |||
183 | drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL); | ||
184 | if (drvdata->desc.name == NULL) { | ||
185 | dev_err(&pdev->dev, "Failed to allocate supply name\n"); | ||
186 | ret = -ENOMEM; | ||
187 | goto err; | ||
188 | } | ||
189 | |||
190 | drvdata->gpios = kmemdup(config->gpios, | ||
191 | config->nr_gpios * sizeof(struct gpio), | ||
192 | GFP_KERNEL); | ||
193 | if (drvdata->gpios == NULL) { | ||
194 | dev_err(&pdev->dev, "Failed to allocate gpio data\n"); | ||
195 | ret = -ENOMEM; | ||
196 | goto err_name; | ||
197 | } | ||
198 | |||
199 | drvdata->states = kmemdup(config->states, | ||
200 | config->nr_states * | ||
201 | sizeof(struct gpio_regulator_state), | ||
202 | GFP_KERNEL); | ||
203 | if (drvdata->states == NULL) { | ||
204 | dev_err(&pdev->dev, "Failed to allocate state data\n"); | ||
205 | ret = -ENOMEM; | ||
206 | goto err_memgpio; | ||
207 | } | ||
208 | drvdata->nr_states = config->nr_states; | ||
209 | |||
210 | drvdata->desc.owner = THIS_MODULE; | ||
211 | |||
212 | /* handle regulator type*/ | ||
213 | switch (config->type) { | ||
214 | case REGULATOR_VOLTAGE: | ||
215 | drvdata->desc.type = REGULATOR_VOLTAGE; | ||
216 | drvdata->desc.ops = &gpio_regulator_voltage_ops; | ||
217 | drvdata->desc.n_voltages = config->nr_states; | ||
218 | break; | ||
219 | case REGULATOR_CURRENT: | ||
220 | drvdata->desc.type = REGULATOR_CURRENT; | ||
221 | drvdata->desc.ops = &gpio_regulator_current_ops; | ||
222 | break; | ||
223 | default: | ||
224 | dev_err(&pdev->dev, "No regulator type set\n"); | ||
225 | ret = -EINVAL; | ||
226 | goto err_memgpio; | ||
227 | break; | ||
228 | } | ||
229 | |||
230 | drvdata->enable_gpio = config->enable_gpio; | ||
231 | drvdata->startup_delay = config->startup_delay; | ||
232 | |||
233 | if (gpio_is_valid(config->enable_gpio)) { | ||
234 | drvdata->enable_high = config->enable_high; | ||
235 | |||
236 | ret = gpio_request(config->enable_gpio, config->supply_name); | ||
237 | if (ret) { | ||
238 | dev_err(&pdev->dev, | ||
239 | "Could not obtain regulator enable GPIO %d: %d\n", | ||
240 | config->enable_gpio, ret); | ||
241 | goto err_memstate; | ||
242 | } | ||
243 | |||
244 | /* set output direction without changing state | ||
245 | * to prevent glitch | ||
246 | */ | ||
247 | if (config->enabled_at_boot) { | ||
248 | drvdata->is_enabled = true; | ||
249 | ret = gpio_direction_output(config->enable_gpio, | ||
250 | config->enable_high); | ||
251 | } else { | ||
252 | drvdata->is_enabled = false; | ||
253 | ret = gpio_direction_output(config->enable_gpio, | ||
254 | !config->enable_high); | ||
255 | } | ||
256 | |||
257 | if (ret) { | ||
258 | dev_err(&pdev->dev, | ||
259 | "Could not configure regulator enable GPIO %d direction: %d\n", | ||
260 | config->enable_gpio, ret); | ||
261 | goto err_enablegpio; | ||
262 | } | ||
263 | } else { | ||
264 | /* Regulator without GPIO control is considered | ||
265 | * always enabled | ||
266 | */ | ||
267 | drvdata->is_enabled = true; | ||
268 | } | ||
269 | |||
270 | drvdata->nr_gpios = config->nr_gpios; | ||
271 | ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios); | ||
272 | if (ret) { | ||
273 | dev_err(&pdev->dev, | ||
274 | "Could not obtain regulator setting GPIOs: %d\n", ret); | ||
275 | goto err_enablegpio; | ||
276 | } | ||
277 | |||
278 | /* build initial state from gpio init data. */ | ||
279 | state = 0; | ||
280 | for (ptr = 0; ptr < drvdata->nr_gpios; ptr++) { | ||
281 | if (config->gpios[ptr].flags & GPIOF_OUT_INIT_HIGH) | ||
282 | state |= (1 << ptr); | ||
283 | } | ||
284 | drvdata->state = state; | ||
285 | |||
286 | drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, | ||
287 | config->init_data, drvdata); | ||
288 | if (IS_ERR(drvdata->dev)) { | ||
289 | ret = PTR_ERR(drvdata->dev); | ||
290 | dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); | ||
291 | goto err_stategpio; | ||
292 | } | ||
293 | |||
294 | platform_set_drvdata(pdev, drvdata); | ||
295 | |||
296 | return 0; | ||
297 | |||
298 | err_stategpio: | ||
299 | gpio_free_array(drvdata->gpios, drvdata->nr_gpios); | ||
300 | err_enablegpio: | ||
301 | if (gpio_is_valid(config->enable_gpio)) | ||
302 | gpio_free(config->enable_gpio); | ||
303 | err_memstate: | ||
304 | kfree(drvdata->states); | ||
305 | err_memgpio: | ||
306 | kfree(drvdata->gpios); | ||
307 | err_name: | ||
308 | kfree(drvdata->desc.name); | ||
309 | err: | ||
310 | kfree(drvdata); | ||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | static int __devexit gpio_regulator_remove(struct platform_device *pdev) | ||
315 | { | ||
316 | struct gpio_regulator_data *drvdata = platform_get_drvdata(pdev); | ||
317 | |||
318 | regulator_unregister(drvdata->dev); | ||
319 | |||
320 | gpio_free_array(drvdata->gpios, drvdata->nr_gpios); | ||
321 | |||
322 | kfree(drvdata->states); | ||
323 | kfree(drvdata->gpios); | ||
324 | |||
325 | if (gpio_is_valid(drvdata->enable_gpio)) | ||
326 | gpio_free(drvdata->enable_gpio); | ||
327 | |||
328 | kfree(drvdata->desc.name); | ||
329 | kfree(drvdata); | ||
330 | |||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | static struct platform_driver gpio_regulator_driver = { | ||
335 | .probe = gpio_regulator_probe, | ||
336 | .remove = __devexit_p(gpio_regulator_remove), | ||
337 | .driver = { | ||
338 | .name = "gpio-regulator", | ||
339 | .owner = THIS_MODULE, | ||
340 | }, | ||
341 | }; | ||
342 | |||
343 | static int __init gpio_regulator_init(void) | ||
344 | { | ||
345 | return platform_driver_register(&gpio_regulator_driver); | ||
346 | } | ||
347 | subsys_initcall(gpio_regulator_init); | ||
348 | |||
349 | static void __exit gpio_regulator_exit(void) | ||
350 | { | ||
351 | platform_driver_unregister(&gpio_regulator_driver); | ||
352 | } | ||
353 | module_exit(gpio_regulator_exit); | ||
354 | |||
355 | MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); | ||
356 | MODULE_DESCRIPTION("gpio voltage regulator"); | ||
357 | MODULE_LICENSE("GPL"); | ||
358 | MODULE_ALIAS("platform:gpio-regulator"); | ||
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 30eb9e54f7ec..1062cf9f02dc 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c | |||
@@ -221,7 +221,7 @@ static int max8649_enable_time(struct regulator_dev *rdev) | |||
221 | ret = (ret & MAX8649_RAMP_MASK) >> 5; | 221 | ret = (ret & MAX8649_RAMP_MASK) >> 5; |
222 | rate = (32 * 1000) >> ret; /* uV/uS */ | 222 | rate = (32 * 1000) >> ret; /* uV/uS */ |
223 | 223 | ||
224 | return (voltage / rate); | 224 | return DIV_ROUND_UP(voltage, rate); |
225 | } | 225 | } |
226 | 226 | ||
227 | static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode) | 227 | static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode) |
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 486ed8141fcd..3883d85c5b88 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/regulator/driver.h> | 27 | #include <linux/regulator/driver.h> |
28 | #include <linux/regulator/max8952.h> | 28 | #include <linux/regulator/max8952.h> |
29 | #include <linux/mutex.h> | ||
30 | #include <linux/gpio.h> | 29 | #include <linux/gpio.h> |
31 | #include <linux/io.h> | 30 | #include <linux/io.h> |
32 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
@@ -47,7 +46,6 @@ enum { | |||
47 | struct max8952_data { | 46 | struct max8952_data { |
48 | struct i2c_client *client; | 47 | struct i2c_client *client; |
49 | struct device *dev; | 48 | struct device *dev; |
50 | struct mutex mutex; | ||
51 | struct max8952_platform_data *pdata; | 49 | struct max8952_platform_data *pdata; |
52 | struct regulator_dev *rdev; | 50 | struct regulator_dev *rdev; |
53 | 51 | ||
@@ -208,7 +206,6 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, | |||
208 | max8952->client = client; | 206 | max8952->client = client; |
209 | max8952->dev = &client->dev; | 207 | max8952->dev = &client->dev; |
210 | max8952->pdata = pdata; | 208 | max8952->pdata = pdata; |
211 | mutex_init(&max8952->mutex); | ||
212 | 209 | ||
213 | max8952->rdev = regulator_register(®ulator, max8952->dev, | 210 | max8952->rdev = regulator_register(®ulator, max8952->dev, |
214 | &pdata->reg_data, max8952); | 211 | &pdata->reg_data, max8952); |
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 701a5900f83f..9fb4c7b81753 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c | |||
@@ -63,6 +63,13 @@ | |||
63 | #define TPS65023_REG_CTRL_LDO2_EN BIT(2) | 63 | #define TPS65023_REG_CTRL_LDO2_EN BIT(2) |
64 | #define TPS65023_REG_CTRL_LDO1_EN BIT(1) | 64 | #define TPS65023_REG_CTRL_LDO1_EN BIT(1) |
65 | 65 | ||
66 | /* REG_CTRL2 bitfields */ | ||
67 | #define TPS65023_REG_CTRL2_GO BIT(7) | ||
68 | #define TPS65023_REG_CTRL2_CORE_ADJ BIT(6) | ||
69 | #define TPS65023_REG_CTRL2_DCDC2 BIT(2) | ||
70 | #define TPS65023_REG_CTRL2_DCDC1 BIT(1) | ||
71 | #define TPS65023_REG_CTRL2_DCDC3 BIT(0) | ||
72 | |||
66 | /* LDO_CTRL bitfields */ | 73 | /* LDO_CTRL bitfields */ |
67 | #define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id) ((ldo_id)*4) | 74 | #define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id) ((ldo_id)*4) |
68 | #define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id) (0xF0 >> ((ldo_id)*4)) | 75 | #define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id) (0xF0 >> ((ldo_id)*4)) |
@@ -85,7 +92,7 @@ | |||
85 | #define TPS65023_MAX_REG_ID TPS65023_LDO_2 | 92 | #define TPS65023_MAX_REG_ID TPS65023_LDO_2 |
86 | 93 | ||
87 | /* Supported voltage values for regulators */ | 94 | /* Supported voltage values for regulators */ |
88 | static const u16 VDCDC1_VSEL_table[] = { | 95 | static const u16 VCORE_VSEL_table[] = { |
89 | 800, 825, 850, 875, | 96 | 800, 825, 850, 875, |
90 | 900, 925, 950, 975, | 97 | 900, 925, 950, 975, |
91 | 1000, 1025, 1050, 1075, | 98 | 1000, 1025, 1050, 1075, |
@@ -96,20 +103,29 @@ static const u16 VDCDC1_VSEL_table[] = { | |||
96 | 1500, 1525, 1550, 1600, | 103 | 1500, 1525, 1550, 1600, |
97 | }; | 104 | }; |
98 | 105 | ||
99 | static const u16 LDO1_VSEL_table[] = { | 106 | /* Supported voltage values for LDO regulators for tps65020 */ |
107 | static const u16 TPS65020_LDO1_VSEL_table[] = { | ||
108 | 1000, 1050, 1100, 1300, | ||
109 | 1800, 2500, 3000, 3300, | ||
110 | }; | ||
111 | |||
112 | static const u16 TPS65020_LDO2_VSEL_table[] = { | ||
113 | 1000, 1050, 1100, 1300, | ||
114 | 1800, 2500, 3000, 3300, | ||
115 | }; | ||
116 | |||
117 | /* Supported voltage values for LDO regulators | ||
118 | * for tps65021 and tps65023 */ | ||
119 | static const u16 TPS65023_LDO1_VSEL_table[] = { | ||
100 | 1000, 1100, 1300, 1800, | 120 | 1000, 1100, 1300, 1800, |
101 | 2200, 2600, 2800, 3150, | 121 | 2200, 2600, 2800, 3150, |
102 | }; | 122 | }; |
103 | 123 | ||
104 | static const u16 LDO2_VSEL_table[] = { | 124 | static const u16 TPS65023_LDO2_VSEL_table[] = { |
105 | 1050, 1200, 1300, 1800, | 125 | 1050, 1200, 1300, 1800, |
106 | 2500, 2800, 3000, 3300, | 126 | 2500, 2800, 3000, 3300, |
107 | }; | 127 | }; |
108 | 128 | ||
109 | static unsigned int num_voltages[] = {ARRAY_SIZE(VDCDC1_VSEL_table), | ||
110 | 0, 0, ARRAY_SIZE(LDO1_VSEL_table), | ||
111 | ARRAY_SIZE(LDO2_VSEL_table)}; | ||
112 | |||
113 | /* Regulator specific details */ | 129 | /* Regulator specific details */ |
114 | struct tps_info { | 130 | struct tps_info { |
115 | const char *name; | 131 | const char *name; |
@@ -127,6 +143,13 @@ struct tps_pmic { | |||
127 | struct regulator_dev *rdev[TPS65023_NUM_REGULATOR]; | 143 | struct regulator_dev *rdev[TPS65023_NUM_REGULATOR]; |
128 | const struct tps_info *info[TPS65023_NUM_REGULATOR]; | 144 | const struct tps_info *info[TPS65023_NUM_REGULATOR]; |
129 | struct regmap *regmap; | 145 | struct regmap *regmap; |
146 | u8 core_regulator; | ||
147 | }; | ||
148 | |||
149 | /* Struct passed as driver data */ | ||
150 | struct tps_driver_data { | ||
151 | const struct tps_info *info; | ||
152 | u8 core_regulator; | ||
130 | }; | 153 | }; |
131 | 154 | ||
132 | static int tps_65023_set_bits(struct tps_pmic *tps, u8 reg, u8 mask) | 155 | static int tps_65023_set_bits(struct tps_pmic *tps, u8 reg, u8 mask) |
@@ -253,7 +276,7 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev) | |||
253 | if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) | 276 | if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) |
254 | return -EINVAL; | 277 | return -EINVAL; |
255 | 278 | ||
256 | if (dcdc == TPS65023_DCDC_1) { | 279 | if (dcdc == tps->core_regulator) { |
257 | data = tps_65023_reg_read(tps, TPS65023_REG_DEF_CORE); | 280 | data = tps_65023_reg_read(tps, TPS65023_REG_DEF_CORE); |
258 | if (data < 0) | 281 | if (data < 0) |
259 | return data; | 282 | return data; |
@@ -270,10 +293,10 @@ static int tps65023_dcdc_set_voltage(struct regulator_dev *dev, | |||
270 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 293 | struct tps_pmic *tps = rdev_get_drvdata(dev); |
271 | int dcdc = rdev_get_id(dev); | 294 | int dcdc = rdev_get_id(dev); |
272 | int vsel; | 295 | int vsel; |
296 | int ret; | ||
273 | 297 | ||
274 | if (dcdc != TPS65023_DCDC_1) | 298 | if (dcdc != tps->core_regulator) |
275 | return -EINVAL; | 299 | return -EINVAL; |
276 | |||
277 | if (min_uV < tps->info[dcdc]->min_uV | 300 | if (min_uV < tps->info[dcdc]->min_uV |
278 | || min_uV > tps->info[dcdc]->max_uV) | 301 | || min_uV > tps->info[dcdc]->max_uV) |
279 | return -EINVAL; | 302 | return -EINVAL; |
@@ -292,11 +315,21 @@ static int tps65023_dcdc_set_voltage(struct regulator_dev *dev, | |||
292 | 315 | ||
293 | *selector = vsel; | 316 | *selector = vsel; |
294 | 317 | ||
295 | /* write to the register in case we found a match */ | ||
296 | if (vsel == tps->info[dcdc]->table_len) | 318 | if (vsel == tps->info[dcdc]->table_len) |
297 | return -EINVAL; | 319 | goto failed; |
298 | else | 320 | |
299 | return tps_65023_reg_write(tps, TPS65023_REG_DEF_CORE, vsel); | 321 | ret = tps_65023_reg_write(tps, TPS65023_REG_DEF_CORE, vsel); |
322 | |||
323 | /* Tell the chip that we have changed the value in DEFCORE | ||
324 | * and its time to update the core voltage | ||
325 | */ | ||
326 | tps_65023_set_bits(tps, TPS65023_REG_CON_CTRL2, | ||
327 | TPS65023_REG_CTRL2_GO); | ||
328 | |||
329 | return ret; | ||
330 | |||
331 | failed: | ||
332 | return -EINVAL; | ||
300 | } | 333 | } |
301 | 334 | ||
302 | static int tps65023_ldo_get_voltage(struct regulator_dev *dev) | 335 | static int tps65023_ldo_get_voltage(struct regulator_dev *dev) |
@@ -362,7 +395,7 @@ static int tps65023_dcdc_list_voltage(struct regulator_dev *dev, | |||
362 | if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) | 395 | if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) |
363 | return -EINVAL; | 396 | return -EINVAL; |
364 | 397 | ||
365 | if (dcdc == TPS65023_DCDC_1) { | 398 | if (dcdc == tps->core_regulator) { |
366 | if (selector >= tps->info[dcdc]->table_len) | 399 | if (selector >= tps->info[dcdc]->table_len) |
367 | return -EINVAL; | 400 | return -EINVAL; |
368 | else | 401 | else |
@@ -414,7 +447,8 @@ static struct regmap_config tps65023_regmap_config = { | |||
414 | static int __devinit tps_65023_probe(struct i2c_client *client, | 447 | static int __devinit tps_65023_probe(struct i2c_client *client, |
415 | const struct i2c_device_id *id) | 448 | const struct i2c_device_id *id) |
416 | { | 449 | { |
417 | const struct tps_info *info = (void *)id->driver_data; | 450 | const struct tps_driver_data *drv_data = (void *)id->driver_data; |
451 | const struct tps_info *info = drv_data->info; | ||
418 | struct regulator_init_data *init_data; | 452 | struct regulator_init_data *init_data; |
419 | struct regulator_dev *rdev; | 453 | struct regulator_dev *rdev; |
420 | struct tps_pmic *tps; | 454 | struct tps_pmic *tps; |
@@ -446,6 +480,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client, | |||
446 | 480 | ||
447 | /* common for all regulators */ | 481 | /* common for all regulators */ |
448 | tps->client = client; | 482 | tps->client = client; |
483 | tps->core_regulator = drv_data->core_regulator; | ||
449 | 484 | ||
450 | for (i = 0; i < TPS65023_NUM_REGULATOR; i++, info++, init_data++) { | 485 | for (i = 0; i < TPS65023_NUM_REGULATOR; i++, info++, init_data++) { |
451 | /* Store regulator specific information */ | 486 | /* Store regulator specific information */ |
@@ -453,7 +488,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client, | |||
453 | 488 | ||
454 | tps->desc[i].name = info->name; | 489 | tps->desc[i].name = info->name; |
455 | tps->desc[i].id = i; | 490 | tps->desc[i].id = i; |
456 | tps->desc[i].n_voltages = num_voltages[i]; | 491 | tps->desc[i].n_voltages = info->table_len; |
457 | tps->desc[i].ops = (i > TPS65023_DCDC_3 ? | 492 | tps->desc[i].ops = (i > TPS65023_DCDC_3 ? |
458 | &tps65023_ldo_ops : &tps65023_dcdc_ops); | 493 | &tps65023_ldo_ops : &tps65023_dcdc_ops); |
459 | tps->desc[i].type = REGULATOR_VOLTAGE; | 494 | tps->desc[i].type = REGULATOR_VOLTAGE; |
@@ -475,6 +510,14 @@ static int __devinit tps_65023_probe(struct i2c_client *client, | |||
475 | 510 | ||
476 | i2c_set_clientdata(client, tps); | 511 | i2c_set_clientdata(client, tps); |
477 | 512 | ||
513 | /* Enable setting output voltage by I2C */ | ||
514 | tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2, | ||
515 | TPS65023_REG_CTRL2_CORE_ADJ); | ||
516 | |||
517 | /* Enable setting output voltage by I2C */ | ||
518 | tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2, | ||
519 | TPS65023_REG_CTRL2_CORE_ADJ); | ||
520 | |||
478 | return 0; | 521 | return 0; |
479 | 522 | ||
480 | fail: | 523 | fail: |
@@ -507,13 +550,86 @@ static int __devexit tps_65023_remove(struct i2c_client *client) | |||
507 | return 0; | 550 | return 0; |
508 | } | 551 | } |
509 | 552 | ||
553 | static const struct tps_info tps65020_regs[] = { | ||
554 | { | ||
555 | .name = "VDCDC1", | ||
556 | .min_uV = 3300000, | ||
557 | .max_uV = 3300000, | ||
558 | .fixed = 1, | ||
559 | }, | ||
560 | { | ||
561 | .name = "VDCDC2", | ||
562 | .min_uV = 1800000, | ||
563 | .max_uV = 1800000, | ||
564 | .fixed = 1, | ||
565 | }, | ||
566 | { | ||
567 | .name = "VDCDC3", | ||
568 | .min_uV = 800000, | ||
569 | .max_uV = 1600000, | ||
570 | .table_len = ARRAY_SIZE(VCORE_VSEL_table), | ||
571 | .table = VCORE_VSEL_table, | ||
572 | }, | ||
573 | |||
574 | { | ||
575 | .name = "LDO1", | ||
576 | .min_uV = 1000000, | ||
577 | .max_uV = 3150000, | ||
578 | .table_len = ARRAY_SIZE(TPS65020_LDO1_VSEL_table), | ||
579 | .table = TPS65020_LDO1_VSEL_table, | ||
580 | }, | ||
581 | { | ||
582 | .name = "LDO2", | ||
583 | .min_uV = 1050000, | ||
584 | .max_uV = 3300000, | ||
585 | .table_len = ARRAY_SIZE(TPS65020_LDO2_VSEL_table), | ||
586 | .table = TPS65020_LDO2_VSEL_table, | ||
587 | }, | ||
588 | }; | ||
589 | |||
590 | static const struct tps_info tps65021_regs[] = { | ||
591 | { | ||
592 | .name = "VDCDC1", | ||
593 | .min_uV = 3300000, | ||
594 | .max_uV = 3300000, | ||
595 | .fixed = 1, | ||
596 | }, | ||
597 | { | ||
598 | .name = "VDCDC2", | ||
599 | .min_uV = 1800000, | ||
600 | .max_uV = 1800000, | ||
601 | .fixed = 1, | ||
602 | }, | ||
603 | { | ||
604 | .name = "VDCDC3", | ||
605 | .min_uV = 800000, | ||
606 | .max_uV = 1600000, | ||
607 | .table_len = ARRAY_SIZE(VCORE_VSEL_table), | ||
608 | .table = VCORE_VSEL_table, | ||
609 | }, | ||
610 | { | ||
611 | .name = "LDO1", | ||
612 | .min_uV = 1000000, | ||
613 | .max_uV = 3150000, | ||
614 | .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table), | ||
615 | .table = TPS65023_LDO1_VSEL_table, | ||
616 | }, | ||
617 | { | ||
618 | .name = "LDO2", | ||
619 | .min_uV = 1050000, | ||
620 | .max_uV = 3300000, | ||
621 | .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table), | ||
622 | .table = TPS65023_LDO2_VSEL_table, | ||
623 | }, | ||
624 | }; | ||
625 | |||
510 | static const struct tps_info tps65023_regs[] = { | 626 | static const struct tps_info tps65023_regs[] = { |
511 | { | 627 | { |
512 | .name = "VDCDC1", | 628 | .name = "VDCDC1", |
513 | .min_uV = 800000, | 629 | .min_uV = 800000, |
514 | .max_uV = 1600000, | 630 | .max_uV = 1600000, |
515 | .table_len = ARRAY_SIZE(VDCDC1_VSEL_table), | 631 | .table_len = ARRAY_SIZE(VCORE_VSEL_table), |
516 | .table = VDCDC1_VSEL_table, | 632 | .table = VCORE_VSEL_table, |
517 | }, | 633 | }, |
518 | { | 634 | { |
519 | .name = "VDCDC2", | 635 | .name = "VDCDC2", |
@@ -531,23 +647,40 @@ static const struct tps_info tps65023_regs[] = { | |||
531 | .name = "LDO1", | 647 | .name = "LDO1", |
532 | .min_uV = 1000000, | 648 | .min_uV = 1000000, |
533 | .max_uV = 3150000, | 649 | .max_uV = 3150000, |
534 | .table_len = ARRAY_SIZE(LDO1_VSEL_table), | 650 | .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table), |
535 | .table = LDO1_VSEL_table, | 651 | .table = TPS65023_LDO1_VSEL_table, |
536 | }, | 652 | }, |
537 | { | 653 | { |
538 | .name = "LDO2", | 654 | .name = "LDO2", |
539 | .min_uV = 1050000, | 655 | .min_uV = 1050000, |
540 | .max_uV = 3300000, | 656 | .max_uV = 3300000, |
541 | .table_len = ARRAY_SIZE(LDO2_VSEL_table), | 657 | .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table), |
542 | .table = LDO2_VSEL_table, | 658 | .table = TPS65023_LDO2_VSEL_table, |
543 | }, | 659 | }, |
544 | }; | 660 | }; |
545 | 661 | ||
662 | static struct tps_driver_data tps65020_drv_data = { | ||
663 | .info = tps65020_regs, | ||
664 | .core_regulator = TPS65023_DCDC_3, | ||
665 | }; | ||
666 | |||
667 | static struct tps_driver_data tps65021_drv_data = { | ||
668 | .info = tps65021_regs, | ||
669 | .core_regulator = TPS65023_DCDC_3, | ||
670 | }; | ||
671 | |||
672 | static struct tps_driver_data tps65023_drv_data = { | ||
673 | .info = tps65023_regs, | ||
674 | .core_regulator = TPS65023_DCDC_1, | ||
675 | }; | ||
676 | |||
546 | static const struct i2c_device_id tps_65023_id[] = { | 677 | static const struct i2c_device_id tps_65023_id[] = { |
547 | {.name = "tps65023", | 678 | {.name = "tps65023", |
548 | .driver_data = (unsigned long) tps65023_regs,}, | 679 | .driver_data = (unsigned long) &tps65023_drv_data}, |
549 | {.name = "tps65021", | 680 | {.name = "tps65021", |
550 | .driver_data = (unsigned long) tps65023_regs,}, | 681 | .driver_data = (unsigned long) &tps65021_drv_data,}, |
682 | {.name = "tps65020", | ||
683 | .driver_data = (unsigned long) &tps65020_drv_data}, | ||
551 | { }, | 684 | { }, |
552 | }; | 685 | }; |
553 | 686 | ||
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index bfffabc21eda..bdef70365f52 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c | |||
@@ -90,12 +90,6 @@ static const u16 LDO2_VSEL_table[] = { | |||
90 | 3000, 3100, 3200, 3300, | 90 | 3000, 3100, 3200, 3300, |
91 | }; | 91 | }; |
92 | 92 | ||
93 | static unsigned int num_voltages[] = {ARRAY_SIZE(VDCDCx_VSEL_table), | ||
94 | ARRAY_SIZE(VDCDCx_VSEL_table), | ||
95 | ARRAY_SIZE(VDCDCx_VSEL_table), | ||
96 | ARRAY_SIZE(LDO1_VSEL_table), | ||
97 | ARRAY_SIZE(LDO2_VSEL_table)}; | ||
98 | |||
99 | struct tps_info { | 93 | struct tps_info { |
100 | const char *name; | 94 | const char *name; |
101 | unsigned min_uV; | 95 | unsigned min_uV; |
@@ -598,7 +592,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev) | |||
598 | 592 | ||
599 | tps->desc[i].name = info->name; | 593 | tps->desc[i].name = info->name; |
600 | tps->desc[i].id = i; | 594 | tps->desc[i].id = i; |
601 | tps->desc[i].n_voltages = num_voltages[i]; | 595 | tps->desc[i].n_voltages = info->table_len; |
602 | tps->desc[i].ops = (i > TPS6507X_DCDC_3 ? | 596 | tps->desc[i].ops = (i > TPS6507X_DCDC_3 ? |
603 | &tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops); | 597 | &tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops); |
604 | tps->desc[i].type = REGULATOR_VOLTAGE; | 598 | tps->desc[i].type = REGULATOR_VOLTAGE; |
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index bb04a75a4c98..dbcf09d5080c 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c | |||
@@ -332,6 +332,36 @@ static inline int tps6586x_regulator_preinit(struct device *parent, | |||
332 | 1 << ri->enable_bit[1]); | 332 | 1 << ri->enable_bit[1]); |
333 | } | 333 | } |
334 | 334 | ||
335 | static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev) | ||
336 | { | ||
337 | struct device *parent = pdev->dev.parent; | ||
338 | struct regulator_init_data *p = pdev->dev.platform_data; | ||
339 | struct tps6586x_settings *setting = p->driver_data; | ||
340 | uint8_t reg; | ||
341 | |||
342 | if (setting == NULL) | ||
343 | return 0; | ||
344 | |||
345 | if (!(setting->slew_rate & TPS6586X_SLEW_RATE_SET)) | ||
346 | return 0; | ||
347 | |||
348 | /* only SM0 and SM1 can have the slew rate settings */ | ||
349 | switch (pdev->id) { | ||
350 | case TPS6586X_ID_SM_0: | ||
351 | reg = TPS6586X_SM0SL; | ||
352 | break; | ||
353 | case TPS6586X_ID_SM_1: | ||
354 | reg = TPS6586X_SM1SL; | ||
355 | break; | ||
356 | default: | ||
357 | dev_warn(&pdev->dev, "Only SM0/SM1 can set slew rate\n"); | ||
358 | return -EINVAL; | ||
359 | } | ||
360 | |||
361 | return tps6586x_write(parent, reg, | ||
362 | setting->slew_rate & TPS6586X_SLEW_RATE_MASK); | ||
363 | } | ||
364 | |||
335 | static inline struct tps6586x_regulator *find_regulator_info(int id) | 365 | static inline struct tps6586x_regulator *find_regulator_info(int id) |
336 | { | 366 | { |
337 | struct tps6586x_regulator *ri; | 367 | struct tps6586x_regulator *ri; |
@@ -374,7 +404,7 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev) | |||
374 | 404 | ||
375 | platform_set_drvdata(pdev, rdev); | 405 | platform_set_drvdata(pdev, rdev); |
376 | 406 | ||
377 | return 0; | 407 | return tps6586x_regulator_set_slew_rate(pdev); |
378 | } | 408 | } |
379 | 409 | ||
380 | static int __devexit tps6586x_regulator_remove(struct platform_device *pdev) | 410 | static int __devexit tps6586x_regulator_remove(struct platform_device *pdev) |
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index 3a9313e00fac..39d4a1749e71 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c | |||
@@ -43,8 +43,6 @@ | |||
43 | #define TPS65912_REG_LDO9 12 | 43 | #define TPS65912_REG_LDO9 12 |
44 | #define TPS65912_REG_LDO10 13 | 44 | #define TPS65912_REG_LDO10 13 |
45 | 45 | ||
46 | #define TPS65912_MAX_REG_ID TPS65912_REG_LDO_10 | ||
47 | |||
48 | /* Number of step-down converters available */ | 46 | /* Number of step-down converters available */ |
49 | #define TPS65912_NUM_DCDC 4 | 47 | #define TPS65912_NUM_DCDC 4 |
50 | 48 | ||
diff --git a/include/linux/mfd/tps6586x.h b/include/linux/mfd/tps6586x.h index b6bab1b04e25..b19176eab44d 100644 --- a/include/linux/mfd/tps6586x.h +++ b/include/linux/mfd/tps6586x.h | |||
@@ -1,6 +1,18 @@ | |||
1 | #ifndef __LINUX_MFD_TPS6586X_H | 1 | #ifndef __LINUX_MFD_TPS6586X_H |
2 | #define __LINUX_MFD_TPS6586X_H | 2 | #define __LINUX_MFD_TPS6586X_H |
3 | 3 | ||
4 | #define TPS6586X_SLEW_RATE_INSTANTLY 0x00 | ||
5 | #define TPS6586X_SLEW_RATE_110UV 0x01 | ||
6 | #define TPS6586X_SLEW_RATE_220UV 0x02 | ||
7 | #define TPS6586X_SLEW_RATE_440UV 0x03 | ||
8 | #define TPS6586X_SLEW_RATE_880UV 0x04 | ||
9 | #define TPS6586X_SLEW_RATE_1760UV 0x05 | ||
10 | #define TPS6586X_SLEW_RATE_3520UV 0x06 | ||
11 | #define TPS6586X_SLEW_RATE_7040UV 0x07 | ||
12 | |||
13 | #define TPS6586X_SLEW_RATE_SET 0x08 | ||
14 | #define TPS6586X_SLEW_RATE_MASK 0x07 | ||
15 | |||
4 | enum { | 16 | enum { |
5 | TPS6586X_ID_SM_0, | 17 | TPS6586X_ID_SM_0, |
6 | TPS6586X_ID_SM_1, | 18 | TPS6586X_ID_SM_1, |
@@ -48,6 +60,10 @@ enum { | |||
48 | TPS6586X_INT_RTC_ALM2, | 60 | TPS6586X_INT_RTC_ALM2, |
49 | }; | 61 | }; |
50 | 62 | ||
63 | struct tps6586x_settings { | ||
64 | int slew_rate; | ||
65 | }; | ||
66 | |||
51 | struct tps6586x_subdev_info { | 67 | struct tps6586x_subdev_info { |
52 | int id; | 68 | int id; |
53 | const char *name; | 69 | const char *name; |
diff --git a/include/linux/regulator/gpio-regulator.h b/include/linux/regulator/gpio-regulator.h new file mode 100644 index 000000000000..19fbd267406d --- /dev/null +++ b/include/linux/regulator/gpio-regulator.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * gpio-regulator.h | ||
3 | * | ||
4 | * Copyright 2011 Heiko Stuebner <heiko@sntech.de> | ||
5 | * | ||
6 | * based on fixed.h | ||
7 | * | ||
8 | * Copyright 2008 Wolfson Microelectronics PLC. | ||
9 | * | ||
10 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
11 | * | ||
12 | * Copyright (c) 2009 Nokia Corporation | ||
13 | * Roger Quadros <ext-roger.quadros@nokia.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License as | ||
17 | * published by the Free Software Foundation; either version 2 of the | ||
18 | * License, or (at your option) any later version. | ||
19 | */ | ||
20 | |||
21 | #ifndef __REGULATOR_GPIO_H | ||
22 | #define __REGULATOR_GPIO_H | ||
23 | |||
24 | struct regulator_init_data; | ||
25 | |||
26 | enum regulator_type; | ||
27 | |||
28 | /** | ||
29 | * struct gpio_regulator_state - state description | ||
30 | * @value: microvolts or microamps | ||
31 | * @gpios: bitfield of gpio target-states for the value | ||
32 | * | ||
33 | * This structure describes a supported setting of the regulator | ||
34 | * and the necessary gpio-state to achieve it. | ||
35 | * | ||
36 | * The n-th bit in the bitfield describes the state of the n-th GPIO | ||
37 | * from the gpios-array defined in gpio_regulator_config below. | ||
38 | */ | ||
39 | struct gpio_regulator_state { | ||
40 | int value; | ||
41 | int gpios; | ||
42 | }; | ||
43 | |||
44 | /** | ||
45 | * struct gpio_regulator_config - config structure | ||
46 | * @supply_name: Name of the regulator supply | ||
47 | * @enable_gpio: GPIO to use for enable control | ||
48 | * set to -EINVAL if not used | ||
49 | * @enable_high: Polarity of enable GPIO | ||
50 | * 1 = Active high, 0 = Active low | ||
51 | * @enabled_at_boot: Whether regulator has been enabled at | ||
52 | * boot or not. 1 = Yes, 0 = No | ||
53 | * This is used to keep the regulator at | ||
54 | * the default state | ||
55 | * @startup_delay: Start-up time in microseconds | ||
56 | * @gpios: Array containing the gpios needed to control | ||
57 | * the setting of the regulator | ||
58 | * @nr_gpios: Number of gpios | ||
59 | * @states: Array of gpio_regulator_state entries describing | ||
60 | * the gpio state for specific voltages | ||
61 | * @nr_states: Number of states available | ||
62 | * @regulator_type: either REGULATOR_CURRENT or REGULATOR_VOLTAGE | ||
63 | * @init_data: regulator_init_data | ||
64 | * | ||
65 | * This structure contains gpio-voltage regulator configuration | ||
66 | * information that must be passed by platform code to the | ||
67 | * gpio-voltage regulator driver. | ||
68 | */ | ||
69 | struct gpio_regulator_config { | ||
70 | const char *supply_name; | ||
71 | |||
72 | int enable_gpio; | ||
73 | unsigned enable_high:1; | ||
74 | unsigned enabled_at_boot:1; | ||
75 | unsigned startup_delay; | ||
76 | |||
77 | struct gpio *gpios; | ||
78 | int nr_gpios; | ||
79 | |||
80 | struct gpio_regulator_state *states; | ||
81 | int nr_states; | ||
82 | |||
83 | enum regulator_type type; | ||
84 | struct regulator_init_data *init_data; | ||
85 | }; | ||
86 | |||
87 | #endif | ||
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index ce3127a75c88..f3f13fd5868f 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h | |||
@@ -95,7 +95,7 @@ struct regulator_state { | |||
95 | */ | 95 | */ |
96 | struct regulation_constraints { | 96 | struct regulation_constraints { |
97 | 97 | ||
98 | char *name; | 98 | const char *name; |
99 | 99 | ||
100 | /* voltage output range (inclusive) - for voltage control */ | 100 | /* voltage output range (inclusive) - for voltage control */ |
101 | int min_uV; | 101 | int min_uV; |