@@ -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;
}