blob: 8f782a99e4a57cc7fd5631c933dc8eca8040edf3 [file] [log] [blame]
Brian Swetlandf030d7b2008-09-29 14:07:14 -07001/* arch/arm/mach-msm/vreg.c
2 *
3 * Copyright (C) 2008 Google, Inc.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004 * Copyright (c) 2009-2011 Code Aurora Forum. All rights reserved.
Brian Swetlandf030d7b2008-09-29 14:07:14 -07005 * 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>
Matt Wilson0e441062009-06-29 14:13:04 -050022#include <linux/string.h>
Brian Swetlandf030d7b2008-09-29 14:07:14 -070023#include <mach/vreg.h>
24
25#include "proc_comm.h"
26
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070027#if defined(CONFIG_MSM_VREG_SWITCH_INVERTED)
28#define VREG_SWITCH_ENABLE 0
29#define VREG_SWITCH_DISABLE 1
30#else
31#define VREG_SWITCH_ENABLE 1
32#define VREG_SWITCH_DISABLE 0
33#endif
34
Brian Swetlandf030d7b2008-09-29 14:07:14 -070035struct vreg {
36 const char *name;
37 unsigned id;
Steve Muckle4783de92008-12-12 19:33:55 -050038 int status;
Matt Wilson0e441062009-06-29 14:13:04 -050039 unsigned refcnt;
Brian Swetlandf030d7b2008-09-29 14:07:14 -070040};
41
Matt Wilson0e441062009-06-29 14:13:04 -050042#define VREG(_name, _id, _status, _refcnt) \
43 { .name = _name, .id = _id, .status = _status, .refcnt = _refcnt }
Brian Swetlandf030d7b2008-09-29 14:07:14 -070044
45static struct vreg vregs[] = {
Matt Wilson0e441062009-06-29 14:13:04 -050046 VREG("msma", 0, 0, 0),
47 VREG("msmp", 1, 0, 0),
48 VREG("msme1", 2, 0, 0),
49 VREG("msmc1", 3, 0, 0),
50 VREG("msmc2", 4, 0, 0),
51 VREG("gp3", 5, 0, 0),
52 VREG("msme2", 6, 0, 0),
53 VREG("gp4", 7, 0, 0),
54 VREG("gp1", 8, 0, 0),
55 VREG("tcxo", 9, 0, 0),
56 VREG("pa", 10, 0, 0),
57 VREG("rftx", 11, 0, 0),
58 VREG("rfrx1", 12, 0, 0),
59 VREG("rfrx2", 13, 0, 0),
60 VREG("synt", 14, 0, 0),
61 VREG("wlan", 15, 0, 0),
62 VREG("usb", 16, 0, 0),
63 VREG("boost", 17, 0, 0),
64 VREG("mmc", 18, 0, 0),
65 VREG("ruim", 19, 0, 0),
66 VREG("msmc0", 20, 0, 0),
67 VREG("gp2", 21, 0, 0),
68 VREG("gp5", 22, 0, 0),
69 VREG("gp6", 23, 0, 0),
70 VREG("rf", 24, 0, 0),
71 VREG("rf_vco", 26, 0, 0),
72 VREG("mpll", 27, 0, 0),
73 VREG("s2", 28, 0, 0),
74 VREG("s3", 29, 0, 0),
75 VREG("rfubm", 30, 0, 0),
76 VREG("ncp", 31, 0, 0),
Willie Ruan1b70de32009-07-24 17:21:21 -070077 VREG("gp7", 32, 0, 0),
78 VREG("gp8", 33, 0, 0),
79 VREG("gp9", 34, 0, 0),
80 VREG("gp10", 35, 0, 0),
81 VREG("gp11", 36, 0, 0),
82 VREG("gp12", 37, 0, 0),
83 VREG("gp13", 38, 0, 0),
84 VREG("gp14", 39, 0, 0),
85 VREG("gp15", 40, 0, 0),
86 VREG("gp16", 41, 0, 0),
87 VREG("gp17", 42, 0, 0),
88 VREG("s4", 43, 0, 0),
89 VREG("usb2", 44, 0, 0),
90 VREG("wlan2", 45, 0, 0),
91 VREG("xo_out", 46, 0, 0),
92 VREG("lvsw0", 47, 0, 0),
93 VREG("lvsw1", 48, 0, 0),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070094 VREG("mddi", 49, 0, 0),
95 VREG("pllx", 50, 0, 0),
96 VREG("wlan3", 51, 0, 0),
97 VREG("emmc", 52, 0, 0),
98 VREG("wlan_tcx0", 53, 0, 0),
99 VREG("usim2", 54, 0, 0),
100 VREG("usim", 55, 0, 0),
101 VREG("bt", 56, 0, 0),
102 VREG("wlan4", 57, 0, 0),
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700103};
104
105struct vreg *vreg_get(struct device *dev, const char *id)
106{
107 int n;
108 for (n = 0; n < ARRAY_SIZE(vregs); n++) {
109 if (!strcmp(vregs[n].name, id))
110 return vregs + n;
111 }
Steve Muckle0c50b442010-03-04 12:38:05 -0800112 return ERR_PTR(-ENOENT);
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700113}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700114EXPORT_SYMBOL(vreg_get);
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700115
116void vreg_put(struct vreg *vreg)
117{
118}
119
120int vreg_enable(struct vreg *vreg)
121{
122 unsigned id = vreg->id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700123 int enable = VREG_SWITCH_ENABLE;
Steve Muckle4783de92008-12-12 19:33:55 -0500124
Matt Wilson0e441062009-06-29 14:13:04 -0500125 if (vreg->refcnt == 0)
126 vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
127
128 if ((vreg->refcnt < UINT_MAX) && (!vreg->status))
129 vreg->refcnt++;
130
Steve Muckle4783de92008-12-12 19:33:55 -0500131 return vreg->status;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700132}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700133EXPORT_SYMBOL(vreg_enable);
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700134
Steve Muckle4783de92008-12-12 19:33:55 -0500135int vreg_disable(struct vreg *vreg)
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700136{
137 unsigned id = vreg->id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700138 int disable = VREG_SWITCH_DISABLE;
Steve Muckle4783de92008-12-12 19:33:55 -0500139
Matt Wilson0e441062009-06-29 14:13:04 -0500140 if (!vreg->refcnt)
141 return 0;
142
143 if (vreg->refcnt == 1)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700144 vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &disable);
Matt Wilson0e441062009-06-29 14:13:04 -0500145
146 if (!vreg->status)
147 vreg->refcnt--;
148
Steve Muckle4783de92008-12-12 19:33:55 -0500149 return vreg->status;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700150}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700151EXPORT_SYMBOL(vreg_disable);
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700152
153int vreg_set_level(struct vreg *vreg, unsigned mv)
154{
155 unsigned id = vreg->id;
Steve Muckle4783de92008-12-12 19:33:55 -0500156
157 vreg->status = msm_proc_comm(PCOM_VREG_SET_LEVEL, &id, &mv);
158 return vreg->status;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700159}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700160EXPORT_SYMBOL(vreg_set_level);
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700161
162#if defined(CONFIG_DEBUG_FS)
163
164static int vreg_debug_set(void *data, u64 val)
165{
166 struct vreg *vreg = data;
167 switch (val) {
168 case 0:
169 vreg_disable(vreg);
170 break;
171 case 1:
172 vreg_enable(vreg);
173 break;
174 default:
175 vreg_set_level(vreg, val);
176 break;
177 }
178 return 0;
179}
180
181static int vreg_debug_get(void *data, u64 *val)
182{
Steve Muckle4783de92008-12-12 19:33:55 -0500183 struct vreg *vreg = data;
184
185 if (!vreg->status)
186 *val = 0;
187 else
188 *val = 1;
189
190 return 0;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700191}
192
Matt Wilson0e441062009-06-29 14:13:04 -0500193static int vreg_debug_count_set(void *data, u64 val)
194{
195 struct vreg *vreg = data;
196 if (val > UINT_MAX)
197 val = UINT_MAX;
198 vreg->refcnt = val;
199 return 0;
200}
201
202static int vreg_debug_count_get(void *data, u64 *val)
203{
204 struct vreg *vreg = data;
205
206 *val = vreg->refcnt;
207
208 return 0;
209}
210
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700211DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n");
Matt Wilson0e441062009-06-29 14:13:04 -0500212DEFINE_SIMPLE_ATTRIBUTE(vreg_count_fops, vreg_debug_count_get,
213 vreg_debug_count_set, "%llu\n");
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700214
215static int __init vreg_debug_init(void)
216{
217 struct dentry *dent;
218 int n;
Matt Wilson0e441062009-06-29 14:13:04 -0500219 char name[32];
220 const char *refcnt_name = "_refcnt";
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700221
222 dent = debugfs_create_dir("vreg", 0);
223 if (IS_ERR(dent))
224 return 0;
225
Matt Wilson0e441062009-06-29 14:13:04 -0500226 for (n = 0; n < ARRAY_SIZE(vregs); n++) {
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700227 (void) debugfs_create_file(vregs[n].name, 0644,
228 dent, vregs + n, &vreg_fops);
229
Matt Wilson0e441062009-06-29 14:13:04 -0500230 strlcpy(name, vregs[n].name, sizeof(name));
231 strlcat(name, refcnt_name, sizeof(name));
232 (void) debugfs_create_file(name, 0644,
233 dent, vregs + n, &vreg_count_fops);
234 }
235
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700236 return 0;
237}
238
239device_initcall(vreg_debug_init);
240#endif