There is no generic function to get OPP corresponding to frequency
and vice versa.

Function get_opp() - in resource34xx.c - is included only when
CONFIG_OMAP_PM_SRF is enabled. Moreover, it is always called with
an explicit addition of MAX_VDDn_OPP e.g.
  opp = get_opp(mpu_opps + MAX_VDD1_OPP, clk->rate);
  opp = get_opp(l3_opps + MAX_VDD2_OPP, clk->rate);

This is 'addition' is required as there is no encapsulation of
MIN and MAX VDDs associated to the table.

This patch fixes the issue by creating a 'table' object that
encapsulates the MIN and MAX values and the existing rate table.

Signed-off-by: Sanjeev Premi <pr...@ti.com>
---
 arch/arm/mach-omap2/omap3-opp.h           |   42 +++------------------
 arch/arm/mach-omap2/pm.c                  |   49 +++++++++++++++++++++++++
 arch/arm/mach-omap2/pm34xx.c              |   57 +++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/mach/omap-pm.h |   22 +++++++++++
 4 files changed, 134 insertions(+), 36 deletions(-)

diff --git a/arch/arm/mach-omap2/omap3-opp.h b/arch/arm/mach-omap2/omap3-opp.h
index 3c9a582..52deb4a 100644
--- a/arch/arm/mach-omap2/omap3-opp.h
+++ b/arch/arm/mach-omap2/omap3-opp.h
@@ -21,42 +21,12 @@
 #define S83M    83000000
 #define S166M   166000000
 
-static struct omap_opp omap3_mpu_rate_table[] = {
-       {0, 0, 0},
-       /*OPP1*/
-       {S125M, VDD1_OPP1, 0x1E},
-       /*OPP2*/
-       {S250M, VDD1_OPP2, 0x26},
-       /*OPP3*/
-       {S500M, VDD1_OPP3, 0x30},
-       /*OPP4*/
-       {S550M, VDD1_OPP4, 0x36},
-       /*OPP5*/
-       {S600M, VDD1_OPP5, 0x3C},
-};
+extern struct omap_opp omap3_mpu_rate_table[];
+extern struct omap_opp omap3_dsp_rate_table[];
+extern struct omap_opp omap3_l3_rate_table[];
 
-static struct omap_opp omap3_l3_rate_table[] = {
-       {0, 0, 0},
-       /*OPP1*/
-       {0, VDD2_OPP1, 0x1E},
-       /*OPP2*/
-       {S83M, VDD2_OPP2, 0x24},
-       /*OPP3*/
-       {S166M, VDD2_OPP3, 0x2C},
-};
-
-static struct omap_opp omap3_dsp_rate_table[] = {
-       {0, 0, 0},
-       /*OPP1*/
-       {S90M, VDD1_OPP1, 0x1E},
-       /*OPP2*/
-       {S180M, VDD1_OPP2, 0x26},
-       /*OPP3*/
-       {S360M, VDD1_OPP3, 0x30},
-       /*OPP4*/
-       {S400M, VDD1_OPP4, 0x36},
-       /*OPP5*/
-       {S430M, VDD1_OPP5, 0x3C},
-};
+extern const struct omap_opp_table omap3_mpu_opp_table;
+extern const struct omap_opp_table omap3_dsp_opp_table;
+extern const struct omap_opp_table omap3_l3_opp_table;
 
 #endif
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index fec7d00..2bbe63f 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -33,6 +33,7 @@
 #include <mach/powerdomain.h>
 #include <mach/resource.h>
 #include <mach/omap34xx.h>
+#include <mach/omap-pm.h>
 
 #include "prm-regbits-34xx.h"
 #include "pm.h"
@@ -281,3 +282,51 @@ static int __init omap_pm_init(void)
        return error;
 }
 late_initcall(omap_pm_init);
+
+/*
+ * Get frequency corresponding to an OPP
+ */
+int opp_to_freq(unsigned long* freq, const struct omap_opp_table* table, u8 
opp)
+{
+        int i, found=0;
+
+        if (table && table->opps) {
+               for (i = table->min; i <= table->max; i++) {
+                       if (table->opps[i].opp_id == opp) {
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (found) {
+                       *freq = table->opps[i].rate;
+                       return 1;
+               }
+       }
+
+        return 0;
+}
+
+/*
+ * Get OPP corresponding to a frequency
+ */
+int freq_to_opp(u8* opp, const struct omap_opp_table* table, unsigned long 
freq)
+{
+        int i, found=0;
+
+        if (table && table->opps) {
+               for (i = table->min; i <= table->max; i++) {
+                       if (table->opps[i].rate == freq) {
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (found) {
+                       *opp = table->opps[i].opp_id;
+                       return 1;
+               }
+       }
+
+        return 0;
+}
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index a9eda25..dc966ae 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -50,6 +50,7 @@
 #include "prm.h"
 #include "pm.h"
 #include "sdrc.h"
+#include "omap3-opp.h"
 
 static int regset_save_on_suspend;
 
@@ -93,6 +94,62 @@ static struct prm_setup_vc prm_setup = {
        .vdd1_off = 0x00,       /* 0.6v */
 };
 
+struct omap_opp omap3_mpu_rate_table[] = {
+       {0, 0, 0},
+       /*OPP1*/
+       {S125M, VDD1_OPP1, 0x1E},
+       /*OPP2*/
+       {S250M, VDD1_OPP2, 0x26},
+       /*OPP3*/
+       {S500M, VDD1_OPP3, 0x30},
+       /*OPP4*/
+       {S550M, VDD1_OPP4, 0x36},
+       /*OPP5*/
+       {S600M, VDD1_OPP5, 0x3C},
+};
+
+struct omap_opp omap3_l3_rate_table[] = {
+       {0, 0, 0},
+       /*OPP1*/
+       {0, VDD2_OPP1, 0x1E},
+       /*OPP2*/
+       {S83M, VDD2_OPP2, 0x24},
+       /*OPP3*/
+       {S166M, VDD2_OPP3, 0x2C},
+};
+
+struct omap_opp omap3_dsp_rate_table[] = {
+       {0, 0, 0},
+       /*OPP1*/
+       {S90M, VDD1_OPP1, 0x1E},
+       /*OPP2*/
+       {S180M, VDD1_OPP2, 0x26},
+       /*OPP3*/
+       {S360M, VDD1_OPP3, 0x30},
+       /*OPP4*/
+       {S400M, VDD1_OPP4, 0x36},
+       /*OPP5*/
+       {S430M, VDD1_OPP5, 0x3C},
+};
+
+const struct omap_opp_table omap3_mpu_opp_table = {
+       VDD1_OPP1,
+       VDD1_OPP5,
+       omap3_mpu_rate_table
+};
+
+const struct omap_opp_table omap3_dsp_opp_table = {
+        VDD1_OPP1,
+        VDD1_OPP5,
+        omap3_dsp_rate_table
+};
+
+const struct omap_opp_table omap3_l3_opp_table = {
+        VDD2_OPP1,
+        VDD2_OPP3,
+        omap3_l3_rate_table
+};
+
 static inline void omap3_per_save_context(void)
 {
        omap3_gpio_save_context();
diff --git a/arch/arm/plat-omap/include/mach/omap-pm.h 
b/arch/arm/plat-omap/include/mach/omap-pm.h
index 583e540..51216cf 100644
--- a/arch/arm/plat-omap/include/mach/omap-pm.h
+++ b/arch/arm/plat-omap/include/mach/omap-pm.h
@@ -33,6 +33,20 @@ struct omap_opp {
        u16 vsel;
 };
 
+/* struct omap_opp_table - View OPP table as an object
+ * @min: Minimum OPP id
+ * @max: Maximim OPP id
+ * @opps: Pointer to array defining the OPPs.
+ *
+ * An OPP table has varied length. Knowing minimum and maximum
+ * OPP ids allow easy traversal.
+ */
+struct omap_opp_table {
+       u8      min;
+       u8      max;
+       struct omap_opp* opps;
+};
+
 extern struct omap_opp *mpu_opps;
 extern struct omap_opp *dsp_opps;
 extern struct omap_opp *l3_opps;
@@ -48,6 +62,14 @@ extern struct omap_opp *l3_opps;
 #define OCP_TARGET_AGENT               1
 #define OCP_INITIATOR_AGENT            2
 
+int opp_to_freq(unsigned long* freq,
+               const struct omap_opp_table* table,
+               u8 opp);
+
+int freq_to_opp(u8* opp,
+               const struct omap_opp_table* table,
+               unsigned long freq);
+
 /**
  * omap_pm_if_early_init - OMAP PM init code called before clock fw init
  * @mpu_opp_table: array ptr to struct omap_opp for MPU
-- 
1.6.2.2

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

Reply via email to