Re: [RFC][Patch] OMAP3 PM: sysfs vdd_opp change to use Constraint Framework
Sripathy, Vishwanath vishwanath...@ti.com writes: Sysfs entry vdd_opp currently does not use constraint framework. Because of this, even if you set the opp via this entry, it has no effect since it can be overridden by on demand governor any time. This patch has changes to make vdd_opp to use constraint framework. vdd_lock variable has to be used when application wants to disable DVFS altogether. This will override any other constraints and will lock the OPP to given value. Signed-off-by: Vishwanath BS vishwanath...@ti.com This raises an issue that I've been thinking about for awhile. Basically, I'd like to drop all the /sys/power/vdd* options. Since we can do the equivalent with CPUFreq using the userspace governor, I don't see the point of having an additional interface. Comments? Kevin --- diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 13783f3..bcdc00d 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -47,6 +47,8 @@ static ssize_t idle_store(struct kobject *k, struct kobj_attribute *, 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 ssize_t vdd_opp_lock_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); @@ -103,6 +105,41 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { unsigned short value; + struct omap_opp *opp_table; + + if (sscanf(buf, %hu, value) != 1) + return -EINVAL; + + if (attr == vdd1_opp_attr) { + if (value MIN_VDD1_OPP || value MAX_VDD1_OPP) { + printk(KERN_ERR vdd_opp_store: Invalid value\n); + return -EINVAL; + } + opp_table = omap_get_mpu_rate_table(); + omap_pm_cpu_set_freq(sysfs_cpufreq_dev, + opp_table[value].rate); + } else if (attr == vdd2_opp_attr) { + if (value MIN_VDD2_OPP || (value MAX_VDD2_OPP)) { + printk(KERN_ERR vdd_opp_store: Invalid value\n); + return -EINVAL; + } + if (value == VDD2_OPP2) + omap_pm_set_min_bus_tput(sysfs_cpufreq_dev, + OCP_INITIATOR_AGENT, 83*1000*4); + else if (value == VDD2_OPP3) + omap_pm_set_min_bus_tput(sysfs_cpufreq_dev, + OCP_INITIATOR_AGENT, 166*1000*4); + + } else { + return -EINVAL; + } + return n; +} + +static ssize_t vdd_opp_lock_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t n) +{ + unsigned short value; int flags = 0; if (sscanf(buf, %hu, value) != 1) @@ -121,6 +158,11 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, if (vdd1_locked == 0 value != 0) { resource_lock_opp(VDD1_OPP); vdd1_locked = 1; + if (value MIN_VDD1_OPP || value MAX_VDD1_OPP) { + printk(KERN_ERR vdd_opp_store: Invalid value\n); + return -EINVAL; + } + resource_set_opp_level(VDD1_OPP, value, flags); } } else if (attr == vdd2_lock_attr) { flags = OPP_IGNORE_LOCK; @@ -134,21 +176,12 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, if (vdd2_locked == 0 value != 0) { resource_lock_opp(VDD2_OPP); vdd2_locked = 1; + if (value MIN_VDD2_OPP || value MAX_VDD2_OPP) { + printk(KERN_ERR vdd_opp_store: Invalid value\n); + return -EINVAL; + } + resource_set_opp_level(VDD2_OPP, value, flags); } - } - - if (attr == vdd1_opp_attr) { - if (value 1 || value 5) { - printk(KERN_ERR vdd_opp_store: Invalid value\n); - return -EINVAL; - } - resource_set_opp_level(VDD1_OPP, value, flags); - } else if (attr == vdd2_opp_attr) { - if (value 2 || value 3) { - printk(KERN_ERR vdd_opp_store: Invalid value\n); - return -EINVAL; - } - resource_set_opp_level(VDD2_OPP, value, flags); } else { return -EINVAL; } -- To unsubscribe from this list:
Re: [RFC][Patch] OMAP3 PM: sysfs vdd_opp change to use Constraint Framework
* Kevin Hilman khil...@deeprootsystems.com [091020 08:51]: Sripathy, Vishwanath vishwanath...@ti.com writes: Sysfs entry vdd_opp currently does not use constraint framework. Because of this, even if you set the opp via this entry, it has no effect since it can be overridden by on demand governor any time. This patch has changes to make vdd_opp to use constraint framework. vdd_lock variable has to be used when application wants to disable DVFS altogether. This will override any other constraints and will lock the OPP to given value. Signed-off-by: Vishwanath BS vishwanath...@ti.com This raises an issue that I've been thinking about for awhile. Basically, I'd like to drop all the /sys/power/vdd* options. Since we can do the equivalent with CPUFreq using the userspace governor, I don't see the point of having an additional interface. Comments? Total ack from me! Tony Kevin --- diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 13783f3..bcdc00d 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -47,6 +47,8 @@ static ssize_t idle_store(struct kobject *k, struct kobj_attribute *, 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 ssize_t vdd_opp_lock_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); @@ -103,6 +105,41 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { unsigned short value; + struct omap_opp *opp_table; + + if (sscanf(buf, %hu, value) != 1) + return -EINVAL; + + if (attr == vdd1_opp_attr) { + if (value MIN_VDD1_OPP || value MAX_VDD1_OPP) { + printk(KERN_ERR vdd_opp_store: Invalid value\n); + return -EINVAL; + } + opp_table = omap_get_mpu_rate_table(); + omap_pm_cpu_set_freq(sysfs_cpufreq_dev, + opp_table[value].rate); + } else if (attr == vdd2_opp_attr) { + if (value MIN_VDD2_OPP || (value MAX_VDD2_OPP)) { + printk(KERN_ERR vdd_opp_store: Invalid value\n); + return -EINVAL; + } + if (value == VDD2_OPP2) + omap_pm_set_min_bus_tput(sysfs_cpufreq_dev, + OCP_INITIATOR_AGENT, 83*1000*4); + else if (value == VDD2_OPP3) + omap_pm_set_min_bus_tput(sysfs_cpufreq_dev, + OCP_INITIATOR_AGENT, 166*1000*4); + + } else { + return -EINVAL; + } + return n; +} + +static ssize_t vdd_opp_lock_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t n) +{ + unsigned short value; int flags = 0; if (sscanf(buf, %hu, value) != 1) @@ -121,6 +158,11 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, if (vdd1_locked == 0 value != 0) { resource_lock_opp(VDD1_OPP); vdd1_locked = 1; + if (value MIN_VDD1_OPP || value MAX_VDD1_OPP) { + printk(KERN_ERR vdd_opp_store: Invalid value\n); + return -EINVAL; + } + resource_set_opp_level(VDD1_OPP, value, flags); } } else if (attr == vdd2_lock_attr) { flags = OPP_IGNORE_LOCK; @@ -134,21 +176,12 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, if (vdd2_locked == 0 value != 0) { resource_lock_opp(VDD2_OPP); vdd2_locked = 1; + if (value MIN_VDD2_OPP || value MAX_VDD2_OPP) { + printk(KERN_ERR vdd_opp_store: Invalid value\n); + return -EINVAL; + } + resource_set_opp_level(VDD2_OPP, value, flags); } - } - - if (attr == vdd1_opp_attr) { - if (value 1 || value 5) { - printk(KERN_ERR vdd_opp_store: Invalid value\n); - return -EINVAL; - } - resource_set_opp_level(VDD1_OPP, value, flags); - } else if (attr == vdd2_opp_attr) { - if (value 2 || value 3) { - printk(KERN_ERR vdd_opp_store: Invalid value\n); - return -EINVAL; - } - resource_set_opp_level(VDD2_OPP, value, flags); } else {
RE: [RFC][Patch] OMAP3 PM: sysfs vdd_opp change to use Constraint Framework
Note that this patch has dependency on Patch sent by Romit (in attached email). Vishwanath -Original Message- From: Sripathy, Vishwanath Sent: Friday, October 16, 2009 2:26 PM To: Sripathy, Vishwanath; linux-omap@vger.kernel.org; Hilman, Kevin Subject: [RFC][Patch] OMAP3 PM: sysfs vdd_opp change to use Constraint Framework Sysfs entry vdd_opp currently does not use constraint framework. Because of this, even if you set the opp via this entry, it has no effect since it can be overridden by on demand governor any time. This patch has changes to make vdd_opp to use constraint framework. vdd_lock variable has to be used when application wants to disable DVFS altogether. This will override any other constraints and will lock the OPP to given value. Signed-off-by: Vishwanath BS vishwanath...@ti.com --- diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 13783f3..bcdc00d 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -47,6 +47,8 @@ static ssize_t idle_store(struct kobject *k, struct kobj_attribute *, 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 ssize_t vdd_opp_lock_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); @@ -103,6 +105,41 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { unsigned short value; + struct omap_opp *opp_table; + + if (sscanf(buf, %hu, value) != 1) + return -EINVAL; + + if (attr == vdd1_opp_attr) { + if (value MIN_VDD1_OPP || value MAX_VDD1_OPP) { + printk(KERN_ERR vdd_opp_store: Invalid value\n); + return -EINVAL; + } + opp_table = omap_get_mpu_rate_table(); + omap_pm_cpu_set_freq(sysfs_cpufreq_dev, + opp_table[value].rate); + } else if (attr == vdd2_opp_attr) { + if (value MIN_VDD2_OPP || (value MAX_VDD2_OPP)) { + printk(KERN_ERR vdd_opp_store: Invalid value\n); + return -EINVAL; + } + if (value == VDD2_OPP2) + omap_pm_set_min_bus_tput(sysfs_cpufreq_dev, + OCP_INITIATOR_AGENT, 83*1000*4); + else if (value == VDD2_OPP3) + omap_pm_set_min_bus_tput(sysfs_cpufreq_dev, + OCP_INITIATOR_AGENT, 166*1000*4); + + } else { + return -EINVAL; + } + return n; +} + +static ssize_t vdd_opp_lock_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t n) +{ + unsigned short value; int flags = 0; if (sscanf(buf, %hu, value) != 1) @@ -121,6 +158,11 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, if (vdd1_locked == 0 value != 0) { resource_lock_opp(VDD1_OPP); vdd1_locked = 1; + if (value MIN_VDD1_OPP || value MAX_VDD1_OPP) { + printk(KERN_ERR vdd_opp_store: Invalid value\n); + return -EINVAL; + } + resource_set_opp_level(VDD1_OPP, value, flags); } } else if (attr == vdd2_lock_attr) { flags = OPP_IGNORE_LOCK; @@ -134,21 +176,12 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, if (vdd2_locked == 0 value != 0) { resource_lock_opp(VDD2_OPP); vdd2_locked = 1; + if (value MIN_VDD2_OPP || value MAX_VDD2_OPP) { + printk(KERN_ERR vdd_opp_store: Invalid value\n); + return -EINVAL; + } + resource_set_opp_level(VDD2_OPP, value, flags); } - } - - if (attr == vdd1_opp_attr) { - if (value 1 || value 5) { - printk(KERN_ERR vdd_opp_store: Invalid value\n); - return -EINVAL; - } - resource_set_opp_level(VDD1_OPP, value, flags); - } else if (attr == vdd2_opp_attr) { - if (value 2 || value 3) { - printk(KERN_ERR vdd_opp_store: Invalid value\n); - return -EINVAL; - } - resource_set_opp_level(VDD2_OPP, value, flags); } else { return -EINVAL;