blob: bd66ed04d6dc0edfdc489a56a7f1e9fb84dbafc1 [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>
David Brown5e1a0f92012-01-05 15:55:46 -080022#include <linux/module.h>
Matt Wilson0e441062009-06-29 14:13:04 -050023#include <linux/string.h>
Brian Swetlandf030d7b2008-09-29 14:07:14 -070024#include <mach/vreg.h>
25
26#include "proc_comm.h"
27
28struct vreg {
29 const char *name;
30 unsigned id;
Steve Muckle4783de92008-12-12 19:33:55 -050031 int status;
Matt Wilson0e441062009-06-29 14:13:04 -050032 unsigned refcnt;
Brian Swetlandf030d7b2008-09-29 14:07:14 -070033};
34
Matt Wilson0e441062009-06-29 14:13:04 -050035#define VREG(_name, _id, _status, _refcnt) \
36 { .name = _name, .id = _id, .status = _status, .refcnt = _refcnt }
Brian Swetlandf030d7b2008-09-29 14:07:14 -070037
38static struct vreg vregs[] = {
Matt Wilson0e441062009-06-29 14:13:04 -050039 VREG("msma", 0, 0, 0),
40 VREG("msmp", 1, 0, 0),
41 VREG("msme1", 2, 0, 0),
42 VREG("msmc1", 3, 0, 0),
43 VREG("msmc2", 4, 0, 0),
44 VREG("gp3", 5, 0, 0),
45 VREG("msme2", 6, 0, 0),
46 VREG("gp4", 7, 0, 0),
47 VREG("gp1", 8, 0, 0),
48 VREG("tcxo", 9, 0, 0),
49 VREG("pa", 10, 0, 0),
50 VREG("rftx", 11, 0, 0),
51 VREG("rfrx1", 12, 0, 0),
52 VREG("rfrx2", 13, 0, 0),
53 VREG("synt", 14, 0, 0),
54 VREG("wlan", 15, 0, 0),
55 VREG("usb", 16, 0, 0),
56 VREG("boost", 17, 0, 0),
57 VREG("mmc", 18, 0, 0),
58 VREG("ruim", 19, 0, 0),
59 VREG("msmc0", 20, 0, 0),
60 VREG("gp2", 21, 0, 0),
61 VREG("gp5", 22, 0, 0),
62 VREG("gp6", 23, 0, 0),
63 VREG("rf", 24, 0, 0),
64 VREG("rf_vco", 26, 0, 0),
65 VREG("mpll", 27, 0, 0),
66 VREG("s2", 28, 0, 0),
67 VREG("s3", 29, 0, 0),
68 VREG("rfubm", 30, 0, 0),
69 VREG("ncp", 31, 0, 0),
Willie Ruan1b70de32009-07-24 17:21:21 -070070 VREG("gp7", 32, 0, 0),
71 VREG("gp8", 33, 0, 0),
72 VREG("gp9", 34, 0, 0),
73 VREG("gp10", 35, 0, 0),
74 VREG("gp11", 36, 0, 0),
75 VREG("gp12", 37, 0, 0),
76 VREG("gp13", 38, 0, 0),
77 VREG("gp14", 39, 0, 0),
78 VREG("gp15", 40, 0, 0),
79 VREG("gp16", 41, 0, 0),
80 VREG("gp17", 42, 0, 0),
81 VREG("s4", 43, 0, 0),
82 VREG("usb2", 44, 0, 0),
83 VREG("wlan2", 45, 0, 0),
84 VREG("xo_out", 46, 0, 0),
85 VREG("lvsw0", 47, 0, 0),
86 VREG("lvsw1", 48, 0, 0),
Brian Swetlandf030d7b2008-09-29 14:07:14 -070087};
88
89struct vreg *vreg_get(struct device *dev, const char *id)
90{
91 int n;
92 for (n = 0; n < ARRAY_SIZE(vregs); n++) {
93 if (!strcmp(vregs[n].name, id))
94 return vregs + n;
95 }
Steve Muckle0c50b442010-03-04 12:38:05 -080096 return ERR_PTR(-ENOENT);
Brian Swetlandf030d7b2008-09-29 14:07:14 -070097}
98
99void vreg_put(struct vreg *vreg)
100{
101}
102
103int vreg_enable(struct vreg *vreg)
104{
105 unsigned id = vreg->id;
106 unsigned enable = 1;
Steve Muckle4783de92008-12-12 19:33:55 -0500107
Matt Wilson0e441062009-06-29 14:13:04 -0500108 if (vreg->refcnt == 0)
109 vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
110
111 if ((vreg->refcnt < UINT_MAX) && (!vreg->status))
112 vreg->refcnt++;
113
Steve Muckle4783de92008-12-12 19:33:55 -0500114 return vreg->status;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700115}
116
Steve Muckle4783de92008-12-12 19:33:55 -0500117int vreg_disable(struct vreg *vreg)
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700118{
119 unsigned id = vreg->id;
120 unsigned enable = 0;
Steve Muckle4783de92008-12-12 19:33:55 -0500121
Matt Wilson0e441062009-06-29 14:13:04 -0500122 if (!vreg->refcnt)
123 return 0;
124
125 if (vreg->refcnt == 1)
126 vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
127
128 if (!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}
133
134int vreg_set_level(struct vreg *vreg, unsigned mv)
135{
136 unsigned id = vreg->id;
Steve Muckle4783de92008-12-12 19:33:55 -0500137
138 vreg->status = msm_proc_comm(PCOM_VREG_SET_LEVEL, &id, &mv);
139 return vreg->status;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700140}
141
142#if defined(CONFIG_DEBUG_FS)
143
144static int vreg_debug_set(void *data, u64 val)
145{
146 struct vreg *vreg = data;
147 switch (val) {
148 case 0:
149 vreg_disable(vreg);
150 break;
151 case 1:
152 vreg_enable(vreg);
153 break;
154 default:
155 vreg_set_level(vreg, val);
156 break;
157 }
158 return 0;
159}
160
161static int vreg_debug_get(void *data, u64 *val)
162{
Steve Muckle4783de92008-12-12 19:33:55 -0500163 struct vreg *vreg = data;
164
165 if (!vreg->status)
166 *val = 0;
167 else
168 *val = 1;
169
170 return 0;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700171}
172
Matt Wilson0e441062009-06-29 14:13:04 -0500173static int vreg_debug_count_set(void *data, u64 val)
174{
175 struct vreg *vreg = data;
176 if (val > UINT_MAX)
177 val = UINT_MAX;
178 vreg->refcnt = val;
179 return 0;
180}
181
182static int vreg_debug_count_get(void *data, u64 *val)
183{
184 struct vreg *vreg = data;
185
186 *val = vreg->refcnt;
187
188 return 0;
189}
190
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700191DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n");
Matt Wilson0e441062009-06-29 14:13:04 -0500192DEFINE_SIMPLE_ATTRIBUTE(vreg_count_fops, vreg_debug_count_get,
193 vreg_debug_count_set, "%llu\n");
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700194
195static int __init vreg_debug_init(void)
196{
197 struct dentry *dent;
198 int n;
Matt Wilson0e441062009-06-29 14:13:04 -0500199 char name[32];
200 const char *refcnt_name = "_refcnt";
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700201
202 dent = debugfs_create_dir("vreg", 0);
203 if (IS_ERR(dent))
204 return 0;
205
Matt Wilson0e441062009-06-29 14:13:04 -0500206 for (n = 0; n < ARRAY_SIZE(vregs); n++) {
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700207 (void) debugfs_create_file(vregs[n].name, 0644,
208 dent, vregs + n, &vreg_fops);
209
Matt Wilson0e441062009-06-29 14:13:04 -0500210 strlcpy(name, vregs[n].name, sizeof(name));
211 strlcat(name, refcnt_name, sizeof(name));
212 (void) debugfs_create_file(name, 0644,
213 dent, vregs + n, &vreg_count_fops);
214 }
215
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700216 return 0;
217}
218
219device_initcall(vreg_debug_init);
220#endif