aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-msm/vreg.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-msm/vreg.c')
-rw-r--r--arch/arm/mach-msm/vreg.c115
1 files changed, 79 insertions, 36 deletions
diff --git a/arch/arm/mach-msm/vreg.c b/arch/arm/mach-msm/vreg.c
index 8b0f7b2fd8f7..63db0b3ece53 100644
--- a/arch/arm/mach-msm/vreg.c
+++ b/arch/arm/mach-msm/vreg.c
@@ -19,6 +19,7 @@
19#include <linux/device.h> 19#include <linux/device.h>
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/debugfs.h> 21#include <linux/debugfs.h>
22#include <linux/string.h>
22#include <mach/vreg.h> 23#include <mach/vreg.h>
23 24
24#include "proc_comm.h" 25#include "proc_comm.h"
@@ -27,43 +28,44 @@ struct vreg {
27 const char *name; 28 const char *name;
28 unsigned id; 29 unsigned id;
29 int status; 30 int status;
31 unsigned refcnt;
30}; 32};
31 33
32#define VREG(_name, _id, _status) \ 34#define VREG(_name, _id, _status, _refcnt) \
33 { .name = _name, .id = _id, .status = _status } 35 { .name = _name, .id = _id, .status = _status, .refcnt = _refcnt }
34 36
35static struct vreg vregs[] = { 37static struct vreg vregs[] = {
36 VREG("msma", 0, 0), 38 VREG("msma", 0, 0, 0),
37 VREG("msmp", 1, 0), 39 VREG("msmp", 1, 0, 0),
38 VREG("msme1", 2, 0), 40 VREG("msme1", 2, 0, 0),
39 VREG("msmc1", 3, 0), 41 VREG("msmc1", 3, 0, 0),
40 VREG("msmc2", 4, 0), 42 VREG("msmc2", 4, 0, 0),
41 VREG("gp3", 5, 0), 43 VREG("gp3", 5, 0, 0),
42 VREG("msme2", 6, 0), 44 VREG("msme2", 6, 0, 0),
43 VREG("gp4", 7, 0), 45 VREG("gp4", 7, 0, 0),
44 VREG("gp1", 8, 0), 46 VREG("gp1", 8, 0, 0),
45 VREG("tcxo", 9, 0), 47 VREG("tcxo", 9, 0, 0),
46 VREG("pa", 10, 0), 48 VREG("pa", 10, 0, 0),
47 VREG("rftx", 11, 0), 49 VREG("rftx", 11, 0, 0),
48 VREG("rfrx1", 12, 0), 50 VREG("rfrx1", 12, 0, 0),
49 VREG("rfrx2", 13, 0), 51 VREG("rfrx2", 13, 0, 0),
50 VREG("synt", 14, 0), 52 VREG("synt", 14, 0, 0),
51 VREG("wlan", 15, 0), 53 VREG("wlan", 15, 0, 0),
52 VREG("usb", 16, 0), 54 VREG("usb", 16, 0, 0),
53 VREG("boost", 17, 0), 55 VREG("boost", 17, 0, 0),
54 VREG("mmc", 18, 0), 56 VREG("mmc", 18, 0, 0),
55 VREG("ruim", 19, 0), 57 VREG("ruim", 19, 0, 0),
56 VREG("msmc0", 20, 0), 58 VREG("msmc0", 20, 0, 0),
57 VREG("gp2", 21, 0), 59 VREG("gp2", 21, 0, 0),
58 VREG("gp5", 22, 0), 60 VREG("gp5", 22, 0, 0),
59 VREG("gp6", 23, 0), 61 VREG("gp6", 23, 0, 0),
60 VREG("rf", 24, 0), 62 VREG("rf", 24, 0, 0),
61 VREG("rf_vco", 26, 0), 63 VREG("rf_vco", 26, 0, 0),
62 VREG("mpll", 27, 0), 64 VREG("mpll", 27, 0, 0),
63 VREG("s2", 28, 0), 65 VREG("s2", 28, 0, 0),
64 VREG("s3", 29, 0), 66 VREG("s3", 29, 0, 0),
65 VREG("rfubm", 30, 0), 67 VREG("rfubm", 30, 0, 0),
66 VREG("ncp", 31, 0), 68 VREG("ncp", 31, 0, 0),
67}; 69};
68 70
69struct vreg *vreg_get(struct device *dev, const char *id) 71struct vreg *vreg_get(struct device *dev, const char *id)
@@ -85,7 +87,12 @@ int vreg_enable(struct vreg *vreg)
85 unsigned id = vreg->id; 87 unsigned id = vreg->id;
86 unsigned enable = 1; 88 unsigned enable = 1;
87 89
88 vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable); 90 if (vreg->refcnt == 0)
91 vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
92
93 if ((vreg->refcnt < UINT_MAX) && (!vreg->status))
94 vreg->refcnt++;
95
89 return vreg->status; 96 return vreg->status;
90} 97}
91 98
@@ -94,7 +101,15 @@ int vreg_disable(struct vreg *vreg)
94 unsigned id = vreg->id; 101 unsigned id = vreg->id;
95 unsigned enable = 0; 102 unsigned enable = 0;
96 103
97 vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable); 104 if (!vreg->refcnt)
105 return 0;
106
107 if (vreg->refcnt == 1)
108 vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
109
110 if (!vreg->status)
111 vreg->refcnt--;
112
98 return vreg->status; 113 return vreg->status;
99} 114}
100 115
@@ -137,21 +152,49 @@ static int vreg_debug_get(void *data, u64 *val)
137 return 0; 152 return 0;
138} 153}
139 154
155static int vreg_debug_count_set(void *data, u64 val)
156{
157 struct vreg *vreg = data;
158 if (val > UINT_MAX)
159 val = UINT_MAX;
160 vreg->refcnt = val;
161 return 0;
162}
163
164static int vreg_debug_count_get(void *data, u64 *val)
165{
166 struct vreg *vreg = data;
167
168 *val = vreg->refcnt;
169
170 return 0;
171}
172
140DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n"); 173DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n");
174DEFINE_SIMPLE_ATTRIBUTE(vreg_count_fops, vreg_debug_count_get,
175 vreg_debug_count_set, "%llu\n");
141 176
142static int __init vreg_debug_init(void) 177static int __init vreg_debug_init(void)
143{ 178{
144 struct dentry *dent; 179 struct dentry *dent;
145 int n; 180 int n;
181 char name[32];
182 const char *refcnt_name = "_refcnt";
146 183
147 dent = debugfs_create_dir("vreg", 0); 184 dent = debugfs_create_dir("vreg", 0);
148 if (IS_ERR(dent)) 185 if (IS_ERR(dent))
149 return 0; 186 return 0;
150 187
151 for (n = 0; n < ARRAY_SIZE(vregs); n++) 188 for (n = 0; n < ARRAY_SIZE(vregs); n++) {
152 (void) debugfs_create_file(vregs[n].name, 0644, 189 (void) debugfs_create_file(vregs[n].name, 0644,
153 dent, vregs + n, &vreg_fops); 190 dent, vregs + n, &vreg_fops);
154 191
192 strlcpy(name, vregs[n].name, sizeof(name));
193 strlcat(name, refcnt_name, sizeof(name));
194 (void) debugfs_create_file(name, 0644,
195 dent, vregs + n, &vreg_count_fops);
196 }
197
155 return 0; 198 return 0;
156} 199}
157 200