aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPer Fransson <per.xx.fransson@stericsson.com>2011-03-17 13:46:12 +0100
committerJonas ABERG <jonas.aberg@stericsson.com>2011-03-30 16:36:36 +0200
commit1c6a560b99f943219bf2f7745b7caa25c2dd0953 (patch)
treebe907b4dcb841c84857916774c439239e13ea74b
parente85c6325d482d1bcb195059775134b431b319e01 (diff)
ARM: ux500: Make it possible to force DDR and APE OPP
Forces the OPPs to the values written, regardless of the QoS requirements. echo 25 > /debugfs/prcmu/ddr_opp echo 50 > /debugfs/prcmu/ddr_opp echo 100 > /debugfs/prcmu/ddr_opp echo 50 > /debugfs/prcmu/ape_opp echo 100 > /debugfs/prcmu/ape_opp ST-Ericsson ID: CR 323730 Change-Id: I5fd18e254f3da5342a17cd207b0ee94da0a8cc28 Signed-off-by: Per Fransson <per.xx.fransson@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/18702 Reviewed-by: Martin PERSSON <martin.persson@stericsson.com>
-rw-r--r--arch/arm/mach-ux500/include/mach/prcmu-fw-api.h3
-rw-r--r--arch/arm/mach-ux500/prcmu-debug.c40
-rw-r--r--arch/arm/mach-ux500/prcmu-qos-power.c40
3 files changed, 72 insertions, 11 deletions
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h b/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h
index 6785b9dff6e..d4c964fa2d9 100644
--- a/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h
+++ b/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h
@@ -257,6 +257,7 @@ int prcmu_set_ddr_opp(u8 opp);
int prcmu_get_ddr_opp(void);
unsigned long prcmu_qos_get_cpufreq_opp_delay(void);
void prcmu_qos_set_cpufreq_opp_delay(unsigned long);
+void prcmu_qos_force_opp(int, s32);
/* NOTE! Use regulator framework instead */
int prcmu_set_hwacc(u16 hw_acc_dev, u8 state);
int prcmu_set_epod(u16 epod_id, u8 epod_state);
@@ -369,6 +370,8 @@ static inline unsigned long prcmu_qos_get_cpufreq_opp_delay(void)
static inline void prcmu_qos_set_cpufreq_opp_delay(unsigned long n) {}
+void prcmu_qos_force_opp(int prcmu_qos_class, s32 i) {}
+
static inline int prcmu_set_hwacc(u16 hw_acc_dev, u8 state)
{
return 0;
diff --git a/arch/arm/mach-ux500/prcmu-debug.c b/arch/arm/mach-ux500/prcmu-debug.c
index 942740b4a23..42892d59fb1 100644
--- a/arch/arm/mach-ux500/prcmu-debug.c
+++ b/arch/arm/mach-ux500/prcmu-debug.c
@@ -280,6 +280,44 @@ static int ddr_opp_read(struct seq_file *s, void *p)
"unknown", opp);
}
+static ssize_t opp_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos, int prcmu_qos_class)
+{
+ char buf[32];
+ ssize_t buf_size;
+ long unsigned int i;
+
+ /* Get userspace string and assure termination */
+ buf_size = min(count, (sizeof(buf)-1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ if (strict_strtoul(buf, 0, &i) != 0)
+ return buf_size;
+
+ prcmu_qos_force_opp(prcmu_qos_class, i);
+
+ pr_info("prcmu debug: forced OPP for %d to %d\n", prcmu_qos_class, i);
+
+ return buf_size;
+}
+
+static ssize_t ddr_opp_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return opp_write(file, user_buf, count, ppos, PRCMU_QOS_DDR_OPP);
+}
+
+static ssize_t ape_opp_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return opp_write(file, user_buf, count, ppos, PRCMU_QOS_APE_OPP);
+}
+
static int cpufreq_delay_read(struct seq_file *s, void *p)
{
return seq_printf(s, "%lu\n", prcmu_qos_get_cpufreq_opp_delay());
@@ -351,6 +389,7 @@ static const struct file_operations arm_opp_fops = {
static const struct file_operations ape_opp_fops = {
.open = ape_opp_open_file,
+ .write = ape_opp_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
@@ -359,6 +398,7 @@ static const struct file_operations ape_opp_fops = {
static const struct file_operations ddr_opp_fops = {
.open = ddr_opp_open_file,
+ .write = ddr_opp_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
diff --git a/arch/arm/mach-ux500/prcmu-qos-power.c b/arch/arm/mach-ux500/prcmu-qos-power.c
index df20e67cf67..c7fa4160f62 100644
--- a/arch/arm/mach-ux500/prcmu-qos-power.c
+++ b/arch/arm/mach-ux500/prcmu-qos-power.c
@@ -55,6 +55,7 @@ struct prcmu_qos_object {
struct miscdevice prcmu_qos_power_miscdev;
char *name;
s32 default_value;
+ s32 force_value;
atomic_t target_value;
s32 (*comparitor)(s32, s32);
};
@@ -71,6 +72,7 @@ static struct prcmu_qos_object ape_opp_qos = {
.name = "ape_opp",
/* Target value in % APE OPP */
.default_value = 50,
+ .force_value = 0,
.target_value = ATOMIC_INIT(0),
.comparitor = max_compare
};
@@ -83,6 +85,7 @@ static struct prcmu_qos_object ddr_opp_qos = {
.name = "ddr_opp",
/* Target value in % DDR OPP */
.default_value = 25,
+ .force_value = 0,
.target_value = ATOMIC_INIT(0),
.comparitor = max_compare
};
@@ -140,18 +143,27 @@ static void update_target(int target)
spin_lock_irqsave(&prcmu_qos_lock, flags);
extreme_value = prcmu_qos_array[target]->default_value;
- list_for_each_entry(node,
- &prcmu_qos_array[target]->requirements.list, list) {
- extreme_value = prcmu_qos_array[target]->comparitor(
- extreme_value, node->value);
- }
- if (atomic_read(&prcmu_qos_array[target]->target_value)
- != extreme_value) {
+
+ if (prcmu_qos_array[target]->force_value != 0) {
+ extreme_value = prcmu_qos_array[target]->force_value;
update = 1;
- atomic_set(&prcmu_qos_array[target]->target_value,
- extreme_value);
- pr_debug("prcmu qos: new target for qos %d is %d\n", target,
- atomic_read(&prcmu_qos_array[target]->target_value));
+ } else {
+ list_for_each_entry(node,
+ &prcmu_qos_array[target]->requirements.list,
+ list) {
+ extreme_value = prcmu_qos_array[target]->comparitor(
+ extreme_value, node->value);
+ }
+ if (atomic_read(&prcmu_qos_array[target]->target_value)
+ != extreme_value) {
+ update = 1;
+ atomic_set(&prcmu_qos_array[target]->target_value,
+ extreme_value);
+ pr_debug("prcmu qos: new target for qos %d is %d\n",
+ target, atomic_read(
+ &prcmu_qos_array[target]->target_value
+ ));
+ }
}
spin_unlock_irqrestore(&prcmu_qos_lock, flags);
@@ -201,6 +213,12 @@ static void update_target(int target)
}
}
+void prcmu_qos_force_opp(int prcmu_qos_class, s32 i)
+{
+ prcmu_qos_array[prcmu_qos_class]->force_value = i;
+ update_target(prcmu_qos_class);
+}
+
/**
* prcmu_qos_requirement - returns current prcmu qos expectation
* @prcmu_qos_class: identification of which qos value is requested