From 890184a1000bb0fb477d6de6507bafd39c05fb1b Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Mon, 10 Nov 2008 16:59:10 +0530 Subject: [PATCH] OMAP3 SRF: Adds sysfs control for VDD1/VDD2 OPP's Adds sysfs hooks to control VDD1 and VDD2 OPP's in the absense of a CPUFreq driver/governor Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/pm.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 9b2c51dd2c7..c530dd767f4 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,7 @@ #include #include +#include #include "prm-regbits-34xx.h" #include "pm.h" @@ -41,6 +43,18 @@ static ssize_t idle_show(struct kobject *, struct kobj_attribute *, char *); static ssize_t idle_store(struct kobject *k, struct kobj_attribute *, const char *buf, size_t n); +#ifdef CONFIG_OMAP_PM_SRF +static struct device dummy_sysfs_dev; +static ssize_t vdd_opp_show(struct kobject *, struct kobj_attribute *, char *); +static ssize_t vdd_opp_store(struct kobject *k, struct kobj_attribute *, + const char *buf, size_t n); +static struct kobj_attribute vdd1_opp_attr = + __ATTR(vdd1_opp, 0644, vdd_opp_show, vdd_opp_store); + +static struct kobj_attribute vdd2_opp_attr = + __ATTR(vdd2_opp, 0644, vdd_opp_show, vdd_opp_store); +#endif + static ssize_t idle_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -61,6 +75,45 @@ static ssize_t idle_store(struct kobject *kobj, struct kobj_attribute *attr, return n; } +#ifdef CONFIG_OMAP_PM_SRF +static ssize_t vdd_opp_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + if (attr == &vdd1_opp_attr) + return sprintf(buf, "%hu\n", resource_get_level("vdd1_opp")); + else if (attr == &vdd2_opp_attr) + return sprintf(buf, "%hu\n", resource_get_level("vdd2_opp")); + else + return -EINVAL; +} + +static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n) +{ + unsigned short value; + + if (sscanf(buf, "%hu", &value) != 1) + return -EINVAL; + + if (attr == &vdd1_opp_attr) { + if (value < 1 || value > 5) { + printk(KERN_ERR "vdd_opp_store: Invalid value\n"); + return -EINVAL; + } + resource_request("vdd1_opp", &dummy_sysfs_dev, value); + } else if (attr == &vdd2_opp_attr) { + if (value < 2 || value > 3) { + printk(KERN_ERR "vdd_opp_store: Invalid value\n"); + return -EINVAL; + } + resource_request("vdd2_opp", &dummy_sysfs_dev, value); + } else { + return -EINVAL; + } + return n; +} +#endif + void omap2_block_sleep(void) { atomic_inc(&sleep_block); @@ -93,6 +146,21 @@ static int __init omap_pm_init(void) { int error = -1; +#ifdef CONFIG_OMAP_PM_SRF + error = sysfs_create_file(power_kobj, + &vdd1_opp_attr.attr); + if (error) { + printk(KERN_ERR "sysfs_create_file failed: %d\n", error); + return error; + } + error = sysfs_create_file(power_kobj, + &vdd2_opp_attr.attr); + if (error) { + printk(KERN_ERR "sysfs_create_file failed: %d\n", error); + return error; + } +#endif + return error; } late_initcall(omap_pm_init); -- 2.11.4.GIT