aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-msm/vreg.c
diff options
context:
space:
mode:
authorMatt Wilson <mtwilson@quicinc.com>2009-06-29 15:13:04 -0400
committerDaniel Walker <dwalker@codeaurora.org>2010-05-12 12:14:40 -0400
commit0e44106de5adffc32e0a9294ed406f20d9a3f38d (patch)
tree0d7212a1df34f46fdf882fc288c4ec133a875e93 /arch/arm/mach-msm/vreg.c
parent4eab62519f8f58aa5f72787877c459925399d617 (diff)
arm: msm: add vreg reference count
Support independent enable and disable by clients for common vreg. First enable switches on and last disable switches off. This change has no check for voltage level so clients must agree on level for common vreg. Signed-off-by: Matthew Wilson <mtwilson@quicinc.com>
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