[PATCH 1/8] OMAP3: PM: Fixed VDD2 control to work from both sysfs and SRF API

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



SRF API for setting throughput requirement attempted to use throughput values
as parameter to set_opp() and sysfs was attempting to use OPP levels (1..3.)

Signed-off-by: Tero Kristo <tero.kristo@xxxxxxxxx>
---
 arch/arm/mach-omap2/pm.c                   |    8 +--
 arch/arm/mach-omap2/pm.h                   |    1 +
 arch/arm/mach-omap2/resource34xx.c         |   70 +++++++++++++++++----------
 arch/arm/plat-omap/include/mach/omap34xx.h |    4 ++
 4 files changed, 51 insertions(+), 32 deletions(-)

diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 3429531..d33eba8 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -62,7 +62,6 @@ static struct kobj_attribute voltage_off_while_idle_attr =
 	__ATTR(voltage_off_while_idle, 0644, idle_show, idle_store);
 
 #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);
@@ -137,7 +136,6 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr,
 			  const char *buf, size_t n)
 {
 	unsigned short value;
-	unsigned long bus_tput;
 
 	if (sscanf(buf, "%hu", &value) != 1)
 		return -EINVAL;
@@ -147,15 +145,13 @@ static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr,
 			printk(KERN_ERR "vdd_opp_store: Invalid value\n");
 			return -EINVAL;
 		}
-		resource_request("vdd1_opp", &dummy_sysfs_dev, value);
+		set_opp_level(VDD1_OPP, value);
 	} else if (attr == &vdd2_opp_attr) {
 		if (value < 2 || value > 3) {
 			printk(KERN_ERR "vdd_opp_store: Invalid value\n");
 			return -EINVAL;
 		}
-		/* Convert OPP's requested to appr. bus throughtput in KiB/s */
-		bus_tput = ((l3_opps + value)->rate/1000) * 4;
-		resource_request("vdd2_opp", &dummy_sysfs_dev, bus_tput);
+		set_opp_level(VDD2_OPP, value);
 	} else {
 		return -EINVAL;
 	}
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index a209819..4c0052f 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -42,6 +42,7 @@ extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state);
 #define omap3_pm_set_suspend_state(pwrdm,state) do {} while (0);
 #endif
 extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
+extern int set_opp_level(int res, u32 target_level);
 
 #ifdef CONFIG_PM_DEBUG
 extern void omap2_pm_dump(int mode, int resume, unsigned int us);
diff --git a/arch/arm/mach-omap2/resource34xx.c b/arch/arm/mach-omap2/resource34xx.c
index cb9bff0..15e6d89 100644
--- a/arch/arm/mach-omap2/resource34xx.c
+++ b/arch/arm/mach-omap2/resource34xx.c
@@ -135,6 +135,8 @@ int set_pd_latency(struct shared_resource *resp, u32 latency)
 
 static struct clk *vdd1_clk;
 static struct clk *vdd2_clk;
+static struct shared_resource *vdd1_resp;
+static struct shared_resource *vdd2_resp;
 static struct device dummy_mpu_dev;
 static struct device dummy_dsp_dev;
 
@@ -154,20 +156,29 @@ void init_opp(struct shared_resource *resp)
 	if (strcmp(resp->name, "vdd1_opp") == 0) {
 		resp->curr_level = curr_vdd1_prcm_set->opp_id;
 		vdd1_clk = clk_get(NULL, "virt_vdd1_prcm_set");
+		vdd1_resp = resp;
 	} else if (strcmp(resp->name, "vdd2_opp") == 0) {
 		resp->curr_level = curr_vdd2_prcm_set->opp_id;
 		vdd2_clk = clk_get(NULL, "virt_vdd2_prcm_set");
+		vdd2_resp = resp;
 	}
 	return;
 }
 
 static struct device vdd2_dev;
 
-int set_opp(struct shared_resource *resp, u32 target_level)
+int set_opp_level(int res, u32 target_level)
 {
-	unsigned long mpu_freq, mpu_old_freq, l3_freq, req_l3_freq, tput, t_opp;
-	int ind;
+	unsigned long mpu_freq, mpu_old_freq, l3_freq, req_l3_freq, t_opp;
 	struct cpufreq_freqs freqs_notify;
+	struct shared_resource *resp;
+
+	if (res == VDD1_OPP)
+		resp = vdd1_resp;
+	else if (res == VDD2_OPP)
+		resp = vdd2_resp;
+	else
+		return 0;
 
 	if (resp->curr_level == target_level)
 		return 0;
@@ -175,7 +186,7 @@ int set_opp(struct shared_resource *resp, u32 target_level)
 	if (!mpu_opps || !dsp_opps || !l3_opps)
 		return 0;
 
-	if (strcmp(resp->name, "vdd1_opp") == 0) {
+	if (res == VDD1_OPP) {
 		mpu_old_freq = get_freq(mpu_opps + MAX_VDD1_OPP,
 					curr_vdd1_prcm_set->opp_id);
 		mpu_freq = get_freq(mpu_opps + MAX_VDD1_OPP,
@@ -222,28 +233,7 @@ int set_opp(struct shared_resource *resp, u32 target_level)
 		/* Send a post notification to CPUFreq */
 		cpufreq_notify_transition(&freqs_notify, CPUFREQ_POSTCHANGE);
 #endif
-	} else if (strcmp(resp->name, "vdd2_opp") == 0) {
-		tput = target_level;
-
-		/* Convert the tput in KiB/s to Bus frequency in Mhz*/
-		req_l3_freq = (tput * 1000)/4;
-
-		for (ind = 2; ind <= MAX_VDD2_OPP; ind++) {
-			if ((l3_opps + ind)->rate >= req_l3_freq) {
-				target_level = ind;
-				break;
-			}
-		}
-
-		/* Set the highest OPP possible */
-		if (ind > MAX_VDD2_OPP)
-			target_level = MAX_VDD2_OPP;
-
-		if (resp->curr_level == target_level)
-			return 0;
-
-		resp->curr_level = target_level;
-
+	} else {
 		l3_freq = get_freq(l3_opps + MAX_VDD2_OPP,
 					target_level);
 		t_opp = ID_VDD(PRCM_VDD2) |
@@ -268,6 +258,34 @@ int set_opp(struct shared_resource *resp, u32 target_level)
 	return 0;
 }
 
+int set_opp(struct shared_resource *resp, u32 target_level)
+{
+	unsigned long tput;
+	unsigned long req_l3_freq;
+	int ind;
+
+	if (resp == vdd1_resp) {
+		set_opp_level(VDD1_OPP, target_level);
+	} else if (resp == vdd2_resp) {
+		tput = target_level;
+
+		/* Convert the tput in KiB/s to Bus frequency in MHz */
+		req_l3_freq = (tput * 1000)/4;
+
+		for (ind = 2; ind <= MAX_VDD2_OPP; ind++)
+			if ((l3_opps + ind)->rate >= req_l3_freq) {
+				target_level = ind;
+				break;
+			}
+
+		/* Set the highest OPP possible */
+		if (ind > MAX_VDD2_OPP)
+			target_level = ind-1;
+		set_opp_level(VDD2_OPP, target_level);
+	}
+	return 0;
+}
+
 /**
  * validate_opp - Validates if valid VDD1 OPP's are passed as the
  * target_level.
diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h
index 2e4e4ed..382e741 100644
--- a/arch/arm/plat-omap/include/mach/omap34xx.h
+++ b/arch/arm/plat-omap/include/mach/omap34xx.h
@@ -74,6 +74,10 @@
 #define OMAP34XX_DSP_IPI_BASE	(OMAP34XX_DSP_BASE + 0x1000000)
 #define OMAP34XX_DSP_MMU_BASE	(OMAP34XX_DSP_BASE + 0x2000000)
 
+/* VDD OPP identifiers */
+#define VDD1_OPP	0x1
+#define VDD2_OPP	0x2
+
 /* VDD1 OPPS */
 #define VDD1_OPP1	0x1
 #define VDD1_OPP2	0x2
-- 
1.5.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux