summaryrefslogtreecommitdiff
path: root/arch/arm/mach-msm/vreg.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-msm/vreg.c')
-rw-r--r--arch/arm/mach-msm/vreg.c115
1 files changed, 79 insertions, 36 deletions
diff --git a/arch/arm/mach-msm/vreg.c b/arch/arm/mach-msm/vreg.c
index 8b0f7b2fd8f7..63db0b3ece53 100644
--- a/arch/arm/mach-msm/vreg.c
+++ b/arch/arm/mach-msm/vreg.c
@@ -19,6 +19,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/debugfs.h>
+#include <linux/string.h>
#include <mach/vreg.h>
#include "proc_comm.h"
@@ -27,43 +28,44 @@ struct vreg {
const char *name;
unsigned id;
int status;
+ unsigned refcnt;
};
-#define VREG(_name, _id, _status) \
- { .name = _name, .id = _id, .status = _status }
+#define VREG(_name, _id, _status, _refcnt) \
+ { .name = _name, .id = _id, .status = _status, .refcnt = _refcnt }
static struct vreg vregs[] = {
- VREG("msma", 0, 0),
- VREG("msmp", 1, 0),
- VREG("msme1", 2, 0),
- VREG("msmc1", 3, 0),
- VREG("msmc2", 4, 0),
- VREG("gp3", 5, 0),
- VREG("msme2", 6, 0),
- VREG("gp4", 7, 0),
- VREG("gp1", 8, 0),
- VREG("tcxo", 9, 0),
- VREG("pa", 10, 0),
- VREG("rftx", 11, 0),
- VREG("rfrx1", 12, 0),
- VREG("rfrx2", 13, 0),
- VREG("synt", 14, 0),
- VREG("wlan", 15, 0),
- VREG("usb", 16, 0),
- VREG("boost", 17, 0),
- VREG("mmc", 18, 0),
- VREG("ruim", 19, 0),
- VREG("msmc0", 20, 0),
- VREG("gp2", 21, 0),
- VREG("gp5", 22, 0),
- VREG("gp6", 23, 0),
- VREG("rf", 24, 0),
- VREG("rf_vco", 26, 0),
- VREG("mpll", 27, 0),
- VREG("s2", 28, 0),
- VREG("s3", 29, 0),
- VREG("rfubm", 30, 0),
- VREG("ncp", 31, 0),
+ VREG("msma", 0, 0, 0),
+ VREG("msmp", 1, 0, 0),
+ VREG("msme1", 2, 0, 0),
+ VREG("msmc1", 3, 0, 0),
+ VREG("msmc2", 4, 0, 0),
+ VREG("gp3", 5, 0, 0),
+ VREG("msme2", 6, 0, 0),
+ VREG("gp4", 7, 0, 0),
+ VREG("gp1", 8, 0, 0),
+ VREG("tcxo", 9, 0, 0),
+ VREG("pa", 10, 0, 0),
+ VREG("rftx", 11, 0, 0),
+ VREG("rfrx1", 12, 0, 0),
+ VREG("rfrx2", 13, 0, 0),
+ VREG("synt", 14, 0, 0),
+ VREG("wlan", 15, 0, 0),
+ VREG("usb", 16, 0, 0),
+ VREG("boost", 17, 0, 0),
+ VREG("mmc", 18, 0, 0),
+ VREG("ruim", 19, 0, 0),
+ VREG("msmc0", 20, 0, 0),
+ VREG("gp2", 21, 0, 0),
+ VREG("gp5", 22, 0, 0),
+ VREG("gp6", 23, 0, 0),
+ VREG("rf", 24, 0, 0),
+ VREG("rf_vco", 26, 0, 0),
+ VREG("mpll", 27, 0, 0),
+ VREG("s2", 28, 0, 0),
+ VREG("s3", 29, 0, 0),
+ VREG("rfubm", 30, 0, 0),
+ VREG("ncp", 31, 0, 0),
};
struct vreg *vreg_get(struct device *dev, const char *id)
@@ -85,7 +87,12 @@ int vreg_enable(struct vreg *vreg)
unsigned id = vreg->id;
unsigned enable = 1;
- vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
+ if (vreg->refcnt == 0)
+ vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
+
+ if ((vreg->refcnt < UINT_MAX) && (!vreg->status))
+ vreg->refcnt++;
+
return vreg->status;
}
@@ -94,7 +101,15 @@ int vreg_disable(struct vreg *vreg)
unsigned id = vreg->id;
unsigned enable = 0;
- vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
+ if (!vreg->refcnt)
+ return 0;
+
+ if (vreg->refcnt == 1)
+ vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
+
+ if (!vreg->status)
+ vreg->refcnt--;
+
return vreg->status;
}
@@ -137,21 +152,49 @@ static int vreg_debug_get(void *data, u64 *val)
return 0;
}
+static int vreg_debug_count_set(void *data, u64 val)
+{
+ struct vreg *vreg = data;
+ if (val > UINT_MAX)
+ val = UINT_MAX;
+ vreg->refcnt = val;
+ return 0;
+}
+
+static int vreg_debug_count_get(void *data, u64 *val)
+{
+ struct vreg *vreg = data;
+
+ *val = vreg->refcnt;
+
+ return 0;
+}
+
DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(vreg_count_fops, vreg_debug_count_get,
+ vreg_debug_count_set, "%llu\n");
static int __init vreg_debug_init(void)
{
struct dentry *dent;
int n;
+ char name[32];
+ const char *refcnt_name = "_refcnt";
dent = debugfs_create_dir("vreg", 0);
if (IS_ERR(dent))
return 0;
- for (n = 0; n < ARRAY_SIZE(vregs); n++)
+ for (n = 0; n < ARRAY_SIZE(vregs); n++) {
(void) debugfs_create_file(vregs[n].name, 0644,
dent, vregs + n, &vreg_fops);
+ strlcpy(name, vregs[n].name, sizeof(name));
+ strlcat(name, refcnt_name, sizeof(name));
+ (void) debugfs_create_file(name, 0644,
+ dent, vregs + n, &vreg_count_fops);
+ }
+
return 0;
}