Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / mach-msm / vreg.c
CommitLineData
f030d7b6
BS
1/* arch/arm/mach-msm/vreg.c
2 *
3 * Copyright (C) 2008 Google, Inc.
4783de9b 4 * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
f030d7b6
BS
5 * Author: Brian Swetland <swetland@google.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/kernel.h>
19#include <linux/device.h>
20#include <linux/init.h>
21#include <linux/debugfs.h>
0e44106d 22#include <linux/string.h>
f030d7b6
BS
23#include <mach/vreg.h>
24
25#include "proc_comm.h"
26
27struct vreg {
28 const char *name;
29 unsigned id;
4783de9b 30 int status;
0e44106d 31 unsigned refcnt;
f030d7b6
BS
32};
33
0e44106d
MW
34#define VREG(_name, _id, _status, _refcnt) \
35 { .name = _name, .id = _id, .status = _status, .refcnt = _refcnt }
f030d7b6
BS
36
37static struct vreg vregs[] = {
0e44106d
MW
38 VREG("msma", 0, 0, 0),
39 VREG("msmp", 1, 0, 0),
40 VREG("msme1", 2, 0, 0),
41 VREG("msmc1", 3, 0, 0),
42 VREG("msmc2", 4, 0, 0),
43 VREG("gp3", 5, 0, 0),
44 VREG("msme2", 6, 0, 0),
45 VREG("gp4", 7, 0, 0),
46 VREG("gp1", 8, 0, 0),
47 VREG("tcxo", 9, 0, 0),
48 VREG("pa", 10, 0, 0),
49 VREG("rftx", 11, 0, 0),
50 VREG("rfrx1", 12, 0, 0),
51 VREG("rfrx2", 13, 0, 0),
52 VREG("synt", 14, 0, 0),
53 VREG("wlan", 15, 0, 0),
54 VREG("usb", 16, 0, 0),
55 VREG("boost", 17, 0, 0),
56 VREG("mmc", 18, 0, 0),
57 VREG("ruim", 19, 0, 0),
58 VREG("msmc0", 20, 0, 0),
59 VREG("gp2", 21, 0, 0),
60 VREG("gp5", 22, 0, 0),
61 VREG("gp6", 23, 0, 0),
62 VREG("rf", 24, 0, 0),
63 VREG("rf_vco", 26, 0, 0),
64 VREG("mpll", 27, 0, 0),
65 VREG("s2", 28, 0, 0),
66 VREG("s3", 29, 0, 0),
67 VREG("rfubm", 30, 0, 0),
68 VREG("ncp", 31, 0, 0),
1b70de32
WR
69 VREG("gp7", 32, 0, 0),
70 VREG("gp8", 33, 0, 0),
71 VREG("gp9", 34, 0, 0),
72 VREG("gp10", 35, 0, 0),
73 VREG("gp11", 36, 0, 0),
74 VREG("gp12", 37, 0, 0),
75 VREG("gp13", 38, 0, 0),
76 VREG("gp14", 39, 0, 0),
77 VREG("gp15", 40, 0, 0),
78 VREG("gp16", 41, 0, 0),
79 VREG("gp17", 42, 0, 0),
80 VREG("s4", 43, 0, 0),
81 VREG("usb2", 44, 0, 0),
82 VREG("wlan2", 45, 0, 0),
83 VREG("xo_out", 46, 0, 0),
84 VREG("lvsw0", 47, 0, 0),
85 VREG("lvsw1", 48, 0, 0),
f030d7b6
BS
86};
87
88struct vreg *vreg_get(struct device *dev, const char *id)
89{
90 int n;
91 for (n = 0; n < ARRAY_SIZE(vregs); n++) {
92 if (!strcmp(vregs[n].name, id))
93 return vregs + n;
94 }
0c50b444 95 return ERR_PTR(-ENOENT);
f030d7b6
BS
96}
97
98void vreg_put(struct vreg *vreg)
99{
100}
101
102int vreg_enable(struct vreg *vreg)
103{
104 unsigned id = vreg->id;
105 unsigned enable = 1;
4783de9b 106
0e44106d
MW
107 if (vreg->refcnt == 0)
108 vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
109
110 if ((vreg->refcnt < UINT_MAX) && (!vreg->status))
111 vreg->refcnt++;
112
4783de9b 113 return vreg->status;
f030d7b6
BS
114}
115
4783de9b 116int vreg_disable(struct vreg *vreg)
f030d7b6
BS
117{
118 unsigned id = vreg->id;
119 unsigned enable = 0;
4783de9b 120
0e44106d
MW
121 if (!vreg->refcnt)
122 return 0;
123
124 if (vreg->refcnt == 1)
125 vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
126
127 if (!vreg->status)
128 vreg->refcnt--;
129
4783de9b 130 return vreg->status;
f030d7b6
BS
131}
132
133int vreg_set_level(struct vreg *vreg, unsigned mv)
134{
135 unsigned id = vreg->id;
4783de9b
SM
136
137 vreg->status = msm_proc_comm(PCOM_VREG_SET_LEVEL, &id, &mv);
138 return vreg->status;
f030d7b6
BS
139}
140
141#if defined(CONFIG_DEBUG_FS)
142
143static int vreg_debug_set(void *data, u64 val)
144{
145 struct vreg *vreg = data;
146 switch (val) {
147 case 0:
148 vreg_disable(vreg);
149 break;
150 case 1:
151 vreg_enable(vreg);
152 break;
153 default:
154 vreg_set_level(vreg, val);
155 break;
156 }
157 return 0;
158}
159
160static int vreg_debug_get(void *data, u64 *val)
161{
4783de9b
SM
162 struct vreg *vreg = data;
163
164 if (!vreg->status)
165 *val = 0;
166 else
167 *val = 1;
168
169 return 0;
f030d7b6
BS
170}
171
0e44106d
MW
172static int vreg_debug_count_set(void *data, u64 val)
173{
174 struct vreg *vreg = data;
175 if (val > UINT_MAX)
176 val = UINT_MAX;
177 vreg->refcnt = val;
178 return 0;
179}
180
181static int vreg_debug_count_get(void *data, u64 *val)
182{
183 struct vreg *vreg = data;
184
185 *val = vreg->refcnt;
186
187 return 0;
188}
189
f030d7b6 190DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n");
0e44106d
MW
191DEFINE_SIMPLE_ATTRIBUTE(vreg_count_fops, vreg_debug_count_get,
192 vreg_debug_count_set, "%llu\n");
f030d7b6
BS
193
194static int __init vreg_debug_init(void)
195{
196 struct dentry *dent;
197 int n;
0e44106d
MW
198 char name[32];
199 const char *refcnt_name = "_refcnt";
f030d7b6
BS
200
201 dent = debugfs_create_dir("vreg", 0);
202 if (IS_ERR(dent))
203 return 0;
204
0e44106d 205 for (n = 0; n < ARRAY_SIZE(vregs); n++) {
f030d7b6
BS
206 (void) debugfs_create_file(vregs[n].name, 0644,
207 dent, vregs + n, &vreg_fops);
208
0e44106d
MW
209 strlcpy(name, vregs[n].name, sizeof(name));
210 strlcat(name, refcnt_name, sizeof(name));
211 (void) debugfs_create_file(name, 0644,
212 dent, vregs + n, &vreg_count_fops);
213 }
214
f030d7b6
BS
215 return 0;
216}
217
218device_initcall(vreg_debug_init);
219#endif