blob: 63db0b3ece538a7ac3a58d3d2f6d1c6e4d785853 [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),
Brian Swetlandf030d7b2008-09-29 14:07:14 -070069};
70
71struct vreg *vreg_get(struct device *dev, const char *id)
72{
73 int n;
74 for (n = 0; n < ARRAY_SIZE(vregs); n++) {
75 if (!strcmp(vregs[n].name, id))
76 return vregs + n;
77 }
Steve Muckle0c50b442010-03-04 12:38:05 -080078 return ERR_PTR(-ENOENT);
Brian Swetlandf030d7b2008-09-29 14:07:14 -070079}
80
81void vreg_put(struct vreg *vreg)
82{
83}
84
85int vreg_enable(struct vreg *vreg)
86{
87 unsigned id = vreg->id;
88 unsigned enable = 1;
Steve Muckle4783de92008-12-12 19:33:55 -050089
Matt Wilson0e441062009-06-29 14:13:04 -050090 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
Steve Muckle4783de92008-12-12 19:33:55 -050096 return vreg->status;
Brian Swetlandf030d7b2008-09-29 14:07:14 -070097}
98
Steve Muckle4783de92008-12-12 19:33:55 -050099int vreg_disable(struct vreg *vreg)
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700100{
101 unsigned id = vreg->id;
102 unsigned enable = 0;
Steve Muckle4783de92008-12-12 19:33:55 -0500103
Matt Wilson0e441062009-06-29 14:13:04 -0500104 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
Steve Muckle4783de92008-12-12 19:33:55 -0500113 return vreg->status;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700114}
115
116int vreg_set_level(struct vreg *vreg, unsigned mv)
117{
118 unsigned id = vreg->id;
Steve Muckle4783de92008-12-12 19:33:55 -0500119
120 vreg->status = msm_proc_comm(PCOM_VREG_SET_LEVEL, &id, &mv);
121 return vreg->status;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700122}
123
124#if defined(CONFIG_DEBUG_FS)
125
126static int vreg_debug_set(void *data, u64 val)
127{
128 struct vreg *vreg = data;
129 switch (val) {
130 case 0:
131 vreg_disable(vreg);
132 break;
133 case 1:
134 vreg_enable(vreg);
135 break;
136 default:
137 vreg_set_level(vreg, val);
138 break;
139 }
140 return 0;
141}
142
143static int vreg_debug_get(void *data, u64 *val)
144{
Steve Muckle4783de92008-12-12 19:33:55 -0500145 struct vreg *vreg = data;
146
147 if (!vreg->status)
148 *val = 0;
149 else
150 *val = 1;
151
152 return 0;
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700153}
154
Matt Wilson0e441062009-06-29 14:13:04 -0500155static 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
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700173DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n");
Matt Wilson0e441062009-06-29 14:13:04 -0500174DEFINE_SIMPLE_ATTRIBUTE(vreg_count_fops, vreg_debug_count_get,
175 vreg_debug_count_set, "%llu\n");
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700176
177static int __init vreg_debug_init(void)
178{
179 struct dentry *dent;
180 int n;
Matt Wilson0e441062009-06-29 14:13:04 -0500181 char name[32];
182 const char *refcnt_name = "_refcnt";
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700183
184 dent = debugfs_create_dir("vreg", 0);
185 if (IS_ERR(dent))
186 return 0;
187
Matt Wilson0e441062009-06-29 14:13:04 -0500188 for (n = 0; n < ARRAY_SIZE(vregs); n++) {
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700189 (void) debugfs_create_file(vregs[n].name, 0644,
190 dent, vregs + n, &vreg_fops);
191
Matt Wilson0e441062009-06-29 14:13:04 -0500192 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
Brian Swetlandf030d7b2008-09-29 14:07:14 -0700198 return 0;
199}
200
201device_initcall(vreg_debug_init);
202#endif