aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/regulator/Kconfig4
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/db8500-prcmu.c118
-rw-r--r--drivers/regulator/dbx500-prcmu.c241
-rw-r--r--drivers/regulator/dbx500-prcmu.h63
5 files changed, 341 insertions, 86 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index b9ad3d8e03c7..c7e49b140be9 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -299,9 +299,13 @@ config REGULATOR_AB8500
299 This driver supports the regulators found on the ST-Ericsson mixed 299 This driver supports the regulators found on the ST-Ericsson mixed
300 signal AB8500 PMIC 300 signal AB8500 PMIC
301 301
302config REGULATOR_DBX500_PRCMU
303 bool
304
302config REGULATOR_DB8500_PRCMU 305config REGULATOR_DB8500_PRCMU
303 bool "ST-Ericsson DB8500 Voltage Domain Regulators" 306 bool "ST-Ericsson DB8500 Voltage Domain Regulators"
304 depends on MFD_DB8500_PRCMU 307 depends on MFD_DB8500_PRCMU
308 select REGULATOR_DBX500_PRCMU
305 help 309 help
306 This driver supports the voltage domain regulators controlled by the 310 This driver supports the voltage domain regulators controlled by the
307 DB8500 PRCMU 311 DB8500 PRCMU
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 1668b2e667ce..bf5951352484 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
45obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o 45obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
46obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o 46obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
47obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o 47obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
48obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
48obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o 49obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
49obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o 50obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
50obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o 51obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c
index 515443fcd26b..4bd25e75efa0 100644
--- a/drivers/regulator/db8500-prcmu.c
+++ b/drivers/regulator/db8500-prcmu.c
@@ -18,74 +18,11 @@
18#include <linux/regulator/machine.h> 18#include <linux/regulator/machine.h>
19#include <linux/regulator/db8500-prcmu.h> 19#include <linux/regulator/db8500-prcmu.h>
20#include <linux/module.h> 20#include <linux/module.h>
21 21#include "dbx500-prcmu.h"
22/*
23 * power state reference count
24 */
25static int power_state_active_cnt; /* will initialize to zero */
26static DEFINE_SPINLOCK(power_state_active_lock);
27
28static void power_state_active_enable(void)
29{
30 unsigned long flags;
31
32 spin_lock_irqsave(&power_state_active_lock, flags);
33 power_state_active_cnt++;
34 spin_unlock_irqrestore(&power_state_active_lock, flags);
35}
36
37static int power_state_active_disable(void)
38{
39 int ret = 0;
40 unsigned long flags;
41
42 spin_lock_irqsave(&power_state_active_lock, flags);
43 if (power_state_active_cnt <= 0) {
44 pr_err("power state: unbalanced enable/disable calls\n");
45 ret = -EINVAL;
46 goto out;
47 }
48
49 power_state_active_cnt--;
50out:
51 spin_unlock_irqrestore(&power_state_active_lock, flags);
52 return ret;
53}
54
55/*
56 * Exported interface for CPUIdle only. This function is called when interrupts
57 * are turned off. Hence, no locking.
58 */
59int power_state_active_is_enabled(void)
60{
61 return (power_state_active_cnt > 0);
62}
63
64/**
65 * struct db8500_regulator_info - db8500 regulator information
66 * @dev: device pointer
67 * @desc: regulator description
68 * @rdev: regulator device pointer
69 * @is_enabled: status of the regulator
70 * @epod_id: id for EPOD (power domain)
71 * @is_ramret: RAM retention switch for EPOD (power domain)
72 * @operating_point: operating point (only for vape, to be removed)
73 *
74 */
75struct db8500_regulator_info {
76 struct device *dev;
77 struct regulator_desc desc;
78 struct regulator_dev *rdev;
79 bool is_enabled;
80 u16 epod_id;
81 bool is_ramret;
82 bool exclude_from_power_state;
83 unsigned int operating_point;
84};
85 22
86static int db8500_regulator_enable(struct regulator_dev *rdev) 23static int db8500_regulator_enable(struct regulator_dev *rdev)
87{ 24{
88 struct db8500_regulator_info *info = rdev_get_drvdata(rdev); 25 struct dbx500_regulator_info *info = rdev_get_drvdata(rdev);
89 26
90 if (info == NULL) 27 if (info == NULL)
91 return -EINVAL; 28 return -EINVAL;
@@ -93,16 +30,18 @@ static int db8500_regulator_enable(struct regulator_dev *rdev)
93 dev_vdbg(rdev_get_dev(rdev), "regulator-%s-enable\n", 30 dev_vdbg(rdev_get_dev(rdev), "regulator-%s-enable\n",
94 info->desc.name); 31 info->desc.name);
95 32
96 info->is_enabled = true; 33 if (!info->is_enabled) {
97 if (!info->exclude_from_power_state) 34 info->is_enabled = true;
98 power_state_active_enable(); 35 if (!info->exclude_from_power_state)
36 power_state_active_enable();
37 }
99 38
100 return 0; 39 return 0;
101} 40}
102 41
103static int db8500_regulator_disable(struct regulator_dev *rdev) 42static int db8500_regulator_disable(struct regulator_dev *rdev)
104{ 43{
105 struct db8500_regulator_info *info = rdev_get_drvdata(rdev); 44 struct dbx500_regulator_info *info = rdev_get_drvdata(rdev);
106 int ret = 0; 45 int ret = 0;
107 46
108 if (info == NULL) 47 if (info == NULL)
@@ -111,16 +50,18 @@ static int db8500_regulator_disable(struct regulator_dev *rdev)
111 dev_vdbg(rdev_get_dev(rdev), "regulator-%s-disable\n", 50 dev_vdbg(rdev_get_dev(rdev), "regulator-%s-disable\n",
112 info->desc.name); 51 info->desc.name);
113 52
114 info->is_enabled = false; 53 if (info->is_enabled) {
115 if (!info->exclude_from_power_state) 54 info->is_enabled = false;
116 ret = power_state_active_disable(); 55 if (!info->exclude_from_power_state)
56 ret = power_state_active_disable();
57 }
117 58
118 return ret; 59 return ret;
119} 60}
120 61
121static int db8500_regulator_is_enabled(struct regulator_dev *rdev) 62static int db8500_regulator_is_enabled(struct regulator_dev *rdev)
122{ 63{
123 struct db8500_regulator_info *info = rdev_get_drvdata(rdev); 64 struct dbx500_regulator_info *info = rdev_get_drvdata(rdev);
124 65
125 if (info == NULL) 66 if (info == NULL)
126 return -EINVAL; 67 return -EINVAL;
@@ -197,7 +138,7 @@ static int disable_epod(u16 epod_id, bool ramret)
197 */ 138 */
198static int db8500_regulator_switch_enable(struct regulator_dev *rdev) 139static int db8500_regulator_switch_enable(struct regulator_dev *rdev)
199{ 140{
200 struct db8500_regulator_info *info = rdev_get_drvdata(rdev); 141 struct dbx500_regulator_info *info = rdev_get_drvdata(rdev);
201 int ret; 142 int ret;
202 143
203 if (info == NULL) 144 if (info == NULL)
@@ -221,7 +162,7 @@ out:
221 162
222static int db8500_regulator_switch_disable(struct regulator_dev *rdev) 163static int db8500_regulator_switch_disable(struct regulator_dev *rdev)
223{ 164{
224 struct db8500_regulator_info *info = rdev_get_drvdata(rdev); 165 struct dbx500_regulator_info *info = rdev_get_drvdata(rdev);
225 int ret; 166 int ret;
226 167
227 if (info == NULL) 168 if (info == NULL)
@@ -245,7 +186,7 @@ out:
245 186
246static int db8500_regulator_switch_is_enabled(struct regulator_dev *rdev) 187static int db8500_regulator_switch_is_enabled(struct regulator_dev *rdev)
247{ 188{
248 struct db8500_regulator_info *info = rdev_get_drvdata(rdev); 189 struct dbx500_regulator_info *info = rdev_get_drvdata(rdev);
249 190
250 if (info == NULL) 191 if (info == NULL)
251 return -EINVAL; 192 return -EINVAL;
@@ -266,8 +207,8 @@ static struct regulator_ops db8500_regulator_switch_ops = {
266/* 207/*
267 * Regulator information 208 * Regulator information
268 */ 209 */
269static struct db8500_regulator_info 210static struct dbx500_regulator_info
270db8500_regulator_info[DB8500_NUM_REGULATORS] = { 211dbx500_regulator_info[DB8500_NUM_REGULATORS] = {
271 [DB8500_REGULATOR_VAPE] = { 212 [DB8500_REGULATOR_VAPE] = {
272 .desc = { 213 .desc = {
273 .name = "db8500-vape", 214 .name = "db8500-vape",
@@ -476,12 +417,12 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev)
476 int i, err; 417 int i, err;
477 418
478 /* register all regulators */ 419 /* register all regulators */
479 for (i = 0; i < ARRAY_SIZE(db8500_regulator_info); i++) { 420 for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) {
480 struct db8500_regulator_info *info; 421 struct dbx500_regulator_info *info;
481 struct regulator_init_data *init_data = &db8500_init_data[i]; 422 struct regulator_init_data *init_data = &db8500_init_data[i];
482 423
483 /* assign per-regulator data */ 424 /* assign per-regulator data */
484 info = &db8500_regulator_info[i]; 425 info = &dbx500_regulator_info[i];
485 info->dev = &pdev->dev; 426 info->dev = &pdev->dev;
486 427
487 /* register with the regulator framework */ 428 /* register with the regulator framework */
@@ -494,7 +435,7 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev)
494 435
495 /* if failing, unregister all earlier regulators */ 436 /* if failing, unregister all earlier regulators */
496 while (--i >= 0) { 437 while (--i >= 0) {
497 info = &db8500_regulator_info[i]; 438 info = &dbx500_regulator_info[i];
498 regulator_unregister(info->rdev); 439 regulator_unregister(info->rdev);
499 } 440 }
500 return err; 441 return err;
@@ -503,17 +444,22 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev)
503 dev_dbg(rdev_get_dev(info->rdev), 444 dev_dbg(rdev_get_dev(info->rdev),
504 "regulator-%s-probed\n", info->desc.name); 445 "regulator-%s-probed\n", info->desc.name);
505 } 446 }
447 err = ux500_regulator_debug_init(pdev,
448 dbx500_regulator_info,
449 ARRAY_SIZE(dbx500_regulator_info));
506 450
507 return 0; 451 return err;
508} 452}
509 453
510static int __exit db8500_regulator_remove(struct platform_device *pdev) 454static int __exit db8500_regulator_remove(struct platform_device *pdev)
511{ 455{
512 int i; 456 int i;
513 457
514 for (i = 0; i < ARRAY_SIZE(db8500_regulator_info); i++) { 458 ux500_regulator_debug_exit();
515 struct db8500_regulator_info *info; 459
516 info = &db8500_regulator_info[i]; 460 for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) {
461 struct dbx500_regulator_info *info;
462 info = &dbx500_regulator_info[i];
517 463
518 dev_vdbg(rdev_get_dev(info->rdev), 464 dev_vdbg(rdev_get_dev(info->rdev),
519 "regulator-%s-remove\n", info->desc.name); 465 "regulator-%s-remove\n", info->desc.name);
diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c
new file mode 100644
index 000000000000..f2e5ecdc5864
--- /dev/null
+++ b/drivers/regulator/dbx500-prcmu.c
@@ -0,0 +1,241 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * License Terms: GNU General Public License v2
5 * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
6 * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
7 *
8 * UX500 common part of Power domain regulators
9 */
10
11#include <linux/kernel.h>
12#include <linux/err.h>
13#include <linux/regulator/driver.h>
14#include <linux/debugfs.h>
15#include <linux/seq_file.h>
16#include <linux/slab.h>
17
18#include "dbx500-prcmu.h"
19
20/*
21 * power state reference count
22 */
23static int power_state_active_cnt; /* will initialize to zero */
24static DEFINE_SPINLOCK(power_state_active_lock);
25
26int power_state_active_get(void)
27{
28 unsigned long flags;
29 int cnt;
30
31 spin_lock_irqsave(&power_state_active_lock, flags);
32 cnt = power_state_active_cnt;
33 spin_unlock_irqrestore(&power_state_active_lock, flags);
34
35 return cnt;
36}
37
38void power_state_active_enable(void)
39{
40 unsigned long flags;
41
42 spin_lock_irqsave(&power_state_active_lock, flags);
43 power_state_active_cnt++;
44 spin_unlock_irqrestore(&power_state_active_lock, flags);
45}
46
47int power_state_active_disable(void)
48{
49 int ret = 0;
50 unsigned long flags;
51
52 spin_lock_irqsave(&power_state_active_lock, flags);
53 if (power_state_active_cnt <= 0) {
54 pr_err("power state: unbalanced enable/disable calls\n");
55 ret = -EINVAL;
56 goto out;
57 }
58
59 power_state_active_cnt--;
60out:
61 spin_unlock_irqrestore(&power_state_active_lock, flags);
62 return ret;
63}
64
65#ifdef CONFIG_REGULATOR_DEBUG
66
67static struct ux500_regulator_debug {
68 struct dentry *dir;
69 struct dentry *status_file;
70 struct dentry *power_state_cnt_file;
71 struct dbx500_regulator_info *regulator_array;
72 int num_regulators;
73 u8 *state_before_suspend;
74 u8 *state_after_suspend;
75} rdebug;
76
77void ux500_regulator_suspend_debug(void)
78{
79 int i;
80 for (i = 0; i < rdebug.num_regulators; i++)
81 rdebug.state_before_suspend[i] =
82 rdebug.regulator_array[i].is_enabled;
83}
84
85void ux500_regulator_resume_debug(void)
86{
87 int i;
88 for (i = 0; i < rdebug.num_regulators; i++)
89 rdebug.state_after_suspend[i] =
90 rdebug.regulator_array[i].is_enabled;
91}
92
93static int ux500_regulator_power_state_cnt_print(struct seq_file *s, void *p)
94{
95 struct device *dev = s->private;
96 int err;
97
98 /* print power state count */
99 err = seq_printf(s, "ux500-regulator power state count: %i\n",
100 power_state_active_get());
101 if (err < 0)
102 dev_err(dev, "seq_printf overflow\n");
103
104 return 0;
105}
106
107static int ux500_regulator_power_state_cnt_open(struct inode *inode,
108 struct file *file)
109{
110 return single_open(file, ux500_regulator_power_state_cnt_print,
111 inode->i_private);
112}
113
114static const struct file_operations ux500_regulator_power_state_cnt_fops = {
115 .open = ux500_regulator_power_state_cnt_open,
116 .read = seq_read,
117 .llseek = seq_lseek,
118 .release = single_release,
119 .owner = THIS_MODULE,
120};
121
122static int ux500_regulator_status_print(struct seq_file *s, void *p)
123{
124 struct device *dev = s->private;
125 int err;
126 int i;
127
128 /* print dump header */
129 err = seq_printf(s, "ux500-regulator status:\n");
130 if (err < 0)
131 dev_err(dev, "seq_printf overflow\n");
132
133 err = seq_printf(s, "%31s : %8s : %8s\n", "current",
134 "before", "after");
135 if (err < 0)
136 dev_err(dev, "seq_printf overflow\n");
137
138 for (i = 0; i < rdebug.num_regulators; i++) {
139 struct dbx500_regulator_info *info;
140 /* Access per-regulator data */
141 info = &rdebug.regulator_array[i];
142
143 /* print status */
144 err = seq_printf(s, "%20s : %8s : %8s : %8s\n", info->desc.name,
145 info->is_enabled ? "enabled" : "disabled",
146 rdebug.state_before_suspend[i] ? "enabled" : "disabled",
147 rdebug.state_after_suspend[i] ? "enabled" : "disabled");
148 if (err < 0)
149 dev_err(dev, "seq_printf overflow\n");
150 }
151
152 return 0;
153}
154
155static int ux500_regulator_status_open(struct inode *inode, struct file *file)
156{
157 return single_open(file, ux500_regulator_status_print,
158 inode->i_private);
159}
160
161static const struct file_operations ux500_regulator_status_fops = {
162 .open = ux500_regulator_status_open,
163 .read = seq_read,
164 .llseek = seq_lseek,
165 .release = single_release,
166 .owner = THIS_MODULE,
167};
168
169int __attribute__((weak)) dbx500_regulator_testcase(
170 struct dbx500_regulator_info *regulator_info,
171 int num_regulators)
172{
173 return 0;
174}
175
176int __devinit
177ux500_regulator_debug_init(struct platform_device *pdev,
178 struct dbx500_regulator_info *regulator_info,
179 int num_regulators)
180{
181 /* create directory */
182 rdebug.dir = debugfs_create_dir("ux500-regulator", NULL);
183 if (!rdebug.dir)
184 goto exit_no_debugfs;
185
186 /* create "status" file */
187 rdebug.status_file = debugfs_create_file("status",
188 S_IRUGO, rdebug.dir, &pdev->dev,
189 &ux500_regulator_status_fops);
190 if (!rdebug.status_file)
191 goto exit_destroy_dir;
192
193 /* create "power-state-count" file */
194 rdebug.power_state_cnt_file = debugfs_create_file("power-state-count",
195 S_IRUGO, rdebug.dir, &pdev->dev,
196 &ux500_regulator_power_state_cnt_fops);
197 if (!rdebug.power_state_cnt_file)
198 goto exit_destroy_status;
199
200 rdebug.regulator_array = regulator_info;
201 rdebug.num_regulators = num_regulators;
202
203 rdebug.state_before_suspend = kzalloc(num_regulators, GFP_KERNEL);
204 if (!rdebug.state_before_suspend) {
205 dev_err(&pdev->dev,
206 "could not allocate memory for saving state\n");
207 goto exit_destroy_power_state;
208 }
209
210 rdebug.state_after_suspend = kzalloc(num_regulators, GFP_KERNEL);
211 if (!rdebug.state_after_suspend) {
212 dev_err(&pdev->dev,
213 "could not allocate memory for saving state\n");
214 goto exit_free;
215 }
216
217 dbx500_regulator_testcase(regulator_info, num_regulators);
218 return 0;
219
220exit_free:
221 kfree(rdebug.state_before_suspend);
222exit_destroy_power_state:
223 debugfs_remove(rdebug.power_state_cnt_file);
224exit_destroy_status:
225 debugfs_remove(rdebug.status_file);
226exit_destroy_dir:
227 debugfs_remove(rdebug.dir);
228exit_no_debugfs:
229 dev_err(&pdev->dev, "failed to create debugfs entries.\n");
230 return -ENOMEM;
231}
232
233int __devexit ux500_regulator_debug_exit(void)
234{
235 debugfs_remove_recursive(rdebug.dir);
236 kfree(rdebug.state_after_suspend);
237 kfree(rdebug.state_before_suspend);
238
239 return 0;
240}
241#endif
diff --git a/drivers/regulator/dbx500-prcmu.h b/drivers/regulator/dbx500-prcmu.h
new file mode 100644
index 000000000000..e763883a44f4
--- /dev/null
+++ b/drivers/regulator/dbx500-prcmu.h
@@ -0,0 +1,63 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * Author: Bengt Jonsson <bengt.jonsson@stericsson.com> for ST-Ericsson,
5 * Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
6 *
7 * License Terms: GNU General Public License v2
8 *
9 */
10
11#ifndef DBX500_REGULATOR_H
12#define DBX500_REGULATOR_H
13
14#include <linux/platform_device.h>
15
16/**
17 * struct dbx500_regulator_info - dbx500 regulator information
18 * @dev: device pointer
19 * @desc: regulator description
20 * @rdev: regulator device pointer
21 * @is_enabled: status of the regulator
22 * @epod_id: id for EPOD (power domain)
23 * @is_ramret: RAM retention switch for EPOD (power domain)
24 * @operating_point: operating point (only for vape, to be removed)
25 *
26 */
27struct dbx500_regulator_info {
28 struct device *dev;
29 struct regulator_desc desc;
30 struct regulator_dev *rdev;
31 bool is_enabled;
32 u16 epod_id;
33 bool is_ramret;
34 bool exclude_from_power_state;
35 unsigned int operating_point;
36};
37
38void power_state_active_enable(void);
39int power_state_active_disable(void);
40
41
42#ifdef CONFIG_REGULATOR_DEBUG
43int ux500_regulator_debug_init(struct platform_device *pdev,
44 struct dbx500_regulator_info *regulator_info,
45 int num_regulators);
46
47int ux500_regulator_debug_exit(void);
48#else
49
50static inline int ux500_regulator_debug_init(struct platform_device *pdev,
51 struct dbx500_regulator_info *regulator_info,
52 int num_regulators)
53{
54 return 0;
55}
56
57static inline int ux500_regulator_debug_exit(void)
58{
59 return 0;
60}
61
62#endif
63#endif