diff options
Diffstat (limited to 'arch/arm/mach-msm/vreg.c')
-rw-r--r-- | arch/arm/mach-msm/vreg.c | 115 |
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 | ||
35 | static struct vreg vregs[] = { | 37 | static 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 | ||
69 | struct vreg *vreg_get(struct device *dev, const char *id) | 71 | struct 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 | ||
155 | static 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 | |||
164 | static 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 | |||
140 | DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n"); | 173 | DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n"); |
174 | DEFINE_SIMPLE_ATTRIBUTE(vreg_count_fops, vreg_debug_count_get, | ||
175 | vreg_debug_count_set, "%llu\n"); | ||
141 | 176 | ||
142 | static int __init vreg_debug_init(void) | 177 | static 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 | ||