]> bbs.cooldavid.org Git - net-next-2.6.git/blame - arch/arm/mach-msm/vreg.c
arm: msm: add vreg reference count
[net-next-2.6.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),
f030d7b6
BS
69};
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 }
0c50b444 78 return ERR_PTR(-ENOENT);
f030d7b6
BS
79}
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;
4783de9b 89
0e44106d
MW
90 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
4783de9b 96 return vreg->status;
f030d7b6
BS
97}
98
4783de9b 99int vreg_disable(struct vreg *vreg)
f030d7b6
BS
100{
101 unsigned id = vreg->id;
102 unsigned enable = 0;
4783de9b 103
0e44106d
MW
104 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
4783de9b 113 return vreg->status;
f030d7b6
BS
114}
115
116int vreg_set_level(struct vreg *vreg, unsigned mv)
117{
118 unsigned id = vreg->id;
4783de9b
SM
119
120 vreg->status = msm_proc_comm(PCOM_VREG_SET_LEVEL, &id, &mv);
121 return vreg->status;
f030d7b6
BS
122}
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{
4783de9b
SM
145 struct vreg *vreg = data;
146
147 if (!vreg->status)
148 *val = 0;
149 else
150 *val = 1;
151
152 return 0;
f030d7b6
BS
153}
154
0e44106d
MW
155static 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
f030d7b6 173DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n");
0e44106d
MW
174DEFINE_SIMPLE_ATTRIBUTE(vreg_count_fops, vreg_debug_count_get,
175 vreg_debug_count_set, "%llu\n");
f030d7b6
BS
176
177static int __init vreg_debug_init(void)
178{
179 struct dentry *dent;
180 int n;
0e44106d
MW
181 char name[32];
182 const char *refcnt_name = "_refcnt";
f030d7b6
BS
183
184 dent = debugfs_create_dir("vreg", 0);
185 if (IS_ERR(dent))
186 return 0;
187
0e44106d 188 for (n = 0; n < ARRAY_SIZE(vregs); n++) {
f030d7b6
BS
189 (void) debugfs_create_file(vregs[n].name, 0644,
190 dent, vregs + n, &vreg_fops);
191
0e44106d
MW
192 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
f030d7b6
BS
198 return 0;
199}
200
201device_initcall(vreg_debug_init);
202#endif