blob: a9103bc6615f01ac526d8b085939fb4f20433ffb [file] [log] [blame]
Brian Swetlandf030d7b2008-09-29 14:07:14 -07001/* arch/arm/mach-msm/vreg.c
2 *
3 * Copyright (C) 2008 Google, Inc.
Steve Muckle4783de92008-12-12 19:33:55 -05004 * Copyright (c) 2009, 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
27struct vreg {
28 const char *name;
29 unsigned id;
Steve Muckle4783de92008-12-12 19:33:55 -050030 int status;
Matt Wilson0e441062009-06-29 14:13:04 -050031 unsigned refcnt;
Brian Swetlandf030d7b2008-09-29 14:07:14 -070032};
33
Matt Wilson0e441062009-06-29 14:13:04 -050034#define VREG(_name, _id, _status, _refcnt) \
35 { .name = _name, .id = _id, .status = _status, .refcnt = _refcnt }
Brian Swetlandf030d7b2008-09-29 14:07:14 -070036
37static struct vreg vregs[] = {
Matt Wilson0e441062009-06-29 14:13:04 -050038 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),
Willie Ruan1b70de32009-07-24 17:21:21 -070069 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),
Brian Swetlandf030d7b2008-09-29 14:07:14 -070086};
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 }
Steve Muckle0c50b442010-03-04 12:38:05 -080095 return ERR_PTR(-ENOENT);
Brian Swetlandf030d7b2008-09-29 14:07:14 -070096}
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;
Steve Muckle4783de92008-12-12 19:33:55 -0500106
Matt Wilson0e441062009-06-29 14:13:04 -0500107 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
Steve Muckle4783de92008-12-12 19:33:55 -0500113 return vreg->status;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700114}
115
Steve Muckle4783de92008-12-12 19:33:55 -0500116int vreg_disable(struct vreg *vreg)
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700117{
118 unsigned id = vreg->id;
119 unsigned enable = 0;
Steve Muckle4783de92008-12-12 19:33:55 -0500120
Matt Wilson0e441062009-06-29 14:13:04 -0500121 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
Steve Muckle4783de92008-12-12 19:33:55 -0500130 return vreg->status;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700131}
132
133int vreg_set_level(struct vreg *vreg, unsigned mv)
134{
135 unsigned id = vreg->id;
Steve Muckle4783de92008-12-12 19:33:55 -0500136
137 vreg->status = msm_proc_comm(PCOM_VREG_SET_LEVEL, &id, &mv);
138 return vreg->status;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700139}
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{
Steve Muckle4783de92008-12-12 19:33:55 -0500162 struct vreg *vreg = data;
163
164 if (!vreg->status)
165 *val = 0;
166 else
167 *val = 1;
168
169 return 0;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700170}
171
Matt Wilson0e441062009-06-29 14:13:04 -0500172static 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
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700190DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n");
Matt Wilson0e441062009-06-29 14:13:04 -0500191DEFINE_SIMPLE_ATTRIBUTE(vreg_count_fops, vreg_debug_count_get,
192 vreg_debug_count_set, "%llu\n");
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700193
194static int __init vreg_debug_init(void)
195{
196 struct dentry *dent;
197 int n;
Matt Wilson0e441062009-06-29 14:13:04 -0500198 char name[32];
199 const char *refcnt_name = "_refcnt";
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700200
201 dent = debugfs_create_dir("vreg", 0);
202 if (IS_ERR(dent))
203 return 0;
204
Matt Wilson0e441062009-06-29 14:13:04 -0500205 for (n = 0; n < ARRAY_SIZE(vregs); n++) {
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700206 (void) debugfs_create_file(vregs[n].name, 0644,
207 dent, vregs + n, &vreg_fops);
208
Matt Wilson0e441062009-06-29 14:13:04 -0500209 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
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700215 return 0;
216}
217
218device_initcall(vreg_debug_init);
219#endif