All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10 v3] omap3: pm: introduce support for 3630 OPPs
@ 2009-11-25  4:09 Nishanth Menon
  2009-11-25  4:09 ` [PATCH 01/10] omap3: pm: introduce enabled flag to omap_opp Nishanth Menon
  2009-11-25 15:24 ` [PATCH 00/10 v3] omap3: pm: introduce support for 3630 OPPs Kevin Hilman
  0 siblings, 2 replies; 36+ messages in thread
From: Nishanth Menon @ 2009-11-25  4:09 UTC (permalink / raw)
  To: linux-omap; +Cc: Nishanth Menon

Hi,
Here is V3 of the patch series.  What changed in V3:
* Major rewrite of OPP APIs. This includes changes from offline
  discussions with lots of folks and taking in l-o comments - all
  patches have changed as a result.
* rebased to latest lo-pm

V2: http://marc.info/?l=linux-omap&m=125809232732700&w=2
V1: http://marc.info/?l=linux-omap&m=125800488923479&w=2

NOTE: After a bunch of frustrating efforts, current OPP accessor
implementation is constrained by two files:
smartreflex.c and resource34xx.c. I agree that the current opp
accessor implementation leaves lot to be desired, but the nature of
struct omap_opp cannot change unless we essentially rewrite the
implementation of the mentioned files.

Ref: http://elinux.org/OMAP_Power_Management#Future_directions

I propose we could take this in in three stages:
Stage 1: Introduce this series in as starters if there are no major
 issues
Stage 2: We cleanup/replace resource34xx and smartreflex.c
Stage 3: Go through a second round of optimization/cleanup of opp
 accessors implementation (this time for good hopefully)

Also note that OMAP3630 is dependent on clk tree changes which needs
to come in - but that is an independent parallel activity.

TODO items:
* Add on a dependency b/w vdd1 and vdd2 in a clean manner -> probably
  after we cleanup the resource34xx.c, all folks needing a quick hack
  can easily follow the following pseudo logic:
  resource34xx.c::set_opp:

  if (cpu_is_omap3630()) {
	  vdd1_threshold_freq = 600mhz (opp2)
	  vdd2_required_freq = 200Mhz
  } else {
	  vdd1_threshold_freq = 500 Mhz (opp3)
	  vdd2_required_freq = 100Mhz
  }
  if (vdd1_target < vdd1_threshold_freq)
	free_vdd2_dep_if_acquired();
  /* Do other stuff */
  if (vdd1_target_freq >= vdd1_threshold_freq)
	request_vdd2(at least vdd2_required_freq)

  The 3630 vdd1->vdd2 dependency comes from the OPP table dependency
  of OPP100 and above on VDD1 requires VDD2 to be OPP100. VDD2 is free
  to go as it pleases, but optimal is to be at OPP50 if VDD1 is at
  OPP50. Lots of possible hacks are possible, and I dont recommend any
  at the moment.
* OMAP3630: Add speedbin detection and enable support for OPP-Turbo and
  OPP-SB

Finally,
NOTE: SDP3630 needs the patch for 8250 as discussed here:
http://marc.info/?l=linux-omap&m=125873296522723&w=2

 ====
This patch series is based on previous discussions:
http://www.mail-archive.com/linux-omap@vger.kernel.org/msg17632.html

I have modified the initial patch From Sanjeev:
http://patchwork.kernel.org/patch/50998/

Other than these, we cannot use the old VDDx_MAX based usage
anymore as 3630 OPPs are now different and runtime handling
is a must-have, hence introducing these accessor functions is not
avoidable.

The changes are incremental and tries to avoid intrusive change
as much as possible.

The OPP accessor functions introduced in this series is hopefully
a start for us to optimize this heavily used path.

An alternate approach for detecting 3630 OPP is using FEATURES
instead of detecting the cpu_type as I have implemented in this series.

Testing: mostly on SDP3430: using cpufreq-utils, sysfs vddx_lock
RET/OFF using shell scripts. Further testing requested.
Most of the commands used documented here:
http://elinux.org/OMAP_Power_Management

Nishanth Menon (10):
Following are the OPP accessor function introduction:
  omap3: pm: introduce enabled flag to omap_opp
  omap3: pm: introduce opp accessor functions
  omap3: pm: use opp accessor functions for omap34xx

The following are attempts to cleanup existing code from VDDx dep:
  omap3: pm: srf: use opp accessor functions
  omap3: pm: sr: replace get_opp with freq_to_opp
  omap3: pm: use opp accessor functions for omap-target
  omap3: clk: use pm accessor functions for cpufreq table
  omap3: pm: remove VDDx_MIN/MAX macros

The following two introduce 3630 support:
  omap3: pm: introduce 3630 opps
  omap3: pm: omap3630 boards: enable 3630 opp tables

 arch/arm/mach-omap2/board-3430sdp.c        |    1 +
 arch/arm/mach-omap2/board-3630sdp.c        |    9 +-
 arch/arm/mach-omap2/board-omap3beagle.c    |    1 +
 arch/arm/mach-omap2/board-omap3evm.c       |    1 +
 arch/arm/mach-omap2/board-rx51.c           |    1 +
 arch/arm/mach-omap2/board-zoom2.c          |    2 +
 arch/arm/mach-omap2/board-zoom3.c          |    9 +-
 arch/arm/mach-omap2/clock34xx.c            |   32 ++--
 arch/arm/mach-omap2/omap3-opp.h            |   58 +------
 arch/arm/mach-omap2/pm.h                   |    6 +
 arch/arm/mach-omap2/pm34xx.c               |  113 ++++++++++++
 arch/arm/mach-omap2/resource34xx.c         |  240 +++++++++++++++++++-------
 arch/arm/mach-omap2/smartreflex.c          |   42 ++----
 arch/arm/plat-omap/Makefile                |    3 +
 arch/arm/plat-omap/cpu-omap.c              |   19 ++-
 arch/arm/plat-omap/include/plat/omap-pm.h  |   15 +--
 arch/arm/plat-omap/include/plat/omap34xx.h |    5 -
 arch/arm/plat-omap/include/plat/opp.h      |  208 ++++++++++++++++++++++
 arch/arm/plat-omap/opp.c                   |  260 ++++++++++++++++++++++++++++
 19 files changed, 838 insertions(+), 187 deletions(-)
 create mode 100644 arch/arm/plat-omap/include/plat/opp.h
 create mode 100644 arch/arm/plat-omap/opp.c

 Regards,
 Nishanth Menon

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 01/10] omap3: pm: introduce enabled flag to omap_opp
  2009-11-25  4:09 [PATCH 00/10 v3] omap3: pm: introduce support for 3630 OPPs Nishanth Menon
@ 2009-11-25  4:09 ` Nishanth Menon
  2009-11-25  4:09   ` [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions Nishanth Menon
  2009-11-25 15:24 ` [PATCH 00/10 v3] omap3: pm: introduce support for 3630 OPPs Kevin Hilman
  1 sibling, 1 reply; 36+ messages in thread
From: Nishanth Menon @ 2009-11-25  4:09 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Benoit Cousson, Kevin Hilman,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

We used to enable and disable OPPs based on rate being set to 0, this
has been confusing in general. So, we now allow specific OPPs to be
now enabled/disabled by an explicit enabled flag instead of re-using
rate flag itself.

Tested on: SDP3430

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Romit Dasgupta <romit@ti.com>
Cc: Sanjeev Premi <premi@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 arch/arm/mach-omap2/omap3-opp.h           |   32 ++++++++++++++--------------
 arch/arm/mach-omap2/resource34xx.c        |    4 +++
 arch/arm/plat-omap/include/plat/omap-pm.h |    2 +
 3 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-omap2/omap3-opp.h b/arch/arm/mach-omap2/omap3-opp.h
index c773ea7..42557e1 100644
--- a/arch/arm/mach-omap2/omap3-opp.h
+++ b/arch/arm/mach-omap2/omap3-opp.h
@@ -22,41 +22,41 @@
 #define S166M   166000000
 
 static struct omap_opp omap3_mpu_rate_table[] = {
-	{0, 0, 0},
+	{0, 0, 0, 0},
 	/*OPP1*/
-	{S125M, VDD1_OPP1, 0x1E},
+	{true, S125M, VDD1_OPP1, 0x1E},
 	/*OPP2*/
-	{S250M, VDD1_OPP2, 0x26},
+	{true, S250M, VDD1_OPP2, 0x26},
 	/*OPP3*/
-	{S500M, VDD1_OPP3, 0x30},
+	{true, S500M, VDD1_OPP3, 0x30},
 	/*OPP4*/
-	{S550M, VDD1_OPP4, 0x36},
+	{true, S550M, VDD1_OPP4, 0x36},
 	/*OPP5*/
-	{S600M, VDD1_OPP5, 0x3C},
+	{true, S600M, VDD1_OPP5, 0x3C},
 };
 
 static struct omap_opp omap3_l3_rate_table[] = {
-	{0, 0, 0},
+	{0, 0, 0, 0},
 	/*OPP1*/
-	{0, VDD2_OPP1, 0x1E},
+	{false, 0, VDD2_OPP1, 0x1E},
 	/*OPP2*/
-	{S83M, VDD2_OPP2, 0x24},
+	{true, S83M, VDD2_OPP2, 0x24},
 	/*OPP3*/
-	{S166M, VDD2_OPP3, 0x2C},
+	{true, S166M, VDD2_OPP3, 0x2C},
 };
 
 static struct omap_opp omap3_dsp_rate_table[] = {
-	{0, 0, 0},
+	{0, 0, 0, 0},
 	/*OPP1*/
-	{S90M, VDD1_OPP1, 0x1E},
+	{true, S90M, VDD1_OPP1, 0x1E},
 	/*OPP2*/
-	{S180M, VDD1_OPP2, 0x26},
+	{true, S180M, VDD1_OPP2, 0x26},
 	/*OPP3*/
-	{S360M, VDD1_OPP3, 0x30},
+	{true, S360M, VDD1_OPP3, 0x30},
 	/*OPP4*/
-	{S400M, VDD1_OPP4, 0x36},
+	{true, S400M, VDD1_OPP4, 0x36},
 	/*OPP5*/
-	{S430M, VDD1_OPP5, 0x3C},
+	{true, S430M, VDD1_OPP5, 0x3C},
 };
 
 #endif
diff --git a/arch/arm/mach-omap2/resource34xx.c b/arch/arm/mach-omap2/resource34xx.c
index 04be4d2..af6b3c1 100644
--- a/arch/arm/mach-omap2/resource34xx.c
+++ b/arch/arm/mach-omap2/resource34xx.c
@@ -285,6 +285,10 @@ static int program_opp(int res, struct omap_opp *opp, int target_level,
 	c_opp = ID_VDD(res) | ID_OPP_NO(opp[current_level].opp_id);
 #endif
 
+	/* Only allow enabled OPPs */
+	if (!opp[target_level].enabled)
+		return -EINVAL;
+
 	/* Sanity check of the OPP params before attempting to set */
 	if (!opp[target_level].rate || !opp[target_level].vsel)
 		return -EINVAL;
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
index 583e540..5dc2048 100644
--- a/arch/arm/plat-omap/include/plat/omap-pm.h
+++ b/arch/arm/plat-omap/include/plat/omap-pm.h
@@ -21,6 +21,7 @@
 
 /**
  * struct omap_opp - clock frequency-to-OPP ID table for DSP, MPU
+ * @enabled: enabled if true, disabled if false
  * @rate: target clock rate
  * @opp_id: OPP ID
  * @min_vdd: minimum VDD1 voltage (in millivolts) for this OPP
@@ -28,6 +29,7 @@
  * Operating performance point data.  Can vary by OMAP chip and board.
  */
 struct omap_opp {
+	bool enabled;
 	unsigned long rate;
 	u8 opp_id;
 	u16 vsel;
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions
  2009-11-25  4:09 ` [PATCH 01/10] omap3: pm: introduce enabled flag to omap_opp Nishanth Menon
@ 2009-11-25  4:09   ` Nishanth Menon
  2009-11-25  4:09     ` [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx Nishanth Menon
  2009-11-25 16:30     ` [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions Kevin Hilman
  0 siblings, 2 replies; 36+ messages in thread
From: Nishanth Menon @ 2009-11-25  4:09 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Benoit Cousson,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Santosh Shilimkar, Sergio Alberto Aguirre Rodriguez,
	Thara Gopinath, Vishwanath Sripathy, Sanjeev Premi, Kevin Hilman

Modifies the initial patch From Sanjeev:
http://patchwork.kernel.org/patch/50998/
Discussions and comments from:
http://marc.info/?l=linux-omap&m=125482970102327&w=2
http://marc.info/?t=125809247500002&r=1&w=2
incorporated.

OMAP SOCs have a standard set of tuples consisting of frequency and
voltage pairs that the device will support per voltage domain. This
is called Operating Points or OPP. The actual definitions of OMAP
Operating Points varies over silicon within the same family of
devices. For a specific domain, you can have a set of
{frequency, voltage} pairs. As the kernel boots and more information
is available, a set of these are activated based on the precise
nature of device the kernel boots up on. It is interesting to
remember that each IP which belongs to a voltage domain may define
their own set of OPPs on top of this.

This introduces a common handling OPP mechanism accross all OMAPs.
As a start this is introduced for OMAP3 and intends to replace
current OMAP3 opp handling mechanism.

Note:
fields of struct omap_opp is currently exposed due to the necessity
that SRF and SR logic directly indexes the structure array fields.
The goal however, is to make the direct usage of omap_opp deprecated
and move to using these accessor functions. The usage in SRF and SR
indexes based on opp_id and hence opp_id is marked deprecated to
generate build warnings at least. Further, this usage necessitates
need of terminator entries at the start and end of opp_* tables which
are dynamically allocated.

The accessor function definitions were collaborated with Kevin, and
doing justice here, this implementation could not go with some of
the better suggestions from kevin due to constraint imposed by SRF
and SR. A better and more optimal implementation is definitely
possible once SRF and SR are cleanedup/replaced.

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Romit Dasgupta <romit@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>

Signed-off-by: Sanjeev Premi <premi@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: Nishanth Menon <nm@ti.com>
---
 arch/arm/plat-omap/Makefile           |    3 +
 arch/arm/plat-omap/include/plat/opp.h |  208 ++++++++++++++++++++++++++
 arch/arm/plat-omap/opp.c              |  260 +++++++++++++++++++++++++++++++++
 3 files changed, 471 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-omap/include/plat/opp.h
 create mode 100644 arch/arm/plat-omap/opp.c

diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 95f8413..e9cf601 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -12,6 +12,9 @@ obj-  :=
 # OCPI interconnect support for 1710, 1610 and 5912
 obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
 
+# OPP support in (OMAP3+ only at the moment)
+obj-$(CONFIG_ARCH_OMAP3) += opp.o
+
 # omap_device support (OMAP2+ only at the moment)
 obj-$(CONFIG_ARCH_OMAP2) += omap_device.o
 obj-$(CONFIG_ARCH_OMAP3) += omap_device.o
diff --git a/arch/arm/plat-omap/include/plat/opp.h b/arch/arm/plat-omap/include/plat/opp.h
new file mode 100644
index 0000000..d8ae2d3
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/opp.h
@@ -0,0 +1,208 @@
+/*
+ * OMAP OPP Interface
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated.
+ *	Nishanth Menon
+ * Copyright (C) 2009 Deep Root Systems, LLC.
+ *	Kevin Hilman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARM_OMAP_OPP_H
+#define __ASM_ARM_OMAP_OPP_H
+
+/**
+ * struct omap_opp - OMAP OPP description structure
+ * @enabled:	true/false - marking this OPP as enabled/disabled
+ * @rate:	Frequency in hertz
+ * @opp_id:	(DEPRECATED) opp identifier
+ * @vsel:	Voltage in volt processor level(this usage is
+ *		DEPRECATED to use Voltage in microvolts in future)
+ *		uV = ((vsel * 12.5) + 600) * 1000
+ *
+ * This structure stores the OPP information for a given domain.
+ * Due to legacy reasons, this structure is currently exposed and
+ * will soon be removed elsewhere and will only be used as a handle
+ * from the OPP internal referencing mechanism
+ */
+struct omap_opp {
+	bool enabled;
+	unsigned long rate;
+	u8 opp_id __deprecated;
+	u16 vsel;
+};
+
+/**
+ * opp_get_voltage - Gets the voltage corresponding to an opp
+ * @u_volt:	Voltage in microvolts corresponding to an opp
+ * @opp:	opp for which voltage has to be returned for
+ *
+ * Return 0 and the voltage in micro volt corresponding to the opp,
+ * else return the corresponding error value.
+ */
+int opp_get_voltage(u32 *u_volt, const struct omap_opp *opp);
+
+/**
+ * opp_get_freq - Gets the frequency corresponding to an opp
+ * @freq:	Frequency in hertz corresponding to an opp
+ * @opp:	opp for which frequency has to be returned for
+ *
+ * Return 0 and the frequency in hertz corresponding to the opp,
+ * else return the corresponding error value.
+ */
+int opp_get_freq(unsigned long *freq, const struct omap_opp *opp);
+
+/**
+ * opp_is_valid - Verifies if a given frequency is enabled in the opp list
+ * @opp:	Pointer to opp returned if opp match is achieved
+ * @oppl:	opp list
+ * @freq:	Frequency in hertz to check for
+ *
+ * Searches the OPP list to find if the provided frequency is an enabled
+ * frequency. If a match is achieved, it returns 0 and the pointer to the opp
+ * is returned, else a corresponding error value is returned.
+ */
+int opp_is_valid(struct omap_opp **opp, const struct omap_opp *oppl,
+		const unsigned long freq);
+
+/**
+ * opp_has_freq - Checks if a frequency is exists(enabled/disabled) in opp list
+ * @opp:	Pointer to opp returned if opp match is achieved
+ * @oppl:	opp list
+ * @freq:	Frequency in hertz to check for
+ *
+ * Searches the OPP list to find a frequency. This is a more generic function
+ * than the opp_is_valid since it searches for both enabled/disabled
+ * frequencies.
+ *
+ * This function may be used by detection logic to enable a disabled OPP as
+ * all other search functions work on enabled OPPs only.
+ */
+int opp_has_freq(struct omap_opp **opp, const struct omap_opp *oppl,
+		const unsigned long freq);
+
+/**
+ * opp_get_opp_count - Get number of opps enabled in the opp list
+ * @num:	returns the number of opps
+ * @oppl:	opp list
+ *
+ * This functions returns 0 and the number of opps are updated in num if
+ * success, else returns corresponding error value.
+ */
+int opp_get_opp_count(u8 *num, const struct omap_opp *oppl);
+
+/**
+ * opp_get_higher_opp - search for the next highest opp in the list
+ * @opp:	pointer to the opp
+ * @freq:	frequency to start the search on
+ * @oppl:	opp list to search on
+ *
+ * Searches for the higher *enabled* OPP than a starting freq/opp
+ * Decision of start condition:
+ *	if *opp is NULL, *freq is checked (usually the start condition)
+ *	if *opp is populated, *freq is ignored
+ * Returns 0 and *opp and *freq is populated with the next highest match,
+ * else returns corresponding error value.
+ *
+ * Example usage:
+ *	* print a all frequencies ascending order *
+ *	unsigned long freq = 0;
+ *	struct omap_opp *opp = NULL;
+ *	while(!opp_get_higher_opp(&opp, &freq, oppl))
+ *		pr_info("%ld ", freq);
+ * NOTE: if we set freq as 0, we get the lowest enabled frequency
+ */
+int opp_get_higher_opp(struct omap_opp **opp, unsigned long *freq,
+			const struct omap_opp *oppl);
+
+/**
+ * opp_get_lower_opp - search for the next lower opp in the list
+ * @opp:	pointer to the opp
+ * @freq:	frequency to start the search on
+ * @oppl:	opp list to search on
+ *
+ * Search for the lower *enabled* OPP than a starting freq/opp
+ * Decision of start condition:
+ *	if *opp is NULL, *freq is checked (usually the start condition)
+ *	if *opp is populated, *freq is ignored
+ * Returns 0 and *opp and *freq is populated with the next lowest match,
+ * else returns corresponding error value.
+ *
+ * Example usage:
+ *	* print a all frequencies in descending order *
+ *	unsigned long freq = ULONG_MAX;
+ *	struct omap_opp *opp = NULL;
+ *	while(!opp_get_lower_opp(&opp, &freq, oppl))
+ *		pr_info("%ld ", freq);
+ * NOTE: if we set freq as ULONG_MAX, we get the highest enabled frequency
+ */
+int opp_get_lower_opp(struct omap_opp **opp, unsigned long *freq,
+			const struct omap_opp *oppl);
+
+/**
+ * struct omap_opp_def - OMAP OPP Definition
+ * @enabled:	True/false - is this OPP enabled/disabled by default
+ * @freq:	Frequency in hertz corresponding to this OPP
+ * @u_volt:	Nominal voltage in microvolts corresponding to this OPP
+ *
+ * OMAP SOCs have a standard set of tuples consisting of frequency and voltage
+ * pairs that the device will support per voltage domain. This is called
+ * Operating Points or OPP. The actual definitions of OMAP Operating Points
+ * varies over silicon within the same family of devices. For a specific
+ * domain, you can have a set of {frequency, voltage} pairs and this is denoted
+ * by an array of omap_opp_def. As the kernel boots and more information is
+ * available, a set of these are activated based on the precise nature of
+ * device the kernel boots up on. It is interesting to remember that each IP
+ * which belongs to a voltage domain may define their own set of OPPs on top
+ * of this - but this is handled by the appropriate driver.
+ */
+struct omap_opp_def {
+	bool enabled;
+	unsigned long freq;
+	u32 u_volt;
+};
+
+/**
+ * opp_init - Initialize an OPP table from the initial table definition
+ * @oppl:	Returned back to caller as the opp list to reference the OPP
+ * @opp_defs:	Array of omap_opp_def to describe the OPP. This list should be
+ *		0 terminated.
+ *
+ * This function creates the internal datastructure representing the OPP list
+ * from an initial definition table. this handle is then used for further
+ * validation, search, modification operations on the OPP list.
+ *
+ * This function returns 0 and the pointer to the allocated list through oppl if
+ * success, else corresponding error value. Caller should NOT free the oppl.
+ * opps_defs can be freed after use.
+ */
+int __init opp_init(struct omap_opp **oppl,
+		const struct omap_opp_def *opp_defs);
+
+/**
+ * opp_enable - Enable a specific OPP
+ * @opp:	pointer to opp
+ *
+ * Enables a provided opp. If the operation is valid, this returns 0, else the
+ * corresponding error value.
+ *
+ * OPP used here is from the the opp_is_valid/opp_has_freq or other search
+ * functions
+ */
+int __init opp_enable(struct omap_opp *opp);
+
+/**
+ * opp_disable - Disable a specific OPP
+ * @opp:	pointer to opp
+ *
+ * Disables a provided opp. If the operation is valid, this returns 0, else the
+ * corresponding error value.
+ *
+ * OPP used here is from the the opp_is_valid/opp_has_freq or other search
+ * functions
+ */
+int __init opp_disable(struct omap_opp *opp);
+
+#endif		/* __ASM_ARM_OMAP_OPP_H */
diff --git a/arch/arm/plat-omap/opp.c b/arch/arm/plat-omap/opp.c
new file mode 100644
index 0000000..23929b8
--- /dev/null
+++ b/arch/arm/plat-omap/opp.c
@@ -0,0 +1,260 @@
+/*
+ * OMAP OPP Interface
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated.
+ *	Nishanth Menon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+
+#include <plat/opp.h>
+
+/*
+ * DEPRECATED: Meant to detect end of opp array
+ * This is meant to help co-exist with current SRF etc
+ * TODO: REMOVE!
+ */
+#define OPP_TERM(opp) (!(opp)->rate && !(opp)->vsel && !(opp)->enabled)
+
+/*
+ * DEPRECATED: Meant to convert vsel value to uVolt
+ * This is meant to help co-exist with current SRF etc
+ * TODO: REMOVE!
+ */
+static inline unsigned long vsel_to_uv(const u8 vsel)
+{
+	return (((vsel * 125) + 6000)) * 100;
+}
+
+/*
+ * DEPRECATED: Meant to convert uVolt to vsel value
+ * This is meant to help co-exist with current SRF etc
+ * TODO: REMOVE!
+ */
+static inline unsigned char uv_to_vsel(unsigned long uV)
+{
+	return ((uV / 100) - 6000) / 125;
+}
+
+int opp_get_voltage(u32 *u_volt, const struct omap_opp *opp)
+{
+	if (unlikely(!u_volt || !opp || !opp->enabled)) {
+		pr_err("Invalid parameters being passed\n");
+		return -EINVAL;
+	}
+	*u_volt = vsel_to_uv(opp->vsel);
+	return 0;
+}
+
+int opp_get_freq(unsigned long *freq, const struct omap_opp *opp)
+{
+	if (unlikely(!freq || !opp || !opp->enabled)) {
+		pr_err("Invalid parameters being passed\n");
+		return -EINVAL;
+	}
+	*freq = opp->rate;
+	return 0;
+}
+
+/* find the opp for a frequency */
+static struct omap_opp *find_opp_freq(const struct omap_opp *oppl,
+				      const unsigned long freq)
+{
+	struct omap_opp *opp = (struct omap_opp *)oppl;
+	opp++;			/* skip initial terminator */
+	while (!OPP_TERM(opp) && (opp->rate != freq))
+		opp++;
+
+	return (opp->rate == freq) ? opp : NULL;
+
+}
+
+int opp_is_valid(struct omap_opp **opp, const struct omap_opp *oppl,
+		 const unsigned long freq)
+{
+	struct omap_opp *t;
+	if (unlikely(!opp || !oppl)) {
+		pr_err("Invalid parameters being passed\n");
+		return -EINVAL;
+	}
+	t = find_opp_freq(oppl, freq);
+	if (!t || !t->enabled || OPP_TERM(t))
+		return -EINVAL;
+	*opp = t;
+	return 0;
+}
+
+int opp_has_freq(struct omap_opp **opp, const struct omap_opp *oppl,
+		 const unsigned long freq)
+{
+	struct omap_opp *t;
+	if (unlikely(!opp || !oppl)) {
+		pr_err("Invalid parameters being passed\n");
+		return -EINVAL;
+	}
+	t = find_opp_freq(oppl, freq);
+	if (!t || OPP_TERM(t))
+		return -EINVAL;
+	*opp = t;
+	return 0;
+}
+
+int opp_get_opp_count(u8 *num, const struct omap_opp *oppl)
+{
+	struct omap_opp *opp = (struct omap_opp *)oppl;
+	u8 n = 0;
+	if (unlikely(!num || !oppl)) {
+		pr_err("Invalid parameters being passed\n");
+		return -EINVAL;
+	}
+	opp++;			/* skip initial terminator */
+	while (!OPP_TERM(opp)) {
+		if (opp->enabled)
+			n++;
+		opp++;
+	}
+	*num = n;
+	return 0;
+}
+
+int opp_get_higher_opp(struct omap_opp **opp, unsigned long *freq,
+		       const struct omap_opp *oppl)
+{
+	struct omap_opp *t;
+	unsigned long f;
+
+	if (unlikely((!freq && !opp) || !oppl)) {
+		pr_err("Invalid parameters being passed\n");
+		return -EINVAL;
+	}
+	/* Handle start condition */
+	if (!*opp) {
+		t = (struct omap_opp *)oppl;
+		t++;		/* skip init terminator */
+		f = *freq;
+	} else {
+		t = *opp;
+		f = t->rate;
+	}
+	while (!OPP_TERM(t)) {
+		if (t->enabled && (t->rate > f))
+			break;
+		t++;
+	}
+	if (OPP_TERM(t))
+		return -EINVAL;
+	*opp = t;
+	*freq = t->rate;
+	return 0;
+}
+
+int opp_get_lower_opp(struct omap_opp **opp, unsigned long *freq,
+		      const struct omap_opp *oppl)
+{
+	struct omap_opp *t;
+	unsigned long f;
+
+	if (unlikely((!freq && !opp) || !oppl)) {
+		pr_err("Invalid parameters being passed\n");
+		return -EINVAL;
+	}
+	/* Handle start condition */
+	if (!*opp) {
+		t = (struct omap_opp *)oppl;
+		t++;		/* skip initial terminator */
+		/* seek to top - need to search top bottom */
+		while (!OPP_TERM(t + 1))
+			t++;
+		f = *freq;
+	} else {
+		t = *opp;
+		f = t->rate;
+	}
+
+	do {
+		if (t->enabled && (t->rate < f))
+			break;
+		t--;
+	} while (!OPP_TERM(t));
+
+	/* Check if we did not match */
+	if (!t->enabled || t->rate >= f)
+		return -EINVAL;
+
+	*opp = t;
+	*freq = t->rate;
+	return 0;
+}
+
+int __init opp_init(struct omap_opp **oppl, const struct omap_opp_def *opp_defs)
+{
+	struct omap_opp_def *t = (struct omap_opp_def *)opp_defs;
+	struct omap_opp *opp;
+	u8 n = 0, i = 1;
+	if (unlikely(*oppl || !opp_defs)) {
+		pr_err("Invalid params being passed\n");
+		return -EINVAL;
+	}
+	/* Grab a count */
+	while (t->enabled || t->freq || t->u_volt) {
+		n++;
+		t++;
+	}
+
+	opp = kmalloc(sizeof(struct omap_opp) * (n + 2), GFP_KERNEL);
+	if (!opp) {
+		pr_err("No memory for opp array\n");
+		return -ENOMEM;
+	}
+	*oppl = opp;
+	/* Setup start terminator - SRF depends on this for indexing :( */
+	opp->rate = 0;
+	opp->enabled = 0;
+	opp->vsel = 0;
+	opp++;
+	while (n) {
+		opp->rate = opp_defs->freq;
+		opp->enabled = opp_defs->enabled;
+		opp->opp_id = i;
+		opp->vsel = uv_to_vsel(opp_defs->u_volt);
+		/* round off to higher voltage */
+		if (opp_defs->u_volt > vsel_to_uv(opp->vsel))
+			opp->vsel++;
+		n--;
+		opp++;
+		opp_defs++;
+		i++;
+	}
+	/* Setup terminator - this is for our search algos */
+	opp->rate = 0;
+	opp->enabled = 0;
+	opp->vsel = 0;
+	return 0;
+}
+
+int __init opp_enable(struct omap_opp *opp)
+{
+	if (unlikely(!opp)) {
+		pr_err("Invalid parameters being passed\n");
+		return -EINVAL;
+	}
+	opp->enabled = true;
+	return 0;
+}
+
+int __init opp_disable(struct omap_opp *opp)
+{
+	if (unlikely(!opp)) {
+		pr_err("Invalid parameters being passed\n");
+		return -EINVAL;
+	}
+	opp->enabled = false;
+	return 0;
+}
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx
  2009-11-25  4:09   ` [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions Nishanth Menon
@ 2009-11-25  4:09     ` Nishanth Menon
  2009-11-25  4:09       ` [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions Nishanth Menon
                         ` (2 more replies)
  2009-11-25 16:30     ` [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions Kevin Hilman
  1 sibling, 3 replies; 36+ messages in thread
From: Nishanth Menon @ 2009-11-25  4:09 UTC (permalink / raw)
  To: linux-omap; +Cc: Nishanth Menon

Move the definitions from omap3-opp.h to pm34xx.c. The definitions
are now based on omap_opp_def instead of omap_opp itself.
Since the opp.h has the omap_opp definition, omap-pm.h conflicts and
has been removed in favor of opp.h.

omap3_pm_init_opp_table is used to initialize the OPP table and
relevant board files which have omap2_init_common_hw called with opp
arrays have been updated with omap3_pm_init_opp_table.

This change now allows us to dynamically register OPPs to the system
based on silicon type we detect.

NOTE: This introduces the following warnings highlighting areas we
need to cleanup:
arch/arm/mach-omap2/smartreflex.c: In function 'get_opp':
arch/arm/mach-omap2/smartreflex.c:161: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/smartreflex.c:164: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/smartreflex.c:166: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/smartreflex.c:168: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/resource34xx.c: In function 'get_opp':
arch/arm/mach-omap2/resource34xx.c:165: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/resource34xx.c:168: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/resource34xx.c:170: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/resource34xx.c:172: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/resource34xx.c: In function 'program_opp':
arch/arm/mach-omap2/resource34xx.c:284: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/resource34xx.c:285: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 arch/arm/mach-omap2/board-3430sdp.c       |    1 +
 arch/arm/mach-omap2/board-omap3beagle.c   |    1 +
 arch/arm/mach-omap2/board-omap3evm.c      |    1 +
 arch/arm/mach-omap2/board-rx51.c          |    1 +
 arch/arm/mach-omap2/board-zoom2.c         |    2 +
 arch/arm/mach-omap2/omap3-opp.h           |   58 +-----------------------
 arch/arm/mach-omap2/pm.h                  |    6 +++
 arch/arm/mach-omap2/pm34xx.c              |   68 +++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/omap-pm.h |   17 +-------
 9 files changed, 84 insertions(+), 71 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index eac529f..0ec8327 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -220,6 +220,7 @@ static void __init omap_3430sdp_init_irq(void)
 {
 	omap_board_config = sdp3430_config;
 	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
+	omap3_pm_init_opp_table();
 	omap3_pm_init_vc(&omap3_setuptime_table);
 	omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
 	omap2_init_common_hw(hyb18m512160af6_sdrc_params, NULL, omap3_mpu_rate_table,
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 2ec3520..a937238 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -361,6 +361,7 @@ static void __init omap3_beagle_init_irq(void)
 {
 	omap_board_config = omap3_beagle_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
+	omap3_pm_init_opp_table();
 	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
 			     mt46h32m32lf6_sdrc_params, omap3_mpu_rate_table,
 			     omap3_dsp_rate_table, omap3_l3_rate_table);
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 8130eca..44a5861 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -404,6 +404,7 @@ static void __init omap3_evm_init_irq(void)
 {
 	omap_board_config = omap3_evm_config;
 	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
+	omap3_pm_init_opp_table();
 	omap2_init_common_hw(mt46h32m32lf6_sdrc_params, NULL, omap3_mpu_rate_table,
 	                     omap3_dsp_rate_table, omap3_l3_rate_table);
 	omap_init_irq();
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index 2f1c2be..997fd1c 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -103,6 +103,7 @@ static void __init rx51_init_irq(void)
 
 	omap_board_config = rx51_config;
 	omap_board_config_size = ARRAY_SIZE(rx51_config);
+	omap3_pm_init_opp_table();
 	omap3_pm_init_cpuidle(rx51_cpuidle_params);
 	sdrc_params = rx51_get_sdram_timings();
 	omap2_init_common_hw(sdrc_params, sdrc_params,
diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
index dcc5fb8..9d5b078 100644
--- a/arch/arm/mach-omap2/board-zoom2.c
+++ b/arch/arm/mach-omap2/board-zoom2.c
@@ -24,10 +24,12 @@
 #include <mach/board-zoom.h>
 
 #include "sdram-micron-mt46h32m32lf-6.h"
+#include "pm.h"
 #include "omap3-opp.h"
 
 static void __init omap_zoom2_init_irq(void)
 {
+	omap3_pm_init_opp_table();
 	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
 				 mt46h32m32lf6_sdrc_params, omap3_mpu_rate_table,
 				 omap3_dsp_rate_table, omap3_l3_rate_table);
diff --git a/arch/arm/mach-omap2/omap3-opp.h b/arch/arm/mach-omap2/omap3-opp.h
index 42557e1..994d8d4 100644
--- a/arch/arm/mach-omap2/omap3-opp.h
+++ b/arch/arm/mach-omap2/omap3-opp.h
@@ -3,60 +3,8 @@
 
 #include <plat/omap-pm.h>
 
-/* MPU speeds */
-#define S600M   600000000
-#define S550M   550000000
-#define S500M   500000000
-#define S250M   250000000
-#define S125M   125000000
-
-/* DSP speeds */
-#define S430M   430000000
-#define S400M   400000000
-#define S360M   360000000
-#define S180M   180000000
-#define S90M    90000000
-
-/* L3 speeds */
-#define S83M    83000000
-#define S166M   166000000
-
-static struct omap_opp omap3_mpu_rate_table[] = {
-	{0, 0, 0, 0},
-	/*OPP1*/
-	{true, S125M, VDD1_OPP1, 0x1E},
-	/*OPP2*/
-	{true, S250M, VDD1_OPP2, 0x26},
-	/*OPP3*/
-	{true, S500M, VDD1_OPP3, 0x30},
-	/*OPP4*/
-	{true, S550M, VDD1_OPP4, 0x36},
-	/*OPP5*/
-	{true, S600M, VDD1_OPP5, 0x3C},
-};
-
-static struct omap_opp omap3_l3_rate_table[] = {
-	{0, 0, 0, 0},
-	/*OPP1*/
-	{false, 0, VDD2_OPP1, 0x1E},
-	/*OPP2*/
-	{true, S83M, VDD2_OPP2, 0x24},
-	/*OPP3*/
-	{true, S166M, VDD2_OPP3, 0x2C},
-};
-
-static struct omap_opp omap3_dsp_rate_table[] = {
-	{0, 0, 0, 0},
-	/*OPP1*/
-	{true, S90M, VDD1_OPP1, 0x1E},
-	/*OPP2*/
-	{true, S180M, VDD1_OPP2, 0x26},
-	/*OPP3*/
-	{true, S360M, VDD1_OPP3, 0x30},
-	/*OPP4*/
-	{true, S400M, VDD1_OPP4, 0x36},
-	/*OPP5*/
-	{true, S430M, 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;
 
 #endif
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 7bc86b6..80a1c1d 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -58,6 +58,12 @@ static inline void omap3_pm_init_cpuidle(
 {
 }
 #endif
+/**
+ * omap3_pm_init_opp_table - OMAP opp table lookup called after cpu is detected.
+ * Initialize the basic opp table here, board files could choose to modify opp
+ * table after the basic initialization
+ */
+extern void omap3_pm_init_opp_table(void);
 
 extern int resource_set_opp_level(int res, u32 target_level, int flags);
 extern int resource_access_opp_lock(int res, int delta);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 627a509..ad21f5f 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -40,6 +40,7 @@
 #include <plat/dmtimer.h>
 #include <plat/usb.h>
 
+#include <plat/opp.h>
 #include <plat/resource.h>
 
 #include <asm/tlbflush.h>
@@ -52,6 +53,7 @@
 #include "prm.h"
 #include "pm.h"
 #include "sdrc.h"
+#include "omap3-opp.h"
 
 static int regset_save_on_suspend;
 
@@ -100,6 +102,52 @@ static struct prm_setup_vc prm_setup = {
 	.vdd1_off = 0x00,	/* 0.6v */
 };
 
+static struct omap_opp_def __initdata omap34xx_mpu_rate_table[] = {
+	/*OPP1 975mV */
+	{.enabled = true, .freq = 125000000, .u_volt = 975000},
+	/*OPP2 1.075V */
+	{.enabled = true, .freq = 250000000, .u_volt = 1075000},
+	/*OPP3 1.2V */
+	{.enabled = true, .freq = 500000000, .u_volt = 1200000},
+	/*OPP4 1.270V */
+	{.enabled = true, .freq = 550000000, .u_volt = 1270000},
+	/*OPP5 1.35V */
+	{.enabled = true, .freq = 600000000, .u_volt = 1350000},
+	/* Terminator */
+	{.enabled = 0, .freq = 0, .u_volt = 0}
+};
+
+static struct omap_opp_def __initdata omap34xx_l3_rate_table[] = {
+	/*OPP1 - 975mV */
+	{.enabled = false, .freq = 0, .u_volt = 975000},
+	/*OPP2 1.05V */
+	{.enabled = true, .freq = 83000000, .u_volt = 1050000},
+	/*OPP3 1.15V*/
+	{.enabled = true, .freq = 166000000, .u_volt = 1150000},
+	/* Terminator */
+	{.enabled = 0, .freq = 0, .u_volt = 0}
+};
+
+static struct omap_opp_def __initdata omap34xx_dsp_rate_table[] = {
+	/*OPP1*/
+	{.enabled = true, .freq = 90000000, .u_volt = 975000},
+	/*OPP2*/
+	{.enabled = true, .freq = 180000000, .u_volt = 1075000},
+	/*OPP3*/
+	{.enabled = true, .freq = 360000000, .u_volt = 1200000},
+	/*OPP4*/
+	{.enabled = true, .freq = 400000000, .u_volt = 1270000},
+	/*OPP5*/
+	{.enabled = true, .freq = 430000000, .u_volt = 1350000},
+	/* Terminator */
+	{.enabled = 0, .freq = 0, .u_volt = 0}
+};
+
+struct omap_opp *omap3_mpu_rate_table;
+struct omap_opp *omap3_dsp_rate_table;
+struct omap_opp *omap3_l3_rate_table;
+
+
 static inline void omap3_per_save_context(void)
 {
 	omap_gpio_save_context();
@@ -1248,6 +1296,26 @@ static void __init configure_vc(void)
 	pm_dbg_regset_init(2);
 }
 
+void __init omap3_pm_init_opp_table(void)
+{
+	int ret, i;
+	struct omap_opp_def *omap34xx_opp_def_list[] = {
+		omap34xx_mpu_rate_table,
+		omap34xx_l3_rate_table,
+		omap34xx_dsp_rate_table
+	};
+	struct omap_opp **omap3_rate_tables[] = {
+		&omap3_mpu_rate_table,
+		&omap3_l3_rate_table,
+		&omap3_dsp_rate_table
+	};
+	for (i = 0; i < ARRAY_SIZE(omap34xx_opp_def_list); i++) {
+		ret = opp_init(omap3_rate_tables[i], omap34xx_opp_def_list[i]);
+		/* We dont want half configured system at the moment */
+		BUG_ON(ret);
+	}
+}
+
 static int __init omap3_pm_early_init(void)
 {
 	prm_clear_mod_reg_bits(OMAP3430_OFFMODE_POL, OMAP3430_GR_MOD,
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
index 5dc2048..aa36339 100644
--- a/arch/arm/plat-omap/include/plat/omap-pm.h
+++ b/arch/arm/plat-omap/include/plat/omap-pm.h
@@ -18,22 +18,7 @@
 #include <linux/cpufreq.h>
 
 #include "powerdomain.h"
-
-/**
- * struct omap_opp - clock frequency-to-OPP ID table for DSP, MPU
- * @enabled: enabled if true, disabled if false
- * @rate: target clock rate
- * @opp_id: OPP ID
- * @min_vdd: minimum VDD1 voltage (in millivolts) for this OPP
- *
- * Operating performance point data.  Can vary by OMAP chip and board.
- */
-struct omap_opp {
-	bool enabled;
-	unsigned long rate;
-	u8 opp_id;
-	u16 vsel;
-};
+#include <plat/opp.h>
 
 extern struct omap_opp *mpu_opps;
 extern struct omap_opp *dsp_opps;
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions
  2009-11-25  4:09     ` [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx Nishanth Menon
@ 2009-11-25  4:09       ` Nishanth Menon
  2009-11-25  4:09         ` [PATCH 05/10 V3] omap3: pm: sr: replace get_opp with freq_to_opp Nishanth Menon
  2009-12-07 16:59         ` [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions Tero.Kristo
  2009-11-25 17:22       ` [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx Kevin Hilman
  2009-12-08  8:08       ` Eduardo Valentin
  2 siblings, 2 replies; 36+ messages in thread
From: Nishanth Menon @ 2009-11-25  4:09 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Benoit Cousson, Kevin Hilman,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

With the accessor functions, many of the direct accesses are
redundant. However we do not want to rewrite SRF at this point of time
We do the following here:
Remove get_opp and introduce three SRF specific accessor functions:
	opp_to_freq, freq_to_opp - need this coz of usage of opp IDs
	NOTE: These functions should be removed at a later point
	of time.
get_opp is removed because, with the above functions, it is
redundant.

NOTE: this implementation is just a start and leaves scope for
further cleanups which can be added on top.

NOTE: this increases the number of warnings to:

arch/arm/mach-omap2/resource34xx.c: In function 'opp_to_freq':
arch/arm/mach-omap2/resource34xx.c:182: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/resource34xx.c: In function 'freq_to_opp':
arch/arm/mach-omap2/resource34xx.c:213: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/resource34xx.c: In function 'init_opp':
arch/arm/mach-omap2/resource34xx.c:242: warning: 'freq_to_opp' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
arch/arm/mach-omap2/resource34xx.c:249: warning: 'freq_to_opp' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
arch/arm/mach-omap2/resource34xx.c: In function 'program_opp_freq':
arch/arm/mach-omap2/resource34xx.c:302: warning: 'opp_to_freq' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
arch/arm/mach-omap2/resource34xx.c:303: warning: 'opp_to_freq' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
arch/arm/mach-omap2/resource34xx.c:308: warning: 'opp_to_freq' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
arch/arm/mach-omap2/resource34xx.c: In function 'program_opp':
arch/arm/mach-omap2/resource34xx.c:351: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/resource34xx.c:352: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/resource34xx.c:356: warning: 'opp_to_freq' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
arch/arm/mach-omap2/resource34xx.c:380: warning: 'opp_to_freq' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
arch/arm/mach-omap2/resource34xx.c: In function 'resource_set_opp_level':
arch/arm/mach-omap2/resource34xx.c:417: warning: 'opp_to_freq' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
arch/arm/mach-omap2/resource34xx.c:418: warning: 'opp_to_freq' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
arch/arm/mach-omap2/resource34xx.c:420: warning: 'opp_to_freq' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
arch/arm/mach-omap2/resource34xx.c: In function 'set_opp':
arch/arm/mach-omap2/resource34xx.c:497: warning: 'freq_to_opp' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
arch/arm/mach-omap2/resource34xx.c: In function 'validate_opp':
arch/arm/mach-omap2/resource34xx.c:516: warning: 'opp_to_freq' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
arch/arm/mach-omap2/resource34xx.c:518: warning: 'opp_to_freq' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
arch/arm/mach-omap2/resource34xx.c: In function 'init_freq':
arch/arm/mach-omap2/resource34xx.c:541: warning: 'opp_to_freq' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
arch/arm/mach-omap2/resource34xx.c:544: warning: 'opp_to_freq' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
arch/arm/mach-omap2/resource34xx.c: In function 'set_freq':
arch/arm/mach-omap2/resource34xx.c:560: warning: 'freq_to_opp' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
arch/arm/mach-omap2/resource34xx.c:565: warning: 'freq_to_opp' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
arch/arm/mach-omap2/resource34xx.c: In function 'validate_freq':
arch/arm/mach-omap2/resource34xx.c:579: warning: 'freq_to_opp' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
arch/arm/mach-omap2/resource34xx.c:581: warning: 'freq_to_opp' is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Romit Dasgupta <romit@ti.com>
Cc: Sanjeev Premi <premi@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 arch/arm/mach-omap2/resource34xx.c |  244 ++++++++++++++++++++++++++----------
 1 files changed, 180 insertions(+), 64 deletions(-)

diff --git a/arch/arm/mach-omap2/resource34xx.c b/arch/arm/mach-omap2/resource34xx.c
index af6b3c1..349f54e 100644
--- a/arch/arm/mach-omap2/resource34xx.c
+++ b/arch/arm/mach-omap2/resource34xx.c
@@ -155,21 +155,68 @@ static int curr_vdd1_opp;
 static int curr_vdd2_opp;
 static DEFINE_MUTEX(dvfs_mutex);
 
-static unsigned short get_opp(struct omap_opp *opp_freq_table,
+/* Introducing deprecated function because we got to.. */
+#define IS_OPP_TERMINATOR(opps, i) (!(opps)[(i)].enabled &&\
+		((opps)[(i)].rate == 0) && ((opps)[(i)].vsel == 0))
+
+/**
+ * opp_to_freq - convert OPPID to frequency (DEPRECATED)
+ * @freq: return frequency back to caller
+ * @opps: opp list
+ * @opp_id: OPP ID we are searching for
+ *
+ * return 0 and freq is populated if we find the opp_id, else,
+ * we return error
+ *
+ * NOTE: this function is a standin for the timebeing as opp_id is deprecated
+ */
+static int __deprecated opp_to_freq(unsigned long *freq,
+		const struct omap_opp *opps, u8 opp_id)
+{
+	int i = 1;
+
+	BUG_ON(!freq || !opps);
+
+	/* The first entry is a dummy one, loop till we hit terminator */
+	while (!IS_OPP_TERMINATOR(opps, i)) {
+		if (opps[i].enabled && (opps[i].opp_id == opp_id)) {
+			*freq = opps[i].rate;
+			return 0;
+		}
+		i++;
+	}
+
+	return -EINVAL;
+}
+
+/**
+ * freq_to_opp - convert a frequency back to OPP ID (DEPRECATED)
+ * @opp_id: opp ID returned back to caller
+ * @opps: opp list
+ * @freq: frequency we are searching for
+ *
+ * return 0 and opp_id is populated if we find the freq, else,
+ * we return error
+ *
+ * NOTE: this function is a standin for the timebeing as opp_id is deprecated
+ */
+static int __deprecated freq_to_opp(u8 *opp_id, const struct omap_opp *opps,
 		unsigned long freq)
 {
-	struct omap_opp *prcm_config;
-	prcm_config = opp_freq_table;
-
-	if (prcm_config->rate <= freq)
-		return prcm_config->opp_id; /* Return the Highest OPP */
-	for (; prcm_config->rate; prcm_config--)
-		if (prcm_config->rate < freq)
-			return (prcm_config+1)->opp_id;
-		else if (prcm_config->rate == freq)
-			return prcm_config->opp_id;
-	/* Return the least OPP */
-	return (prcm_config+1)->opp_id;
+	int i = 1;
+
+	BUG_ON(!opp_id || !opps);
+
+	/* The first entry is a dummy one, loop till we hit terminator */
+	while (!IS_OPP_TERMINATOR(opps, i)) {
+		if (opps[i].enabled && (opps[i].rate == freq)) {
+			*opp_id = opps[i].opp_id;
+			return 0;
+		}
+		i++;
+	}
+
+	return -EINVAL;
 }
 
 /**
@@ -178,6 +225,8 @@ static unsigned short get_opp(struct omap_opp *opp_freq_table,
 void init_opp(struct shared_resource *resp)
 {
 	struct clk *l3_clk;
+	int ret;
+	u8 opp_id;
 	resp->no_of_users = 0;
 
 	if (!mpu_opps || !dsp_opps || !l3_opps)
@@ -190,17 +239,18 @@ void init_opp(struct shared_resource *resp)
 		vdd1_resp = resp;
 		dpll1_clk = clk_get(NULL, "dpll1_ck");
 		dpll2_clk = clk_get(NULL, "dpll2_ck");
-		resp->curr_level = get_opp(mpu_opps + MAX_VDD1_OPP,
-				dpll1_clk->rate);
-		curr_vdd1_opp = resp->curr_level;
+		ret = freq_to_opp(&opp_id, mpu_opps, dpll1_clk->rate);
+		BUG_ON(ret); /* TBD Cleanup handling */
+		curr_vdd1_opp = opp_id;
 	} else if (strcmp(resp->name, "vdd2_opp") == 0) {
 		vdd2_resp = resp;
 		dpll3_clk = clk_get(NULL, "dpll3_m2_ck");
 		l3_clk = clk_get(NULL, "l3_ick");
-		resp->curr_level = get_opp(l3_opps + MAX_VDD2_OPP,
-				l3_clk->rate);
-		curr_vdd2_opp = resp->curr_level;
+		ret = freq_to_opp(&opp_id, l3_opps, l3_clk->rate);
+		BUG_ON(ret); /* TBD Cleanup handling */
+		curr_vdd2_opp = opp_id;
 	}
+	resp->curr_level = opp_id;
 	return;
 }
 
@@ -242,24 +292,40 @@ static int program_opp_freq(int res, int target_level, int current_level)
 {
 	int ret = 0, l3_div;
 	int *curr_opp;
+	unsigned long mpu_freq, dsp_freq, l3_freq;
+#ifndef CONFIG_CPU_FREQ
+	unsigned long mpu_cur_freq
+#endif
+
+	/* Check if I can actually switch or not */
+	if (res == VDD1_OPP) {
+		ret = opp_to_freq(&mpu_freq, mpu_opps, target_level);
+		ret |= opp_to_freq(&dsp_freq, dsp_opps, target_level);
+#ifndef CONFIG_CPU_FREQ
+		ret |= opp_to_freq(&mpu_cur_freq, mpu_opps, current_level);
+#endif
+	} else {
+		ret = opp_to_freq(&l3_freq, l3_opps, target_level);
+	}
+	/* we would have caught all bad levels earlier.. */
+	if (unlikely(ret))
+		return ret;
 
 	lock_scratchpad_sem();
 	if (res == VDD1_OPP) {
 		curr_opp = &curr_vdd1_opp;
-		clk_set_rate(dpll1_clk, mpu_opps[target_level].rate);
-		clk_set_rate(dpll2_clk, dsp_opps[target_level].rate);
+		clk_set_rate(dpll1_clk, mpu_freq);
+		clk_set_rate(dpll2_clk, dsp_freq);
 #ifndef CONFIG_CPU_FREQ
 		/*Update loops_per_jiffy if processor speed is being changed*/
 		loops_per_jiffy = compute_lpj(loops_per_jiffy,
-			mpu_opps[current_level].rate/1000,
-			mpu_opps[target_level].rate/1000);
+			mpu_cur_freq / 1000, mpu_freq / 1000);
 #endif
 	} else {
 		curr_opp = &curr_vdd2_opp;
 		l3_div = cm_read_mod_reg(CORE_MOD, CM_CLKSEL) &
 			OMAP3430_CLKSEL_L3_MASK;
-		ret = clk_set_rate(dpll3_clk,
-				l3_opps[target_level].rate * l3_div);
+		ret = clk_set_rate(dpll3_clk, l3_freq * l3_div);
 	}
 	if (ret) {
 		unlock_scratchpad_sem();
@@ -278,6 +344,7 @@ static int program_opp(int res, struct omap_opp *opp, int target_level,
 		int current_level)
 {
 	int i, ret = 0, raise;
+	unsigned long freq;
 #ifdef CONFIG_OMAP_SMARTREFLEX
 	unsigned long t_opp, c_opp;
 
@@ -285,13 +352,10 @@ static int program_opp(int res, struct omap_opp *opp, int target_level,
 	c_opp = ID_VDD(res) | ID_OPP_NO(opp[current_level].opp_id);
 #endif
 
-	/* Only allow enabled OPPs */
-	if (!opp[target_level].enabled)
-		return -EINVAL;
-
-	/* Sanity check of the OPP params before attempting to set */
-	if (!opp[target_level].rate || !opp[target_level].vsel)
-		return -EINVAL;
+	/* See if have a freq associated, if not, invalid opp */
+	ret = opp_to_freq(&freq, opp, target_level);
+	if (unlikely(ret))
+		return ret;
 
 	if (target_level > current_level)
 		raise = 1;
@@ -303,10 +367,23 @@ static int program_opp(int res, struct omap_opp *opp, int target_level,
 			ret = program_opp_freq(res, target_level,
 					current_level);
 #ifdef CONFIG_OMAP_SMARTREFLEX
-		else
-			sr_voltagescale_vcbypass(t_opp, c_opp,
-				opp[target_level].vsel,
-				opp[current_level].vsel);
+		else {
+			u8 vc, vt;
+			struct omap_opp *oppx;
+			/*
+			 * transitioning from good to good OPP
+			 * none of the following should fail..
+			 */
+			BUG_ON(opp_is_valid(&oppx, opp, freq));
+			vt = oppx->vsel;
+
+			BUG_ON(opp_to_freq(&freq, opp, current_level));
+			BUG_ON(opp_is_valid(&oppx, opp, freq));
+			vc = oppx->vsel;
+
+			/* ok to scale.. */
+			sr_voltagescale_vcbypass(t_opp, c_opp, vt, vc);
+		}
 #endif
 	}
 
@@ -315,7 +392,8 @@ static int program_opp(int res, struct omap_opp *opp, int target_level,
 
 int resource_set_opp_level(int res, u32 target_level, int flags)
 {
-	unsigned long mpu_freq, mpu_old_freq;
+	unsigned long mpu_freq, mpu_old_freq, l3_freq;
+	int ret;
 #ifdef CONFIG_CPU_FREQ
 	struct cpufreq_freqs freqs_notify;
 #endif
@@ -334,6 +412,16 @@ int resource_set_opp_level(int res, u32 target_level, int flags)
 	if (!mpu_opps || !dsp_opps || !l3_opps)
 		return 0;
 
+	/* Check if I can actually switch or not */
+	if (res == VDD1_OPP) {
+		ret = opp_to_freq(&mpu_freq, mpu_opps, target_level);
+		ret |= opp_to_freq(&mpu_old_freq, mpu_opps, resp->curr_level);
+	} else {
+		ret = opp_to_freq(&l3_freq, l3_opps, target_level);
+	}
+	if (ret)
+		return ret;
+
 	mutex_lock(&dvfs_mutex);
 
 	if (res == VDD1_OPP) {
@@ -341,9 +429,6 @@ int resource_set_opp_level(int res, u32 target_level, int flags)
 			mutex_unlock(&dvfs_mutex);
 			return 0;
 		}
-		mpu_old_freq = mpu_opps[resp->curr_level].rate;
-		mpu_freq = mpu_opps[target_level].rate;
-
 #ifdef CONFIG_CPU_FREQ
 		freqs_notify.old = mpu_old_freq/1000;
 		freqs_notify.new = mpu_freq/1000;
@@ -371,15 +456,13 @@ int resource_set_opp_level(int res, u32 target_level, int flags)
 
 int set_opp(struct shared_resource *resp, u32 target_level)
 {
-	unsigned long tput;
-	unsigned long req_l3_freq;
-	int ind;
+	int ret = -EINVAL;
 
 	if (resp == vdd1_resp) {
 		if (target_level < 3)
 			resource_release("vdd2_opp", &vdd2_dev);
 
-		resource_set_opp_level(VDD1_OPP, target_level, 0);
+		ret = resource_set_opp_level(VDD1_OPP, target_level, 0);
 		/*
 		 * For VDD1 OPP3 and above, make sure the interconnect
 		 * is at 100Mhz or above.
@@ -389,21 +472,33 @@ int set_opp(struct shared_resource *resp, u32 target_level)
 			resource_request("vdd2_opp", &vdd2_dev, 400000);
 
 	} else if (resp == vdd2_resp) {
-		tput = target_level;
+		unsigned long req_l3_freq;
+		struct omap_opp *oppx = NULL;
 
 		/* 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;
+		req_l3_freq = (target_level * 1000)/4;
+
+		/* Do I have an exact match */
+		ret = opp_is_valid(&oppx, l3_opps, req_l3_freq);
+		if (ret) {
+			/* Do I have a next best match */
+			ret = opp_get_higher_opp(&oppx, &req_l3_freq, l3_opps);
+			if (ret) {
+				/* Give me the best we got */
+				req_l3_freq = ULONG_MAX;
+				ret = opp_get_lower_opp(&oppx, &req_l3_freq,
+						l3_opps);
 			}
+		}
 
-		/* Set the highest OPP possible */
-		if (ind > MAX_VDD2_OPP)
-			target_level = ind-1;
-		resource_set_opp_level(VDD2_OPP, target_level, 0);
+		/* uh uh.. no OPPs?? */
+		BUG_ON(ret);
+
+		ret = freq_to_opp((u8 *)&target_level, l3_opps, req_l3_freq);
+		/* we dont expect this to fail */
+		BUG_ON(ret);
+
+		ret = resource_set_opp_level(VDD2_OPP, target_level, 0);
 	}
 	return 0;
 }
@@ -416,6 +511,11 @@ int set_opp(struct shared_resource *resp, u32 target_level)
  */
 int validate_opp(struct shared_resource *resp, u32 target_level)
 {
+	unsigned long x;
+	if (strcmp(resp->name, "mpu_freq") == 0)
+		return opp_to_freq(&x, mpu_opps, target_level);
+	else if (strcmp(resp->name, "dsp_freq") == 0)
+		return opp_to_freq(&x, dsp_opps, target_level);
 	return 0;
 }
 
@@ -425,6 +525,8 @@ int validate_opp(struct shared_resource *resp, u32 target_level)
 void init_freq(struct shared_resource *resp)
 {
 	char *linked_res_name;
+	int ret = -EINVAL;
+	unsigned long freq;
 	resp->no_of_users = 0;
 
 	if (!mpu_opps || !dsp_opps)
@@ -436,32 +538,46 @@ void init_freq(struct shared_resource *resp)
 	*/
 	if (strcmp(resp->name, "mpu_freq") == 0)
 		/* MPU freq in Mhz */
-		resp->curr_level = mpu_opps[curr_vdd1_opp].rate;
+		ret = opp_to_freq(&freq, mpu_opps, curr_vdd1_opp);
 	else if (strcmp(resp->name, "dsp_freq") == 0)
 		/* DSP freq in Mhz */
-		resp->curr_level = dsp_opps[curr_vdd1_opp].rate;
+		ret = opp_to_freq(&freq, dsp_opps, curr_vdd1_opp);
+	BUG_ON(ret);
+
+	resp->curr_level = freq;
 	return;
 }
 
 int set_freq(struct shared_resource *resp, u32 target_level)
 {
-	unsigned int vdd1_opp;
+	u8 vdd1_opp;
+	int ret = -EINVAL;
 
 	if (!mpu_opps || !dsp_opps)
 		return 0;
 
 	if (strcmp(resp->name, "mpu_freq") == 0) {
-		vdd1_opp = get_opp(mpu_opps + MAX_VDD1_OPP, target_level);
-		resource_request("vdd1_opp", &dummy_mpu_dev, vdd1_opp);
+		ret = freq_to_opp(&vdd1_opp, mpu_opps, target_level);
+		if (!ret)
+			ret = resource_request("vdd1_opp", &dummy_mpu_dev,
+					vdd1_opp);
 	} else if (strcmp(resp->name, "dsp_freq") == 0) {
-		vdd1_opp = get_opp(dsp_opps + MAX_VDD1_OPP, target_level);
-		resource_request("vdd1_opp", &dummy_dsp_dev, vdd1_opp);
+		ret = freq_to_opp(&vdd1_opp, dsp_opps, target_level);
+		if (!ret)
+			ret = resource_request("vdd1_opp", &dummy_dsp_dev,
+					vdd1_opp);
 	}
-	resp->curr_level = target_level;
-	return 0;
+	if (!ret)
+		resp->curr_level = target_level;
+	return ret;
 }
 
 int validate_freq(struct shared_resource *resp, u32 target_level)
 {
+	u8 x;
+	if (strcmp(resp->name, "mpu_freq") == 0)
+		return freq_to_opp(&x, mpu_opps, target_level);
+	else if (strcmp(resp->name, "dsp_freq") == 0)
+		return freq_to_opp(&x, dsp_opps, target_level);
 	return 0;
 }
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 05/10 V3] omap3: pm: sr: replace get_opp with freq_to_opp
  2009-11-25  4:09       ` [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions Nishanth Menon
@ 2009-11-25  4:09         ` Nishanth Menon
  2009-11-25  4:09           ` [PATCH 06/10 V3] omap3: pm: use opp accessor functions for omap-target Nishanth Menon
  2009-12-07 16:59         ` [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions Tero.Kristo
  1 sibling, 1 reply; 36+ messages in thread
From: Nishanth Menon @ 2009-11-25  4:09 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Benoit Cousson, Kevin Hilman,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

SmartReflex implements a get_opp to search through the opp table,
replace it opp_is_valid to verify the OPPs and getting the opp_id.

NOTE: usage of opp_id is deprecated and this introduces the following
warnings:
arch/arm/mach-omap2/smartreflex.c: In function 'get_vdd1_opp':
arch/arm/mach-omap2/smartreflex.c:160: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
arch/arm/mach-omap2/smartreflex.c: In function 'get_vdd2_opp':
arch/arm/mach-omap2/smartreflex.c:174: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Romit Dasgupta <romit@ti.com>
Cc: Sanjeev Premi <premi@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 arch/arm/mach-omap2/smartreflex.c |   42 ++++++++++--------------------------
 1 files changed, 12 insertions(+), 30 deletions(-)

diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index be3a1da..6f8b7cc 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -146,50 +146,32 @@ static u32 cal_test_nvalue(u32 sennval, u32 senpval)
 		(rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT);
 }
 
-/* determine the current OPP from the frequency
- * we need to give this function last element of OPP rate table
- * and the frequency
- */
-static u16 get_opp(struct omap_opp *opp_freq_table,
-					unsigned long freq)
-{
-	struct omap_opp *prcm_config;
-
-	prcm_config = opp_freq_table;
-
-	if (prcm_config->rate <= freq)
-		return prcm_config->opp_id; /* Return the Highest OPP */
-	for (; prcm_config->rate; prcm_config--)
-		if (prcm_config->rate < freq)
-			return (prcm_config+1)->opp_id;
-		else if (prcm_config->rate == freq)
-			return prcm_config->opp_id;
-	/* Return the least OPP */
-	return (prcm_config+1)->opp_id;
-}
-
-static u16 get_vdd1_opp(void)
+static u8 get_vdd1_opp(void)
 {
-	u16 opp;
+	struct omap_opp *opp;
 
 	if (sr1.vdd_opp_clk == NULL || IS_ERR(sr1.vdd_opp_clk) ||
 							mpu_opps == NULL)
 		return 0;
 
-	opp = get_opp(mpu_opps + MAX_VDD1_OPP, sr1.vdd_opp_clk->rate);
-	return opp;
+	if (unlikely(opp_is_valid(&opp, mpu_opps, sr1.vdd_opp_clk->rate)))
+		return 0;
+
+	return opp->opp_id;
 }
 
-static u16 get_vdd2_opp(void)
+static u8 get_vdd2_opp(void)
 {
-	u16 opp;
+	struct omap_opp *opp;
 
 	if (sr2.vdd_opp_clk == NULL || IS_ERR(sr2.vdd_opp_clk) ||
 							l3_opps == NULL)
 		return 0;
 
-	opp = get_opp(l3_opps + MAX_VDD2_OPP, sr2.vdd_opp_clk->rate);
-	return opp;
+	if (unlikely(opp_is_valid(&opp, l3_opps, sr2.vdd_opp_clk->rate)))
+		return 0;
+
+	return opp->opp_id;
 }
 
 
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 06/10 V3] omap3: pm: use opp accessor functions for omap-target
  2009-11-25  4:09         ` [PATCH 05/10 V3] omap3: pm: sr: replace get_opp with freq_to_opp Nishanth Menon
@ 2009-11-25  4:09           ` Nishanth Menon
  2009-11-25  4:09             ` [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table Nishanth Menon
  2009-11-25 17:56             ` [PATCH 06/10 V3] omap3: pm: use opp accessor functions for omap-target Kevin Hilman
  0 siblings, 2 replies; 36+ messages in thread
From: Nishanth Menon @ 2009-11-25  4:09 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Benoit Cousson, Kevin Hilman,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

The logic in omap-target can now be improved with the accessor
functions. Dont scan through the list manually, instead use
get_next_freq to do the scanning.

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Romit Dasgupta <romit@ti.com>
Cc: Sanjeev Premi <premi@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 arch/arm/plat-omap/cpu-omap.c |   19 +++++++++++--------
 1 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index 449b6b6..7b3ca11 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -111,14 +111,17 @@ static int omap_target(struct cpufreq_policy *policy,
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 #elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
 	if (mpu_opps) {
-		int ind;
-		for (ind = 1; ind <= MAX_VDD1_OPP; ind++) {
-			if (mpu_opps[ind].rate/1000 >= target_freq) {
-				omap_pm_cpu_set_freq
-					(mpu_opps[ind].rate);
-				break;
-			}
-		}
+		unsigned long freq = target_freq * 1000;
+		struct omap_opp *opp = NULL;
+		int res;
+		/* see if we have exact freq match */
+		res = opp_is_valid(&opp, mpu_opps, freq);
+		/* Get next best if we cant find a exact match */
+		if (res)
+			res = opp_get_higher_opp(&opp, &freq, mpu_opps);
+
+		if (!res)
+			omap_pm_cpu_set_freq(freq);
 	}
 #endif
 	return ret;
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table
  2009-11-25  4:09           ` [PATCH 06/10 V3] omap3: pm: use opp accessor functions for omap-target Nishanth Menon
@ 2009-11-25  4:09             ` Nishanth Menon
  2009-11-25  4:09               ` [PATCH 08/10] omap3: pm: remove VDDx_MIN/MAX macros Nishanth Menon
                                 ` (2 more replies)
  2009-11-25 17:56             ` [PATCH 06/10 V3] omap3: pm: use opp accessor functions for omap-target Kevin Hilman
  1 sibling, 3 replies; 36+ messages in thread
From: Nishanth Menon @ 2009-11-25  4:09 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Benoit Cousson, Kevin Hilman,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

omap2_clk_init_cpufreq_table currently directly accesses the opp
table, making it unscalable to various OMAPs. Instead use the
accessor functions to populate the cpufreq table

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Romit Dasgupta <romit@ti.com>
Cc: Sanjeev Premi <premi@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 arch/arm/mach-omap2/clock34xx.c |   32 +++++++++++++++++++-------------
 1 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 5150939..d07f1c1 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -1042,30 +1042,36 @@ static unsigned long omap3_clkoutx2_recalc(struct clk *clk)
 #if defined(CONFIG_ARCH_OMAP3)
 
 #ifdef CONFIG_CPU_FREQ
-static struct cpufreq_frequency_table freq_table[MAX_VDD1_OPP+1];
+
+static struct cpufreq_frequency_table *freq_table;
 
 void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
 {
-	struct omap_opp *prcm;
 	int i = 0;
+	u8 opp_num;
+	struct omap_opp *opp = NULL;
+	unsigned long freq = ULONG_MAX;
 
-	if (!mpu_opps)
+	if (!mpu_opps || opp_get_opp_count(&opp_num, mpu_opps)) {
+		pr_warning("%s: failed to initialize frequency"
+				"table\n", __func__);
 		return;
-
-	prcm = mpu_opps + MAX_VDD1_OPP;
-	for (; prcm->rate; prcm--) {
-		freq_table[i].index = i;
-		freq_table[i].frequency = prcm->rate / 1000;
-		i++;
 	}
 
-	if (i == 0) {
-		printk(KERN_WARNING "%s: failed to initialize frequency \
-								table\n",
-								__func__);
+	freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
+			(opp_num + 1), GFP_KERNEL);
+	if (!freq_table) {
+		pr_warning("%s: failed to allocate frequency"
+				"table\n", __func__);
 		return;
 	}
 
+	while (!opp_get_lower_opp(&opp, &freq, mpu_opps)) {
+		freq_table[i].index = i;
+		freq_table[i].frequency =  freq / 1000;
+		i++;
+	}
+
 	freq_table[i].index = i;
 	freq_table[i].frequency = CPUFREQ_TABLE_END;
 
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 08/10] omap3: pm: remove VDDx_MIN/MAX macros
  2009-11-25  4:09             ` [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table Nishanth Menon
@ 2009-11-25  4:09               ` Nishanth Menon
  2009-11-25  4:09                 ` [PATCH 09/10 V3] omap3: pm: introduce 3630 opps Nishanth Menon
  2009-12-07 16:54               ` [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table Tero.Kristo
  2009-12-08  7:54               ` Eduardo Valentin
  2 siblings, 1 reply; 36+ messages in thread
From: Nishanth Menon @ 2009-11-25  4:09 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Benoit Cousson, Kevin Hilman,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

Since accessor functions are used through out, we dont depend
on the predefined macros to know the limits of the opp table.
Hence, remove these.

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Romit Dasgupta <romit@ti.com>
Cc: Sanjeev Premi <premi@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 arch/arm/plat-omap/include/plat/omap34xx.h |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/omap34xx.h b/arch/arm/plat-omap/include/plat/omap34xx.h
index 6b849e5..9768f8a 100644
--- a/arch/arm/plat-omap/include/plat/omap34xx.h
+++ b/arch/arm/plat-omap/include/plat/omap34xx.h
@@ -98,10 +98,5 @@
 #define VDD2_OPP2	0x2
 #define VDD2_OPP3	0x3
 
-#define MIN_VDD1_OPP	VDD1_OPP1
-#define MAX_VDD1_OPP	VDD1_OPP5
-#define MIN_VDD2_OPP	VDD2_OPP1
-#define MAX_VDD2_OPP	VDD2_OPP3
-
 #endif /* __ASM_ARCH_OMAP34XX_H */
 
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 09/10 V3] omap3: pm: introduce 3630 opps
  2009-11-25  4:09               ` [PATCH 08/10] omap3: pm: remove VDDx_MIN/MAX macros Nishanth Menon
@ 2009-11-25  4:09                 ` Nishanth Menon
  2009-11-25  4:09                   ` [PATCH 10/10] omap3: pm: omap3630 boards: enable 3630 opp tables Nishanth Menon
  2009-12-08  7:49                   ` [PATCH 09/10 V3] omap3: pm: introduce 3630 opps Eduardo Valentin
  0 siblings, 2 replies; 36+ messages in thread
From: Nishanth Menon @ 2009-11-25  4:09 UTC (permalink / raw)
  To: linux-omap
  Cc: Nishanth Menon, Benoit Cousson, Kevin Hilman,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

Introduce the OMAP3630 OPPs including the defined OPP tuples.

Further information on OMAP3630 can be found here:
http://focus.ti.com/general/docs/wtbu/wtbuproductcontent.tsp?templateId=6123&navigationId=12836&contentId=52606

OMAP36xx family introduces:
VDD1 with 4 OPPs, of which OPP3 & 4 are available only on devices yet
to be introduced in 36xx family. Meanwhile, VDD2 has 2 opps.

Device Support of OPPs->
           |<-3630-600->| (default)
           |<-      3630-800    ->| (device: TBD)
           |<-      3630-1000            ->| (device: TBD)
H/w OPP-> OPP50 OPP100       OPP-Turbo   OPP1G-SB
VDD1      OPP1  OPP2         OPP3        OPP4
VDD2      OPP1  OPP2         OPP2        OPP2

Note:
a) TI h/w naming for OPPs are now standardized in terms of OPP50, 100,
   Turbo and SB. This maps as shown above to the opp IDs (s/w term).
b) For boards which need custom VDD1/2 OPPs, the opp table can be
   updated by the board file on a need basis after the
   omap3_pm_init_opp_table call. The OPPs introduced here are the
   official OPP table at this point in time.

Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Romit Dasgupta <romit@ti.com>
Cc: Sanjeev Premi <premi@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 arch/arm/mach-omap2/pm34xx.c |   49 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index ad21f5f..05ecf02 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -143,6 +143,41 @@ static struct omap_opp_def __initdata omap34xx_dsp_rate_table[] = {
 	{.enabled = 0, .freq = 0, .u_volt = 0}
 };
 
+static struct omap_opp_def __initdata omap36xx_mpu_rate_table[] = {
+	/*OPP1 - OPP50*/
+	{.enabled = true,  .freq = 300000000, .u_volt = 930000},
+	/*OPP2 - OPP100*/
+	{.enabled = true,  .freq = 600000000, .u_volt = 1100000},
+	/*OPP3 - OPP-Turbo*/
+	{.enabled = false, .freq = 800000000, .u_volt = 1260000},
+	/*OPP4 - OPP-SB*/
+	{.enabled = false, .freq = 1000000000, .u_volt = 1310000},
+	/* Terminator */
+	{.enabled = 0, .freq = 0, .u_volt = 0}
+};
+
+static struct omap_opp_def __initdata omap36xx_l3_rate_table[] = {
+	/*OPP1 - OPP50 */
+	{.enabled = true, .freq = 100000000, .u_volt = 930000},
+	/*OPP2 - OPP100, OPP-Turbo, OPP-SB*/
+	{.enabled = true, .freq = 200000000, .u_volt = 1137500},
+	/* Terminator */
+	{.enabled = 0, .freq = 0, .u_volt = 0}
+};
+
+static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
+	/*OPP1 - OPP50*/
+	{.enabled = true,  .freq = 260000000, .u_volt = 930000},
+	/*OPP2 - OPP100*/
+	{.enabled = true,  .freq = 520000000, .u_volt = 1100000},
+	/*OPP3 - OPP-Turbo*/
+	{.enabled = false, .freq = 660000000, .u_volt = 1260000},
+	/*OPP4 - OPP-SB*/
+	{.enabled = false, .freq = 875000000, .u_volt = 1310000},
+	/* Terminator */
+	{.enabled = 0, .freq = 0, .u_volt = 0}
+};
+
 struct omap_opp *omap3_mpu_rate_table;
 struct omap_opp *omap3_dsp_rate_table;
 struct omap_opp *omap3_l3_rate_table;
@@ -1299,18 +1334,28 @@ static void __init configure_vc(void)
 void __init omap3_pm_init_opp_table(void)
 {
 	int ret, i;
+	struct omap_opp_def **omap3_opp_def_list;
 	struct omap_opp_def *omap34xx_opp_def_list[] = {
 		omap34xx_mpu_rate_table,
 		omap34xx_l3_rate_table,
 		omap34xx_dsp_rate_table
 	};
+	struct omap_opp_def *omap36xx_opp_def_list[] = {
+		omap36xx_mpu_rate_table,
+		omap36xx_l3_rate_table,
+		omap36xx_dsp_rate_table
+	};
 	struct omap_opp **omap3_rate_tables[] = {
 		&omap3_mpu_rate_table,
 		&omap3_l3_rate_table,
 		&omap3_dsp_rate_table
 	};
-	for (i = 0; i < ARRAY_SIZE(omap34xx_opp_def_list); i++) {
-		ret = opp_init(omap3_rate_tables[i], omap34xx_opp_def_list[i]);
+
+	omap3_opp_def_list = cpu_is_omap3630() ? omap36xx_opp_def_list :
+				omap34xx_opp_def_list;
+
+	for (i = 0; i < ARRAY_SIZE(omap3_rate_tables); i++) {
+		ret = opp_init(omap3_rate_tables[i], omap3_opp_def_list[i]);
 		/* We dont want half configured system at the moment */
 		BUG_ON(ret);
 	}
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 10/10] omap3: pm: omap3630 boards: enable 3630 opp tables
  2009-11-25  4:09                 ` [PATCH 09/10 V3] omap3: pm: introduce 3630 opps Nishanth Menon
@ 2009-11-25  4:09                   ` Nishanth Menon
  2009-12-08  7:49                   ` [PATCH 09/10 V3] omap3: pm: introduce 3630 opps Eduardo Valentin
  1 sibling, 0 replies; 36+ messages in thread
From: Nishanth Menon @ 2009-11-25  4:09 UTC (permalink / raw)
  To: linux-omap; +Cc: Nishanth Menon

enable the OPP tables for 3630 platforms: SDP3630, zoom3.
NOTE: This needs the corresponding clockframework changes.

Currently this dumps the following on OPP transitions on SDP3630:
[<c002d734>] (dump_backtrace+0x0/0x110) from [<c02c9698>] (dump_stack+0x18/0x1c)
r7:00000000 r6:c003bff8 r5:c034a227 r4:00000309
[<c02c9680>] (dump_stack+0x0/0x1c) from [<c0052f24>] (warn_slowpath_common+0x50/0x68)
[<c0052ed4>] (warn_slowpath_common+0x0/0x68) from [<c0052f54>] (warn_slowpath_null+0x18/0x1c)
r7:c7801000 r6:0f7f4900 r5:80000013 r4:00000000
[<c0052f3c>] (warn_slowpath_null+0x0/0x1c) from [<c003bff8>] (omap3_noncore_dpll_set_rate+0x294/0x2d8)
[<c003bd64>] (omap3_noncore_dpll_set_rate+0x0/0x2d8) from [<c0036e24>] (omap2_clk_set_rate+0x28/0x34)
[<c0036dfc>] (omap2_clk_set_rate+0x0/0x34) from [<c003ecec>] (clk_set_rate+0x54/0xb8)
[<c003ec98>] (clk_set_rate+0x0/0xb8) from [<c003c750>] (program_opp+0x120/0x228)
r7:c7801000 r6:00000000 r5:c03c9fe0 r4:c03c9fd8
[<c003c630>] (program_opp+0x0/0x228) from [<c003c990>] (resource_set_opp_level+0x138/0x1b0)
[<c003c858>] (resource_set_opp_level+0x0/0x1b0) from [<c0038534>] (vdd_opp_store+0x148/0x17c)
[<c00383ec>] (vdd_opp_store+0x0/0x17c) from [<c01b39dc>] (kobj_attr_store+0x20/0x24)
r7:c7833740 r6:c794bec0 r5:c78c8960 r4:00000001
[<c01b39bc>] (kobj_attr_store+0x0/0x24) from [<c0102c3c>] (sysfs_write_file+0x110/0x144)
[<c0102b2c>] (sysfs_write_file+0x0/0x144) from [<c00b2f90>] (vfs_write+0xb8/0x164)
[<c00b2ed8>] (vfs_write+0x0/0x164) from [<c00b3100>] (sys_write+0x44/0x70)
r8:40000000 r7:00000001 r6:c783de00 r5:00000000 r4:00000000
[<c00b30bc>] (sys_write+0x0/0x70) from [<c0029f80>] (ret_fast_syscall+0x0/0x2c)
r8:c002a104 r7:00000004 r6:001d7918 r5:40000000 r4:00000001

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 arch/arm/mach-omap2/board-3630sdp.c |    9 ++++++++-
 arch/arm/mach-omap2/board-zoom3.c   |    9 ++++++++-
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 185f48d..7a429db 100755
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -24,6 +24,8 @@
 #include <mach/board-zoom.h>
 
 #include "sdram-hynix-h8mbx00u0mer-0em.h"
+#include "pm.h"
+#include "omap3-opp.h"
 
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
 
@@ -76,9 +78,14 @@ static void __init omap_sdp_init_irq(void)
 {
 	omap_board_config = sdp_config;
 	omap_board_config_size = ARRAY_SIZE(sdp_config);
+
+	omap3_pm_init_opp_table();
+	/* TODO: Add RET, OFF, cpu_idle params */
+
 	omap2_init_common_hw(h8mbx00u0mer0em_sdrc_params,
 			     h8mbx00u0mer0em_sdrc_params,
-                             NULL, NULL, NULL);
+			     omap3_mpu_rate_table, omap3_dsp_rate_table,
+			     omap3_l3_rate_table);
 	omap_init_irq();
 	omap_gpio_init();
 }
diff --git a/arch/arm/mach-omap2/board-zoom3.c b/arch/arm/mach-omap2/board-zoom3.c
index fe97324..0574811 100644
--- a/arch/arm/mach-omap2/board-zoom3.c
+++ b/arch/arm/mach-omap2/board-zoom3.c
@@ -22,6 +22,8 @@
 #include <plat/board.h>
 
 #include "sdram-hynix-h8mbx00u0mer-0em.h"
+#include "pm.h"
+#include "omap3-opp.h"
 
 static void __init omap_zoom_map_io(void)
 {
@@ -36,9 +38,14 @@ static void __init omap_zoom_init_irq(void)
 {
 	omap_board_config = zoom_config;
 	omap_board_config_size = ARRAY_SIZE(zoom_config);
+
+	omap3_pm_init_opp_table();
+	/* TODO: Add RET, OFF, cpu_idle params */
+
 	omap2_init_common_hw(h8mbx00u0mer0em_sdrc_params,
 			     h8mbx00u0mer0em_sdrc_params,
-			     NULL, NULL, NULL);
+			     omap3_mpu_rate_table, omap3_dsp_rate_table,
+			     omap3_l3_rate_table);
 	omap_init_irq();
 	omap_gpio_init();
 }
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH 00/10 v3] omap3: pm: introduce support for 3630 OPPs
  2009-11-25  4:09 [PATCH 00/10 v3] omap3: pm: introduce support for 3630 OPPs Nishanth Menon
  2009-11-25  4:09 ` [PATCH 01/10] omap3: pm: introduce enabled flag to omap_opp Nishanth Menon
@ 2009-11-25 15:24 ` Kevin Hilman
  1 sibling, 0 replies; 36+ messages in thread
From: Kevin Hilman @ 2009-11-25 15:24 UTC (permalink / raw)
  To: Nishanth Menon; +Cc: linux-omap

Nishanth Menon <nm@ti.com> writes:

> Hi,
> Here is V3 of the patch series.  What changed in V3:
> * Major rewrite of OPP APIs. This includes changes from offline
>   discussions with lots of folks and taking in l-o comments - all
>   patches have changed as a result.
> * rebased to latest lo-pm
>
> V2: http://marc.info/?l=linux-omap&m=125809232732700&w=2
> V1: http://marc.info/?l=linux-omap&m=125800488923479&w=2
>
> NOTE: After a bunch of frustrating efforts, current OPP accessor
> implementation is constrained by two files:
> smartreflex.c and resource34xx.c. I agree that the current opp
> accessor implementation leaves lot to be desired, but the nature of
> struct omap_opp cannot change unless we essentially rewrite the
> implementation of the mentioned files.
>
> Ref: http://elinux.org/OMAP_Power_Management#Future_directions
>
> I propose we could take this in in three stages:
> Stage 1: Introduce this series in as starters if there are no major
>  issues
> Stage 2: We cleanup/replace resource34xx and smartreflex.c
> Stage 3: Go through a second round of optimization/cleanup of opp
>  accessors implementation (this time for good hopefully)

I'm open to this 3-step approach assuming that stage 2 and 3 remain a
priority.  This "stage 1" series will not go upstream.  I will only
push upstream after getting to stage 3. 

After some review and discussion, I can pull Stage 1 into the PM
branch for broader testing and as a base for more people to help on
stage 2 and stage 3.

Review comments on individual patches to follow.

Kevin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions
  2009-11-25  4:09   ` [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions Nishanth Menon
  2009-11-25  4:09     ` [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx Nishanth Menon
@ 2009-11-25 16:30     ` Kevin Hilman
  2009-11-25 20:31       ` Nishanth Menon
  1 sibling, 1 reply; 36+ messages in thread
From: Kevin Hilman @ 2009-11-25 16:30 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: linux-omap, Benoit Cousson, Madhusudhan Chikkature Rajashekar,
	Paul Walmsley, Romit Dasgupta, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy, Sanjeev Premi

Nishanth Menon <nm@ti.com> writes:

> Modifies the initial patch From Sanjeev:
> http://patchwork.kernel.org/patch/50998/
> Discussions and comments from:
> http://marc.info/?l=linux-omap&m=125482970102327&w=2
> http://marc.info/?t=125809247500002&r=1&w=2
> incorporated.
>
> OMAP SOCs have a standard set of tuples consisting of frequency and
> voltage pairs that the device will support per voltage domain. This
> is called Operating Points or OPP. The actual definitions of OMAP
> Operating Points varies over silicon within the same family of
> devices. For a specific domain, you can have a set of
> {frequency, voltage} pairs. As the kernel boots and more information
> is available, a set of these are activated based on the precise
> nature of device the kernel boots up on. It is interesting to
> remember that each IP which belongs to a voltage domain may define
> their own set of OPPs on top of this.
>
> This introduces a common handling OPP mechanism accross all OMAPs.
> As a start this is introduced for OMAP3 and intends to replace
> current OMAP3 opp handling mechanism.
>
> Note:
> fields of struct omap_opp is currently exposed due to the necessity
> that SRF and SR logic directly indexes the structure array fields.
> The goal however, is to make the direct usage of omap_opp deprecated
> and move to using these accessor functions. The usage in SRF and SR
> indexes based on opp_id and hence opp_id is marked deprecated to
> generate build warnings at least. Further, this usage necessitates
> need of terminator entries at the start and end of opp_* tables which
> are dynamically allocated.

Nice. I like the use of 'deprecated' here to be clear that this stuff
is going way.

> The accessor function definitions were collaborated with Kevin, and
> doing justice here, this implementation could not go with some of
> the better suggestions from kevin due to constraint imposed by SRF
> and SR. A better and more optimal implementation is definitely
> possible once SRF and SR are cleanedup/replaced.
>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Romit Dasgupta <romit@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
> Cc: Thara Gopinath <thara@ti.com>
> Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
>
> Signed-off-by: Sanjeev Premi <premi@ti.com>
> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>

Not yet. :)

> Signed-off-by: Nishanth Menon <nm@ti.com>

Some general comments.

I think the forcing of an int return code for all the functions is a
bit artificial, and is a loss in readability IMHO.  I've never liked
getting results values in function arguments, and find that style
difficult to read.  More comments on this for each function below.

> ---
>  arch/arm/plat-omap/Makefile           |    3 +
>  arch/arm/plat-omap/include/plat/opp.h |  208 ++++++++++++++++++++++++++
>  arch/arm/plat-omap/opp.c              |  260 +++++++++++++++++++++++++++++++++

I think this should be mach-omap2/opp.c

>  3 files changed, 471 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/plat-omap/include/plat/opp.h
>  create mode 100644 arch/arm/plat-omap/opp.c
>
> diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
> index 95f8413..e9cf601 100644
> --- a/arch/arm/plat-omap/Makefile
> +++ b/arch/arm/plat-omap/Makefile
> @@ -12,6 +12,9 @@ obj-  :=
>  # OCPI interconnect support for 1710, 1610 and 5912
>  obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
>  
> +# OPP support in (OMAP3+ only at the moment)
> +obj-$(CONFIG_ARCH_OMAP3) += opp.o
> +
>  # omap_device support (OMAP2+ only at the moment)
>  obj-$(CONFIG_ARCH_OMAP2) += omap_device.o
>  obj-$(CONFIG_ARCH_OMAP3) += omap_device.o
> diff --git a/arch/arm/plat-omap/include/plat/opp.h b/arch/arm/plat-omap/include/plat/opp.h
> new file mode 100644
> index 0000000..d8ae2d3
> --- /dev/null
> +++ b/arch/arm/plat-omap/include/plat/opp.h
> @@ -0,0 +1,208 @@
> +/*
> + * OMAP OPP Interface
> + *
> + * Copyright (C) 2009 Texas Instruments Incorporated.
> + *	Nishanth Menon
> + * Copyright (C) 2009 Deep Root Systems, LLC.
> + *	Kevin Hilman
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#ifndef __ASM_ARM_OMAP_OPP_H
> +#define __ASM_ARM_OMAP_OPP_H
> +
> +/**
> + * struct omap_opp - OMAP OPP description structure
> + * @enabled:	true/false - marking this OPP as enabled/disabled
> + * @rate:	Frequency in hertz
> + * @opp_id:	(DEPRECATED) opp identifier
> + * @vsel:	Voltage in volt processor level(this usage is
> + *		DEPRECATED to use Voltage in microvolts in future)
> + *		uV = ((vsel * 12.5) + 600) * 1000
> + *
> + * This structure stores the OPP information for a given domain.
> + * Due to legacy reasons, this structure is currently exposed and
> + * will soon be removed elsewhere and will only be used as a handle
> + * from the OPP internal referencing mechanism
> + */
> +struct omap_opp {
> +	bool enabled;
> +	unsigned long rate;
> +	u8 opp_id __deprecated;
> +	u16 vsel;
> +};
> +
> +/**
> + * opp_get_voltage - Gets the voltage corresponding to an opp
> + * @u_volt:	Voltage in microvolts corresponding to an opp
> + * @opp:	opp for which voltage has to be returned for
> + *
> + * Return 0 and the voltage in micro volt corresponding to the opp,
> + * else return the corresponding error value.
> + */
> +int opp_get_voltage(u32 *u_volt, const struct omap_opp *opp);

Should just return voltage or -EINVAL

int opp_get_voltage(const struct omap_opp *opp);

> +
> +/**
> + * opp_get_freq - Gets the frequency corresponding to an opp
> + * @freq:	Frequency in hertz corresponding to an opp
> + * @opp:	opp for which frequency has to be returned for
> + *
> + * Return 0 and the frequency in hertz corresponding to the opp,
> + * else return the corresponding error value.
> + */
> +int opp_get_freq(unsigned long *freq, const struct omap_opp *opp);

ditto

> +
> +/**
> + * opp_is_valid - Verifies if a given frequency is enabled in the opp list
> + * @opp:	Pointer to opp returned if opp match is achieved
> + * @oppl:	opp list
> + * @freq:	Frequency in hertz to check for
> + *
> + * Searches the OPP list to find if the provided frequency is an enabled
> + * frequency. If a match is achieved, it returns 0 and the pointer to the opp
> + * is returned, else a corresponding error value is returned.
> + */
> +int opp_is_valid(struct omap_opp **opp, const struct omap_opp *oppl,
> +		const unsigned long freq);
> +
> +/**
> + * opp_has_freq - Checks if a frequency is exists(enabled/disabled) in opp list
> + * @opp:	Pointer to opp returned if opp match is achieved
> + * @oppl:	opp list
> + * @freq:	Frequency in hertz to check for
> + *
> + * Searches the OPP list to find a frequency. This is a more generic function
> + * than the opp_is_valid since it searches for both enabled/disabled
> + * frequencies.
> + *
> + * This function may be used by detection logic to enable a disabled OPP as
> + * all other search functions work on enabled OPPs only.
> + */
> +int opp_has_freq(struct omap_opp **opp, const struct omap_opp *oppl,
> +		const unsigned long freq);

Don't see any users of this, and it looks like the same functionality
as opp_is_valid().

Both of these are just a "find opp by freq".  How about having
something like this instead:

/**
 * opp_find_freq()
 * @oppl:        OPP list
 * @freq:        Frequency to look for in OPP table
 *
 * Look for an enabled OPP with a frequency value matching @freq.
 *
 * Returns pointer to OPP entry if match is found, or NULL if no match
 * found.
 */
struct omap_opp *opp_find_freq(const struct omap_opp *oppl, u32 freq);


> +/**
> + * opp_get_opp_count - Get number of opps enabled in the opp list
> + * @num:	returns the number of opps
> + * @oppl:	opp list
> + *
> + * This functions returns 0 and the number of opps are updated in num if
> + * success, else returns corresponding error value.
> + */
> +int opp_get_opp_count(u8 *num, const struct omap_opp *oppl2);

Should just return count:

int opp_get_opp_count(const struct omap_opp *oppl);

> +/**
> + * opp_get_higher_opp - search for the next highest opp in the list
> + * @opp:	pointer to the opp
> + * @freq:	frequency to start the search on
> + * @oppl:	opp list to search on
> + *
> + * Searches for the higher *enabled* OPP than a starting freq/opp
> + * Decision of start condition:
> + *	if *opp is NULL, *freq is checked (usually the start condition)
> + *	if *opp is populated, *freq is ignored
> + * Returns 0 and *opp and *freq is populated with the next highest match,
> + * else returns corresponding error value.
> + *
> + * Example usage:
> + *	* print a all frequencies ascending order *
> + *	unsigned long freq = 0;
> + *	struct omap_opp *opp = NULL;
> + *	while(!opp_get_higher_opp(&opp, &freq, oppl))
> + *		pr_info("%ld ", freq);
> + * NOTE: if we set freq as 0, we get the lowest enabled frequency
> + */
> +int opp_get_higher_opp(struct omap_opp **opp, unsigned long *freq,
> +			const struct omap_opp *oppl);
> +
> +/**
> + * opp_get_lower_opp - search for the next lower opp in the list
> + * @opp:	pointer to the opp
> + * @freq:	frequency to start the search on
> + * @oppl:	opp list to search on
> + *
> + * Search for the lower *enabled* OPP than a starting freq/opp
> + * Decision of start condition:
> + *	if *opp is NULL, *freq is checked (usually the start condition)
> + *	if *opp is populated, *freq is ignored
> + * Returns 0 and *opp and *freq is populated with the next lowest match,
> + * else returns corresponding error value.
> + *
> + * Example usage:
> + *	* print a all frequencies in descending order *
> + *	unsigned long freq = ULONG_MAX;
> + *	struct omap_opp *opp = NULL;
> + *	while(!opp_get_lower_opp(&opp, &freq, oppl))
> + *		pr_info("%ld ", freq);
> + * NOTE: if we set freq as ULONG_MAX, we get the highest enabled frequency
> + */
> +int opp_get_lower_opp(struct omap_opp **opp, unsigned long *freq,
> +			const struct omap_opp *oppl);

I think these should be combined to a single function for finding a
nearby OPP using rounding.  Something like this:

/**
 * opp_find_freq_rounded()
 * @oppl:        OPP list
 * @freq:        Frequency to look for in OPP table
 * @rounding:    Rounding option: NONE, UP, DOWN
 *
 * Look for an OPP with a frequency value matching @freq.  If
 * @rounding != ROUND_NONE, find closest match using rounding.
 *
 * Can be used to find exact OPP, or match using given rounding:

 * @rounding == UP:      find next highest frequency
 * @rounding == DOWN:    find next lowest frequency
 * @rounding == CLOSEST: find closest frequency
 *
 * Returns pointer to OPP entry if match is found, or NULL if no match
 * found (only possible when no rounding is used)
 */
struct omap_opp *opp_find_freq_rounded(struct omap_opp *oppl, u32 freq, u32 rounding);

Looking at the users of the 'higher' and 'lower' OPPs in the current
code, I see that SRF tries to use all three one after the other.
First it checks for exact match, then for higher, then for lower.
This could be replaced simply by doing a 'closest' match.

> +/**
> + * struct omap_opp_def - OMAP OPP Definition
> + * @enabled:	True/false - is this OPP enabled/disabled by default
> + * @freq:	Frequency in hertz corresponding to this OPP
> + * @u_volt:	Nominal voltage in microvolts corresponding to this OPP
> + *
> + * OMAP SOCs have a standard set of tuples consisting of frequency and voltage
> + * pairs that the device will support per voltage domain. This is called
> + * Operating Points or OPP. The actual definitions of OMAP Operating Points
> + * varies over silicon within the same family of devices. For a specific
> + * domain, you can have a set of {frequency, voltage} pairs and this is denoted
> + * by an array of omap_opp_def. As the kernel boots and more information is
> + * available, a set of these are activated based on the precise nature of
> + * device the kernel boots up on. It is interesting to remember that each IP
> + * which belongs to a voltage domain may define their own set of OPPs on top
> + * of this - but this is handled by the appropriate driver.
> + */
> +struct omap_opp_def {
> +	bool enabled;
> +	unsigned long freq;
> +	u32 u_volt;
> +};
> +
> +/**
> + * opp_init - Initialize an OPP table from the initial table definition
> + * @oppl:	Returned back to caller as the opp list to reference the OPP
> + * @opp_defs:	Array of omap_opp_def to describe the OPP. This list should be
> + *		0 terminated.
> + *
> + * This function creates the internal datastructure representing the OPP list
> + * from an initial definition table. this handle is then used for further
> + * validation, search, modification operations on the OPP list.
> + *
> + * This function returns 0 and the pointer to the allocated list through oppl if
> + * success, else corresponding error value. Caller should NOT free the oppl.
> + * opps_defs can be freed after use.
> + */
> +int __init opp_init(struct omap_opp **oppl,
> +		const struct omap_opp_def *opp_defs);

I think this should be generalized as an 'opp_add' that adds a single
OPP to the master list.

The init code can iterate over its tables to add OPPs.  This has a
few benefits:

1) separates the structure of OPPs in init code from that of OPP core
2) board and/or custom code can later add OPPs to the table
3) enables (enforces) the OPP core to keep OPPs in an order suitable
   for its own search algorithms (sorted list, etc.)

> +/**
> + * opp_enable - Enable a specific OPP
> + * @opp:	pointer to opp
> + *
> + * Enables a provided opp. If the operation is valid, this returns 0, else the
> + * corresponding error value.
> + *
> + * OPP used here is from the the opp_is_valid/opp_has_freq or other search
> + * functions
> + */
> +int __init opp_enable(struct omap_opp *opp);
> +
> +/**
> + * opp_disable - Disable a specific OPP
> + * @opp:	pointer to opp
> + *
> + * Disables a provided opp. If the operation is valid, this returns 0, else the
> + * corresponding error value.
> + *
> + * OPP used here is from the the opp_is_valid/opp_has_freq or other search
> + * functions
> + */
> +int __init opp_disable(struct omap_opp *opp);

OK, but why are these __init?

There may be reasons, such as thermal, that we might want do disable
and (re)enable OPPs later at runtime.

No other particular comments on the implementation in opp.c, other
than the complaints you already know about and are a result of the SRF
and smartreflex usage of OPP layer.

Kevin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx
  2009-11-25  4:09     ` [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx Nishanth Menon
  2009-11-25  4:09       ` [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions Nishanth Menon
@ 2009-11-25 17:22       ` Kevin Hilman
  2009-11-25 17:27         ` Kevin Hilman
  2009-12-07 17:02         ` Tero.Kristo
  2009-12-08  8:08       ` Eduardo Valentin
  2 siblings, 2 replies; 36+ messages in thread
From: Kevin Hilman @ 2009-11-25 17:22 UTC (permalink / raw)
  To: Nishanth Menon; +Cc: linux-omap

Nishanth Menon <nm@ti.com> writes:

> Move the definitions from omap3-opp.h to pm34xx.c. The definitions
> are now based on omap_opp_def instead of omap_opp itself.
> Since the opp.h has the omap_opp definition, omap-pm.h conflicts and
> has been removed in favor of opp.h.

ok

> omap3_pm_init_opp_table is used to initialize the OPP table and
> relevant board files which have omap2_init_common_hw called with opp
> arrays have been updated with omap3_pm_init_opp_table.
>
> This change now allows us to dynamically register OPPs to the system
> based on silicon type we detect.

Nice.

With this patch, I would suggest a couple more cleanups in how we are handling
the master OPP lists for MPU, DSP and L3.

Namely, It's time we could remove the rate_table passing from the OMAP
PM layer all together and just keep them as pointers in opp.h.

The longer term goal is to remove OPP handling from OMAP PM all together,
so this will be a step in that direction.

I've attached a patch that applies on top of your series that drops
the OPPs from OMAP PM layer.  After doing this, we now have some
duplicate global pointers to the various rate tables that could be
cleaned up.  In addition, all the rate tables could be dropped from
init_common_hw.

If you follow my proposal for using opp_add() instead of opp_init()
the board files that want to just use default OPPs do not have to do
anyting with the rate tables.  Only board files wanting to add OPPs
would have to include opp.h and use opp_add().

Also, dropping the rate tables from init_common_hw would mean you
shouldn't have init sequence issues anymore and you can do the OPP
init inside existing PM init.

Kevin

> NOTE: This introduces the following warnings highlighting areas we
> need to cleanup:
> arch/arm/mach-omap2/smartreflex.c: In function 'get_opp':
> arch/arm/mach-omap2/smartreflex.c:161: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/smartreflex.c:164: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/smartreflex.c:166: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/smartreflex.c:168: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/resource34xx.c: In function 'get_opp':
> arch/arm/mach-omap2/resource34xx.c:165: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/resource34xx.c:168: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/resource34xx.c:170: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/resource34xx.c:172: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/resource34xx.c: In function 'program_opp':
> arch/arm/mach-omap2/resource34xx.c:284: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/resource34xx.c:285: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>
> Signed-off-by: Nishanth Menon <nm@ti.com>
> ---
>  arch/arm/mach-omap2/board-3430sdp.c       |    1 +
>  arch/arm/mach-omap2/board-omap3beagle.c   |    1 +
>  arch/arm/mach-omap2/board-omap3evm.c      |    1 +
>  arch/arm/mach-omap2/board-rx51.c          |    1 +
>  arch/arm/mach-omap2/board-zoom2.c         |    2 +
>  arch/arm/mach-omap2/omap3-opp.h           |   58 +-----------------------
>  arch/arm/mach-omap2/pm.h                  |    6 +++
>  arch/arm/mach-omap2/pm34xx.c              |   68 +++++++++++++++++++++++++++++
>  arch/arm/plat-omap/include/plat/omap-pm.h |   17 +-------
>  9 files changed, 84 insertions(+), 71 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
> index eac529f..0ec8327 100644
> --- a/arch/arm/mach-omap2/board-3430sdp.c
> +++ b/arch/arm/mach-omap2/board-3430sdp.c
> @@ -220,6 +220,7 @@ static void __init omap_3430sdp_init_irq(void)
>  {
>  	omap_board_config = sdp3430_config;
>  	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
> +	omap3_pm_init_opp_table();
>  	omap3_pm_init_vc(&omap3_setuptime_table);
>  	omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
>  	omap2_init_common_hw(hyb18m512160af6_sdrc_params, NULL, omap3_mpu_rate_table,
> diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
> index 2ec3520..a937238 100644
> --- a/arch/arm/mach-omap2/board-omap3beagle.c
> +++ b/arch/arm/mach-omap2/board-omap3beagle.c
> @@ -361,6 +361,7 @@ static void __init omap3_beagle_init_irq(void)
>  {
>  	omap_board_config = omap3_beagle_config;
>  	omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
> +	omap3_pm_init_opp_table();
>  	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
>  			     mt46h32m32lf6_sdrc_params, omap3_mpu_rate_table,
>  			     omap3_dsp_rate_table, omap3_l3_rate_table);
> diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
> index 8130eca..44a5861 100644
> --- a/arch/arm/mach-omap2/board-omap3evm.c
> +++ b/arch/arm/mach-omap2/board-omap3evm.c
> @@ -404,6 +404,7 @@ static void __init omap3_evm_init_irq(void)
>  {
>  	omap_board_config = omap3_evm_config;
>  	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
> +	omap3_pm_init_opp_table();
>  	omap2_init_common_hw(mt46h32m32lf6_sdrc_params, NULL, omap3_mpu_rate_table,
>  	                     omap3_dsp_rate_table, omap3_l3_rate_table);
>  	omap_init_irq();
> diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
> index 2f1c2be..997fd1c 100644
> --- a/arch/arm/mach-omap2/board-rx51.c
> +++ b/arch/arm/mach-omap2/board-rx51.c
> @@ -103,6 +103,7 @@ static void __init rx51_init_irq(void)
>  
>  	omap_board_config = rx51_config;
>  	omap_board_config_size = ARRAY_SIZE(rx51_config);
> +	omap3_pm_init_opp_table();
>  	omap3_pm_init_cpuidle(rx51_cpuidle_params);
>  	sdrc_params = rx51_get_sdram_timings();
>  	omap2_init_common_hw(sdrc_params, sdrc_params,
> diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
> index dcc5fb8..9d5b078 100644
> --- a/arch/arm/mach-omap2/board-zoom2.c
> +++ b/arch/arm/mach-omap2/board-zoom2.c
> @@ -24,10 +24,12 @@
>  #include <mach/board-zoom.h>
>  
>  #include "sdram-micron-mt46h32m32lf-6.h"
> +#include "pm.h"
>  #include "omap3-opp.h"
>  
>  static void __init omap_zoom2_init_irq(void)
>  {
> +	omap3_pm_init_opp_table();
>  	omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
>  				 mt46h32m32lf6_sdrc_params, omap3_mpu_rate_table,
>  				 omap3_dsp_rate_table, omap3_l3_rate_table);
> diff --git a/arch/arm/mach-omap2/omap3-opp.h b/arch/arm/mach-omap2/omap3-opp.h
> index 42557e1..994d8d4 100644
> --- a/arch/arm/mach-omap2/omap3-opp.h
> +++ b/arch/arm/mach-omap2/omap3-opp.h
> @@ -3,60 +3,8 @@
>  
>  #include <plat/omap-pm.h>
>  
> -/* MPU speeds */
> -#define S600M   600000000
> -#define S550M   550000000
> -#define S500M   500000000
> -#define S250M   250000000
> -#define S125M   125000000
> -
> -/* DSP speeds */
> -#define S430M   430000000
> -#define S400M   400000000
> -#define S360M   360000000
> -#define S180M   180000000
> -#define S90M    90000000
> -
> -/* L3 speeds */
> -#define S83M    83000000
> -#define S166M   166000000
> -
> -static struct omap_opp omap3_mpu_rate_table[] = {
> -	{0, 0, 0, 0},
> -	/*OPP1*/
> -	{true, S125M, VDD1_OPP1, 0x1E},
> -	/*OPP2*/
> -	{true, S250M, VDD1_OPP2, 0x26},
> -	/*OPP3*/
> -	{true, S500M, VDD1_OPP3, 0x30},
> -	/*OPP4*/
> -	{true, S550M, VDD1_OPP4, 0x36},
> -	/*OPP5*/
> -	{true, S600M, VDD1_OPP5, 0x3C},
> -};
> -
> -static struct omap_opp omap3_l3_rate_table[] = {
> -	{0, 0, 0, 0},
> -	/*OPP1*/
> -	{false, 0, VDD2_OPP1, 0x1E},
> -	/*OPP2*/
> -	{true, S83M, VDD2_OPP2, 0x24},
> -	/*OPP3*/
> -	{true, S166M, VDD2_OPP3, 0x2C},
> -};
> -
> -static struct omap_opp omap3_dsp_rate_table[] = {
> -	{0, 0, 0, 0},
> -	/*OPP1*/
> -	{true, S90M, VDD1_OPP1, 0x1E},
> -	/*OPP2*/
> -	{true, S180M, VDD1_OPP2, 0x26},
> -	/*OPP3*/
> -	{true, S360M, VDD1_OPP3, 0x30},
> -	/*OPP4*/
> -	{true, S400M, VDD1_OPP4, 0x36},
> -	/*OPP5*/
> -	{true, S430M, 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;
>  
>  #endif
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 7bc86b6..80a1c1d 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -58,6 +58,12 @@ static inline void omap3_pm_init_cpuidle(
>  {
>  }
>  #endif
> +/**
> + * omap3_pm_init_opp_table - OMAP opp table lookup called after cpu is detected.
> + * Initialize the basic opp table here, board files could choose to modify opp
> + * table after the basic initialization
> + */
> +extern void omap3_pm_init_opp_table(void);
>  
>  extern int resource_set_opp_level(int res, u32 target_level, int flags);
>  extern int resource_access_opp_lock(int res, int delta);
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index 627a509..ad21f5f 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -40,6 +40,7 @@
>  #include <plat/dmtimer.h>
>  #include <plat/usb.h>
>  
> +#include <plat/opp.h>
>  #include <plat/resource.h>
>  
>  #include <asm/tlbflush.h>
> @@ -52,6 +53,7 @@
>  #include "prm.h"
>  #include "pm.h"
>  #include "sdrc.h"
> +#include "omap3-opp.h"
>  
>  static int regset_save_on_suspend;
>  
> @@ -100,6 +102,52 @@ static struct prm_setup_vc prm_setup = {
>  	.vdd1_off = 0x00,	/* 0.6v */
>  };
>  
> +static struct omap_opp_def __initdata omap34xx_mpu_rate_table[] = {
> +	/*OPP1 975mV */
> +	{.enabled = true, .freq = 125000000, .u_volt = 975000},
> +	/*OPP2 1.075V */
> +	{.enabled = true, .freq = 250000000, .u_volt = 1075000},
> +	/*OPP3 1.2V */
> +	{.enabled = true, .freq = 500000000, .u_volt = 1200000},
> +	/*OPP4 1.270V */
> +	{.enabled = true, .freq = 550000000, .u_volt = 1270000},
> +	/*OPP5 1.35V */
> +	{.enabled = true, .freq = 600000000, .u_volt = 1350000},
> +	/* Terminator */
> +	{.enabled = 0, .freq = 0, .u_volt = 0}
> +};
> +
> +static struct omap_opp_def __initdata omap34xx_l3_rate_table[] = {
> +	/*OPP1 - 975mV */
> +	{.enabled = false, .freq = 0, .u_volt = 975000},
> +	/*OPP2 1.05V */
> +	{.enabled = true, .freq = 83000000, .u_volt = 1050000},
> +	/*OPP3 1.15V*/
> +	{.enabled = true, .freq = 166000000, .u_volt = 1150000},
> +	/* Terminator */
> +	{.enabled = 0, .freq = 0, .u_volt = 0}
> +};
> +
> +static struct omap_opp_def __initdata omap34xx_dsp_rate_table[] = {
> +	/*OPP1*/
> +	{.enabled = true, .freq = 90000000, .u_volt = 975000},
> +	/*OPP2*/
> +	{.enabled = true, .freq = 180000000, .u_volt = 1075000},
> +	/*OPP3*/
> +	{.enabled = true, .freq = 360000000, .u_volt = 1200000},
> +	/*OPP4*/
> +	{.enabled = true, .freq = 400000000, .u_volt = 1270000},
> +	/*OPP5*/
> +	{.enabled = true, .freq = 430000000, .u_volt = 1350000},
> +	/* Terminator */
> +	{.enabled = 0, .freq = 0, .u_volt = 0}
> +};
> +
> +struct omap_opp *omap3_mpu_rate_table;
> +struct omap_opp *omap3_dsp_rate_table;
> +struct omap_opp *omap3_l3_rate_table;
> +
> +
>  static inline void omap3_per_save_context(void)
>  {
>  	omap_gpio_save_context();
> @@ -1248,6 +1296,26 @@ static void __init configure_vc(void)
>  	pm_dbg_regset_init(2);
>  }
>  
> +void __init omap3_pm_init_opp_table(void)
> +{
> +	int ret, i;
> +	struct omap_opp_def *omap34xx_opp_def_list[] = {
> +		omap34xx_mpu_rate_table,
> +		omap34xx_l3_rate_table,
> +		omap34xx_dsp_rate_table
> +	};
> +	struct omap_opp **omap3_rate_tables[] = {
> +		&omap3_mpu_rate_table,
> +		&omap3_l3_rate_table,
> +		&omap3_dsp_rate_table
> +	};
> +	for (i = 0; i < ARRAY_SIZE(omap34xx_opp_def_list); i++) {
> +		ret = opp_init(omap3_rate_tables[i], omap34xx_opp_def_list[i]);
> +		/* We dont want half configured system at the moment */
> +		BUG_ON(ret);
> +	}
> +}
> +
>  static int __init omap3_pm_early_init(void)
>  {
>  	prm_clear_mod_reg_bits(OMAP3430_OFFMODE_POL, OMAP3430_GR_MOD,
> diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
> index 5dc2048..aa36339 100644
> --- a/arch/arm/plat-omap/include/plat/omap-pm.h
> +++ b/arch/arm/plat-omap/include/plat/omap-pm.h
> @@ -18,22 +18,7 @@
>  #include <linux/cpufreq.h>
>  
>  #include "powerdomain.h"
> -
> -/**
> - * struct omap_opp - clock frequency-to-OPP ID table for DSP, MPU
> - * @enabled: enabled if true, disabled if false
> - * @rate: target clock rate
> - * @opp_id: OPP ID
> - * @min_vdd: minimum VDD1 voltage (in millivolts) for this OPP
> - *
> - * Operating performance point data.  Can vary by OMAP chip and board.
> - */
> -struct omap_opp {
> -	bool enabled;
> -	unsigned long rate;
> -	u8 opp_id;
> -	u16 vsel;
> -};
> +#include <plat/opp.h>
>  
>  extern struct omap_opp *mpu_opps;
>  extern struct omap_opp *dsp_opps;
> -- 
> 1.6.3.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx
  2009-11-25 17:22       ` [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx Kevin Hilman
@ 2009-11-25 17:27         ` Kevin Hilman
  2009-12-07 17:02         ` Tero.Kristo
  1 sibling, 0 replies; 36+ messages in thread
From: Kevin Hilman @ 2009-11-25 17:27 UTC (permalink / raw)
  To: Nishanth Menon; +Cc: linux-omap

Kevin Hilman <khilman@deeprootsystems.com> writes:

[...]

> I've attached a patch that applies on top of your series 

Forgot the patch.  Here it is.

Kevin

commit 2979ad2ad596618e179f1292e6e7e37d55830096
Author: Kevin Hilman <khilman@deeprootsystems.com>
Date:   Wed Nov 25 09:12:17 2009 -0800

    OMAP3: PM: remove OPP interfaces from OMAP PM layer

diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 91bcfbf..e2f44ec 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -319,7 +319,7 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
 	/* The OPP tables have to be registered before a clk init */
 	omap_hwmod_init(hwmods);
 	omap2_mux_init();
-	omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps);
+	omap_pm_if_early_init();
 	pwrdm_init(powerdomains_omap);
 	clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
 	omap2_clk_init();
diff --git a/arch/arm/mach-omap2/resource34xx.h b/arch/arm/mach-omap2/resource34xx.h
index b6f31a9..0b4e76e 100644
--- a/arch/arm/mach-omap2/resource34xx.h
+++ b/arch/arm/mach-omap2/resource34xx.h
@@ -27,7 +27,7 @@
 #include <plat/powerdomain.h>
 #include <plat/resource.h>
 #include <plat/clock.h>
-#include <plat/omap-pm.h>
+#include <plat/opp.h>
 #include <plat/omap34xx.h>
 
 extern int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel);
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 6f8b7cc..c399aea 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -30,7 +30,7 @@
 #include <plat/omap34xx.h>
 #include <plat/control.h>
 #include <plat/clock.h>
-#include <plat/omap-pm.h>
+#include <plat/opp.h>
 
 #include "prm.h"
 #include "smartreflex.h"
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index 7b3ca11..29e4826 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -32,6 +32,7 @@
 
 #if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
 #include <plat/omap-pm.h>
+#include <plat/opp.h>
 #endif
 
 #define VERY_HI_RATE	900000000
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
index aa36339..bdc11f2 100644
--- a/arch/arm/plat-omap/include/plat/omap-pm.h
+++ b/arch/arm/plat-omap/include/plat/omap-pm.h
@@ -20,10 +20,6 @@
 #include "powerdomain.h"
 #include <plat/opp.h>
 
-extern struct omap_opp *mpu_opps;
-extern struct omap_opp *dsp_opps;
-extern struct omap_opp *l3_opps;
-
 /*
  * agent_id values for use with omap_pm_set_min_bus_tput():
  *
@@ -46,11 +42,9 @@ extern struct omap_opp *l3_opps;
  * PM idle-loop code.
  */
 #ifdef CONFIG_OMAP_PM_NONE
-#define omap_pm_if_early_init(a, b, c) 0
+#define omap_pm_if_early_init() 0
 #else
-int __init omap_pm_if_early_init(struct omap_opp *mpu_opp_table,
-				 struct omap_opp *dsp_opp_table,
-				 struct omap_opp *l3_opp_table);
+int __init omap_pm_if_early_init(void);
 #endif
 
 /**
@@ -197,68 +191,6 @@ void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t);
  */
 void omap_pm_set_max_sdma_lat(struct device *dev, long t);
 
-
-/*
- * DSP Bridge-specific constraints
- */
-
-/**
- * omap_pm_dsp_get_opp_table - get OPP->DSP clock frequency table
- *
- * Intended for use by DSPBridge.  Returns an array of OPP->DSP clock
- * frequency entries.  The final item in the array should have .rate =
- * .opp_id = 0.
- */
-const struct omap_opp *omap_pm_dsp_get_opp_table(void);
-
-/**
- * omap_pm_dsp_set_min_opp - receive desired OPP target ID from DSP Bridge
- * @opp_id: target DSP OPP ID
- *
- * Set a minimum OPP ID for the DSP.  This is intended to be called
- * only from the DSP Bridge MPU-side driver.  Unfortunately, the only
- * information that code receives from the DSP/BIOS load estimator is the
- * target OPP ID; hence, this interface.  No return value.
- */
-void omap_pm_dsp_set_min_opp(u8 opp_id);
-
-/**
- * omap_pm_dsp_get_opp - report the current DSP OPP ID
- *
- * Report the current OPP for the DSP.  Since on OMAP3, the DSP and
- * MPU share a single voltage domain, the OPP ID returned back may
- * represent a higher DSP speed than the OPP requested via
- * omap_pm_dsp_set_min_opp().
- *
- * Returns the current VDD1 OPP ID, or 0 upon error.
- */
-u8 omap_pm_dsp_get_opp(void);
-
-/**
- * omap_pm_vdd1_get_opp - report the current VDD1 OPP
- *
- * Report the current VDD1 OPP number.
- *
- * Returns the current VDD1 OPP ID, or 0 upon error.
- */
-u8 omap_pm_vdd1_get_opp(void);
-
-/**
- * omap_pm_vdd2_get_opp - report the current VDD2 OPP
- *
- * Report the current VDD2 OPP number.
- *
- * Returns the current VDD2 OPP ID, or 0 upon error.
- */
-u8 omap_pm_vdd2_get_opp(void);
-
-/*
- * CPUFreq-originated constraint
- *
- * In the future, this should be handled by custom OPP clocktype
- * functions.
- */
-
 /**
  * omap_pm_cpu_get_freq_table - return a cpufreq_frequency_table array ptr
  *
diff --git a/arch/arm/plat-omap/include/plat/opp.h b/arch/arm/plat-omap/include/plat/opp.h
index d8ae2d3..fedbf44 100644
--- a/arch/arm/plat-omap/include/plat/opp.h
+++ b/arch/arm/plat-omap/include/plat/opp.h
@@ -13,6 +13,10 @@
 #ifndef __ASM_ARM_OMAP_OPP_H
 #define __ASM_ARM_OMAP_OPP_H
 
+extern struct omap_opp *mpu_opps;
+extern struct omap_opp *dsp_opps;
+extern struct omap_opp *l3_opps;
+
 /**
  * struct omap_opp - OMAP OPP description structure
  * @enabled:	true/false - marking this OPP as enabled/disabled
diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c
index cab105f..7932241 100644
--- a/arch/arm/plat-omap/omap-pm-noop.c
+++ b/arch/arm/plat-omap/omap-pm-noop.c
@@ -299,13 +299,8 @@ int omap_pm_get_dev_context_loss_count(struct device *dev)
 
 
 /* Should be called before clk framework init */
-int __init omap_pm_if_early_init(struct omap_opp *mpu_opp_table,
-				 struct omap_opp *dsp_opp_table,
-				 struct omap_opp *l3_opp_table)
+int __init omap_pm_if_early_init()
 {
-	mpu_opps = mpu_opp_table;
-	dsp_opps = dsp_opp_table;
-	l3_opps = l3_opp_table;
 	return 0;
 }
 
diff --git a/arch/arm/plat-omap/omap-pm-srf.c b/arch/arm/plat-omap/omap-pm-srf.c
index 4a0bfbe..5cfefbd 100644
--- a/arch/arm/plat-omap/omap-pm-srf.c
+++ b/arch/arm/plat-omap/omap-pm-srf.c
@@ -296,13 +296,8 @@ int omap_pm_get_dev_context_loss_count(struct device *dev)
 /*
  * Must be called before clk framework init
  */
-int __init omap_pm_if_early_init(struct omap_opp *mpu_opp_table,
-				 struct omap_opp *dsp_opp_table,
-				 struct omap_opp *l3_opp_table)
+int __init omap_pm_if_early_init(void)
 {
-	mpu_opps = mpu_opp_table;
-	dsp_opps = dsp_opp_table;
-	l3_opps = l3_opp_table;
 	return 0;
 }
 



^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH 06/10 V3] omap3: pm: use opp accessor functions for omap-target
  2009-11-25  4:09           ` [PATCH 06/10 V3] omap3: pm: use opp accessor functions for omap-target Nishanth Menon
  2009-11-25  4:09             ` [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table Nishanth Menon
@ 2009-11-25 17:56             ` Kevin Hilman
  2009-12-08  7:59               ` Eduardo Valentin
  1 sibling, 1 reply; 36+ messages in thread
From: Kevin Hilman @ 2009-11-25 17:56 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: linux-omap, Benoit Cousson, Madhusudhan Chikkature Rajashekar,
	Paul Walmsley, Romit Dasgupta, Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

Nishanth Menon <nm@ti.com> writes:

> The logic in omap-target can now be improved with the accessor
> functions. Dont scan through the list manually, instead use
> get_next_freq to do the scanning.
>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Romit Dasgupta <romit@ti.com>
> Cc: Sanjeev Premi <premi@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
> Cc: Thara Gopinath <thara@ti.com>
> Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
>
> Signed-off-by: Nishanth Menon <nm@ti.com>
> ---
>  arch/arm/plat-omap/cpu-omap.c |   19 +++++++++++--------
>  1 files changed, 11 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
> index 449b6b6..7b3ca11 100644
> --- a/arch/arm/plat-omap/cpu-omap.c
> +++ b/arch/arm/plat-omap/cpu-omap.c
> @@ -111,14 +111,17 @@ static int omap_target(struct cpufreq_policy *policy,
>  	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
>  #elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
>  	if (mpu_opps) {
> -		int ind;
> -		for (ind = 1; ind <= MAX_VDD1_OPP; ind++) {
> -			if (mpu_opps[ind].rate/1000 >= target_freq) {
> -				omap_pm_cpu_set_freq
> -					(mpu_opps[ind].rate);
> -				break;
> -			}
> -		}
> +		unsigned long freq = target_freq * 1000;
> +		struct omap_opp *opp = NULL;
> +		int res;
> +		/* see if we have exact freq match */
> +		res = opp_is_valid(&opp, mpu_opps, freq);
> +		/* Get next best if we cant find a exact match */
> +		if (res)
> +			res = opp_get_higher_opp(&opp, &freq, mpu_opps);

These two could just be replaced by a single call to
opp_find_freq_rounding()

Kevin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions
  2009-11-25 16:30     ` [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions Kevin Hilman
@ 2009-11-25 20:31       ` Nishanth Menon
  2009-11-25 23:46         ` Kevin Hilman
  0 siblings, 1 reply; 36+ messages in thread
From: Nishanth Menon @ 2009-11-25 20:31 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, Cousson, Benoit, Chikkature Rajashekar, Madhusudhan,
	Paul Walmsley, Dasgupta, Romit, Shilimkar, Santosh, Aguirre,
	Sergio, Gopinath, Thara, Sripathy, Vishwanath, Premi, Sanjeev

Kevin Hilman had written, on 11/25/2009 10:30 AM, the following:
[..]

>> Signed-off-by: Sanjeev Premi <premi@ti.com>
>> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
> 
> Not yet. :)
:) Thanks a bunch for your detailed comments. have provided answers 
below. I think we are not aligned on the search functions unfortunately.

> 
>> Signed-off-by: Nishanth Menon <nm@ti.com>
> 
> Some general comments.
> 
> I think the forcing of an int return code for all the functions is a
> bit artificial, and is a loss in readability IMHO.  I've never liked
> getting results values in function arguments, and find that style
> difficult to read.  More comments on this for each function below.
Alright, will fix.

> 
>> ---
>>  arch/arm/plat-omap/Makefile           |    3 +
>>  arch/arm/plat-omap/include/plat/opp.h |  208 ++++++++++++++++++++++++++
>>  arch/arm/plat-omap/opp.c              |  260 +++++++++++++++++++++++++++++++++
> 
> I think this should be mach-omap2/opp.c
OPP is a concept that is not limited to omap2. it can be implemented for 
  omap1 if desired (they had 2 OPPs - OPP50 and OPP100), it is hence 
introduced as a common logic across OMAPs in plat-omap.

[...]

>> diff --git a/arch/arm/plat-omap/include/plat/opp.h b/arch/arm/plat-omap/include/plat/opp.h
>> new file mode 100644
>> index 0000000..d8ae2d3
>> --- /dev/null
>> +++ b/arch/arm/plat-omap/include/plat/opp.h
>> @@ -0,0 +1,208 @@
[...]

>> +/**
>> + * opp_get_voltage - Gets the voltage corresponding to an opp
>> + * @u_volt:  Voltage in microvolts corresponding to an opp
>> + * @opp:     opp for which voltage has to be returned for
>> + *
>> + * Return 0 and the voltage in micro volt corresponding to the opp,
>> + * else return the corresponding error value.
>> + */
>> +int opp_get_voltage(u32 *u_volt, const struct omap_opp *opp);
> 
> Should just return voltage or -EINVAL
> 
> int opp_get_voltage(const struct omap_opp *opp);
Ack. it cant be int as uVolt is unsigned long.
/**
  * opp_get_voltage - Gets the voltage corresponding to an opp
  * @opp:        opp for which voltage has to be returned for
  *
  * Return voltage in micro volt corresponding to the opp, else
  * return 0
  */
unsigned long opp_get_voltage(const struct omap_opp *opp);

> 
>> +
>> +/**
>> + * opp_get_freq - Gets the frequency corresponding to an opp
>> + * @freq:    Frequency in hertz corresponding to an opp
>> + * @opp:     opp for which frequency has to be returned for
>> + *
>> + * Return 0 and the frequency in hertz corresponding to the opp,
>> + * else return the corresponding error value.
>> + */
>> +int opp_get_freq(unsigned long *freq, const struct omap_opp *opp);
> 
> ditto
Same as above:
/**
  * opp_get_freq - Gets the frequency corresponding to an opp
  * @opp:        opp for which frequency has to be returned for
  *
  * Return frequency in hertz corresponding to the opp, else
  * return 0
  */
unsigned long opp_get_freq(const struct omap_opp *opp);

> 
>> +
>> +/**
>> + * opp_is_valid - Verifies if a given frequency is enabled in the opp list
>> + * @opp:     Pointer to opp returned if opp match is achieved
>> + * @oppl:    opp list
>> + * @freq:    Frequency in hertz to check for
>> + *
>> + * Searches the OPP list to find if the provided frequency is an enabled
>> + * frequency. If a match is achieved, it returns 0 and the pointer to the opp
>> + * is returned, else a corresponding error value is returned.
>> + */
>> +int opp_is_valid(struct omap_opp **opp, const struct omap_opp *oppl,
>> +             const unsigned long freq);
>> +
>> +/**
>> + * opp_has_freq - Checks if a frequency is exists(enabled/disabled) in opp list
>> + * @opp:     Pointer to opp returned if opp match is achieved
>> + * @oppl:    opp list
>> + * @freq:    Frequency in hertz to check for
>> + *
>> + * Searches the OPP list to find a frequency. This is a more generic function
>> + * than the opp_is_valid since it searches for both enabled/disabled
>> + * frequencies.
>> + *
>> + * This function may be used by detection logic to enable a disabled OPP as
>> + * all other search functions work on enabled OPPs only.
>> + */
>> +int opp_has_freq(struct omap_opp **opp, const struct omap_opp *oppl,
>> +             const unsigned long freq);
> 
> Don't see any users of this, and it looks like the same functionality
> as opp_is_valid().
> 
> Both of these are just a "find opp by freq".  How about having
> something like this instead:
> 
> /**
>  * opp_find_freq()
>  * @oppl:        OPP list
>  * @freq:        Frequency to look for in OPP table
>  *
>  * Look for an enabled OPP with a frequency value matching @freq.
>  *
>  * Returns pointer to OPP entry if match is found, or NULL if no match
>  * found.
>  */
> struct omap_opp *opp_find_freq(const struct omap_opp *oppl, u32 freq);

I did think about it(single function doing multiple things), the 
intention is as follows in reality:
opp_is_valid : Search only for enabled frequencies
opp_has_freq : Searches for enabled/disabled frequencies

This is useful for some logic which wants to enable a frequency which 
may have been disabled in the table. now, to retain that functionality,
A)
/**
  * opp_find_freq() - Find a opp corresponding to frequency
  * @oppl:       opp list to search
  * @freq:       frequency to loopup in OPP table
  * @enabled:    search only enabled frequencies
  *
  * return opp handle corresponding to the frequency found, else
  * return NULL. Search for enabled frequencies if enabled flag
  * is true, else search for disabled frequencies also
  */
struct omap_opp *opp_find_freq(const struct omap_opp *oppl,
                 unsigned long freq, bool enabled);

This will handle the functionalities that are supported in rev 3.

B) I rename existing functions:
opp_has_freq ==> opp_is_disabled()
opp_is_valid ==> opp_is_enabled()

I would still prefer to go with explicit function search APIs..

> 
> 
>> +/**
>> + * opp_get_opp_count - Get number of opps enabled in the opp list
>> + * @num:     returns the number of opps
>> + * @oppl:    opp list
>> + *
>> + * This functions returns 0 and the number of opps are updated in num if
>> + * success, else returns corresponding error value.
>> + */
>> +int opp_get_opp_count(u8 *num, const struct omap_opp *oppl2);
> 
> Should just return count:
> 
> int opp_get_opp_count(const struct omap_opp *oppl);

Ack:
/**
  * opp_get_opp_count - Get number of opps enabled in the opp list
  * @num:        returns the number of opps
  * @oppl:       opp list
  *
  * This functions returns the number of opps if there are any OPPs enabled,
  * else returns corresponding error value.
  */
int opp_get_opp_count(const struct omap_opp *oppl);


> 
>> +/**
>> + * opp_get_higher_opp - search for the next highest opp in the list
>> + * @opp:     pointer to the opp
>> + * @freq:    frequency to start the search on
>> + * @oppl:    opp list to search on
>> + *
>> + * Searches for the higher *enabled* OPP than a starting freq/opp
>> + * Decision of start condition:
>> + *   if *opp is NULL, *freq is checked (usually the start condition)
>> + *   if *opp is populated, *freq is ignored
>> + * Returns 0 and *opp and *freq is populated with the next highest match,
>> + * else returns corresponding error value.
>> + *
>> + * Example usage:
>> + *   * print a all frequencies ascending order *
>> + *   unsigned long freq = 0;
>> + *   struct omap_opp *opp = NULL;
>> + *   while(!opp_get_higher_opp(&opp, &freq, oppl))
>> + *           pr_info("%ld ", freq);
>> + * NOTE: if we set freq as 0, we get the lowest enabled frequency
>> + */
>> +int opp_get_higher_opp(struct omap_opp **opp, unsigned long *freq,
>> +                     const struct omap_opp *oppl);
>> +
>> +/**
>> + * opp_get_lower_opp - search for the next lower opp in the list
>> + * @opp:     pointer to the opp
>> + * @freq:    frequency to start the search on
>> + * @oppl:    opp list to search on
>> + *
>> + * Search for the lower *enabled* OPP than a starting freq/opp
>> + * Decision of start condition:
>> + *   if *opp is NULL, *freq is checked (usually the start condition)
>> + *   if *opp is populated, *freq is ignored
>> + * Returns 0 and *opp and *freq is populated with the next lowest match,
>> + * else returns corresponding error value.
>> + *
>> + * Example usage:
>> + *   * print a all frequencies in descending order *
>> + *   unsigned long freq = ULONG_MAX;
>> + *   struct omap_opp *opp = NULL;
>> + *   while(!opp_get_lower_opp(&opp, &freq, oppl))
>> + *           pr_info("%ld ", freq);
>> + * NOTE: if we set freq as ULONG_MAX, we get the highest enabled frequency
>> + */
>> +int opp_get_lower_opp(struct omap_opp **opp, unsigned long *freq,
>> +                     const struct omap_opp *oppl);
> 
> I think these should be combined to a single function for finding a
> nearby OPP using rounding.  Something like this:
> 
> /**
>  * opp_find_freq_rounded()
>  * @oppl:        OPP list
>  * @freq:        Frequency to look for in OPP table
>  * @rounding:    Rounding option: NONE, UP, DOWN
>  *
>  * Look for an OPP with a frequency value matching @freq.  If
>  * @rounding != ROUND_NONE, find closest match using rounding.
>  *
>  * Can be used to find exact OPP, or match using given rounding:
> 
>  * @rounding == UP:      find next highest frequency
>  * @rounding == DOWN:    find next lowest frequency
>  * @rounding == CLOSEST: find closest frequency
>  *
>  * Returns pointer to OPP entry if match is found, or NULL if no match
>  * found (only possible when no rounding is used)
>  */
> struct omap_opp *opp_find_freq_rounded(struct omap_opp *oppl, u32 freq, u32 rounding);
> 
> Looking at the users of the 'higher' and 'lower' OPPs in the current
> code, I see that SRF tries to use all three one after the other.
> First it checks for exact match, then for higher, then for lower.
> This could be replaced simply by doing a 'closest' match.
hmmm.. I think we are going a full circle here.

/* Search exact frequency */
#define OPP_ROUND_NONE          (0 << 0)
/* Search approx frequency */
#define OPP_ROUND_CLOSEST       (1 << 0)
/* Search up */
#define OPP_ROUND_HIGH      (0 << 1)
/* Search down */
#define OPP_ROUND_LOW    (1 << 1)

struct omap_opp *opp_find_freq_rounded(struct omap_opp *oppl,
                 unsigned long freq, u8 rounding_flag);

Note: the only difference b/w this and opp_find_freq is that 
opp_find_freq will also search for enabled/disabled.
If I add that here, this is exactly the #1 implementation I did in
http://marc.info/?l=linux-omap&m=125800489123496&w=2
ok, I used bool instead of a #define and added the complexity of using
enabled flag also:

bool search_higher, bool search_enabled_only, bool exact_search

what you are proposing is that I go back to my implementation #1 and 
remove my bools instead by adding #defines:
/* Search up */
#define OPP_ROUND_ENABLED (0 << 2)
/* Search down */
#define OPP_ROUND_ANY    (1 << 2)

would even make the find_freq redundant..

Now, in your comment in 
http://marc.info/?l=linux-omap&m=125816031406704&w=2 quote:"I think all 
the options to this function make it not terribly
readable."

Does it become any different now? without taking this in,
exact searches can be done by specific functions and approximate 
searches by another function.. we go generic functions or we go specific 
functions.. generic comments I have been getting is to go specific, 
hence the v2 and v3 series.

> 
>> +/**
>> + * struct omap_opp_def - OMAP OPP Definition
>> + * @enabled: True/false - is this OPP enabled/disabled by default
>> + * @freq:    Frequency in hertz corresponding to this OPP
>> + * @u_volt:  Nominal voltage in microvolts corresponding to this OPP
>> + *
>> + * OMAP SOCs have a standard set of tuples consisting of frequency and voltage
>> + * pairs that the device will support per voltage domain. This is called
>> + * Operating Points or OPP. The actual definitions of OMAP Operating Points
>> + * varies over silicon within the same family of devices. For a specific
>> + * domain, you can have a set of {frequency, voltage} pairs and this is denoted
>> + * by an array of omap_opp_def. As the kernel boots and more information is
>> + * available, a set of these are activated based on the precise nature of
>> + * device the kernel boots up on. It is interesting to remember that each IP
>> + * which belongs to a voltage domain may define their own set of OPPs on top
>> + * of this - but this is handled by the appropriate driver.
>> + */
>> +struct omap_opp_def {
>> +     bool enabled;
>> +     unsigned long freq;
>> +     u32 u_volt;
>> +};
>> +
>> +/**
>> + * opp_init - Initialize an OPP table from the initial table definition
>> + * @oppl:    Returned back to caller as the opp list to reference the OPP
>> + * @opp_defs:        Array of omap_opp_def to describe the OPP. This list should be
>> + *           0 terminated.
>> + *
>> + * This function creates the internal datastructure representing the OPP list
>> + * from an initial definition table. this handle is then used for further
>> + * validation, search, modification operations on the OPP list.
>> + *
>> + * This function returns 0 and the pointer to the allocated list through oppl if
>> + * success, else corresponding error value. Caller should NOT free the oppl.
>> + * opps_defs can be freed after use.
>> + */
>> +int __init opp_init(struct omap_opp **oppl,
>> +             const struct omap_opp_def *opp_defs);
> 
> I think this should be generalized as an 'opp_add' that adds a single
> OPP to the master list.
> 
> The init code can iterate over its tables to add OPPs.  This has a
> few benefits:
> 
> 1) separates the structure of OPPs in init code from that of OPP core
> 2) board and/or custom code can later add OPPs to the table
> 3) enables (enforces) the OPP core to keep OPPs in an order suitable
>    for its own search algorithms (sorted list, etc.)

hmm.. Ack:
/**
  * opp_add  - Add/initialize an OPP table from a table definitions
  * @oppl:       Returned back to caller as the opp list to reference 
the OPP
  * @opp_defs:   Array of omap_opp_def to describe the OPP. This list 
should be
  *              0 terminated.
  *
  * This function adds the opp definition to an internal opp list and 
returns
  * a handle representing the OPP list. This handle is then used for further
  * validation, search, modification operations on the OPP list.
  *
  * This function returns 0 and the pointer to the allocated list 
through oppl if
  * success, else corresponding error value. Caller should NOT free the 
oppl.
  * opps_defs can be freed after use.
  *
  * NOTE: caller should assume that on success, oppl is probably 
populated with
  * a new handle and the new handle should be used for further referencing
  */
int __init opp_add(struct omap_opp **oppl, const struct omap_opp_def 
*opp_defs);



> 
>> +/**
>> + * opp_enable - Enable a specific OPP
>> + * @opp:     pointer to opp
>> + *
>> + * Enables a provided opp. If the operation is valid, this returns 0, else the
>> + * corresponding error value.
>> + *
>> + * OPP used here is from the the opp_is_valid/opp_has_freq or other search
>> + * functions
>> + */
>> +int __init opp_enable(struct omap_opp *opp);
>> +
>> +/**
>> + * opp_disable - Disable a specific OPP
>> + * @opp:     pointer to opp
>> + *
>> + * Disables a provided opp. If the operation is valid, this returns 0, else the
>> + * corresponding error value.
>> + *
>> + * OPP used here is from the the opp_is_valid/opp_has_freq or other search
>> + * functions
>> + */
>> +int __init opp_disable(struct omap_opp *opp);
> 
> OK, but why are these __init?
> 
> There may be reasons, such as thermal, that we might want do disable
> and (re)enable OPPs later at runtime.

Yes, but we dont have those now, I dont particularly care about 
retaining the __init. will kick it out.

> 
> No other particular comments on the implementation in opp.c, other
> than the complaints you already know about and are a result of the SRF
> and smartreflex usage of OPP layer.
> 
> Kevin


-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions
  2009-11-25 20:31       ` Nishanth Menon
@ 2009-11-25 23:46         ` Kevin Hilman
  2009-11-26  0:22           ` Menon, Nishanth
  0 siblings, 1 reply; 36+ messages in thread
From: Kevin Hilman @ 2009-11-25 23:46 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: linux-omap, Cousson, Benoit, Chikkature Rajashekar, Madhusudhan,
	Paul Walmsley, Dasgupta, Romit, Shilimkar, Santosh, Aguirre,
	Sergio, Gopinath, Thara, Sripathy, Vishwanath, Premi, Sanjeev

Nishanth Menon <nm@ti.com> writes:

> Kevin Hilman had written, on 11/25/2009 10:30 AM, the following:
> [..]
>
>>> Signed-off-by: Sanjeev Premi <premi@ti.com>
>>> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
>>
>> Not yet. :)
> :) Thanks a bunch for your detailed comments. have provided answers
> below. I think we are not aligned on the search functions
> unfortunately.

And thanks for your lead on getting a better OPP layer in shape.
We're getting very close now.

>>
>>> Signed-off-by: Nishanth Menon <nm@ti.com>
>>
>> Some general comments.
>>
>> I think the forcing of an int return code for all the functions is a
>> bit artificial, and is a loss in readability IMHO.  I've never liked
>> getting results values in function arguments, and find that style
>> difficult to read.  More comments on this for each function below.
> Alright, will fix.
>
>>
>>> ---
>>>  arch/arm/plat-omap/Makefile           |    3 +
>>>  arch/arm/plat-omap/include/plat/opp.h |  208 ++++++++++++++++++++++++++
>>>  arch/arm/plat-omap/opp.c              |  260 +++++++++++++++++++++++++++++++++
>>
>> I think this should be mach-omap2/opp.c
> OPP is a concept that is not limited to omap2. it can be implemented
> for omap1 if desired (they had 2 OPPs - OPP50 and OPP100), it is hence
> introduced as a common logic across OMAPs in plat-omap.
>
> [...]
>
>>> diff --git a/arch/arm/plat-omap/include/plat/opp.h b/arch/arm/plat-omap/include/plat/opp.h
>>> new file mode 100644
>>> index 0000000..d8ae2d3
>>> --- /dev/null
>>> +++ b/arch/arm/plat-omap/include/plat/opp.h
>>> @@ -0,0 +1,208 @@
> [...]
>
>>> +/**
>>> + * opp_get_voltage - Gets the voltage corresponding to an opp
>>> + * @u_volt:  Voltage in microvolts corresponding to an opp
>>> + * @opp:     opp for which voltage has to be returned for
>>> + *
>>> + * Return 0 and the voltage in micro volt corresponding to the opp,
>>> + * else return the corresponding error value.
>>> + */
>>> +int opp_get_voltage(u32 *u_volt, const struct omap_opp *opp);
>>
>> Should just return voltage or -EINVAL
>>
>> int opp_get_voltage(const struct omap_opp *opp);
> Ack. it cant be int as uVolt is unsigned long.

ok

> /**
>  * opp_get_voltage - Gets the voltage corresponding to an opp
>  * @opp:        opp for which voltage has to be returned for
>  *
>  * Return voltage in micro volt corresponding to the opp, else
>  * return 0
>  */
> unsigned long opp_get_voltage(const struct omap_opp *opp);
>
>>
>>> +
>>> +/**
>>> + * opp_get_freq - Gets the frequency corresponding to an opp
>>> + * @freq:    Frequency in hertz corresponding to an opp
>>> + * @opp:     opp for which frequency has to be returned for
>>> + *
>>> + * Return 0 and the frequency in hertz corresponding to the opp,
>>> + * else return the corresponding error value.
>>> + */
>>> +int opp_get_freq(unsigned long *freq, const struct omap_opp *opp);
>>
>> ditto
> Same as above:

ok

> /**
>  * opp_get_freq - Gets the frequency corresponding to an opp
>  * @opp:        opp for which frequency has to be returned for
>  *
>  * Return frequency in hertz corresponding to the opp, else
>  * return 0
>  */
> unsigned long opp_get_freq(const struct omap_opp *opp);
>
>>
>>> +
>>> +/**
>>> + * opp_is_valid - Verifies if a given frequency is enabled in the opp list
>>> + * @opp:     Pointer to opp returned if opp match is achieved
>>> + * @oppl:    opp list
>>> + * @freq:    Frequency in hertz to check for
>>> + *
>>> + * Searches the OPP list to find if the provided frequency is an enabled
>>> + * frequency. If a match is achieved, it returns 0 and the pointer to the opp
>>> + * is returned, else a corresponding error value is returned.
>>> + */
>>> +int opp_is_valid(struct omap_opp **opp, const struct omap_opp *oppl,
>>> +             const unsigned long freq);
>>> +
>>> +/**
>>> + * opp_has_freq - Checks if a frequency is exists(enabled/disabled) in opp list
>>> + * @opp:     Pointer to opp returned if opp match is achieved
>>> + * @oppl:    opp list
>>> + * @freq:    Frequency in hertz to check for
>>> + *
>>> + * Searches the OPP list to find a frequency. This is a more generic function
>>> + * than the opp_is_valid since it searches for both enabled/disabled
>>> + * frequencies.
>>> + *
>>> + * This function may be used by detection logic to enable a disabled OPP as
>>> + * all other search functions work on enabled OPPs only.
>>> + */
>>> +int opp_has_freq(struct omap_opp **opp, const struct omap_opp *oppl,
>>> +             const unsigned long freq);
>>
>> Don't see any users of this, and it looks like the same functionality
>> as opp_is_valid().
>>
>> Both of these are just a "find opp by freq".  How about having
>> something like this instead:
>>
>> /**
>>  * opp_find_freq()
>>  * @oppl:        OPP list
>>  * @freq:        Frequency to look for in OPP table
>>  *
>>  * Look for an enabled OPP with a frequency value matching @freq.
>>  *
>>  * Returns pointer to OPP entry if match is found, or NULL if no match
>>  * found.
>>  */
>> struct omap_opp *opp_find_freq(const struct omap_opp *oppl, u32 freq);
>
> I did think about it(single function doing multiple things), the
> intention is as follows in reality:
> opp_is_valid : Search only for enabled frequencies
> opp_has_freq : Searches for enabled/disabled frequencies
>
> This is useful for some logic which wants to enable a frequency which
> may have been disabled in the table. now, to retain that
> functionality,
> A)
> /**
>  * opp_find_freq() - Find a opp corresponding to frequency
>  * @oppl:       opp list to search
>  * @freq:       frequency to loopup in OPP table
>  * @enabled:    search only enabled frequencies
>  *
>  * return opp handle corresponding to the frequency found, else
>  * return NULL. Search for enabled frequencies if enabled flag
>  * is true, else search for disabled frequencies also
>  */
> struct omap_opp *opp_find_freq(const struct omap_opp *oppl,
>                 unsigned long freq, bool enabled);
>
> This will handle the functionalities that are supported in rev 3.
>
> B) I rename existing functions:
> opp_has_freq ==> opp_is_disabled()
> opp_is_valid ==> opp_is_enabled()
>
> I would still prefer to go with explicit function search APIs..

I like (A) here.

>>
>>
>>> +/**
>>> + * opp_get_opp_count - Get number of opps enabled in the opp list
>>> + * @num:     returns the number of opps
>>> + * @oppl:    opp list
>>> + *
>>> + * This functions returns 0 and the number of opps are updated in num if
>>> + * success, else returns corresponding error value.
>>> + */
>>> +int opp_get_opp_count(u8 *num, const struct omap_opp *oppl2);
>>
>> Should just return count:
>>
>> int opp_get_opp_count(const struct omap_opp *oppl);
>
> Ack:
> /**
>  * opp_get_opp_count - Get number of opps enabled in the opp list
>  * @num:        returns the number of opps
>  * @oppl:       opp list
>  *
>  * This functions returns the number of opps if there are any OPPs enabled,
>  * else returns corresponding error value.
>  */
> int opp_get_opp_count(const struct omap_opp *oppl);
>
>
>>
>>> +/**
>>> + * opp_get_higher_opp - search for the next highest opp in the list
>>> + * @opp:     pointer to the opp
>>> + * @freq:    frequency to start the search on
>>> + * @oppl:    opp list to search on
>>> + *
>>> + * Searches for the higher *enabled* OPP than a starting freq/opp
>>> + * Decision of start condition:
>>> + *   if *opp is NULL, *freq is checked (usually the start condition)
>>> + *   if *opp is populated, *freq is ignored
>>> + * Returns 0 and *opp and *freq is populated with the next highest match,
>>> + * else returns corresponding error value.
>>> + *
>>> + * Example usage:
>>> + *   * print a all frequencies ascending order *
>>> + *   unsigned long freq = 0;
>>> + *   struct omap_opp *opp = NULL;
>>> + *   while(!opp_get_higher_opp(&opp, &freq, oppl))
>>> + *           pr_info("%ld ", freq);
>>> + * NOTE: if we set freq as 0, we get the lowest enabled frequency
>>> + */
>>> +int opp_get_higher_opp(struct omap_opp **opp, unsigned long *freq,
>>> +                     const struct omap_opp *oppl);
>>> +
>>> +/**
>>> + * opp_get_lower_opp - search for the next lower opp in the list
>>> + * @opp:     pointer to the opp
>>> + * @freq:    frequency to start the search on
>>> + * @oppl:    opp list to search on
>>> + *
>>> + * Search for the lower *enabled* OPP than a starting freq/opp
>>> + * Decision of start condition:
>>> + *   if *opp is NULL, *freq is checked (usually the start condition)
>>> + *   if *opp is populated, *freq is ignored
>>> + * Returns 0 and *opp and *freq is populated with the next lowest match,
>>> + * else returns corresponding error value.
>>> + *
>>> + * Example usage:
>>> + *   * print a all frequencies in descending order *
>>> + *   unsigned long freq = ULONG_MAX;
>>> + *   struct omap_opp *opp = NULL;
>>> + *   while(!opp_get_lower_opp(&opp, &freq, oppl))
>>> + *           pr_info("%ld ", freq);
>>> + * NOTE: if we set freq as ULONG_MAX, we get the highest enabled frequency
>>> + */
>>> +int opp_get_lower_opp(struct omap_opp **opp, unsigned long *freq,
>>> +                     const struct omap_opp *oppl);
>>
>> I think these should be combined to a single function for finding a
>> nearby OPP using rounding.  Something like this:
>>
>> /**
>>  * opp_find_freq_rounded()
>>  * @oppl:        OPP list
>>  * @freq:        Frequency to look for in OPP table
>>  * @rounding:    Rounding option: NONE, UP, DOWN
>>  *
>>  * Look for an OPP with a frequency value matching @freq.  If
>>  * @rounding != ROUND_NONE, find closest match using rounding.
>>  *
>>  * Can be used to find exact OPP, or match using given rounding:
>>
>>  * @rounding == UP:      find next highest frequency
>>  * @rounding == DOWN:    find next lowest frequency
>>  * @rounding == CLOSEST: find closest frequency
>>  *
>>  * Returns pointer to OPP entry if match is found, or NULL if no match
>>  * found (only possible when no rounding is used)
>>  */
>> struct omap_opp *opp_find_freq_rounded(struct omap_opp *oppl, u32 freq, u32 rounding);
>>
>> Looking at the users of the 'higher' and 'lower' OPPs in the current
>> code, I see that SRF tries to use all three one after the other.
>> First it checks for exact match, then for higher, then for lower.
>> This could be replaced simply by doing a 'closest' match.
>
> hmmm.. I think we are going a full circle here.
>
> /* Search exact frequency */
> #define OPP_ROUND_NONE          (0 << 0)
> /* Search approx frequency */
> #define OPP_ROUND_CLOSEST       (1 << 0)
> /* Search up */
> #define OPP_ROUND_HIGH      (0 << 1)
> /* Search down */
> #define OPP_ROUND_LOW    (1 << 1)
>
> struct omap_opp *opp_find_freq_rounded(struct omap_opp *oppl,
>                 unsigned long freq, u8 rounding_flag);
>
> Note: the only difference b/w this and opp_find_freq is that
> opp_find_freq will also search for enabled/disabled.
> If I add that here, this is exactly the #1 implementation I did in
> http://marc.info/?l=linux-omap&m=125800489123496&w=2
> ok, I used bool instead of a #define and added the complexity of using
> enabled flag also:
>
> bool search_higher, bool search_enabled_only, bool exact_search
>
> what you are proposing is that I go back to my implementation #1 and
> remove my bools instead by adding #defines:
> /* Search up */
> #define OPP_ROUND_ENABLED (0 << 2)
> /* Search down */
> #define OPP_ROUND_ANY    (1 << 2)
>
> would even make the find_freq redundant..
>
> Now, in your comment in
> http://marc.info/?l=linux-omap&m=125816031406704&w=2 quote:"I think
> all the options to this function make it not terribly
> readable."
>
> Does it become any different now?
>

Yeah, I still think multiple bools to a function is a readability
problem.  Every time you look at a call, you have to look at the
prototype to remember what all the options are.  A single bool or flag
is better IMHO.

> without taking this in, exact searches can be done by specific
> functions and approximate searches by another function.. we go
> generic functions or we go specific functions.. generic comments I
> have been getting is to go specific, hence the v2 and v3 series.

OK, you're right.  I am causing us to go around in circles now, but
we're going around in increasingly smaller circles and hopefully
converging on the target.  ;)

So what I propose is having two functions.  One for exact matches
(your proposal A above) and one for approximate matches which is
something like my find_freq_rounded(), but should maybe be renamed
something like opp_find_freq_approx() or something.

>>
>>> +/**
>>> + * struct omap_opp_def - OMAP OPP Definition
>>> + * @enabled: True/false - is this OPP enabled/disabled by default
>>> + * @freq:    Frequency in hertz corresponding to this OPP
>>> + * @u_volt:  Nominal voltage in microvolts corresponding to this OPP
>>> + *
>>> + * OMAP SOCs have a standard set of tuples consisting of frequency and voltage
>>> + * pairs that the device will support per voltage domain. This is called
>>> + * Operating Points or OPP. The actual definitions of OMAP Operating Points
>>> + * varies over silicon within the same family of devices. For a specific
>>> + * domain, you can have a set of {frequency, voltage} pairs and this is denoted
>>> + * by an array of omap_opp_def. As the kernel boots and more information is
>>> + * available, a set of these are activated based on the precise nature of
>>> + * device the kernel boots up on. It is interesting to remember that each IP
>>> + * which belongs to a voltage domain may define their own set of OPPs on top
>>> + * of this - but this is handled by the appropriate driver.
>>> + */
>>> +struct omap_opp_def {
>>> +     bool enabled;
>>> +     unsigned long freq;
>>> +     u32 u_volt;
>>> +};
>>> +
>>> +/**
>>> + * opp_init - Initialize an OPP table from the initial table definition
>>> + * @oppl:    Returned back to caller as the opp list to reference the OPP
>>> + * @opp_defs:        Array of omap_opp_def to describe the OPP. This list should be
>>> + *           0 terminated.
>>> + *
>>> + * This function creates the internal datastructure representing the OPP list
>>> + * from an initial definition table. this handle is then used for further
>>> + * validation, search, modification operations on the OPP list.
>>> + *
>>> + * This function returns 0 and the pointer to the allocated list through oppl if
>>> + * success, else corresponding error value. Caller should NOT free the oppl.
>>> + * opps_defs can be freed after use.
>>> + */
>>> +int __init opp_init(struct omap_opp **oppl,
>>> +             const struct omap_opp_def *opp_defs);
>>
>> I think this should be generalized as an 'opp_add' that adds a single
>> OPP to the master list.
>>
>> The init code can iterate over its tables to add OPPs.  This has a
>> few benefits:
>>
>> 1) separates the structure of OPPs in init code from that of OPP core
>> 2) board and/or custom code can later add OPPs to the table
>> 3) enables (enforces) the OPP core to keep OPPs in an order suitable
>>    for its own search algorithms (sorted list, etc.)
>
> hmm.. Ack:
> /**
>  * opp_add  - Add/initialize an OPP table from a table definitions
>  * @oppl:       Returned back to caller as the opp list to reference
> the OPP
>  * @opp_defs:   Array of omap_opp_def to describe the OPP. This list
> should be
>  *              0 terminated.
>  *
>  * This function adds the opp definition to an internal opp list and
> returns
>  * a handle representing the OPP list. This handle is then used for further
>  * validation, search, modification operations on the OPP list.
>  *
>  * This function returns 0 and the pointer to the allocated list
> through oppl if
>  * success, else corresponding error value. Caller should NOT free the
> oppl.
>  * opps_defs can be freed after use.
>  *
>  * NOTE: caller should assume that on success, oppl is probably
> populated with
>  * a new handle and the new handle should be used for further referencing
>  */
> int __init opp_add(struct omap_opp **oppl, const struct omap_opp_def
> *opp_defs);

Mostly, but I was thinking of an API for adding a *single* OPP.  The
init code would iterate over its opp_def table adding OPPs one at a
time resultingin multiple calls to opp_add().

OK, now I'm going around in circles again, but thinking more about his
we probably need your original opp_init() which will create an empty
master list, then repeated calls to opp_add() to add each OPP to the
master list.

Also does add need to be __init?  Not sure why we would need to add
OPPs after boot time if we have the ability to enable/disable them at
runtime, but just a thought.

>
>
>>
>>> +/**
>>> + * opp_enable - Enable a specific OPP
>>> + * @opp:     pointer to opp
>>> + *
>>> + * Enables a provided opp. If the operation is valid, this returns 0, else the
>>> + * corresponding error value.
>>> + *
>>> + * OPP used here is from the the opp_is_valid/opp_has_freq or other search
>>> + * functions
>>> + */
>>> +int __init opp_enable(struct omap_opp *opp);
>>> +
>>> +/**
>>> + * opp_disable - Disable a specific OPP
>>> + * @opp:     pointer to opp
>>> + *
>>> + * Disables a provided opp. If the operation is valid, this returns 0, else the
>>> + * corresponding error value.
>>> + *
>>> + * OPP used here is from the the opp_is_valid/opp_has_freq or other search
>>> + * functions
>>> + */
>>> +int __init opp_disable(struct omap_opp *opp);
>>
>> OK, but why are these __init?
>>
>> There may be reasons, such as thermal, that we might want do disable
>> and (re)enable OPPs later at runtime.
>
> Yes, but we dont have those now, I dont particularly care about
> retaining the __init. will kick it out.
>

ok, thanks.

Kevin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* RE: [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions
  2009-11-25 23:46         ` Kevin Hilman
@ 2009-11-26  0:22           ` Menon, Nishanth
  2009-12-08  8:23             ` Eduardo Valentin
  0 siblings, 1 reply; 36+ messages in thread
From: Menon, Nishanth @ 2009-11-26  0:22 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, Cousson, Benoit, Chikkature Rajashekar, Madhusudhan,
	Paul Walmsley, Dasgupta, Romit, Shilimkar, Santosh, Aguirre,
	Sergio, Gopinath, Thara, Sripathy, Vishwanath, Premi, Sanjeev

Kevin Hilman had written, on 11/25/2009 05:46 PM, the following:
[...]
>>> something like this instead:
>>>
>>> /**
>>>  * opp_find_freq()
>>>  * @oppl:        OPP list
>>>  * @freq:        Frequency to look for in OPP table
>>>  *
>>>  * Look for an enabled OPP with a frequency value matching @freq.
>>>  *
>>>  * Returns pointer to OPP entry if match is found, or NULL if no match
>>>  * found.
>>>  */
>>> struct omap_opp *opp_find_freq(const struct omap_opp *oppl, u32 freq);
>> I did think about it(single function doing multiple things), the
>> intention is as follows in reality:
>> opp_is_valid : Search only for enabled frequencies
>> opp_has_freq : Searches for enabled/disabled frequencies
>>
>> This is useful for some logic which wants to enable a frequency which
>> may have been disabled in the table. now, to retain that
>> functionality,
>> A)
>> /**
>>  * opp_find_freq() - Find a opp corresponding to frequency
>>  * @oppl:       opp list to search
>>  * @freq:       frequency to loopup in OPP table
>>  * @enabled:    search only enabled frequencies
>>  *
>>  * return opp handle corresponding to the frequency found, else
>>  * return NULL. Search for enabled frequencies if enabled flag
>>  * is true, else search for disabled frequencies also
>>  */
>> struct omap_opp *opp_find_freq(const struct omap_opp *oppl,
>>                 unsigned long freq, bool enabled);
>>
>> This will handle the functionalities that are supported in rev 3.
>>
>> B) I rename existing functions:
>> opp_has_freq ==> opp_is_disabled()
>> opp_is_valid ==> opp_is_enabled()
>>
>> I would still prefer to go with explicit function search APIs..
> 
> I like (A) here.
Ack. I can see it useful if we go to a list iterator at a later point of time.
[...]

>>> /**
>>>  * opp_find_freq_rounded()
>>>  * @oppl:        OPP list
>>>  * @freq:        Frequency to look for in OPP table
>>>  * @rounding:    Rounding option: NONE, UP, DOWN
>>>  *
>>>  * Look for an OPP with a frequency value matching @freq.  If
>>>  * @rounding != ROUND_NONE, find closest match using rounding.
>>>  *
>>>  * Can be used to find exact OPP, or match using given rounding:
>>>
>>>  * @rounding == UP:      find next highest frequency
>>>  * @rounding == DOWN:    find next lowest frequency
>>>  * @rounding == CLOSEST: find closest frequency
>>>  *
>>>  * Returns pointer to OPP entry if match is found, or NULL if no match
>>>  * found (only possible when no rounding is used)
>>>  */
>>> struct omap_opp *opp_find_freq_rounded(struct omap_opp *oppl, u32 freq, u32 rounding);
>>>
>>> Looking at the users of the 'higher' and 'lower' OPPs in the current
>>> code, I see that SRF tries to use all three one after the other.
>>> First it checks for exact match, then for higher, then for lower.
>>> This could be replaced simply by doing a 'closest' match.
>> hmmm.. I think we are going a full circle here.
>>
>> /* Search exact frequency */
>> #define OPP_ROUND_NONE          (0 << 0)
>> /* Search approx frequency */
>> #define OPP_ROUND_CLOSEST       (1 << 0)
>> /* Search up */
>> #define OPP_ROUND_HIGH      (0 << 1)
>> /* Search down */
>> #define OPP_ROUND_LOW    (1 << 1)
>>
>> struct omap_opp *opp_find_freq_rounded(struct omap_opp *oppl,
>>                 unsigned long freq, u8 rounding_flag);
>>
>> Note: the only difference b/w this and opp_find_freq is that
>> opp_find_freq will also search for enabled/disabled.
>> If I add that here, this is exactly the #1 implementation I did in
>> http://marc.info/?l=linux-omap&m=125800489123496&w=2
>> ok, I used bool instead of a #define and added the complexity of using
>> enabled flag also:
>>
>> bool search_higher, bool search_enabled_only, bool exact_search
>>
>> what you are proposing is that I go back to my implementation #1 and
>> remove my bools instead by adding #defines:
>> /* Search up */
>> #define OPP_ROUND_ENABLED (0 << 2)
>> /* Search down */
>> #define OPP_ROUND_ANY    (1 << 2)
>>
>> would even make the find_freq redundant..
>>
>> Now, in your comment in
>> http://marc.info/?l=linux-omap&m=125816031406704&w=2 quote:"I think
>> all the options to this function make it not terribly
>> readable."
>>
>> Does it become any different now?
>>
> 
> Yeah, I still think multiple bools to a function is a readability
> problem.  Every time you look at a call, you have to look at the
> prototype to remember what all the options are.  A single bool or flag
> is better IMHO.
> 
>> without taking this in, exact searches can be done by specific
>> functions and approximate searches by another function.. we go
>> generic functions or we go specific functions.. generic comments I
>> have been getting is to go specific, hence the v2 and v3 series.
> 
> OK, you're right.  I am causing us to go around in circles now, but
> we're going around in increasingly smaller circles and hopefully
> converging on the target.  ;)
Yep :)

> 
> So what I propose is having two functions.  One for exact matches
> (your proposal A above) and one for approximate matches which is
> something like my find_freq_rounded(), but should maybe be renamed
> something like opp_find_freq_approx() or something.

OK - Signed-Off. prototypes again :)

Dead functions: opp_has_freq, opp_is_valid, opp_find_freq and other searches.

Only two of them remain: (git diff follows)
opp_find_freq_approx

opp_find_freq_exact


[..]
>> int __init opp_add(struct omap_opp **oppl, const struct omap_opp_def
>> *opp_defs);
> 
> Mostly, but I was thinking of an API for adding a *single* OPP.  The
> init code would iterate over its opp_def table adding OPPs one at a
> time resultingin multiple calls to opp_add().
> 
> OK, now I'm going around in circles again, but thinking more about his
> we probably need your original opp_init() which will create an empty
> master list, then repeated calls to opp_add() to add each OPP to the
> master list.

Opp_init will be a subcase of opp_add. Giving opp_add capabiity to take
More than one def is useful for us in the long run:
a) You can add bunch of them without list iterator repeating in each and every adding code.
b) You can still add a single one if you choose to.
c) add to a NULL list == init the list. That does sound implicit to me, but if we want to create a singular function for it alone, then I recommend:

lets just have opp_init, then see if we need to add opp_add -> none of the systems are mature enough for us to use it..

I am open either way. 

> 
> Also does add need to be __init?  Not sure why we would need to add
> OPPs after boot time if we have the ability to enable/disable them at
> runtime, but just a thought.
Removed.. if in case we would like to do an opp_add at some point.

> 
[...]


diff --git a/arch/arm/plat-omap/include/plat/opp.h b/arch/arm/plat-omap/include/plat/opp.h
new file mode 100644
index 0000000..4a00685
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/opp.h
@@ -0,0 +1,184 @@
+/*
+ * OMAP OPP Interface
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated.
+ *	Nishanth Menon
+ * Copyright (C) 2009 Deep Root Systems, LLC.
+ *	Kevin Hilman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARM_OMAP_OPP_H
+#define __ASM_ARM_OMAP_OPP_H
+
+/**
+ * struct omap_opp - OMAP OPP description structure
+ * @enabled:	true/false - marking this OPP as enabled/disabled
+ * @rate:	Frequency in hertz
+ * @opp_id:	(DEPRECATED) opp identifier
+ * @vsel:	Voltage in volt processor level(this usage is
+ *		DEPRECATED to use Voltage in microvolts in future)
+ *		uV = ((vsel * 12.5) + 600) * 1000
+ *
+ * This structure stores the OPP information for a given domain.
+ * Due to legacy reasons, this structure is currently exposed and
+ * will soon be removed elsewhere and will only be used as a handle
+ * from the OPP internal referencing mechanism
+ */
+struct omap_opp {
+	bool enabled;
+	unsigned long rate;
+	u8 opp_id __deprecated;
+	u16 vsel;
+};
+
+/**
+ * opp_get_voltage() - Gets the voltage corresponding to an opp
+ * @opp:	opp for which voltage has to be returned for
+ *
+ * Return voltage in micro volt corresponding to the opp, else
+ * return 0
+ */
+unsigned long opp_get_voltage(const struct omap_opp *opp);
+
+/**
+ * opp_get_freq() - Gets the frequency corresponding to an opp
+ * @opp:	opp for which frequency has to be returned for
+ *
+ * Return frequency in hertz corresponding to the opp, else
+ * return 0
+ */
+unsigned long opp_get_freq(const struct omap_opp *opp);
+
+/**
+ * opp_get_opp_count - Get number of opps enabled in the opp list
+ * @num:	returns the number of opps
+ * @oppl:	opp list
+ *
+ * This functions returns the number of opps if there are any OPPs enabled,
+ * else returns corresponding error value.
+ */
+int opp_get_opp_count(const struct omap_opp *oppl);
+
+#define OPP_SEARCH_HIGH		(0 << 1)
+#define OPP_SEARCH_LOW		(1 << 1)
+/**
+ * opp_find_freq_approx() - Search for an approximate freq
+ * @oppl:	starting list
+ * @freq:	start frequency
+ * @dir_flags:	search direction
+ *		OPP_SEARCH_HIGH - search for next highest freq
+ *		OPP_SEARCH_LOW - search for next lowest freq
+ *
+ * Search for the higher/lower *enabled* OPP than a starting freq
+ * from a start opp list.
+
+ * Returns *opp and *freq is populated with the next match,
+ * else returns NULL
+ *
+ * Example usages:
+ *	* print all frequencies in descending order *
+ *	unsigned long freq;
+ *	struct omap_opp *opp;
+ *	for(opp = oppl, freq = ULONG_MAX; opp;
+ *		opp = opp_find_freq_approx(opp, &freq, OPP_SEARCH_LOW))
+ *		pr_info("%ld ", freq);
+ *
+ *	* print all frequencies in ascending order *
+ *	unsigned long freq = 0;
+ *	struct omap_opp *opp;
+ *	for(opp = oppl, freq = 0; opp;
+ *		opp = opp_find_freq_approx(opp, &freq, OPP_SEARCH_HIGH))
+ *		pr_info("%ld ", freq);
+ * NOTE: if we set freq as ULONG_MAX, we get the highest enabled frequency
+ *
+ */
+struct omap_opp *opp_find_freq_approx(struct omap_opp *oppl,
+		unsigned long *freq, u8 dir_flags);
+
+/**
+ * opp_find_freq_exact() - search for an exact frequency
+ * @oppl:	OPP list
+ * @freq:	frequency to search for
+ * @enabled:	enabled/disabled OPP to search for
+ *
+ * searches for the match in the opp list and returns handle to the matching
+ * opp if found, else returns NULL.
+ *
+ * Note enabled is a modifier for the search. if enabled=true, then the match is
+ * for exact matching frequency and is enabled. if true, the match is for exact
+ * frequency which is disabled.
+ */
+struct omap_opp *opp_find_freq_exact(struct omap_opp *oppl,
+		unsigned long freq, bool enabled);
+
+
+/**
+ * struct omap_opp_def - OMAP OPP Definition
+ * @enabled:	True/false - is this OPP enabled/disabled by default
+ * @freq:	Frequency in hertz corresponding to this OPP
+ * @u_volt:	Nominal voltage in microvolts corresponding to this OPP
+ *
+ * OMAP SOCs have a standard set of tuples consisting of frequency and voltage
+ * pairs that the device will support per voltage domain. This is called
+ * Operating Points or OPP. The actual definitions of OMAP Operating Points
+ * varies over silicon within the same family of devices. For a specific
+ * domain, you can have a set of {frequency, voltage} pairs and this is denoted
+ * by an array of omap_opp_def. As the kernel boots and more information is
+ * available, a set of these are activated based on the precise nature of
+ * device the kernel boots up on. It is interesting to remember that each IP
+ * which belongs to a voltage domain may define their own set of OPPs on top
+ * of this - but this is handled by the appropriate driver.
+ */
+struct omap_opp_def {
+	bool enabled;
+	unsigned long freq;
+	u32 u_volt;
+};
+
+/**
+ * opp_add  - Add/initialize an OPP table from a table definitions
+ * @oppl:	Returned back to caller as the opp list to reference the OPP
+ * @opp_defs:	Array of omap_opp_def to describe the OPP. This list should be
+ *		0 terminated.
+ *
+ * This function adds the opp definition to an internal opp list and returns
+ * a handle representing the OPP list. This handle is then used for further
+ * validation, search, modification operations on the OPP list.
+ *
+ * This function returns 0 and the pointer to the allocated list through oppl if
+ * success, else corresponding error value. Caller should NOT free the oppl.
+ * opps_defs can be freed after use.
+ *
+ * NOTE: caller should assume that on success, oppl is probably populated with
+ * a new handle and the new handle should be used for further referencing
+ */
+int opp_add(struct omap_opp **oppl, const struct omap_opp_def *opp_defs);
+
+/**
+ * opp_enable - Enable a specific OPP
+ * @opp:	pointer to opp
+ *
+ * Enables a provided opp. If the operation is valid, this returns 0, else the
+ * corresponding error value.
+ *
+ * OPP used here is from the the opp_is_valid/opp_has_freq or other search
+ * functions
+ */
+int opp_enable(struct omap_opp *opp);
+
+/**
+ * opp_disable - Disable a specific OPP
+ * @opp:	pointer to opp
+ *
+ * Disables a provided opp. If the operation is valid, this returns 0, else the
+ * corresponding error value.
+ *
+ * OPP used here is from the the opp_is_valid/opp_has_freq or other search
+ * functions
+ */
+int opp_disable(struct omap_opp *opp);
+
+#endif		/* __ASM_ARM_OMAP_OPP_H *

-- 
Regards,
Nishanth Menon

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* RE: [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table
  2009-11-25  4:09             ` [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table Nishanth Menon
  2009-11-25  4:09               ` [PATCH 08/10] omap3: pm: remove VDDx_MIN/MAX macros Nishanth Menon
@ 2009-12-07 16:54               ` Tero.Kristo
  2009-12-08 11:09                 ` Menon, Nishanth
  2009-12-08  7:54               ` Eduardo Valentin
  2 siblings, 1 reply; 36+ messages in thread
From: Tero.Kristo @ 2009-12-07 16:54 UTC (permalink / raw)
  To: nm, linux-omap
  Cc: b-cousson, khilman, madhu.cr, paul, romit, premi,
	santosh.shilimkar, saaguirre, thara, vishwanath.bs

Hi,

One comment below.

>-----Original Message-----
>From: linux-omap-owner@vger.kernel.org 
>[mailto:linux-omap-owner@vger.kernel.org] On Behalf Of ext 
>Nishanth Menon
>Sent: 25 November, 2009 06:09
>To: linux-omap
>Cc: Nishanth Menon; Benoit Cousson; Kevin Hilman; Madhusudhan 
>Chikkature Rajashekar; Paul Walmsley; Romit Dasgupta; Sanjeev 
>Premi; Santosh Shilimkar; Sergio Alberto Aguirre Rodriguez; 
>Thara Gopinath; Vishwanath Sripathy
>Subject: [PATCH 07/10 V3] omap3: clk: use pm accessor 
>functions for cpufreq table
>
>omap2_clk_init_cpufreq_table currently directly accesses the opp
>table, making it unscalable to various OMAPs. Instead use the
>accessor functions to populate the cpufreq table
>
>Cc: Benoit Cousson <b-cousson@ti.com>
>Cc: Kevin Hilman <khilman@deeprootsystems.com>
>Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
>Cc: Paul Walmsley <paul@pwsan.com>
>Cc: Romit Dasgupta <romit@ti.com>
>Cc: Sanjeev Premi <premi@ti.com>
>Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
>Cc: Thara Gopinath <thara@ti.com>
>Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
>
>Signed-off-by: Nishanth Menon <nm@ti.com>
>---
> arch/arm/mach-omap2/clock34xx.c |   32 
>+++++++++++++++++++-------------
> 1 files changed, 19 insertions(+), 13 deletions(-)
>
>diff --git a/arch/arm/mach-omap2/clock34xx.c 
>b/arch/arm/mach-omap2/clock34xx.c
>index 5150939..d07f1c1 100644
>--- a/arch/arm/mach-omap2/clock34xx.c
>+++ b/arch/arm/mach-omap2/clock34xx.c
>@@ -1042,30 +1042,36 @@ static unsigned long 
>omap3_clkoutx2_recalc(struct clk *clk)
> #if defined(CONFIG_ARCH_OMAP3)
> 
> #ifdef CONFIG_CPU_FREQ
>-static struct cpufreq_frequency_table freq_table[MAX_VDD1_OPP+1];
>+
>+static struct cpufreq_frequency_table *freq_table;
> 
> void omap2_clk_init_cpufreq_table(struct 
>cpufreq_frequency_table **table)
> {
>-	struct omap_opp *prcm;
> 	int i = 0;
>+	u8 opp_num;
>+	struct omap_opp *opp = NULL;
>+	unsigned long freq = ULONG_MAX;
> 
>-	if (!mpu_opps)
>+	if (!mpu_opps || opp_get_opp_count(&opp_num, mpu_opps)) {
>+		pr_warning("%s: failed to initialize frequency"
>+				"table\n", __func__);
> 		return;
>-
>-	prcm = mpu_opps + MAX_VDD1_OPP;
>-	for (; prcm->rate; prcm--) {
>-		freq_table[i].index = i;
>-		freq_table[i].frequency = prcm->rate / 1000;
>-		i++;
> 	}
> 
>-	if (i == 0) {
>-		printk(KERN_WARNING "%s: failed to initialize 
>frequency \
>-								
>table\n",
>-								
>__func__);
>+	freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
>+			(opp_num + 1), GFP_KERNEL);

I guess this should be GFP_ATOMIC, we have clockfw spinlock reserved when this is called (gave me a runtime warning.)

>+	if (!freq_table) {
>+		pr_warning("%s: failed to allocate frequency"
>+				"table\n", __func__);
> 		return;
> 	}
> 
>+	while (!opp_get_lower_opp(&opp, &freq, mpu_opps)) {
>+		freq_table[i].index = i;
>+		freq_table[i].frequency =  freq / 1000;
>+		i++;
>+	}
>+
> 	freq_table[i].index = i;
> 	freq_table[i].frequency = CPUFREQ_TABLE_END;
> 
>-- 
>1.6.3.3
>
>--
>To unsubscribe from this list: send the line "unsubscribe 
>linux-omap" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* RE: [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions
  2009-11-25  4:09       ` [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions Nishanth Menon
  2009-11-25  4:09         ` [PATCH 05/10 V3] omap3: pm: sr: replace get_opp with freq_to_opp Nishanth Menon
@ 2009-12-07 16:59         ` Tero.Kristo
  2009-12-08 11:14           ` Menon, Nishanth
  1 sibling, 1 reply; 36+ messages in thread
From: Tero.Kristo @ 2009-12-07 16:59 UTC (permalink / raw)
  To: nm, linux-omap
  Cc: b-cousson, khilman, madhu.cr, paul, romit, premi,
	santosh.shilimkar, saaguirre, thara, vishwanath.bs

Hi,

Couple of comments below.

>-----Original Message-----
>From: linux-omap-owner@vger.kernel.org
>[mailto:linux-omap-owner@vger.kernel.org] On Behalf Of ext
>Nishanth Menon
>Sent: 25 November, 2009 06:09
>To: linux-omap
>Cc: Nishanth Menon; Benoit Cousson; Kevin Hilman; Madhusudhan
>Chikkature Rajashekar; Paul Walmsley; Romit Dasgupta; Sanjeev
>Premi; Santosh Shilimkar; Sergio Alberto Aguirre Rodriguez;
>Thara Gopinath; Vishwanath Sripathy
>Subject: [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions
>
>With the accessor functions, many of the direct accesses are
>redundant. However we do not want to rewrite SRF at this point of time
>We do the following here:
>Remove get_opp and introduce three SRF specific accessor functions:
>       opp_to_freq, freq_to_opp - need this coz of usage of opp IDs
>       NOTE: These functions should be removed at a later point
>       of time.
>get_opp is removed because, with the above functions, it is
>redundant.
>
>NOTE: this implementation is just a start and leaves scope for
>further cleanups which can be added on top.
>
>NOTE: this increases the number of warnings to:
>
>arch/arm/mach-omap2/resource34xx.c: In function 'opp_to_freq':
>arch/arm/mach-omap2/resource34xx.c:182: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>arch/arm/mach-omap2/resource34xx.c: In function 'freq_to_opp':
>arch/arm/mach-omap2/resource34xx.c:213: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>arch/arm/mach-omap2/resource34xx.c: In function 'init_opp':
>arch/arm/mach-omap2/resource34xx.c:242: warning: 'freq_to_opp'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>arch/arm/mach-omap2/resource34xx.c:249: warning: 'freq_to_opp'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>arch/arm/mach-omap2/resource34xx.c: In function 'program_opp_freq':
>arch/arm/mach-omap2/resource34xx.c:302: warning: 'opp_to_freq'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>arch/arm/mach-omap2/resource34xx.c:303: warning: 'opp_to_freq'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>arch/arm/mach-omap2/resource34xx.c:308: warning: 'opp_to_freq'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>arch/arm/mach-omap2/resource34xx.c: In function 'program_opp':
>arch/arm/mach-omap2/resource34xx.c:351: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>arch/arm/mach-omap2/resource34xx.c:352: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>arch/arm/mach-omap2/resource34xx.c:356: warning: 'opp_to_freq'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>arch/arm/mach-omap2/resource34xx.c:380: warning: 'opp_to_freq'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>arch/arm/mach-omap2/resource34xx.c: In function
>'resource_set_opp_level':
>arch/arm/mach-omap2/resource34xx.c:417: warning: 'opp_to_freq'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>arch/arm/mach-omap2/resource34xx.c:418: warning: 'opp_to_freq'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>arch/arm/mach-omap2/resource34xx.c:420: warning: 'opp_to_freq'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>arch/arm/mach-omap2/resource34xx.c: In function 'set_opp':
>arch/arm/mach-omap2/resource34xx.c:497: warning: 'freq_to_opp'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>arch/arm/mach-omap2/resource34xx.c: In function 'validate_opp':
>arch/arm/mach-omap2/resource34xx.c:516: warning: 'opp_to_freq'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>arch/arm/mach-omap2/resource34xx.c:518: warning: 'opp_to_freq'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>arch/arm/mach-omap2/resource34xx.c: In function 'init_freq':
>arch/arm/mach-omap2/resource34xx.c:541: warning: 'opp_to_freq'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>arch/arm/mach-omap2/resource34xx.c:544: warning: 'opp_to_freq'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>arch/arm/mach-omap2/resource34xx.c: In function 'set_freq':
>arch/arm/mach-omap2/resource34xx.c:560: warning: 'freq_to_opp'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>arch/arm/mach-omap2/resource34xx.c:565: warning: 'freq_to_opp'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>arch/arm/mach-omap2/resource34xx.c: In function 'validate_freq':
>arch/arm/mach-omap2/resource34xx.c:579: warning: 'freq_to_opp'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>arch/arm/mach-omap2/resource34xx.c:581: warning: 'freq_to_opp'
>is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>
>Cc: Benoit Cousson <b-cousson@ti.com>
>Cc: Kevin Hilman <khilman@deeprootsystems.com>
>Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
>Cc: Paul Walmsley <paul@pwsan.com>
>Cc: Romit Dasgupta <romit@ti.com>
>Cc: Sanjeev Premi <premi@ti.com>
>Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
>Cc: Thara Gopinath <thara@ti.com>
>Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
>
>Signed-off-by: Nishanth Menon <nm@ti.com>
>---
> arch/arm/mach-omap2/resource34xx.c |  244
>++++++++++++++++++++++++++----------
> 1 files changed, 180 insertions(+), 64 deletions(-)
>
>diff --git a/arch/arm/mach-omap2/resource34xx.c
>b/arch/arm/mach-omap2/resource34xx.c
>index af6b3c1..349f54e 100644
>--- a/arch/arm/mach-omap2/resource34xx.c
>+++ b/arch/arm/mach-omap2/resource34xx.c
>@@ -155,21 +155,68 @@ static int curr_vdd1_opp;
> static int curr_vdd2_opp;
> static DEFINE_MUTEX(dvfs_mutex);
>
>-static unsigned short get_opp(struct omap_opp *opp_freq_table,
>+/* Introducing deprecated function because we got to.. */
>+#define IS_OPP_TERMINATOR(opps, i) (!(opps)[(i)].enabled &&\
>+              ((opps)[(i)].rate == 0) && ((opps)[(i)].vsel == 0))
>+
>+/**
>+ * opp_to_freq - convert OPPID to frequency (DEPRECATED)
>+ * @freq: return frequency back to caller
>+ * @opps: opp list
>+ * @opp_id: OPP ID we are searching for
>+ *
>+ * return 0 and freq is populated if we find the opp_id, else,
>+ * we return error
>+ *
>+ * NOTE: this function is a standin for the timebeing as
>opp_id is deprecated
>+ */
>+static int __deprecated opp_to_freq(unsigned long *freq,
>+              const struct omap_opp *opps, u8 opp_id)
>+{
>+      int i = 1;
>+
>+      BUG_ON(!freq || !opps);
>+
>+      /* The first entry is a dummy one, loop till we hit
>terminator */
>+      while (!IS_OPP_TERMINATOR(opps, i)) {
>+              if (opps[i].enabled && (opps[i].opp_id == opp_id)) {
>+                      *freq = opps[i].rate;
>+                      return 0;
>+              }
>+              i++;
>+      }
>+
>+      return -EINVAL;
>+}
>+
>+/**
>+ * freq_to_opp - convert a frequency back to OPP ID (DEPRECATED)
>+ * @opp_id: opp ID returned back to caller
>+ * @opps: opp list
>+ * @freq: frequency we are searching for
>+ *
>+ * return 0 and opp_id is populated if we find the freq, else,
>+ * we return error
>+ *
>+ * NOTE: this function is a standin for the timebeing as
>opp_id is deprecated
>+ */
>+static int __deprecated freq_to_opp(u8 *opp_id, const struct
>omap_opp *opps,
>               unsigned long freq)
> {
>-      struct omap_opp *prcm_config;
>-      prcm_config = opp_freq_table;
>-
>-      if (prcm_config->rate <= freq)
>-              return prcm_config->opp_id; /* Return the Highest OPP */
>-      for (; prcm_config->rate; prcm_config--)
>-              if (prcm_config->rate < freq)
>-                      return (prcm_config+1)->opp_id;
>-              else if (prcm_config->rate == freq)
>-                      return prcm_config->opp_id;
>-      /* Return the least OPP */
>-      return (prcm_config+1)->opp_id;
>+      int i = 1;
>+
>+      BUG_ON(!opp_id || !opps);
>+
>+      /* The first entry is a dummy one, loop till we hit
>terminator */
>+      while (!IS_OPP_TERMINATOR(opps, i)) {
>+              if (opps[i].enabled && (opps[i].rate == freq)) {

Here we should check for opps[i].rate >= freq, otherwise resource_refresh() calls will fail with no active users for resources like dsp_freq. This can be tested with:

echo 5 > /sys/power/vdd1_lock
echo 0 > /sys/power/vdd1_lock

>+                      *opp_id = opps[i].opp_id;
>+                      return 0;
>+              }
>+              i++;
>+      }
>+
>+      return -EINVAL;
> }
>
> /**
>@@ -178,6 +225,8 @@ static unsigned short get_opp(struct
>omap_opp *opp_freq_table,
> void init_opp(struct shared_resource *resp)
> {
>       struct clk *l3_clk;
>+      int ret;
>+      u8 opp_id;
>       resp->no_of_users = 0;
>
>       if (!mpu_opps || !dsp_opps || !l3_opps)
>@@ -190,17 +239,18 @@ void init_opp(struct shared_resource *resp)
>               vdd1_resp = resp;
>               dpll1_clk = clk_get(NULL, "dpll1_ck");
>               dpll2_clk = clk_get(NULL, "dpll2_ck");
>-              resp->curr_level = get_opp(mpu_opps + MAX_VDD1_OPP,
>-                              dpll1_clk->rate);
>-              curr_vdd1_opp = resp->curr_level;
>+              ret = freq_to_opp(&opp_id, mpu_opps, dpll1_clk->rate);
>+              BUG_ON(ret); /* TBD Cleanup handling */
>+              curr_vdd1_opp = opp_id;
>       } else if (strcmp(resp->name, "vdd2_opp") == 0) {
>               vdd2_resp = resp;
>               dpll3_clk = clk_get(NULL, "dpll3_m2_ck");
>               l3_clk = clk_get(NULL, "l3_ick");
>-              resp->curr_level = get_opp(l3_opps + MAX_VDD2_OPP,
>-                              l3_clk->rate);
>-              curr_vdd2_opp = resp->curr_level;
>+              ret = freq_to_opp(&opp_id, l3_opps, l3_clk->rate);
>+              BUG_ON(ret); /* TBD Cleanup handling */
>+              curr_vdd2_opp = opp_id;
>       }
>+      resp->curr_level = opp_id;
>       return;
> }
>
>@@ -242,24 +292,40 @@ static int program_opp_freq(int res, int
>target_level, int current_level)
> {
>       int ret = 0, l3_div;
>       int *curr_opp;
>+      unsigned long mpu_freq, dsp_freq, l3_freq;
>+#ifndef CONFIG_CPU_FREQ
>+      unsigned long mpu_cur_freq

Missing semicolon.

>+#endif
>+
>+      /* Check if I can actually switch or not */
>+      if (res == VDD1_OPP) {
>+              ret = opp_to_freq(&mpu_freq, mpu_opps, target_level);
>+              ret |= opp_to_freq(&dsp_freq, dsp_opps, target_level);
>+#ifndef CONFIG_CPU_FREQ
>+              ret |= opp_to_freq(&mpu_cur_freq, mpu_opps,
>current_level);
>+#endif
>+      } else {
>+              ret = opp_to_freq(&l3_freq, l3_opps, target_level);
>+      }
>+      /* we would have caught all bad levels earlier.. */
>+      if (unlikely(ret))
>+              return ret;
>
>       lock_scratchpad_sem();
>       if (res == VDD1_OPP) {
>               curr_opp = &curr_vdd1_opp;
>-              clk_set_rate(dpll1_clk, mpu_opps[target_level].rate);
>-              clk_set_rate(dpll2_clk, dsp_opps[target_level].rate);
>+              clk_set_rate(dpll1_clk, mpu_freq);
>+              clk_set_rate(dpll2_clk, dsp_freq);
> #ifndef CONFIG_CPU_FREQ
>               /*Update loops_per_jiffy if processor speed is
>being changed*/
>               loops_per_jiffy = compute_lpj(loops_per_jiffy,
>-                      mpu_opps[current_level].rate/1000,
>-                      mpu_opps[target_level].rate/1000);
>+                      mpu_cur_freq / 1000, mpu_freq / 1000);
> #endif
>       } else {
>               curr_opp = &curr_vdd2_opp;
>               l3_div = cm_read_mod_reg(CORE_MOD, CM_CLKSEL) &
>                       OMAP3430_CLKSEL_L3_MASK;
>-              ret = clk_set_rate(dpll3_clk,
>-                              l3_opps[target_level].rate * l3_div);
>+              ret = clk_set_rate(dpll3_clk, l3_freq * l3_div);
>       }
>       if (ret) {
>               unlock_scratchpad_sem();
>@@ -278,6 +344,7 @@ static int program_opp(int res, struct
>omap_opp *opp, int target_level,
>               int current_level)
> {
>       int i, ret = 0, raise;
>+      unsigned long freq;
> #ifdef CONFIG_OMAP_SMARTREFLEX
>       unsigned long t_opp, c_opp;
>
>@@ -285,13 +352,10 @@ static int program_opp(int res, struct
>omap_opp *opp, int target_level,
>       c_opp = ID_VDD(res) | ID_OPP_NO(opp[current_level].opp_id);
> #endif
>
>-      /* Only allow enabled OPPs */
>-      if (!opp[target_level].enabled)
>-              return -EINVAL;
>-
>-      /* Sanity check of the OPP params before attempting to set */
>-      if (!opp[target_level].rate || !opp[target_level].vsel)
>-              return -EINVAL;
>+      /* See if have a freq associated, if not, invalid opp */
>+      ret = opp_to_freq(&freq, opp, target_level);
>+      if (unlikely(ret))
>+              return ret;
>
>       if (target_level > current_level)
>               raise = 1;
>@@ -303,10 +367,23 @@ static int program_opp(int res, struct
>omap_opp *opp, int target_level,
>                       ret = program_opp_freq(res, target_level,
>                                       current_level);
> #ifdef CONFIG_OMAP_SMARTREFLEX
>-              else
>-                      sr_voltagescale_vcbypass(t_opp, c_opp,
>-                              opp[target_level].vsel,
>-                              opp[current_level].vsel);
>+              else {
>+                      u8 vc, vt;
>+                      struct omap_opp *oppx;
>+                      /*
>+                       * transitioning from good to good OPP
>+                       * none of the following should fail..
>+                       */
>+                      BUG_ON(opp_is_valid(&oppx, opp, freq));
>+                      vt = oppx->vsel;
>+
>+                      BUG_ON(opp_to_freq(&freq, opp, current_level));
>+                      BUG_ON(opp_is_valid(&oppx, opp, freq));
>+                      vc = oppx->vsel;
>+
>+                      /* ok to scale.. */
>+                      sr_voltagescale_vcbypass(t_opp, c_opp, vt, vc);
>+              }
> #endif
>       }
>
>@@ -315,7 +392,8 @@ static int program_opp(int res, struct
>omap_opp *opp, int target_level,
>
> int resource_set_opp_level(int res, u32 target_level, int flags)
> {
>-      unsigned long mpu_freq, mpu_old_freq;
>+      unsigned long mpu_freq, mpu_old_freq, l3_freq;
>+      int ret;
> #ifdef CONFIG_CPU_FREQ
>       struct cpufreq_freqs freqs_notify;
> #endif
>@@ -334,6 +412,16 @@ int resource_set_opp_level(int res, u32
>target_level, int flags)
>       if (!mpu_opps || !dsp_opps || !l3_opps)
>               return 0;
>
>+      /* Check if I can actually switch or not */
>+      if (res == VDD1_OPP) {
>+              ret = opp_to_freq(&mpu_freq, mpu_opps, target_level);
>+              ret |= opp_to_freq(&mpu_old_freq, mpu_opps,
>resp->curr_level);
>+      } else {
>+              ret = opp_to_freq(&l3_freq, l3_opps, target_level);
>+      }
>+      if (ret)
>+              return ret;
>+
>       mutex_lock(&dvfs_mutex);
>
>       if (res == VDD1_OPP) {
>@@ -341,9 +429,6 @@ int resource_set_opp_level(int res, u32
>target_level, int flags)
>                       mutex_unlock(&dvfs_mutex);
>                       return 0;
>               }
>-              mpu_old_freq = mpu_opps[resp->curr_level].rate;
>-              mpu_freq = mpu_opps[target_level].rate;
>-
> #ifdef CONFIG_CPU_FREQ
>               freqs_notify.old = mpu_old_freq/1000;
>               freqs_notify.new = mpu_freq/1000;
>@@ -371,15 +456,13 @@ int resource_set_opp_level(int res, u32
>target_level, int flags)
>
> int set_opp(struct shared_resource *resp, u32 target_level)
> {
>-      unsigned long tput;
>-      unsigned long req_l3_freq;
>-      int ind;
>+      int ret = -EINVAL;
>
>       if (resp == vdd1_resp) {
>               if (target_level < 3)
>                       resource_release("vdd2_opp", &vdd2_dev);
>
>-              resource_set_opp_level(VDD1_OPP, target_level, 0);
>+              ret = resource_set_opp_level(VDD1_OPP, target_level, 0);
>               /*
>                * For VDD1 OPP3 and above, make sure the interconnect
>                * is at 100Mhz or above.
>@@ -389,21 +472,33 @@ int set_opp(struct shared_resource
>*resp, u32 target_level)
>                       resource_request("vdd2_opp", &vdd2_dev, 400000);
>
>       } else if (resp == vdd2_resp) {
>-              tput = target_level;
>+              unsigned long req_l3_freq;
>+              struct omap_opp *oppx = NULL;
>
>               /* 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;
>+              req_l3_freq = (target_level * 1000)/4;
>+
>+              /* Do I have an exact match */
>+              ret = opp_is_valid(&oppx, l3_opps, req_l3_freq);
>+              if (ret) {
>+                      /* Do I have a next best match */
>+                      ret = opp_get_higher_opp(&oppx,
>&req_l3_freq, l3_opps);
>+                      if (ret) {
>+                              /* Give me the best we got */
>+                              req_l3_freq = ULONG_MAX;
>+                              ret = opp_get_lower_opp(&oppx,
>&req_l3_freq,
>+                                              l3_opps);
>                       }
>+              }
>
>-              /* Set the highest OPP possible */
>-              if (ind > MAX_VDD2_OPP)
>-                      target_level = ind-1;
>-              resource_set_opp_level(VDD2_OPP, target_level, 0);
>+              /* uh uh.. no OPPs?? */
>+              BUG_ON(ret);
>+
>+              ret = freq_to_opp((u8 *)&target_level, l3_opps,
>req_l3_freq);
>+              /* we dont expect this to fail */
>+              BUG_ON(ret);
>+
>+              ret = resource_set_opp_level(VDD2_OPP, target_level, 0);
>       }
>       return 0;
> }
>@@ -416,6 +511,11 @@ int set_opp(struct shared_resource *resp,
>u32 target_level)
>  */
> int validate_opp(struct shared_resource *resp, u32 target_level)
> {
>+      unsigned long x;
>+      if (strcmp(resp->name, "mpu_freq") == 0)
>+              return opp_to_freq(&x, mpu_opps, target_level);
>+      else if (strcmp(resp->name, "dsp_freq") == 0)
>+              return opp_to_freq(&x, dsp_opps, target_level);
>       return 0;
> }
>
>@@ -425,6 +525,8 @@ int validate_opp(struct shared_resource
>*resp, u32 target_level)
> void init_freq(struct shared_resource *resp)
> {
>       char *linked_res_name;
>+      int ret = -EINVAL;
>+      unsigned long freq;
>       resp->no_of_users = 0;
>
>       if (!mpu_opps || !dsp_opps)
>@@ -436,32 +538,46 @@ void init_freq(struct shared_resource *resp)
>       */
>       if (strcmp(resp->name, "mpu_freq") == 0)
>               /* MPU freq in Mhz */
>-              resp->curr_level = mpu_opps[curr_vdd1_opp].rate;
>+              ret = opp_to_freq(&freq, mpu_opps, curr_vdd1_opp);
>       else if (strcmp(resp->name, "dsp_freq") == 0)
>               /* DSP freq in Mhz */
>-              resp->curr_level = dsp_opps[curr_vdd1_opp].rate;
>+              ret = opp_to_freq(&freq, dsp_opps, curr_vdd1_opp);
>+      BUG_ON(ret);
>+
>+      resp->curr_level = freq;
>       return;
> }
>
> int set_freq(struct shared_resource *resp, u32 target_level)
> {
>-      unsigned int vdd1_opp;
>+      u8 vdd1_opp;
>+      int ret = -EINVAL;
>
>       if (!mpu_opps || !dsp_opps)
>               return 0;
>
>       if (strcmp(resp->name, "mpu_freq") == 0) {
>-              vdd1_opp = get_opp(mpu_opps + MAX_VDD1_OPP,
>target_level);
>-              resource_request("vdd1_opp", &dummy_mpu_dev, vdd1_opp);
>+              ret = freq_to_opp(&vdd1_opp, mpu_opps, target_level);
>+              if (!ret)
>+                      ret = resource_request("vdd1_opp",
>&dummy_mpu_dev,
>+                                      vdd1_opp);
>       } else if (strcmp(resp->name, "dsp_freq") == 0) {
>-              vdd1_opp = get_opp(dsp_opps + MAX_VDD1_OPP,
>target_level);
>-              resource_request("vdd1_opp", &dummy_dsp_dev, vdd1_opp);
>+              ret = freq_to_opp(&vdd1_opp, dsp_opps, target_level);
>+              if (!ret)
>+                      ret = resource_request("vdd1_opp",
>&dummy_dsp_dev,
>+                                      vdd1_opp);
>       }
>-      resp->curr_level = target_level;
>-      return 0;
>+      if (!ret)
>+              resp->curr_level = target_level;
>+      return ret;
> }
>
> int validate_freq(struct shared_resource *resp, u32 target_level)
> {
>+      u8 x;
>+      if (strcmp(resp->name, "mpu_freq") == 0)
>+              return freq_to_opp(&x, mpu_opps, target_level);
>+      else if (strcmp(resp->name, "dsp_freq") == 0)
>+              return freq_to_opp(&x, dsp_opps, target_level);
>       return 0;
> }
>--
>1.6.3.3
>
>--
>To unsubscribe from this list: send the line "unsubscribe
>linux-omap" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* RE: [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx
  2009-11-25 17:22       ` [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx Kevin Hilman
  2009-11-25 17:27         ` Kevin Hilman
@ 2009-12-07 17:02         ` Tero.Kristo
  2009-12-08 11:16           ` Menon, Nishanth
  1 sibling, 1 reply; 36+ messages in thread
From: Tero.Kristo @ 2009-12-07 17:02 UTC (permalink / raw)
  To: khilman, nm; +Cc: linux-omap

One additional comment to this patch, compilation of board-rx51.c fails unless #include "pm.h" is added to it. This might be true for other boards also seeing it has been added to zoom2 at least.

>-----Original Message-----
>From: linux-omap-owner@vger.kernel.org
>[mailto:linux-omap-owner@vger.kernel.org] On Behalf Of ext Kevin Hilman
>Sent: 25 November, 2009 19:22
>To: Nishanth Menon
>Cc: linux-omap
>Subject: Re: [PATCH 03/10 V3] omap3: pm: use opp accessor
>functions for omap34xx
>
>Nishanth Menon <nm@ti.com> writes:
>
>> Move the definitions from omap3-opp.h to pm34xx.c. The definitions
>> are now based on omap_opp_def instead of omap_opp itself.
>> Since the opp.h has the omap_opp definition, omap-pm.h conflicts and
>> has been removed in favor of opp.h.
>
>ok
>
>> omap3_pm_init_opp_table is used to initialize the OPP table and
>> relevant board files which have omap2_init_common_hw called with opp
>> arrays have been updated with omap3_pm_init_opp_table.
>>
>> This change now allows us to dynamically register OPPs to the system
>> based on silicon type we detect.
>
>Nice.
>
>With this patch, I would suggest a couple more cleanups in how
>we are handling
>the master OPP lists for MPU, DSP and L3.
>
>Namely, It's time we could remove the rate_table passing from the OMAP
>PM layer all together and just keep them as pointers in opp.h.
>
>The longer term goal is to remove OPP handling from OMAP PM
>all together,
>so this will be a step in that direction.
>
>I've attached a patch that applies on top of your series that drops
>the OPPs from OMAP PM layer.  After doing this, we now have some
>duplicate global pointers to the various rate tables that could be
>cleaned up.  In addition, all the rate tables could be dropped from
>init_common_hw.
>
>If you follow my proposal for using opp_add() instead of opp_init()
>the board files that want to just use default OPPs do not have to do
>anyting with the rate tables.  Only board files wanting to add OPPs
>would have to include opp.h and use opp_add().
>
>Also, dropping the rate tables from init_common_hw would mean you
>shouldn't have init sequence issues anymore and you can do the OPP
>init inside existing PM init.
>
>Kevin
>
>> NOTE: This introduces the following warnings highlighting areas we
>> need to cleanup:
>> arch/arm/mach-omap2/smartreflex.c: In function 'get_opp':
>> arch/arm/mach-omap2/smartreflex.c:161: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>> arch/arm/mach-omap2/smartreflex.c:164: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>> arch/arm/mach-omap2/smartreflex.c:166: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>> arch/arm/mach-omap2/smartreflex.c:168: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>> arch/arm/mach-omap2/resource34xx.c: In function 'get_opp':
>> arch/arm/mach-omap2/resource34xx.c:165: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>> arch/arm/mach-omap2/resource34xx.c:168: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>> arch/arm/mach-omap2/resource34xx.c:170: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>> arch/arm/mach-omap2/resource34xx.c:172: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>> arch/arm/mach-omap2/resource34xx.c: In function 'program_opp':
>> arch/arm/mach-omap2/resource34xx.c:284: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>> arch/arm/mach-omap2/resource34xx.c:285: warning: 'opp_id' is
>deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>>
>> Signed-off-by: Nishanth Menon <nm@ti.com>
>> ---
>>  arch/arm/mach-omap2/board-3430sdp.c       |    1 +
>>  arch/arm/mach-omap2/board-omap3beagle.c   |    1 +
>>  arch/arm/mach-omap2/board-omap3evm.c      |    1 +
>>  arch/arm/mach-omap2/board-rx51.c          |    1 +
>>  arch/arm/mach-omap2/board-zoom2.c         |    2 +
>>  arch/arm/mach-omap2/omap3-opp.h           |   58
>+-----------------------
>>  arch/arm/mach-omap2/pm.h                  |    6 +++
>>  arch/arm/mach-omap2/pm34xx.c              |   68
>+++++++++++++++++++++++++++++
>>  arch/arm/plat-omap/include/plat/omap-pm.h |   17 +-------
>>  9 files changed, 84 insertions(+), 71 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/board-3430sdp.c
>b/arch/arm/mach-omap2/board-3430sdp.c
>> index eac529f..0ec8327 100644
>> --- a/arch/arm/mach-omap2/board-3430sdp.c
>> +++ b/arch/arm/mach-omap2/board-3430sdp.c
>> @@ -220,6 +220,7 @@ static void __init omap_3430sdp_init_irq(void)
>>  {
>>      omap_board_config = sdp3430_config;
>>      omap_board_config_size = ARRAY_SIZE(sdp3430_config);
>> +    omap3_pm_init_opp_table();
>>      omap3_pm_init_vc(&omap3_setuptime_table);
>>      omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
>>      omap2_init_common_hw(hyb18m512160af6_sdrc_params, NULL,
>omap3_mpu_rate_table,
>> diff --git a/arch/arm/mach-omap2/board-omap3beagle.c
>b/arch/arm/mach-omap2/board-omap3beagle.c
>> index 2ec3520..a937238 100644
>> --- a/arch/arm/mach-omap2/board-omap3beagle.c
>> +++ b/arch/arm/mach-omap2/board-omap3beagle.c
>> @@ -361,6 +361,7 @@ static void __init omap3_beagle_init_irq(void)
>>  {
>>      omap_board_config = omap3_beagle_config;
>>      omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
>> +    omap3_pm_init_opp_table();
>>      omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
>>                           mt46h32m32lf6_sdrc_params,
>omap3_mpu_rate_table,
>>                           omap3_dsp_rate_table, omap3_l3_rate_table);
>> diff --git a/arch/arm/mach-omap2/board-omap3evm.c
>b/arch/arm/mach-omap2/board-omap3evm.c
>> index 8130eca..44a5861 100644
>> --- a/arch/arm/mach-omap2/board-omap3evm.c
>> +++ b/arch/arm/mach-omap2/board-omap3evm.c
>> @@ -404,6 +404,7 @@ static void __init omap3_evm_init_irq(void)
>>  {
>>      omap_board_config = omap3_evm_config;
>>      omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
>> +    omap3_pm_init_opp_table();
>>      omap2_init_common_hw(mt46h32m32lf6_sdrc_params, NULL,
>omap3_mpu_rate_table,
>>                           omap3_dsp_rate_table, omap3_l3_rate_table);
>>      omap_init_irq();
>> diff --git a/arch/arm/mach-omap2/board-rx51.c
>b/arch/arm/mach-omap2/board-rx51.c
>> index 2f1c2be..997fd1c 100644
>> --- a/arch/arm/mach-omap2/board-rx51.c
>> +++ b/arch/arm/mach-omap2/board-rx51.c
>> @@ -103,6 +103,7 @@ static void __init rx51_init_irq(void)
>>
>>      omap_board_config = rx51_config;
>>      omap_board_config_size = ARRAY_SIZE(rx51_config);
>> +    omap3_pm_init_opp_table();
>>      omap3_pm_init_cpuidle(rx51_cpuidle_params);
>>      sdrc_params = rx51_get_sdram_timings();
>>      omap2_init_common_hw(sdrc_params, sdrc_params,
>> diff --git a/arch/arm/mach-omap2/board-zoom2.c
>b/arch/arm/mach-omap2/board-zoom2.c
>> index dcc5fb8..9d5b078 100644
>> --- a/arch/arm/mach-omap2/board-zoom2.c
>> +++ b/arch/arm/mach-omap2/board-zoom2.c
>> @@ -24,10 +24,12 @@
>>  #include <mach/board-zoom.h>
>>
>>  #include "sdram-micron-mt46h32m32lf-6.h"
>> +#include "pm.h"
>>  #include "omap3-opp.h"
>>
>>  static void __init omap_zoom2_init_irq(void)
>>  {
>> +    omap3_pm_init_opp_table();
>>      omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
>>                               mt46h32m32lf6_sdrc_params,
>omap3_mpu_rate_table,
>>                               omap3_dsp_rate_table,
>omap3_l3_rate_table);
>> diff --git a/arch/arm/mach-omap2/omap3-opp.h
>b/arch/arm/mach-omap2/omap3-opp.h
>> index 42557e1..994d8d4 100644
>> --- a/arch/arm/mach-omap2/omap3-opp.h
>> +++ b/arch/arm/mach-omap2/omap3-opp.h
>> @@ -3,60 +3,8 @@
>>
>>  #include <plat/omap-pm.h>
>>
>> -/* MPU speeds */
>> -#define S600M   600000000
>> -#define S550M   550000000
>> -#define S500M   500000000
>> -#define S250M   250000000
>> -#define S125M   125000000
>> -
>> -/* DSP speeds */
>> -#define S430M   430000000
>> -#define S400M   400000000
>> -#define S360M   360000000
>> -#define S180M   180000000
>> -#define S90M    90000000
>> -
>> -/* L3 speeds */
>> -#define S83M    83000000
>> -#define S166M   166000000
>> -
>> -static struct omap_opp omap3_mpu_rate_table[] = {
>> -    {0, 0, 0, 0},
>> -    /*OPP1*/
>> -    {true, S125M, VDD1_OPP1, 0x1E},
>> -    /*OPP2*/
>> -    {true, S250M, VDD1_OPP2, 0x26},
>> -    /*OPP3*/
>> -    {true, S500M, VDD1_OPP3, 0x30},
>> -    /*OPP4*/
>> -    {true, S550M, VDD1_OPP4, 0x36},
>> -    /*OPP5*/
>> -    {true, S600M, VDD1_OPP5, 0x3C},
>> -};
>> -
>> -static struct omap_opp omap3_l3_rate_table[] = {
>> -    {0, 0, 0, 0},
>> -    /*OPP1*/
>> -    {false, 0, VDD2_OPP1, 0x1E},
>> -    /*OPP2*/
>> -    {true, S83M, VDD2_OPP2, 0x24},
>> -    /*OPP3*/
>> -    {true, S166M, VDD2_OPP3, 0x2C},
>> -};
>> -
>> -static struct omap_opp omap3_dsp_rate_table[] = {
>> -    {0, 0, 0, 0},
>> -    /*OPP1*/
>> -    {true, S90M, VDD1_OPP1, 0x1E},
>> -    /*OPP2*/
>> -    {true, S180M, VDD1_OPP2, 0x26},
>> -    /*OPP3*/
>> -    {true, S360M, VDD1_OPP3, 0x30},
>> -    /*OPP4*/
>> -    {true, S400M, VDD1_OPP4, 0x36},
>> -    /*OPP5*/
>> -    {true, S430M, 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;
>>
>>  #endif
>> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
>> index 7bc86b6..80a1c1d 100644
>> --- a/arch/arm/mach-omap2/pm.h
>> +++ b/arch/arm/mach-omap2/pm.h
>> @@ -58,6 +58,12 @@ static inline void omap3_pm_init_cpuidle(
>>  {
>>  }
>>  #endif
>> +/**
>> + * omap3_pm_init_opp_table - OMAP opp table lookup called
>after cpu is detected.
>> + * Initialize the basic opp table here, board files could
>choose to modify opp
>> + * table after the basic initialization
>> + */
>> +extern void omap3_pm_init_opp_table(void);
>>
>>  extern int resource_set_opp_level(int res, u32
>target_level, int flags);
>>  extern int resource_access_opp_lock(int res, int delta);
>> diff --git a/arch/arm/mach-omap2/pm34xx.c
>b/arch/arm/mach-omap2/pm34xx.c
>> index 627a509..ad21f5f 100644
>> --- a/arch/arm/mach-omap2/pm34xx.c
>> +++ b/arch/arm/mach-omap2/pm34xx.c
>> @@ -40,6 +40,7 @@
>>  #include <plat/dmtimer.h>
>>  #include <plat/usb.h>
>>
>> +#include <plat/opp.h>
>>  #include <plat/resource.h>
>>
>>  #include <asm/tlbflush.h>
>> @@ -52,6 +53,7 @@
>>  #include "prm.h"
>>  #include "pm.h"
>>  #include "sdrc.h"
>> +#include "omap3-opp.h"
>>
>>  static int regset_save_on_suspend;
>>
>> @@ -100,6 +102,52 @@ static struct prm_setup_vc prm_setup = {
>>      .vdd1_off = 0x00,       /* 0.6v */
>>  };
>>
>> +static struct omap_opp_def __initdata omap34xx_mpu_rate_table[] = {
>> +    /*OPP1 975mV */
>> +    {.enabled = true, .freq = 125000000, .u_volt = 975000},
>> +    /*OPP2 1.075V */
>> +    {.enabled = true, .freq = 250000000, .u_volt = 1075000},
>> +    /*OPP3 1.2V */
>> +    {.enabled = true, .freq = 500000000, .u_volt = 1200000},
>> +    /*OPP4 1.270V */
>> +    {.enabled = true, .freq = 550000000, .u_volt = 1270000},
>> +    /*OPP5 1.35V */
>> +    {.enabled = true, .freq = 600000000, .u_volt = 1350000},
>> +    /* Terminator */
>> +    {.enabled = 0, .freq = 0, .u_volt = 0}
>> +};
>> +
>> +static struct omap_opp_def __initdata omap34xx_l3_rate_table[] = {
>> +    /*OPP1 - 975mV */
>> +    {.enabled = false, .freq = 0, .u_volt = 975000},
>> +    /*OPP2 1.05V */
>> +    {.enabled = true, .freq = 83000000, .u_volt = 1050000},
>> +    /*OPP3 1.15V*/
>> +    {.enabled = true, .freq = 166000000, .u_volt = 1150000},
>> +    /* Terminator */
>> +    {.enabled = 0, .freq = 0, .u_volt = 0}
>> +};
>> +
>> +static struct omap_opp_def __initdata omap34xx_dsp_rate_table[] = {
>> +    /*OPP1*/
>> +    {.enabled = true, .freq = 90000000, .u_volt = 975000},
>> +    /*OPP2*/
>> +    {.enabled = true, .freq = 180000000, .u_volt = 1075000},
>> +    /*OPP3*/
>> +    {.enabled = true, .freq = 360000000, .u_volt = 1200000},
>> +    /*OPP4*/
>> +    {.enabled = true, .freq = 400000000, .u_volt = 1270000},
>> +    /*OPP5*/
>> +    {.enabled = true, .freq = 430000000, .u_volt = 1350000},
>> +    /* Terminator */
>> +    {.enabled = 0, .freq = 0, .u_volt = 0}
>> +};
>> +
>> +struct omap_opp *omap3_mpu_rate_table;
>> +struct omap_opp *omap3_dsp_rate_table;
>> +struct omap_opp *omap3_l3_rate_table;
>> +
>> +
>>  static inline void omap3_per_save_context(void)
>>  {
>>      omap_gpio_save_context();
>> @@ -1248,6 +1296,26 @@ static void __init configure_vc(void)
>>      pm_dbg_regset_init(2);
>>  }
>>
>> +void __init omap3_pm_init_opp_table(void)
>> +{
>> +    int ret, i;
>> +    struct omap_opp_def *omap34xx_opp_def_list[] = {
>> +            omap34xx_mpu_rate_table,
>> +            omap34xx_l3_rate_table,
>> +            omap34xx_dsp_rate_table
>> +    };
>> +    struct omap_opp **omap3_rate_tables[] = {
>> +            &omap3_mpu_rate_table,
>> +            &omap3_l3_rate_table,
>> +            &omap3_dsp_rate_table
>> +    };
>> +    for (i = 0; i < ARRAY_SIZE(omap34xx_opp_def_list); i++) {
>> +            ret = opp_init(omap3_rate_tables[i],
>omap34xx_opp_def_list[i]);
>> +            /* We dont want half configured system at the moment */
>> +            BUG_ON(ret);
>> +    }
>> +}
>> +
>>  static int __init omap3_pm_early_init(void)
>>  {
>>      prm_clear_mod_reg_bits(OMAP3430_OFFMODE_POL, OMAP3430_GR_MOD,
>> diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h
>b/arch/arm/plat-omap/include/plat/omap-pm.h
>> index 5dc2048..aa36339 100644
>> --- a/arch/arm/plat-omap/include/plat/omap-pm.h
>> +++ b/arch/arm/plat-omap/include/plat/omap-pm.h
>> @@ -18,22 +18,7 @@
>>  #include <linux/cpufreq.h>
>>
>>  #include "powerdomain.h"
>> -
>> -/**
>> - * struct omap_opp - clock frequency-to-OPP ID table for DSP, MPU
>> - * @enabled: enabled if true, disabled if false
>> - * @rate: target clock rate
>> - * @opp_id: OPP ID
>> - * @min_vdd: minimum VDD1 voltage (in millivolts) for this OPP
>> - *
>> - * Operating performance point data.  Can vary by OMAP chip
>and board.
>> - */
>> -struct omap_opp {
>> -    bool enabled;
>> -    unsigned long rate;
>> -    u8 opp_id;
>> -    u16 vsel;
>> -};
>> +#include <plat/opp.h>
>>
>>  extern struct omap_opp *mpu_opps;
>>  extern struct omap_opp *dsp_opps;
>> --
>> 1.6.3.3
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe
>linux-omap" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>--
>To unsubscribe from this list: send the line "unsubscribe
>linux-omap" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 09/10 V3] omap3: pm: introduce 3630 opps
  2009-11-25  4:09                 ` [PATCH 09/10 V3] omap3: pm: introduce 3630 opps Nishanth Menon
  2009-11-25  4:09                   ` [PATCH 10/10] omap3: pm: omap3630 boards: enable 3630 opp tables Nishanth Menon
@ 2009-12-08  7:49                   ` Eduardo Valentin
  2009-12-08 10:59                     ` Menon, Nishanth
  1 sibling, 1 reply; 36+ messages in thread
From: Eduardo Valentin @ 2009-12-08  7:49 UTC (permalink / raw)
  To: ext Nishanth Menon
  Cc: linux-omap, Benoit Cousson, Kevin Hilman,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

Hello Nishanth,

Few comments bellow.

On Wed, Nov 25, 2009 at 05:09:18AM +0100, ext Nishanth Menon wrote:
> Introduce the OMAP3630 OPPs including the defined OPP tuples.
> 
> Further information on OMAP3630 can be found here:
> http://focus.ti.com/general/docs/wtbu/wtbuproductcontent.tsp?templateId=6123&navigationId=12836&contentId=52606
> 
> OMAP36xx family introduces:
> VDD1 with 4 OPPs, of which OPP3 & 4 are available only on devices yet
> to be introduced in 36xx family. Meanwhile, VDD2 has 2 opps.
> 
> Device Support of OPPs->
>            |<-3630-600->| (default)
>            |<-      3630-800    ->| (device: TBD)
>            |<-      3630-1000            ->| (device: TBD)
> H/w OPP-> OPP50 OPP100       OPP-Turbo   OPP1G-SB
> VDD1      OPP1  OPP2         OPP3        OPP4
> VDD2      OPP1  OPP2         OPP2        OPP2
> 
> Note:
> a) TI h/w naming for OPPs are now standardized in terms of OPP50, 100,
>    Turbo and SB. This maps as shown above to the opp IDs (s/w term).
> b) For boards which need custom VDD1/2 OPPs, the opp table can be
>    updated by the board file on a need basis after the
>    omap3_pm_init_opp_table call. The OPPs introduced here are the
>    official OPP table at this point in time.
> 
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Romit Dasgupta <romit@ti.com>
> Cc: Sanjeev Premi <premi@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
> Cc: Thara Gopinath <thara@ti.com>
> Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
> 
> Signed-off-by: Nishanth Menon <nm@ti.com>
> ---
>  arch/arm/mach-omap2/pm34xx.c |   49 ++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 47 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index ad21f5f..05ecf02 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -143,6 +143,41 @@ static struct omap_opp_def __initdata omap34xx_dsp_rate_table[] = {
>  	{.enabled = 0, .freq = 0, .u_volt = 0}
>  };
>  
> +static struct omap_opp_def __initdata omap36xx_mpu_rate_table[] = {
> +	/*OPP1 - OPP50*/
> +	{.enabled = true,  .freq = 300000000, .u_volt = 930000},
> +	/*OPP2 - OPP100*/
> +	{.enabled = true,  .freq = 600000000, .u_volt = 1100000},
> +	/*OPP3 - OPP-Turbo*/
> +	{.enabled = false, .freq = 800000000, .u_volt = 1260000},
> +	/*OPP4 - OPP-SB*/
> +	{.enabled = false, .freq = 1000000000, .u_volt = 1310000},
> +	/* Terminator */
> +	{.enabled = 0, .freq = 0, .u_volt = 0}
> +};
> +
> +static struct omap_opp_def __initdata omap36xx_l3_rate_table[] = {
> +	/*OPP1 - OPP50 */
> +	{.enabled = true, .freq = 100000000, .u_volt = 930000},
> +	/*OPP2 - OPP100, OPP-Turbo, OPP-SB*/
> +	{.enabled = true, .freq = 200000000, .u_volt = 1137500},
> +	/* Terminator */
> +	{.enabled = 0, .freq = 0, .u_volt = 0}
> +};
> +
> +static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
> +	/*OPP1 - OPP50*/
> +	{.enabled = true,  .freq = 260000000, .u_volt = 930000},
> +	/*OPP2 - OPP100*/
> +	{.enabled = true,  .freq = 520000000, .u_volt = 1100000},
> +	/*OPP3 - OPP-Turbo*/
> +	{.enabled = false, .freq = 660000000, .u_volt = 1260000},
> +	/*OPP4 - OPP-SB*/
> +	{.enabled = false, .freq = 875000000, .u_volt = 1310000},
> +	/* Terminator */
> +	{.enabled = 0, .freq = 0, .u_volt = 0}
> +};
> +

Although it is not mandatory, I'd say this way of initializing structure array is more common:

static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
	/*OPP1 - OPP50*/
	{
		.enabled	= true,
		.freq		= 260000000,
		.u_volt		= 930000,
	},
	/*OPP2 - OPP100*/
	{
		.enabled	= true,
		.freq		= 520000000,
		.u_volt		= 1100000,
	},
	/*OPP3 - OPP-Turbo*/
	{
		.enabled	= false,
		.freq		= 660000000,
		.u_volt		= 1260000,
	},
	/*OPP4 - OPP-SB*/
	{
		.enabled	= false,
		.freq		= 875000000,
		.u_volt		= 1310000,
	},
	/* Terminator */
	{
		.enabled	= 0,
		.freq		= 0,
		.u_volt		= 0,
	}
};

and if you thing it is line consuming, you can always define a "INIT" macro:
#define	OMAP_OPP_DEF(_enabled, _freq, _uv)	\
{						\
	.enabled	= _enabled,		\
	.freq		= _freq,		\
	.u_volt		= _uv,			\
}

and use it to initialize your array:

	/*OPP1 - OPP50*/
static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
	OMAP_OPP_DEF(true, 260000000, 930000),
	OMAP_OPP_DEF(true, 520000000, 1100000),
	OMAP_OPP_DEF(false, 660000000, 1260000),
	OMAP_OPP_DEF(false, 875000000, 1310000},
	OMAP_OPP_DEF(0, 0, 0),
};


Beside, although it should not hurt as they are not too big, these tables should
be compiled only if omap3630 is the target right?

>  struct omap_opp *omap3_mpu_rate_table;
>  struct omap_opp *omap3_dsp_rate_table;
>  struct omap_opp *omap3_l3_rate_table;
> @@ -1299,18 +1334,28 @@ static void __init configure_vc(void)
>  void __init omap3_pm_init_opp_table(void)
>  {
>  	int ret, i;
> +	struct omap_opp_def **omap3_opp_def_list;
>  	struct omap_opp_def *omap34xx_opp_def_list[] = {
>  		omap34xx_mpu_rate_table,
>  		omap34xx_l3_rate_table,
>  		omap34xx_dsp_rate_table
>  	};
> +	struct omap_opp_def *omap36xx_opp_def_list[] = {
> +		omap36xx_mpu_rate_table,
> +		omap36xx_l3_rate_table,
> +		omap36xx_dsp_rate_table
> +	};
>  	struct omap_opp **omap3_rate_tables[] = {
>  		&omap3_mpu_rate_table,
>  		&omap3_l3_rate_table,
>  		&omap3_dsp_rate_table
>  	};
> -	for (i = 0; i < ARRAY_SIZE(omap34xx_opp_def_list); i++) {
> -		ret = opp_init(omap3_rate_tables[i], omap34xx_opp_def_list[i]);
> +
> +	omap3_opp_def_list = cpu_is_omap3630() ? omap36xx_opp_def_list :
> +				omap34xx_opp_def_list;

here you cared for runtime target check, but tables above could be avoid if not omap3630.

> +
> +	for (i = 0; i < ARRAY_SIZE(omap3_rate_tables); i++) {
> +		ret = opp_init(omap3_rate_tables[i], omap3_opp_def_list[i]);
>  		/* We dont want half configured system at the moment */
>  		BUG_ON(ret);
>  	}
> -- 
> 1.6.3.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Eduardo Valentin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table
  2009-11-25  4:09             ` [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table Nishanth Menon
  2009-11-25  4:09               ` [PATCH 08/10] omap3: pm: remove VDDx_MIN/MAX macros Nishanth Menon
  2009-12-07 16:54               ` [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table Tero.Kristo
@ 2009-12-08  7:54               ` Eduardo Valentin
  2 siblings, 0 replies; 36+ messages in thread
From: Eduardo Valentin @ 2009-12-08  7:54 UTC (permalink / raw)
  To: ext Nishanth Menon
  Cc: linux-omap, Benoit Cousson, Kevin Hilman,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

Little comment bellow,

On Wed, Nov 25, 2009 at 05:09:16AM +0100, ext Nishanth Menon wrote:
> omap2_clk_init_cpufreq_table currently directly accesses the opp
> table, making it unscalable to various OMAPs. Instead use the
> accessor functions to populate the cpufreq table
> 
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Romit Dasgupta <romit@ti.com>
> Cc: Sanjeev Premi <premi@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
> Cc: Thara Gopinath <thara@ti.com>
> Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
> 
> Signed-off-by: Nishanth Menon <nm@ti.com>
> ---
>  arch/arm/mach-omap2/clock34xx.c |   32 +++++++++++++++++++-------------
>  1 files changed, 19 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
> index 5150939..d07f1c1 100644
> --- a/arch/arm/mach-omap2/clock34xx.c
> +++ b/arch/arm/mach-omap2/clock34xx.c
> @@ -1042,30 +1042,36 @@ static unsigned long omap3_clkoutx2_recalc(struct clk *clk)
>  #if defined(CONFIG_ARCH_OMAP3)
>  
>  #ifdef CONFIG_CPU_FREQ
> -static struct cpufreq_frequency_table freq_table[MAX_VDD1_OPP+1];
> +
> +static struct cpufreq_frequency_table *freq_table;
>  
>  void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
>  {
> -	struct omap_opp *prcm;
>  	int i = 0;
> +	u8 opp_num;
> +	struct omap_opp *opp = NULL;
> +	unsigned long freq = ULONG_MAX;
>  
> -	if (!mpu_opps)
> +	if (!mpu_opps || opp_get_opp_count(&opp_num, mpu_opps)) {
> +		pr_warning("%s: failed to initialize frequency"
> +				"table\n", __func__);
>  		return;
> -
> -	prcm = mpu_opps + MAX_VDD1_OPP;
> -	for (; prcm->rate; prcm--) {
> -		freq_table[i].index = i;
> -		freq_table[i].frequency = prcm->rate / 1000;
> -		i++;
>  	}
>  
> -	if (i == 0) {
> -		printk(KERN_WARNING "%s: failed to initialize frequency \
> -								table\n",
> -								__func__);
> +	freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
> +			(opp_num + 1), GFP_KERNEL);
> +	if (!freq_table) {
> +		pr_warning("%s: failed to allocate frequency"
> +				"table\n", __func__);
>  		return;
>  	}
>  
> +	while (!opp_get_lower_opp(&opp, &freq, mpu_opps)) {
> +		freq_table[i].index = i;
> +		freq_table[i].frequency =  freq / 1000;
                                         ^^

Use one space around (on each side of) most binary and ternary operators,
such as any of these:

	=  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :

> +		i++;
> +	}
> +
>  	freq_table[i].index = i;
>  	freq_table[i].frequency = CPUFREQ_TABLE_END;
>  
> -- 
> 1.6.3.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Eduardo Valentin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 06/10 V3] omap3: pm: use opp accessor functions for omap-target
  2009-11-25 17:56             ` [PATCH 06/10 V3] omap3: pm: use opp accessor functions for omap-target Kevin Hilman
@ 2009-12-08  7:59               ` Eduardo Valentin
  0 siblings, 0 replies; 36+ messages in thread
From: Eduardo Valentin @ 2009-12-08  7:59 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: ext Kevin Hilman, linux-omap, Benoit Cousson,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

Hello Nishanth,

Little style comment.

On Wed, Nov 25, 2009 at 06:56:08PM +0100, ext Kevin Hilman wrote:
> Nishanth Menon <nm@ti.com> writes:
> 
> > The logic in omap-target can now be improved with the accessor
> > functions. Dont scan through the list manually, instead use
> > get_next_freq to do the scanning.
> >
> > Cc: Benoit Cousson <b-cousson@ti.com>
> > Cc: Kevin Hilman <khilman@deeprootsystems.com>
> > Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
> > Cc: Paul Walmsley <paul@pwsan.com>
> > Cc: Romit Dasgupta <romit@ti.com>
> > Cc: Sanjeev Premi <premi@ti.com>
> > Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
> > Cc: Thara Gopinath <thara@ti.com>
> > Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
> >
> > Signed-off-by: Nishanth Menon <nm@ti.com>
> > ---
> >  arch/arm/plat-omap/cpu-omap.c |   19 +++++++++++--------
> >  1 files changed, 11 insertions(+), 8 deletions(-)
> >
> > diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
> > index 449b6b6..7b3ca11 100644
> > --- a/arch/arm/plat-omap/cpu-omap.c
> > +++ b/arch/arm/plat-omap/cpu-omap.c
> > @@ -111,14 +111,17 @@ static int omap_target(struct cpufreq_policy *policy,
> >  	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
> >  #elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
> >  	if (mpu_opps) {
> > -		int ind;
> > -		for (ind = 1; ind <= MAX_VDD1_OPP; ind++) {
> > -			if (mpu_opps[ind].rate/1000 >= target_freq) {
> > -				omap_pm_cpu_set_freq
> > -					(mpu_opps[ind].rate);
> > -				break;
> > -			}
> > -		}
> > +		unsigned long freq = target_freq * 1000;
> > +		struct omap_opp *opp = NULL;
> > +		int res;

Not mandatory, but add a blank line to separate declaration from rest of the code.

> > +		/* see if we have exact freq match */
> > +		res = opp_is_valid(&opp, mpu_opps, freq);
> > +		/* Get next best if we cant find a exact match */
> > +		if (res)
> > +			res = opp_get_higher_opp(&opp, &freq, mpu_opps);
> 
> These two could just be replaced by a single call to
> opp_find_freq_rounding()

Indeed, I also agree here that having a "find_rounded" as a search option
would make sense.

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

-- 
Eduardo Valentin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx
  2009-11-25  4:09     ` [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx Nishanth Menon
  2009-11-25  4:09       ` [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions Nishanth Menon
  2009-11-25 17:22       ` [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx Kevin Hilman
@ 2009-12-08  8:08       ` Eduardo Valentin
  2 siblings, 0 replies; 36+ messages in thread
From: Eduardo Valentin @ 2009-12-08  8:08 UTC (permalink / raw)
  To: ext Nishanth Menon; +Cc: linux-omap

Hello Nishanth,

Same comments from patch 09/10 applies here. Copying those to make like easier:

On Wed, Nov 25, 2009 at 05:09:12AM +0100, ext Nishanth Menon wrote:
> Move the definitions from omap3-opp.h to pm34xx.c. The definitions
> are now based on omap_opp_def instead of omap_opp itself.
> Since the opp.h has the omap_opp definition, omap-pm.h conflicts and
> has been removed in favor of opp.h.
> 
> omap3_pm_init_opp_table is used to initialize the OPP table and
> relevant board files which have omap2_init_common_hw called with opp
> arrays have been updated with omap3_pm_init_opp_table.
> 
> This change now allows us to dynamically register OPPs to the system
> based on silicon type we detect.
> 
> NOTE: This introduces the following warnings highlighting areas we
> need to cleanup:
> arch/arm/mach-omap2/smartreflex.c: In function 'get_opp':
> arch/arm/mach-omap2/smartreflex.c:161: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/smartreflex.c:164: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/smartreflex.c:166: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/smartreflex.c:168: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/resource34xx.c: In function 'get_opp':
> arch/arm/mach-omap2/resource34xx.c:165: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/resource34xx.c:168: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/resource34xx.c:170: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/resource34xx.c:172: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/resource34xx.c: In function 'program_opp':
> arch/arm/mach-omap2/resource34xx.c:284: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> arch/arm/mach-omap2/resource34xx.c:285: warning: 'opp_id' is deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
> 
> Signed-off-by: Nishanth Menon <nm@ti.com>
> ---
>  arch/arm/mach-omap2/board-3430sdp.c       |    1 +
>  arch/arm/mach-omap2/board-omap3beagle.c   |    1 +
>  arch/arm/mach-omap2/board-omap3evm.c      |    1 +
>  arch/arm/mach-omap2/board-rx51.c          |    1 +
>  arch/arm/mach-omap2/board-zoom2.c         |    2 +
>  arch/arm/mach-omap2/omap3-opp.h           |   58 +-----------------------
>  arch/arm/mach-omap2/pm.h                  |    6 +++
>  arch/arm/mach-omap2/pm34xx.c              |   68 +++++++++++++++++++++++++++++
>  arch/arm/plat-omap/include/plat/omap-pm.h |   17 +-------
>  9 files changed, 84 insertions(+), 71 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
> index eac529f..0ec8327 100644
> --- a/arch/arm/mach-omap2/board-3430sdp.c
> +++ b/arch/arm/mach-omap2/board-3430sdp.c
> @@ -220,6 +220,7 @@ static void __init omap_3430sdp_init_irq(void)
>  {
>         omap_board_config = sdp3430_config;
>         omap_board_config_size = ARRAY_SIZE(sdp3430_config);
> +       omap3_pm_init_opp_table();
>         omap3_pm_init_vc(&omap3_setuptime_table);
>         omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
>         omap2_init_common_hw(hyb18m512160af6_sdrc_params, NULL, omap3_mpu_rate_table,
> diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
> index 2ec3520..a937238 100644
> --- a/arch/arm/mach-omap2/board-omap3beagle.c
> +++ b/arch/arm/mach-omap2/board-omap3beagle.c
> @@ -361,6 +361,7 @@ static void __init omap3_beagle_init_irq(void)
>  {
>         omap_board_config = omap3_beagle_config;
>         omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
> +       omap3_pm_init_opp_table();
>         omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
>                              mt46h32m32lf6_sdrc_params, omap3_mpu_rate_table,
>                              omap3_dsp_rate_table, omap3_l3_rate_table);
> diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
> index 8130eca..44a5861 100644
> --- a/arch/arm/mach-omap2/board-omap3evm.c
> +++ b/arch/arm/mach-omap2/board-omap3evm.c
> @@ -404,6 +404,7 @@ static void __init omap3_evm_init_irq(void)
>  {
>         omap_board_config = omap3_evm_config;
>         omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
> +       omap3_pm_init_opp_table();
>         omap2_init_common_hw(mt46h32m32lf6_sdrc_params, NULL, omap3_mpu_rate_table,
>                              omap3_dsp_rate_table, omap3_l3_rate_table);
>         omap_init_irq();
> diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
> index 2f1c2be..997fd1c 100644
> --- a/arch/arm/mach-omap2/board-rx51.c
> +++ b/arch/arm/mach-omap2/board-rx51.c
> @@ -103,6 +103,7 @@ static void __init rx51_init_irq(void)
> 
>         omap_board_config = rx51_config;
>         omap_board_config_size = ARRAY_SIZE(rx51_config);
> +       omap3_pm_init_opp_table();
>         omap3_pm_init_cpuidle(rx51_cpuidle_params);
>         sdrc_params = rx51_get_sdram_timings();
>         omap2_init_common_hw(sdrc_params, sdrc_params,
> diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
> index dcc5fb8..9d5b078 100644
> --- a/arch/arm/mach-omap2/board-zoom2.c
> +++ b/arch/arm/mach-omap2/board-zoom2.c
> @@ -24,10 +24,12 @@
>  #include <mach/board-zoom.h>
> 
>  #include "sdram-micron-mt46h32m32lf-6.h"
> +#include "pm.h"
>  #include "omap3-opp.h"
> 
>  static void __init omap_zoom2_init_irq(void)
>  {
> +       omap3_pm_init_opp_table();
>         omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
>                                  mt46h32m32lf6_sdrc_params, omap3_mpu_rate_table,
>                                  omap3_dsp_rate_table, omap3_l3_rate_table);
> diff --git a/arch/arm/mach-omap2/omap3-opp.h b/arch/arm/mach-omap2/omap3-opp.h
> index 42557e1..994d8d4 100644
> --- a/arch/arm/mach-omap2/omap3-opp.h
> +++ b/arch/arm/mach-omap2/omap3-opp.h
> @@ -3,60 +3,8 @@
> 
>  #include <plat/omap-pm.h>
> 
> -/* MPU speeds */
> -#define S600M   600000000
> -#define S550M   550000000
> -#define S500M   500000000
> -#define S250M   250000000
> -#define S125M   125000000
> -
> -/* DSP speeds */
> -#define S430M   430000000
> -#define S400M   400000000
> -#define S360M   360000000
> -#define S180M   180000000
> -#define S90M    90000000
> -
> -/* L3 speeds */
> -#define S83M    83000000
> -#define S166M   166000000
> -
> -static struct omap_opp omap3_mpu_rate_table[] = {
> -       {0, 0, 0, 0},
> -       /*OPP1*/
> -       {true, S125M, VDD1_OPP1, 0x1E},
> -       /*OPP2*/
> -       {true, S250M, VDD1_OPP2, 0x26},
> -       /*OPP3*/
> -       {true, S500M, VDD1_OPP3, 0x30},
> -       /*OPP4*/
> -       {true, S550M, VDD1_OPP4, 0x36},
> -       /*OPP5*/
> -       {true, S600M, VDD1_OPP5, 0x3C},
> -};
> -
> -static struct omap_opp omap3_l3_rate_table[] = {
> -       {0, 0, 0, 0},
> -       /*OPP1*/
> -       {false, 0, VDD2_OPP1, 0x1E},
> -       /*OPP2*/
> -       {true, S83M, VDD2_OPP2, 0x24},
> -       /*OPP3*/
> -       {true, S166M, VDD2_OPP3, 0x2C},
> -};
> -
> -static struct omap_opp omap3_dsp_rate_table[] = {
> -       {0, 0, 0, 0},
> -       /*OPP1*/
> -       {true, S90M, VDD1_OPP1, 0x1E},
> -       /*OPP2*/
> -       {true, S180M, VDD1_OPP2, 0x26},
> -       /*OPP3*/
> -       {true, S360M, VDD1_OPP3, 0x30},
> -       /*OPP4*/
> -       {true, S400M, VDD1_OPP4, 0x36},
> -       /*OPP5*/
> -       {true, S430M, 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;
> 
>  #endif
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 7bc86b6..80a1c1d 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -58,6 +58,12 @@ static inline void omap3_pm_init_cpuidle(
>  {
>  }
>  #endif
> +/**
> + * omap3_pm_init_opp_table - OMAP opp table lookup called after cpu is detected.
> + * Initialize the basic opp table here, board files could choose to modify opp
> + * table after the basic initialization
> + */
> +extern void omap3_pm_init_opp_table(void);
> 
>  extern int resource_set_opp_level(int res, u32 target_level, int flags);
>  extern int resource_access_opp_lock(int res, int delta);
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index 627a509..ad21f5f 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -40,6 +40,7 @@
>  #include <plat/dmtimer.h>
>  #include <plat/usb.h>
> 
> +#include <plat/opp.h>
>  #include <plat/resource.h>
> 
>  #include <asm/tlbflush.h>
> @@ -52,6 +53,7 @@
>  #include "prm.h"
>  #include "pm.h"
>  #include "sdrc.h"
> +#include "omap3-opp.h"
> 
>  static int regset_save_on_suspend;
> 
> @@ -100,6 +102,52 @@ static struct prm_setup_vc prm_setup = {
>         .vdd1_off = 0x00,       /* 0.6v */
>  };
> 
> +static struct omap_opp_def __initdata omap34xx_mpu_rate_table[] = {
> +       /*OPP1 975mV */
> +       {.enabled = true, .freq = 125000000, .u_volt = 975000},
> +       /*OPP2 1.075V */
> +       {.enabled = true, .freq = 250000000, .u_volt = 1075000},
> +       /*OPP3 1.2V */
> +       {.enabled = true, .freq = 500000000, .u_volt = 1200000},
> +       /*OPP4 1.270V */
> +       {.enabled = true, .freq = 550000000, .u_volt = 1270000},
> +       /*OPP5 1.35V */
> +       {.enabled = true, .freq = 600000000, .u_volt = 1350000},
> +       /* Terminator */
> +       {.enabled = 0, .freq = 0, .u_volt = 0}
> +};
> +
> +static struct omap_opp_def __initdata omap34xx_l3_rate_table[] = {
> +       /*OPP1 - 975mV */
> +       {.enabled = false, .freq = 0, .u_volt = 975000},
> +       /*OPP2 1.05V */
> +       {.enabled = true, .freq = 83000000, .u_volt = 1050000},
> +       /*OPP3 1.15V*/
> +       {.enabled = true, .freq = 166000000, .u_volt = 1150000},
> +       /* Terminator */
> +       {.enabled = 0, .freq = 0, .u_volt = 0}
> +};
> +
> +static struct omap_opp_def __initdata omap34xx_dsp_rate_table[] = {
> +       /*OPP1*/
> +       {.enabled = true, .freq = 90000000, .u_volt = 975000},
> +       /*OPP2*/
> +       {.enabled = true, .freq = 180000000, .u_volt = 1075000},
> +       /*OPP3*/
> +       {.enabled = true, .freq = 360000000, .u_volt = 1200000},
> +       /*OPP4*/
> +       {.enabled = true, .freq = 400000000, .u_volt = 1270000},
> +       /*OPP5*/
> +       {.enabled = true, .freq = 430000000, .u_volt = 1350000},
> +       /* Terminator */
> +       {.enabled = 0, .freq = 0, .u_volt = 0}
> +};

Although it is not mandatory, I'd say this way of initializing structure array is more common:

static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
        /* OPP1 */
        {
                .enabled        = true,
                .freq           = 90000000,
                .u_volt         = 975000,
        },
        /* OPP2 */
        {
                .enabled        = true,
                .freq           = 180000000,
                .u_volt         = 1075000,
        },
        /* OPP3 */
        {
                .enabled        = false,
                .freq           = 360000000,
                .u_volt         = 1200000,
        },
        /* OPP4 */
        {
                .enabled        = true,
                .freq           = 400000000,
                .u_volt         = 1270000,
        },
        /* OPP5 */
        {
                .enabled        = true,
                .freq           = 430000000,
                .u_volt         = 1350000,
        },
        /* Terminator */
        {
                .enabled        = 0,
                .freq           = 0,
                .u_volt         = 0,
        }
};

and if you thing it is line consuming, you can always define a "INIT" macro:
#define OMAP_OPP_DEF(_enabled, _freq, _uv)      \
{                                               \
        .enabled        = _enabled,             \
        .freq           = _freq,                \
        .u_volt         = _uv,                  \
}

and use it to initialize your array:

static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
        /* OPP1 */
        OMAP_OPP_DEF(true, 90000000, 975000),
        /* OPP2 */
        OMAP_OPP_DEF(true, 180000000, 1075000),
        /* OPP3 */
        OMAP_OPP_DEF(false, 360000000, 1200000),
        /* OPP4 */
        OMAP_OPP_DEF(false, 400000000, 1270000},
        /* OPP5 */
        OMAP_OPP_DEF(false, 430000000, 1350000},
        /* Terminator */
        OMAP_OPP_DEF(0, 0, 0),
};


> +
> +struct omap_opp *omap3_mpu_rate_table;
> +struct omap_opp *omap3_dsp_rate_table;
> +struct omap_opp *omap3_l3_rate_table;
> +
> +
>  static inline void omap3_per_save_context(void)
>  {
>         omap_gpio_save_context();
> @@ -1248,6 +1296,26 @@ static void __init configure_vc(void)
>         pm_dbg_regset_init(2);
>  }
> 
> +void __init omap3_pm_init_opp_table(void)
> +{
> +       int ret, i;
> +       struct omap_opp_def *omap34xx_opp_def_list[] = {
> +               omap34xx_mpu_rate_table,
> +               omap34xx_l3_rate_table,
> +               omap34xx_dsp_rate_table
> +       };
> +       struct omap_opp **omap3_rate_tables[] = {
> +               &omap3_mpu_rate_table,
> +               &omap3_l3_rate_table,
> +               &omap3_dsp_rate_table
> +       };
> +       for (i = 0; i < ARRAY_SIZE(omap34xx_opp_def_list); i++) {
> +               ret = opp_init(omap3_rate_tables[i], omap34xx_opp_def_list[i]);
> +               /* We dont want half configured system at the moment */
> +               BUG_ON(ret);
> +       }
> +}
> +
>  static int __init omap3_pm_early_init(void)
>  {
>         prm_clear_mod_reg_bits(OMAP3430_OFFMODE_POL, OMAP3430_GR_MOD,
> diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
> index 5dc2048..aa36339 100644
> --- a/arch/arm/plat-omap/include/plat/omap-pm.h
> +++ b/arch/arm/plat-omap/include/plat/omap-pm.h
> @@ -18,22 +18,7 @@
>  #include <linux/cpufreq.h>
> 
>  #include "powerdomain.h"
> -
> -/**
> - * struct omap_opp - clock frequency-to-OPP ID table for DSP, MPU
> - * @enabled: enabled if true, disabled if false
> - * @rate: target clock rate
> - * @opp_id: OPP ID
> - * @min_vdd: minimum VDD1 voltage (in millivolts) for this OPP
> - *
> - * Operating performance point data.  Can vary by OMAP chip and board.
> - */
> -struct omap_opp {
> -       bool enabled;
> -       unsigned long rate;
> -       u8 opp_id;
> -       u16 vsel;
> -};
> +#include <plat/opp.h>
> 
>  extern struct omap_opp *mpu_opps;
>  extern struct omap_opp *dsp_opps;
> --
> 1.6.3.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Eduardo Valentin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions
  2009-11-26  0:22           ` Menon, Nishanth
@ 2009-12-08  8:23             ` Eduardo Valentin
  2009-12-08 11:01               ` Menon, Nishanth
  0 siblings, 1 reply; 36+ messages in thread
From: Eduardo Valentin @ 2009-12-08  8:23 UTC (permalink / raw)
  To: ext Menon, Nishanth
  Cc: Kevin Hilman, linux-omap, Cousson, Benoit, Chikkature Rajashekar,
	Madhusudhan, Paul Walmsley, Dasgupta, Romit, Shilimkar, Santosh,
	Aguirre, Sergio, Gopinath, Thara, Sripathy, Vishwanath, Premi,
	Sanjeev

Hello Nishanth and Kevin,

On Thu, Nov 26, 2009 at 01:22:49AM +0100, ext Nishanth Menon wrote:
> Kevin Hilman had written, on 11/25/2009 05:46 PM, the following:
> [...]
> >>> something like this instead:
> >>>
> >>> /**
> >>>  * opp_find_freq()
> >>>  * @oppl:        OPP list
> >>>  * @freq:        Frequency to look for in OPP table
> >>>  *
> >>>  * Look for an enabled OPP with a frequency value matching @freq.
> >>>  *
> >>>  * Returns pointer to OPP entry if match is found, or NULL if no match
> >>>  * found.
> >>>  */
> >>> struct omap_opp *opp_find_freq(const struct omap_opp *oppl, u32 freq);
> >> I did think about it(single function doing multiple things), the
> >> intention is as follows in reality:
> >> opp_is_valid : Search only for enabled frequencies
> >> opp_has_freq : Searches for enabled/disabled frequencies
> >>
> >> This is useful for some logic which wants to enable a frequency which
> >> may have been disabled in the table. now, to retain that
> >> functionality,
> >> A)
> >> /**
> >>  * opp_find_freq() - Find a opp corresponding to frequency
> >>  * @oppl:       opp list to search
> >>  * @freq:       frequency to loopup in OPP table
> >>  * @enabled:    search only enabled frequencies
> >>  *
> >>  * return opp handle corresponding to the frequency found, else
> >>  * return NULL. Search for enabled frequencies if enabled flag
> >>  * is true, else search for disabled frequencies also
> >>  */
> >> struct omap_opp *opp_find_freq(const struct omap_opp *oppl,
> >>                 unsigned long freq, bool enabled);
> >>
> >> This will handle the functionalities that are supported in rev 3.
> >>
> >> B) I rename existing functions:
> >> opp_has_freq ==> opp_is_disabled()
> >> opp_is_valid ==> opp_is_enabled()
> >>
> >> I would still prefer to go with explicit function search APIs..
> >
> > I like (A) here.
> Ack. I can see it useful if we go to a list iterator at a later point of time.
> [...]
> 
> >>> /**
> >>>  * opp_find_freq_rounded()
> >>>  * @oppl:        OPP list
> >>>  * @freq:        Frequency to look for in OPP table
> >>>  * @rounding:    Rounding option: NONE, UP, DOWN
> >>>  *
> >>>  * Look for an OPP with a frequency value matching @freq.  If
> >>>  * @rounding != ROUND_NONE, find closest match using rounding.
> >>>  *
> >>>  * Can be used to find exact OPP, or match using given rounding:
> >>>
> >>>  * @rounding == UP:      find next highest frequency
> >>>  * @rounding == DOWN:    find next lowest frequency
> >>>  * @rounding == CLOSEST: find closest frequency
> >>>  *
> >>>  * Returns pointer to OPP entry if match is found, or NULL if no match
> >>>  * found (only possible when no rounding is used)
> >>>  */
> >>> struct omap_opp *opp_find_freq_rounded(struct omap_opp *oppl, u32 freq, u32 rounding);
> >>>
> >>> Looking at the users of the 'higher' and 'lower' OPPs in the current
> >>> code, I see that SRF tries to use all three one after the other.
> >>> First it checks for exact match, then for higher, then for lower.
> >>> This could be replaced simply by doing a 'closest' match.
> >> hmmm.. I think we are going a full circle here.
> >>
> >> /* Search exact frequency */
> >> #define OPP_ROUND_NONE          (0 << 0)
> >> /* Search approx frequency */
> >> #define OPP_ROUND_CLOSEST       (1 << 0)
> >> /* Search up */
> >> #define OPP_ROUND_HIGH      (0 << 1)
> >> /* Search down */
> >> #define OPP_ROUND_LOW    (1 << 1)
> >>
> >> struct omap_opp *opp_find_freq_rounded(struct omap_opp *oppl,
> >>                 unsigned long freq, u8 rounding_flag);
> >>
> >> Note: the only difference b/w this and opp_find_freq is that
> >> opp_find_freq will also search for enabled/disabled.
> >> If I add that here, this is exactly the #1 implementation I did in
> >> http://marc.info/?l=linux-omap&m=125800489123496&w=2
> >> ok, I used bool instead of a #define and added the complexity of using
> >> enabled flag also:
> >>
> >> bool search_higher, bool search_enabled_only, bool exact_search
> >>
> >> what you are proposing is that I go back to my implementation #1 and
> >> remove my bools instead by adding #defines:
> >> /* Search up */
> >> #define OPP_ROUND_ENABLED (0 << 2)
> >> /* Search down */
> >> #define OPP_ROUND_ANY    (1 << 2)
> >>
> >> would even make the find_freq redundant..
> >>
> >> Now, in your comment in
> >> http://marc.info/?l=linux-omap&m=125816031406704&w=2 quote:"I think
> >> all the options to this function make it not terribly
> >> readable."
> >>
> >> Does it become any different now?
> >>
> >
> > Yeah, I still think multiple bools to a function is a readability
> > problem.  Every time you look at a call, you have to look at the
> > prototype to remember what all the options are.  A single bool or flag
> > is better IMHO.
> >
> >> without taking this in, exact searches can be done by specific
> >> functions and approximate searches by another function.. we go
> >> generic functions or we go specific functions.. generic comments I
> >> have been getting is to go specific, hence the v2 and v3 series.
> >
> > OK, you're right.  I am causing us to go around in circles now, but
> > we're going around in increasingly smaller circles and hopefully
> > converging on the target.  ;)
> Yep :)
> 
> >
> > So what I propose is having two functions.  One for exact matches
> > (your proposal A above) and one for approximate matches which is
> > something like my find_freq_rounded(), but should maybe be renamed
> > something like opp_find_freq_approx() or something.
> 
> OK - Signed-Off. prototypes again :)
> 
> Dead functions: opp_has_freq, opp_is_valid, opp_find_freq and other searches.
> 
> Only two of them remain: (git diff follows)
> opp_find_freq_approx
> 
> opp_find_freq_exact
> 
> 
> [..]
> >> int __init opp_add(struct omap_opp **oppl, const struct omap_opp_def
> >> *opp_defs);
> >
> > Mostly, but I was thinking of an API for adding a *single* OPP.  The
> > init code would iterate over its opp_def table adding OPPs one at a
> > time resultingin multiple calls to opp_add().
> >
> > OK, now I'm going around in circles again, but thinking more about his
> > we probably need your original opp_init() which will create an empty
> > master list, then repeated calls to opp_add() to add each OPP to the
> > master list.
> 
> Opp_init will be a subcase of opp_add. Giving opp_add capabiity to take
> More than one def is useful for us in the long run:
> a) You can add bunch of them without list iterator repeating in each and every adding code.
> b) You can still add a single one if you choose to.
> c) add to a NULL list == init the list. That does sound implicit to me, but if we want to create a singular function for it alone, then I recommend:
> 
> lets just have opp_init, then see if we need to add opp_add -> none of the systems are mature enough for us to use it..
> 
> I am open either way.
> 
> >
> > Also does add need to be __init?  Not sure why we would need to add
> > OPPs after boot time if we have the ability to enable/disable them at
> > runtime, but just a thought.
> Removed.. if in case we would like to do an opp_add at some point.
> 
> >
> [...]
> 
> 
> diff --git a/arch/arm/plat-omap/include/plat/opp.h b/arch/arm/plat-omap/include/plat/opp.h
> new file mode 100644
> index 0000000..4a00685
> --- /dev/null
> +++ b/arch/arm/plat-omap/include/plat/opp.h
> @@ -0,0 +1,184 @@
> +/*
> + * OMAP OPP Interface
> + *
> + * Copyright (C) 2009 Texas Instruments Incorporated.
> + *     Nishanth Menon
> + * Copyright (C) 2009 Deep Root Systems, LLC.
> + *     Kevin Hilman
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#ifndef __ASM_ARM_OMAP_OPP_H
> +#define __ASM_ARM_OMAP_OPP_H
> +
> +/**
> + * struct omap_opp - OMAP OPP description structure
> + * @enabled:   true/false - marking this OPP as enabled/disabled
> + * @rate:      Frequency in hertz
> + * @opp_id:    (DEPRECATED) opp identifier
> + * @vsel:      Voltage in volt processor level(this usage is
> + *             DEPRECATED to use Voltage in microvolts in future)
> + *             uV = ((vsel * 12.5) + 600) * 1000
> + *
> + * This structure stores the OPP information for a given domain.
> + * Due to legacy reasons, this structure is currently exposed and
> + * will soon be removed elsewhere and will only be used as a handle
> + * from the OPP internal referencing mechanism
> + */
> +struct omap_opp {
> +       bool enabled;
> +       unsigned long rate;
> +       u8 opp_id __deprecated;
> +       u16 vsel;
> +};
> +
> +/**
> + * opp_get_voltage() - Gets the voltage corresponding to an opp
> + * @opp:       opp for which voltage has to be returned for
> + *
> + * Return voltage in micro volt corresponding to the opp, else
> + * return 0
> + */
> +unsigned long opp_get_voltage(const struct omap_opp *opp);
> +
> +/**
> + * opp_get_freq() - Gets the frequency corresponding to an opp
> + * @opp:       opp for which frequency has to be returned for
> + *
> + * Return frequency in hertz corresponding to the opp, else
> + * return 0
> + */
> +unsigned long opp_get_freq(const struct omap_opp *opp);
> +
> +/**
> + * opp_get_opp_count - Get number of opps enabled in the opp list
> + * @num:       returns the number of opps
> + * @oppl:      opp list
> + *
> + * This functions returns the number of opps if there are any OPPs enabled,
> + * else returns corresponding error value.
> + */
> +int opp_get_opp_count(const struct omap_opp *oppl);
> +
> +#define OPP_SEARCH_HIGH                (0 << 1)
> +#define OPP_SEARCH_LOW         (1 << 1)
> +/**
> + * opp_find_freq_approx() - Search for an approximate freq
> + * @oppl:      starting list
> + * @freq:      start frequency
> + * @dir_flags: search direction
> + *             OPP_SEARCH_HIGH - search for next highest freq
> + *             OPP_SEARCH_LOW - search for next lowest freq
> + *
> + * Search for the higher/lower *enabled* OPP than a starting freq
> + * from a start opp list.
> +
> + * Returns *opp and *freq is populated with the next match,
> + * else returns NULL
> + *
> + * Example usages:
> + *     * print all frequencies in descending order *
> + *     unsigned long freq;
> + *     struct omap_opp *opp;
> + *     for(opp = oppl, freq = ULONG_MAX; opp;
> + *             opp = opp_find_freq_approx(opp, &freq, OPP_SEARCH_LOW))
> + *             pr_info("%ld ", freq);
> + *
> + *     * print all frequencies in ascending order *
> + *     unsigned long freq = 0;
> + *     struct omap_opp *opp;
> + *     for(opp = oppl, freq = 0; opp;
> + *             opp = opp_find_freq_approx(opp, &freq, OPP_SEARCH_HIGH))
> + *             pr_info("%ld ", freq);
> + * NOTE: if we set freq as ULONG_MAX, we get the highest enabled frequency
> + *
> + */
> +struct omap_opp *opp_find_freq_approx(struct omap_opp *oppl,
> +               unsigned long *freq, u8 dir_flags);
> +
> +/**
> + * opp_find_freq_exact() - search for an exact frequency
> + * @oppl:      OPP list
> + * @freq:      frequency to search for
> + * @enabled:   enabled/disabled OPP to search for
> + *
> + * searches for the match in the opp list and returns handle to the matching
> + * opp if found, else returns NULL.
> + *
> + * Note enabled is a modifier for the search. if enabled=true, then the match is
> + * for exact matching frequency and is enabled. if true, the match is for exact
> + * frequency which is disabled.
> + */
> +struct omap_opp *opp_find_freq_exact(struct omap_opp *oppl,
> +               unsigned long freq, bool enabled);
> +
> +
> +/**
> + * struct omap_opp_def - OMAP OPP Definition
> + * @enabled:   True/false - is this OPP enabled/disabled by default
> + * @freq:      Frequency in hertz corresponding to this OPP
> + * @u_volt:    Nominal voltage in microvolts corresponding to this OPP
> + *
> + * OMAP SOCs have a standard set of tuples consisting of frequency and voltage
> + * pairs that the device will support per voltage domain. This is called
> + * Operating Points or OPP. The actual definitions of OMAP Operating Points
> + * varies over silicon within the same family of devices. For a specific
> + * domain, you can have a set of {frequency, voltage} pairs and this is denoted
> + * by an array of omap_opp_def. As the kernel boots and more information is
> + * available, a set of these are activated based on the precise nature of
> + * device the kernel boots up on. It is interesting to remember that each IP
> + * which belongs to a voltage domain may define their own set of OPPs on top
> + * of this - but this is handled by the appropriate driver.
> + */
> +struct omap_opp_def {
> +       bool enabled;
> +       unsigned long freq;
> +       u32 u_volt;
> +};
> +
> +/**
> + * opp_add  - Add/initialize an OPP table from a table definitions
> + * @oppl:      Returned back to caller as the opp list to reference the OPP
> + * @opp_defs:  Array of omap_opp_def to describe the OPP. This list should be
> + *             0 terminated.
> + *
> + * This function adds the opp definition to an internal opp list and returns
> + * a handle representing the OPP list. This handle is then used for further
> + * validation, search, modification operations on the OPP list.
> + *
> + * This function returns 0 and the pointer to the allocated list through oppl if
> + * success, else corresponding error value. Caller should NOT free the oppl.
> + * opps_defs can be freed after use.
> + *
> + * NOTE: caller should assume that on success, oppl is probably populated with
> + * a new handle and the new handle should be used for further referencing
> + */
> +int opp_add(struct omap_opp **oppl, const struct omap_opp_def *opp_defs);


I'd prefer to see what has been proposed by Kevin previously. If I understood correctly,
you would to split this one into two functions:

opp_add - To add a single opp. At least that is what one would expect from its name.
opp_init - iterate over all opps definition that need to be added and call opp_add.
I'd name it 'opp_init_table' though, as opp_init sounds like initializing a single opp.


> +
> +/**
> + * opp_enable - Enable a specific OPP
> + * @opp:       pointer to opp
> + *
> + * Enables a provided opp. If the operation is valid, this returns 0, else the
> + * corresponding error value.
> + *
> + * OPP used here is from the the opp_is_valid/opp_has_freq or other search
> + * functions
> + */
> +int opp_enable(struct omap_opp *opp);
> +
> +/**
> + * opp_disable - Disable a specific OPP
> + * @opp:       pointer to opp
> + *
> + * Disables a provided opp. If the operation is valid, this returns 0, else the
> + * corresponding error value.
> + *
> + * OPP used here is from the the opp_is_valid/opp_has_freq or other search
> + * functions
> + */
> +int opp_disable(struct omap_opp *opp);
> +
> +#endif         /* __ASM_ARM_OMAP_OPP_H *
> 
> --
> Regards,
> Nishanth Menon
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Eduardo Valentin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 09/10 V3] omap3: pm: introduce 3630 opps
  2009-12-08  7:49                   ` [PATCH 09/10 V3] omap3: pm: introduce 3630 opps Eduardo Valentin
@ 2009-12-08 10:59                     ` Menon, Nishanth
  2009-12-08 11:18                       ` Eduardo Valentin
  0 siblings, 1 reply; 36+ messages in thread
From: Menon, Nishanth @ 2009-12-08 10:59 UTC (permalink / raw)
  To: eduardo.valentin
  Cc: linux-omap, Benoit Cousson, Kevin Hilman,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

Hi,
thanks for your comments. few thoughts below.

Eduardo Valentin said the following on 12/08/2009 01:49 AM:
> Hello Nishanth,
>
> Few comments bellow.
>
> On Wed, Nov 25, 2009 at 05:09:18AM +0100, ext Nishanth Menon wrote:
>   
>> Introduce the OMAP3630 OPPs including the defined OPP tuples.
>>
>> Further information on OMAP3630 can be found here:
>> http://focus.ti.com/general/docs/wtbu/wtbuproductcontent.tsp?templateId=6123&navigationId=12836&contentId=52606
>>
>> OMAP36xx family introduces:
>> VDD1 with 4 OPPs, of which OPP3 & 4 are available only on devices yet
>> to be introduced in 36xx family. Meanwhile, VDD2 has 2 opps.
>>
>> Device Support of OPPs->
>>            |<-3630-600->| (default)
>>            |<-      3630-800    ->| (device: TBD)
>>            |<-      3630-1000            ->| (device: TBD)
>> H/w OPP-> OPP50 OPP100       OPP-Turbo   OPP1G-SB
>> VDD1      OPP1  OPP2         OPP3        OPP4
>> VDD2      OPP1  OPP2         OPP2        OPP2
>>
>> Note:
>> a) TI h/w naming for OPPs are now standardized in terms of OPP50, 100,
>>    Turbo and SB. This maps as shown above to the opp IDs (s/w term).
>> b) For boards which need custom VDD1/2 OPPs, the opp table can be
>>    updated by the board file on a need basis after the
>>    omap3_pm_init_opp_table call. The OPPs introduced here are the
>>    official OPP table at this point in time.
>>
>> Cc: Benoit Cousson <b-cousson@ti.com>
>> Cc: Kevin Hilman <khilman@deeprootsystems.com>
>> Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
>> Cc: Paul Walmsley <paul@pwsan.com>
>> Cc: Romit Dasgupta <romit@ti.com>
>> Cc: Sanjeev Premi <premi@ti.com>
>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
>> Cc: Thara Gopinath <thara@ti.com>
>> Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
>>
>> Signed-off-by: Nishanth Menon <nm@ti.com>
>> ---
>>  arch/arm/mach-omap2/pm34xx.c |   49 ++++++++++++++++++++++++++++++++++++++++-
>>  1 files changed, 47 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
>> index ad21f5f..05ecf02 100644
>> --- a/arch/arm/mach-omap2/pm34xx.c
>> +++ b/arch/arm/mach-omap2/pm34xx.c
>> @@ -143,6 +143,41 @@ static struct omap_opp_def __initdata omap34xx_dsp_rate_table[] = {
>>  	{.enabled = 0, .freq = 0, .u_volt = 0}
>>  };
>>  
>> +static struct omap_opp_def __initdata omap36xx_mpu_rate_table[] = {
>> +	/*OPP1 - OPP50*/
>> +	{.enabled = true,  .freq = 300000000, .u_volt = 930000},
>> +	/*OPP2 - OPP100*/
>> +	{.enabled = true,  .freq = 600000000, .u_volt = 1100000},
>> +	/*OPP3 - OPP-Turbo*/
>> +	{.enabled = false, .freq = 800000000, .u_volt = 1260000},
>> +	/*OPP4 - OPP-SB*/
>> +	{.enabled = false, .freq = 1000000000, .u_volt = 1310000},
>> +	/* Terminator */
>> +	{.enabled = 0, .freq = 0, .u_volt = 0}
>> +};
>> +
>> +static struct omap_opp_def __initdata omap36xx_l3_rate_table[] = {
>> +	/*OPP1 - OPP50 */
>> +	{.enabled = true, .freq = 100000000, .u_volt = 930000},
>> +	/*OPP2 - OPP100, OPP-Turbo, OPP-SB*/
>> +	{.enabled = true, .freq = 200000000, .u_volt = 1137500},
>> +	/* Terminator */
>> +	{.enabled = 0, .freq = 0, .u_volt = 0}
>> +};
>> +
>> +static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
>> +	/*OPP1 - OPP50*/
>> +	{.enabled = true,  .freq = 260000000, .u_volt = 930000},
>> +	/*OPP2 - OPP100*/
>> +	{.enabled = true,  .freq = 520000000, .u_volt = 1100000},
>> +	/*OPP3 - OPP-Turbo*/
>> +	{.enabled = false, .freq = 660000000, .u_volt = 1260000},
>> +	/*OPP4 - OPP-SB*/
>> +	{.enabled = false, .freq = 875000000, .u_volt = 1310000},
>> +	/* Terminator */
>> +	{.enabled = 0, .freq = 0, .u_volt = 0}
>> +};
>> +
>>     
>
> Although it is not mandatory, I'd say this way of initializing structure array is more common:
>
> static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
> 	/*OPP1 - OPP50*/
> 	{
> 		.enabled	= true,
> 		.freq		= 260000000,
> 		.u_volt		= 930000,
> 	},
> 	/*OPP2 - OPP100*/
> 	{
> 		.enabled	= true,
> 		.freq		= 520000000,
> 		.u_volt		= 1100000,
> 	},
> 	/*OPP3 - OPP-Turbo*/
> 	{
> 		.enabled	= false,
> 		.freq		= 660000000,
> 		.u_volt		= 1260000,
> 	},
> 	/*OPP4 - OPP-SB*/
> 	{
> 		.enabled	= false,
> 		.freq		= 875000000,
> 		.u_volt		= 1310000,
> 	},
> 	/* Terminator */
> 	{
> 		.enabled	= 0,
> 		.freq		= 0,
> 		.u_volt		= 0,
> 	}
> };
>
> and if you thing it is line consuming, you can always define a "INIT" macro:
> #define	OMAP_OPP_DEF(_enabled, _freq, _uv)	\
> {						\
> 	.enabled	= _enabled,		\
> 	.freq		= _freq,		\
> 	.u_volt		= _uv,			\
> }
>
> and use it to initialize your array:
>
> 	/*OPP1 - OPP50*/
> static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
> 	OMAP_OPP_DEF(true, 260000000, 930000),
> 	OMAP_OPP_DEF(true, 520000000, 1100000),
> 	OMAP_OPP_DEF(false, 660000000, 1260000),
> 	OMAP_OPP_DEF(false, 875000000, 1310000},
> 	OMAP_OPP_DEF(0, 0, 0),
> };
>   
Thanks. yep, I agree this looks cleaner. I vote for this. probably will
use OMAP_OPP_TERM to denote (0,0,0)

>
> Beside, although it should not hurt as they are not too big, these tables should
> be compiled only if omap3630 is the target right?
>
>   
>>  struct omap_opp *omap3_mpu_rate_table;
>>  struct omap_opp *omap3_dsp_rate_table;
>>  struct omap_opp *omap3_l3_rate_table;
>> @@ -1299,18 +1334,28 @@ static void __init configure_vc(void)
>>  void __init omap3_pm_init_opp_table(void)
>>  {
>>  	int ret, i;
>> +	struct omap_opp_def **omap3_opp_def_list;
>>  	struct omap_opp_def *omap34xx_opp_def_list[] = {
>>  		omap34xx_mpu_rate_table,
>>  		omap34xx_l3_rate_table,
>>  		omap34xx_dsp_rate_table
>>  	};
>> +	struct omap_opp_def *omap36xx_opp_def_list[] = {
>> +		omap36xx_mpu_rate_table,
>> +		omap36xx_l3_rate_table,
>> +		omap36xx_dsp_rate_table
>> +	};
>>  	struct omap_opp **omap3_rate_tables[] = {
>>  		&omap3_mpu_rate_table,
>>  		&omap3_l3_rate_table,
>>  		&omap3_dsp_rate_table
>>  	};
>> -	for (i = 0; i < ARRAY_SIZE(omap34xx_opp_def_list); i++) {
>> -		ret = opp_init(omap3_rate_tables[i], omap34xx_opp_def_list[i]);
>> +
>> +	omap3_opp_def_list = cpu_is_omap3630() ? omap36xx_opp_def_list :
>> +				omap34xx_opp_def_list;
>>     
>
> here you cared for runtime target check, but tables above could be avoid if not omap3630.
>   
If your concern is memory size: the tables are __initdata, they will get
freed once kernel boot is complete. the only representation of omap_opp
will be what the opp layer's definition of the same.

The intention was to be able to have a single uImage booting across
multiple boards with multiple silicon -> e.g. today same uImage with
omap_pm_defconfig will equally boot on sdp3430 as it does on sdp3630..
which is what we all prefer.. so no ways of a compile time inclusion- it
has to be runtime determined..

>   
>> +
>> +	for (i = 0; i < ARRAY_SIZE(omap3_rate_tables); i++) {
>> +		ret = opp_init(omap3_rate_tables[i], omap3_opp_def_list[i]);
>>  		/* We dont want half configured system at the moment */
>>  		BUG_ON(ret);
>>  	}
>> -- 
>> 1.6.3.3
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>     
>
>   


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions
  2009-12-08  8:23             ` Eduardo Valentin
@ 2009-12-08 11:01               ` Menon, Nishanth
  0 siblings, 0 replies; 36+ messages in thread
From: Menon, Nishanth @ 2009-12-08 11:01 UTC (permalink / raw)
  To: eduardo.valentin
  Cc: Kevin Hilman, linux-omap, Cousson, Benoit, Chikkature Rajashekar,
	Madhusudhan, Paul Walmsley, Dasgupta, Romit, Shilimkar, Santosh,
	Aguirre, Sergio, Gopinath, Thara, Sripathy, Vishwanath, Premi,
	Sanjeev

Eduardo Valentin said the following on 12/08/2009 02:23 AM:
> Hello Nishanth and Kevin,
>
> On Thu, Nov 26, 2009 at 01:22:49AM +0100, ext Nishanth Menon wrote:
>   
>> Kevin Hilman had written, on 11/25/2009 05:46 PM, the following:
>> [...]
>>     
>>>>> something like this instead:
>>>>>
>>>>> /**
>>>>>  * opp_find_freq()
>>>>>  * @oppl:        OPP list
>>>>>  * @freq:        Frequency to look for in OPP table
>>>>>  *
>>>>>  * Look for an enabled OPP with a frequency value matching @freq.
>>>>>  *
>>>>>  * Returns pointer to OPP entry if match is found, or NULL if no match
>>>>>  * found.
>>>>>  */
>>>>> struct omap_opp *opp_find_freq(const struct omap_opp *oppl, u32 freq);
>>>>>           
>>>> I did think about it(single function doing multiple things), the
>>>> intention is as follows in reality:
>>>> opp_is_valid : Search only for enabled frequencies
>>>> opp_has_freq : Searches for enabled/disabled frequencies
>>>>
>>>> This is useful for some logic which wants to enable a frequency which
>>>> may have been disabled in the table. now, to retain that
>>>> functionality,
>>>> A)
>>>> /**
>>>>  * opp_find_freq() - Find a opp corresponding to frequency
>>>>  * @oppl:       opp list to search
>>>>  * @freq:       frequency to loopup in OPP table
>>>>  * @enabled:    search only enabled frequencies
>>>>  *
>>>>  * return opp handle corresponding to the frequency found, else
>>>>  * return NULL. Search for enabled frequencies if enabled flag
>>>>  * is true, else search for disabled frequencies also
>>>>  */
>>>> struct omap_opp *opp_find_freq(const struct omap_opp *oppl,
>>>>                 unsigned long freq, bool enabled);
>>>>
>>>> This will handle the functionalities that are supported in rev 3.
>>>>
>>>> B) I rename existing functions:
>>>> opp_has_freq ==> opp_is_disabled()
>>>> opp_is_valid ==> opp_is_enabled()
>>>>
>>>> I would still prefer to go with explicit function search APIs..
>>>>         
>>> I like (A) here.
>>>       
>> Ack. I can see it useful if we go to a list iterator at a later point of time.
>> [...]
>>
>>     
>>>>> /**
>>>>>  * opp_find_freq_rounded()
>>>>>  * @oppl:        OPP list
>>>>>  * @freq:        Frequency to look for in OPP table
>>>>>  * @rounding:    Rounding option: NONE, UP, DOWN
>>>>>  *
>>>>>  * Look for an OPP with a frequency value matching @freq.  If
>>>>>  * @rounding != ROUND_NONE, find closest match using rounding.
>>>>>  *
>>>>>  * Can be used to find exact OPP, or match using given rounding:
>>>>>
>>>>>  * @rounding == UP:      find next highest frequency
>>>>>  * @rounding == DOWN:    find next lowest frequency
>>>>>  * @rounding == CLOSEST: find closest frequency
>>>>>  *
>>>>>  * Returns pointer to OPP entry if match is found, or NULL if no match
>>>>>  * found (only possible when no rounding is used)
>>>>>  */
>>>>> struct omap_opp *opp_find_freq_rounded(struct omap_opp *oppl, u32 freq, u32 rounding);
>>>>>
>>>>> Looking at the users of the 'higher' and 'lower' OPPs in the current
>>>>> code, I see that SRF tries to use all three one after the other.
>>>>> First it checks for exact match, then for higher, then for lower.
>>>>> This could be replaced simply by doing a 'closest' match.
>>>>>           
>>>> hmmm.. I think we are going a full circle here.
>>>>
>>>> /* Search exact frequency */
>>>> #define OPP_ROUND_NONE          (0 << 0)
>>>> /* Search approx frequency */
>>>> #define OPP_ROUND_CLOSEST       (1 << 0)
>>>> /* Search up */
>>>> #define OPP_ROUND_HIGH      (0 << 1)
>>>> /* Search down */
>>>> #define OPP_ROUND_LOW    (1 << 1)
>>>>
>>>> struct omap_opp *opp_find_freq_rounded(struct omap_opp *oppl,
>>>>                 unsigned long freq, u8 rounding_flag);
>>>>
>>>> Note: the only difference b/w this and opp_find_freq is that
>>>> opp_find_freq will also search for enabled/disabled.
>>>> If I add that here, this is exactly the #1 implementation I did in
>>>> http://marc.info/?l=linux-omap&m=125800489123496&w=2
>>>> ok, I used bool instead of a #define and added the complexity of using
>>>> enabled flag also:
>>>>
>>>> bool search_higher, bool search_enabled_only, bool exact_search
>>>>
>>>> what you are proposing is that I go back to my implementation #1 and
>>>> remove my bools instead by adding #defines:
>>>> /* Search up */
>>>> #define OPP_ROUND_ENABLED (0 << 2)
>>>> /* Search down */
>>>> #define OPP_ROUND_ANY    (1 << 2)
>>>>
>>>> would even make the find_freq redundant..
>>>>
>>>> Now, in your comment in
>>>> http://marc.info/?l=linux-omap&m=125816031406704&w=2 quote:"I think
>>>> all the options to this function make it not terribly
>>>> readable."
>>>>
>>>> Does it become any different now?
>>>>
>>>>         
>>> Yeah, I still think multiple bools to a function is a readability
>>> problem.  Every time you look at a call, you have to look at the
>>> prototype to remember what all the options are.  A single bool or flag
>>> is better IMHO.
>>>
>>>       
>>>> without taking this in, exact searches can be done by specific
>>>> functions and approximate searches by another function.. we go
>>>> generic functions or we go specific functions.. generic comments I
>>>> have been getting is to go specific, hence the v2 and v3 series.
>>>>         
>>> OK, you're right.  I am causing us to go around in circles now, but
>>> we're going around in increasingly smaller circles and hopefully
>>> converging on the target.  ;)
>>>       
>> Yep :)
>>
>>     
>>> So what I propose is having two functions.  One for exact matches
>>> (your proposal A above) and one for approximate matches which is
>>> something like my find_freq_rounded(), but should maybe be renamed
>>> something like opp_find_freq_approx() or something.
>>>       
>> OK - Signed-Off. prototypes again :)
>>
>> Dead functions: opp_has_freq, opp_is_valid, opp_find_freq and other searches.
>>
>> Only two of them remain: (git diff follows)
>> opp_find_freq_approx
>>
>> opp_find_freq_exact
>>
>>
>> [..]
>>     
>>>> int __init opp_add(struct omap_opp **oppl, const struct omap_opp_def
>>>> *opp_defs);
>>>>         
>>> Mostly, but I was thinking of an API for adding a *single* OPP.  The
>>> init code would iterate over its opp_def table adding OPPs one at a
>>> time resultingin multiple calls to opp_add().
>>>
>>> OK, now I'm going around in circles again, but thinking more about his
>>> we probably need your original opp_init() which will create an empty
>>> master list, then repeated calls to opp_add() to add each OPP to the
>>> master list.
>>>       
>> Opp_init will be a subcase of opp_add. Giving opp_add capabiity to take
>> More than one def is useful for us in the long run:
>> a) You can add bunch of them without list iterator repeating in each and every adding code.
>> b) You can still add a single one if you choose to.
>> c) add to a NULL list == init the list. That does sound implicit to me, but if we want to create a singular function for it alone, then I recommend:
>>
>> lets just have opp_init, then see if we need to add opp_add -> none of the systems are mature enough for us to use it..
>>
>> I am open either way.
>>
>>     
>>> Also does add need to be __init?  Not sure why we would need to add
>>> OPPs after boot time if we have the ability to enable/disable them at
>>> runtime, but just a thought.
>>>       
>> Removed.. if in case we would like to do an opp_add at some point.
>>
>>     
>> [...]
>>
>>
>> diff --git a/arch/arm/plat-omap/include/plat/opp.h b/arch/arm/plat-omap/include/plat/opp.h
>> new file mode 100644
>> index 0000000..4a00685
>> --- /dev/null
>> +++ b/arch/arm/plat-omap/include/plat/opp.h
>> @@ -0,0 +1,184 @@
>> +/*
>> + * OMAP OPP Interface
>> + *
>> + * Copyright (C) 2009 Texas Instruments Incorporated.
>> + *     Nishanth Menon
>> + * Copyright (C) 2009 Deep Root Systems, LLC.
>> + *     Kevin Hilman
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +#ifndef __ASM_ARM_OMAP_OPP_H
>> +#define __ASM_ARM_OMAP_OPP_H
>> +
>> +/**
>> + * struct omap_opp - OMAP OPP description structure
>> + * @enabled:   true/false - marking this OPP as enabled/disabled
>> + * @rate:      Frequency in hertz
>> + * @opp_id:    (DEPRECATED) opp identifier
>> + * @vsel:      Voltage in volt processor level(this usage is
>> + *             DEPRECATED to use Voltage in microvolts in future)
>> + *             uV = ((vsel * 12.5) + 600) * 1000
>> + *
>> + * This structure stores the OPP information for a given domain.
>> + * Due to legacy reasons, this structure is currently exposed and
>> + * will soon be removed elsewhere and will only be used as a handle
>> + * from the OPP internal referencing mechanism
>> + */
>> +struct omap_opp {
>> +       bool enabled;
>> +       unsigned long rate;
>> +       u8 opp_id __deprecated;
>> +       u16 vsel;
>> +};
>> +
>> +/**
>> + * opp_get_voltage() - Gets the voltage corresponding to an opp
>> + * @opp:       opp for which voltage has to be returned for
>> + *
>> + * Return voltage in micro volt corresponding to the opp, else
>> + * return 0
>> + */
>> +unsigned long opp_get_voltage(const struct omap_opp *opp);
>> +
>> +/**
>> + * opp_get_freq() - Gets the frequency corresponding to an opp
>> + * @opp:       opp for which frequency has to be returned for
>> + *
>> + * Return frequency in hertz corresponding to the opp, else
>> + * return 0
>> + */
>> +unsigned long opp_get_freq(const struct omap_opp *opp);
>> +
>> +/**
>> + * opp_get_opp_count - Get number of opps enabled in the opp list
>> + * @num:       returns the number of opps
>> + * @oppl:      opp list
>> + *
>> + * This functions returns the number of opps if there are any OPPs enabled,
>> + * else returns corresponding error value.
>> + */
>> +int opp_get_opp_count(const struct omap_opp *oppl);
>> +
>> +#define OPP_SEARCH_HIGH                (0 << 1)
>> +#define OPP_SEARCH_LOW         (1 << 1)
>> +/**
>> + * opp_find_freq_approx() - Search for an approximate freq
>> + * @oppl:      starting list
>> + * @freq:      start frequency
>> + * @dir_flags: search direction
>> + *             OPP_SEARCH_HIGH - search for next highest freq
>> + *             OPP_SEARCH_LOW - search for next lowest freq
>> + *
>> + * Search for the higher/lower *enabled* OPP than a starting freq
>> + * from a start opp list.
>> +
>> + * Returns *opp and *freq is populated with the next match,
>> + * else returns NULL
>> + *
>> + * Example usages:
>> + *     * print all frequencies in descending order *
>> + *     unsigned long freq;
>> + *     struct omap_opp *opp;
>> + *     for(opp = oppl, freq = ULONG_MAX; opp;
>> + *             opp = opp_find_freq_approx(opp, &freq, OPP_SEARCH_LOW))
>> + *             pr_info("%ld ", freq);
>> + *
>> + *     * print all frequencies in ascending order *
>> + *     unsigned long freq = 0;
>> + *     struct omap_opp *opp;
>> + *     for(opp = oppl, freq = 0; opp;
>> + *             opp = opp_find_freq_approx(opp, &freq, OPP_SEARCH_HIGH))
>> + *             pr_info("%ld ", freq);
>> + * NOTE: if we set freq as ULONG_MAX, we get the highest enabled frequency
>> + *
>> + */
>> +struct omap_opp *opp_find_freq_approx(struct omap_opp *oppl,
>> +               unsigned long *freq, u8 dir_flags);
>> +
>> +/**
>> + * opp_find_freq_exact() - search for an exact frequency
>> + * @oppl:      OPP list
>> + * @freq:      frequency to search for
>> + * @enabled:   enabled/disabled OPP to search for
>> + *
>> + * searches for the match in the opp list and returns handle to the matching
>> + * opp if found, else returns NULL.
>> + *
>> + * Note enabled is a modifier for the search. if enabled=true, then the match is
>> + * for exact matching frequency and is enabled. if true, the match is for exact
>> + * frequency which is disabled.
>> + */
>> +struct omap_opp *opp_find_freq_exact(struct omap_opp *oppl,
>> +               unsigned long freq, bool enabled);
>> +
>> +
>> +/**
>> + * struct omap_opp_def - OMAP OPP Definition
>> + * @enabled:   True/false - is this OPP enabled/disabled by default
>> + * @freq:      Frequency in hertz corresponding to this OPP
>> + * @u_volt:    Nominal voltage in microvolts corresponding to this OPP
>> + *
>> + * OMAP SOCs have a standard set of tuples consisting of frequency and voltage
>> + * pairs that the device will support per voltage domain. This is called
>> + * Operating Points or OPP. The actual definitions of OMAP Operating Points
>> + * varies over silicon within the same family of devices. For a specific
>> + * domain, you can have a set of {frequency, voltage} pairs and this is denoted
>> + * by an array of omap_opp_def. As the kernel boots and more information is
>> + * available, a set of these are activated based on the precise nature of
>> + * device the kernel boots up on. It is interesting to remember that each IP
>> + * which belongs to a voltage domain may define their own set of OPPs on top
>> + * of this - but this is handled by the appropriate driver.
>> + */
>> +struct omap_opp_def {
>> +       bool enabled;
>> +       unsigned long freq;
>> +       u32 u_volt;
>> +};
>> +
>> +/**
>> + * opp_add  - Add/initialize an OPP table from a table definitions
>> + * @oppl:      Returned back to caller as the opp list to reference the OPP
>> + * @opp_defs:  Array of omap_opp_def to describe the OPP. This list should be
>> + *             0 terminated.
>> + *
>> + * This function adds the opp definition to an internal opp list and returns
>> + * a handle representing the OPP list. This handle is then used for further
>> + * validation, search, modification operations on the OPP list.
>> + *
>> + * This function returns 0 and the pointer to the allocated list through oppl if
>> + * success, else corresponding error value. Caller should NOT free the oppl.
>> + * opps_defs can be freed after use.
>> + *
>> + * NOTE: caller should assume that on success, oppl is probably populated with
>> + * a new handle and the new handle should be used for further referencing
>> + */
>> +int opp_add(struct omap_opp **oppl, const struct omap_opp_def *opp_defs);
>>     
>
>
> I'd prefer to see what has been proposed by Kevin previously. If I understood correctly,
> you would to split this one into two functions:
>
> opp_add - To add a single opp. At least that is what one would expect from its name.
> opp_init - iterate over all opps definition that need to be added and call opp_add.
> I'd name it 'opp_init_table' though, as opp_init sounds like initializing a single opp.
>
>
>   
okay.

let me try and send out a updated proposal later today..
>> +
>> +/**
>> + * opp_enable - Enable a specific OPP
>> + * @opp:       pointer to opp
>> + *
>> + * Enables a provided opp. If the operation is valid, this returns 0, else the
>> + * corresponding error value.
>> + *
>> + * OPP used here is from the the opp_is_valid/opp_has_freq or other search
>> + * functions
>> + */
>> +int opp_enable(struct omap_opp *opp);
>> +
>> +/**
>> + * opp_disable - Disable a specific OPP
>> + * @opp:       pointer to opp
>> + *
>> + * Disables a provided opp. If the operation is valid, this returns 0, else the
>> + * corresponding error value.
>> + *
>> + * OPP used here is from the the opp_is_valid/opp_has_freq or other search
>> + * functions
>> + */
>> +int opp_disable(struct omap_opp *opp);
>> +
>> +#endif         /* __ASM_ARM_OMAP_OPP_H *
>>
>> --
>> Regards,
>> Nishanth Menon
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>     
>
>   


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table
  2009-12-07 16:54               ` [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table Tero.Kristo
@ 2009-12-08 11:09                 ` Menon, Nishanth
  0 siblings, 0 replies; 36+ messages in thread
From: Menon, Nishanth @ 2009-12-08 11:09 UTC (permalink / raw)
  To: Tero.Kristo
  Cc: linux-omap, b-cousson, khilman, madhu.cr, paul, romit, premi,
	santosh.shilimkar, saaguirre, thara, vishwanath.bs

Tero.Kristo@nokia.com said the following on 12/07/2009 10:54 AM:
> Hi,
>
> One comment below.
>
>   
>> -----Original Message-----
>> From: linux-omap-owner@vger.kernel.org 
>> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of ext 
>> Nishanth Menon
>> Sent: 25 November, 2009 06:09
>> To: linux-omap
>> Cc: Nishanth Menon; Benoit Cousson; Kevin Hilman; Madhusudhan 
>> Chikkature Rajashekar; Paul Walmsley; Romit Dasgupta; Sanjeev 
>> Premi; Santosh Shilimkar; Sergio Alberto Aguirre Rodriguez; 
>> Thara Gopinath; Vishwanath Sripathy
>> Subject: [PATCH 07/10 V3] omap3: clk: use pm accessor 
>> functions for cpufreq table
>>
>> omap2_clk_init_cpufreq_table currently directly accesses the opp
>> table, making it unscalable to various OMAPs. Instead use the
>> accessor functions to populate the cpufreq table
>>
>> Cc: Benoit Cousson <b-cousson@ti.com>
>> Cc: Kevin Hilman <khilman@deeprootsystems.com>
>> Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
>> Cc: Paul Walmsley <paul@pwsan.com>
>> Cc: Romit Dasgupta <romit@ti.com>
>> Cc: Sanjeev Premi <premi@ti.com>
>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
>> Cc: Thara Gopinath <thara@ti.com>
>> Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
>>
>> Signed-off-by: Nishanth Menon <nm@ti.com>
>> ---
>> arch/arm/mach-omap2/clock34xx.c |   32 
>> +++++++++++++++++++-------------
>> 1 files changed, 19 insertions(+), 13 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/clock34xx.c 
>> b/arch/arm/mach-omap2/clock34xx.c
>> index 5150939..d07f1c1 100644
>> --- a/arch/arm/mach-omap2/clock34xx.c
>> +++ b/arch/arm/mach-omap2/clock34xx.c
>> @@ -1042,30 +1042,36 @@ static unsigned long 
>> omap3_clkoutx2_recalc(struct clk *clk)
>> #if defined(CONFIG_ARCH_OMAP3)
>>
>> #ifdef CONFIG_CPU_FREQ
>> -static struct cpufreq_frequency_table freq_table[MAX_VDD1_OPP+1];
>> +
>> +static struct cpufreq_frequency_table *freq_table;
>>
>> void omap2_clk_init_cpufreq_table(struct 
>> cpufreq_frequency_table **table)
>> {
>> -	struct omap_opp *prcm;
>> 	int i = 0;
>> +	u8 opp_num;
>> +	struct omap_opp *opp = NULL;
>> +	unsigned long freq = ULONG_MAX;
>>
>> -	if (!mpu_opps)
>> +	if (!mpu_opps || opp_get_opp_count(&opp_num, mpu_opps)) {
>> +		pr_warning("%s: failed to initialize frequency"
>> +				"table\n", __func__);
>> 		return;
>> -
>> -	prcm = mpu_opps + MAX_VDD1_OPP;
>> -	for (; prcm->rate; prcm--) {
>> -		freq_table[i].index = i;
>> -		freq_table[i].frequency = prcm->rate / 1000;
>> -		i++;
>> 	}
>>
>> -	if (i == 0) {
>> -		printk(KERN_WARNING "%s: failed to initialize 
>> frequency \
>> -								
>> table\n",
>> -								
>> __func__);
>> +	freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
>> +			(opp_num + 1), GFP_KERNEL);
>>     
>
> I guess this should be GFP_ATOMIC, we have clockfw spinlock reserved when this is called (gave me a runtime warning.)
>   
Thanks.. I must have missed the warning.. :( will check and add..

>   
>> +	if (!freq_table) {
>> +		pr_warning("%s: failed to allocate frequency"
>> +				"table\n", __func__);
>> 		return;
>> 	}
>>
>> +	while (!opp_get_lower_opp(&opp, &freq, mpu_opps)) {
>> +		freq_table[i].index = i;
>> +		freq_table[i].frequency =  freq / 1000;
>> +		i++;
>> +	}
>> +
>> 	freq_table[i].index = i;
>> 	freq_table[i].frequency = CPUFREQ_TABLE_END;
>>
>> -- 
>> 1.6.3.3
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe 
>> linux-omap" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> --
>>     
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>   


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions
  2009-12-07 16:59         ` [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions Tero.Kristo
@ 2009-12-08 11:14           ` Menon, Nishanth
  0 siblings, 0 replies; 36+ messages in thread
From: Menon, Nishanth @ 2009-12-08 11:14 UTC (permalink / raw)
  To: Tero.Kristo
  Cc: linux-omap, b-cousson, khilman, madhu.cr, paul, romit, premi,
	santosh.shilimkar, saaguirre, thara, vishwanath.bs

Tero.Kristo@nokia.com said the following on 12/07/2009 10:59 AM:
> Hi,
>
> Couple of comments below.
>
>   
>> -----Original Message-----
>> From: linux-omap-owner@vger.kernel.org
>> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of ext
>> Nishanth Menon
>> Sent: 25 November, 2009 06:09
>> To: linux-omap
>> Cc: Nishanth Menon; Benoit Cousson; Kevin Hilman; Madhusudhan
>> Chikkature Rajashekar; Paul Walmsley; Romit Dasgupta; Sanjeev
>> Premi; Santosh Shilimkar; Sergio Alberto Aguirre Rodriguez;
>> Thara Gopinath; Vishwanath Sripathy
>> Subject: [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions
>>
>> With the accessor functions, many of the direct accesses are
>> redundant. However we do not want to rewrite SRF at this point of time
>> We do the following here:
>> Remove get_opp and introduce three SRF specific accessor functions:
>>       opp_to_freq, freq_to_opp - need this coz of usage of opp IDs
>>       NOTE: These functions should be removed at a later point
>>       of time.
>> get_opp is removed because, with the above functions, it is
>> redundant.
>>
>> NOTE: this implementation is just a start and leaves scope for
>> further cleanups which can be added on top.
>>
>> NOTE: this increases the number of warnings to:
>>
>> arch/arm/mach-omap2/resource34xx.c: In function 'opp_to_freq':
>> arch/arm/mach-omap2/resource34xx.c:182: warning: 'opp_id' is
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>> arch/arm/mach-omap2/resource34xx.c: In function 'freq_to_opp':
>> arch/arm/mach-omap2/resource34xx.c:213: warning: 'opp_id' is
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>> arch/arm/mach-omap2/resource34xx.c: In function 'init_opp':
>> arch/arm/mach-omap2/resource34xx.c:242: warning: 'freq_to_opp'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>> arch/arm/mach-omap2/resource34xx.c:249: warning: 'freq_to_opp'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>> arch/arm/mach-omap2/resource34xx.c: In function 'program_opp_freq':
>> arch/arm/mach-omap2/resource34xx.c:302: warning: 'opp_to_freq'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>> arch/arm/mach-omap2/resource34xx.c:303: warning: 'opp_to_freq'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>> arch/arm/mach-omap2/resource34xx.c:308: warning: 'opp_to_freq'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>> arch/arm/mach-omap2/resource34xx.c: In function 'program_opp':
>> arch/arm/mach-omap2/resource34xx.c:351: warning: 'opp_id' is
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>> arch/arm/mach-omap2/resource34xx.c:352: warning: 'opp_id' is
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>> arch/arm/mach-omap2/resource34xx.c:356: warning: 'opp_to_freq'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>> arch/arm/mach-omap2/resource34xx.c:380: warning: 'opp_to_freq'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>> arch/arm/mach-omap2/resource34xx.c: In function
>> 'resource_set_opp_level':
>> arch/arm/mach-omap2/resource34xx.c:417: warning: 'opp_to_freq'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>> arch/arm/mach-omap2/resource34xx.c:418: warning: 'opp_to_freq'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>> arch/arm/mach-omap2/resource34xx.c:420: warning: 'opp_to_freq'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>> arch/arm/mach-omap2/resource34xx.c: In function 'set_opp':
>> arch/arm/mach-omap2/resource34xx.c:497: warning: 'freq_to_opp'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>> arch/arm/mach-omap2/resource34xx.c: In function 'validate_opp':
>> arch/arm/mach-omap2/resource34xx.c:516: warning: 'opp_to_freq'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>> arch/arm/mach-omap2/resource34xx.c:518: warning: 'opp_to_freq'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>> arch/arm/mach-omap2/resource34xx.c: In function 'init_freq':
>> arch/arm/mach-omap2/resource34xx.c:541: warning: 'opp_to_freq'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>> arch/arm/mach-omap2/resource34xx.c:544: warning: 'opp_to_freq'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:175)
>> arch/arm/mach-omap2/resource34xx.c: In function 'set_freq':
>> arch/arm/mach-omap2/resource34xx.c:560: warning: 'freq_to_opp'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>> arch/arm/mach-omap2/resource34xx.c:565: warning: 'freq_to_opp'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>> arch/arm/mach-omap2/resource34xx.c: In function 'validate_freq':
>> arch/arm/mach-omap2/resource34xx.c:579: warning: 'freq_to_opp'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>> arch/arm/mach-omap2/resource34xx.c:581: warning: 'freq_to_opp'
>> is deprecated (declared at arch/arm/mach-omap2/resource34xx.c:205)
>>
>> Cc: Benoit Cousson <b-cousson@ti.com>
>> Cc: Kevin Hilman <khilman@deeprootsystems.com>
>> Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
>> Cc: Paul Walmsley <paul@pwsan.com>
>> Cc: Romit Dasgupta <romit@ti.com>
>> Cc: Sanjeev Premi <premi@ti.com>
>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
>> Cc: Thara Gopinath <thara@ti.com>
>> Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
>>
>> Signed-off-by: Nishanth Menon <nm@ti.com>
>> ---
>> arch/arm/mach-omap2/resource34xx.c |  244
>> ++++++++++++++++++++++++++----------
>> 1 files changed, 180 insertions(+), 64 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/resource34xx.c
>> b/arch/arm/mach-omap2/resource34xx.c
>> index af6b3c1..349f54e 100644
>> --- a/arch/arm/mach-omap2/resource34xx.c
>> +++ b/arch/arm/mach-omap2/resource34xx.c
>> @@ -155,21 +155,68 @@ static int curr_vdd1_opp;
>> static int curr_vdd2_opp;
>> static DEFINE_MUTEX(dvfs_mutex);
>>
>> -static unsigned short get_opp(struct omap_opp *opp_freq_table,
>> +/* Introducing deprecated function because we got to.. */
>> +#define IS_OPP_TERMINATOR(opps, i) (!(opps)[(i)].enabled &&\
>> +              ((opps)[(i)].rate == 0) && ((opps)[(i)].vsel == 0))
>> +
>> +/**
>> + * opp_to_freq - convert OPPID to frequency (DEPRECATED)
>> + * @freq: return frequency back to caller
>> + * @opps: opp list
>> + * @opp_id: OPP ID we are searching for
>> + *
>> + * return 0 and freq is populated if we find the opp_id, else,
>> + * we return error
>> + *
>> + * NOTE: this function is a standin for the timebeing as
>> opp_id is deprecated
>> + */
>> +static int __deprecated opp_to_freq(unsigned long *freq,
>> +              const struct omap_opp *opps, u8 opp_id)
>> +{
>> +      int i = 1;
>> +
>> +      BUG_ON(!freq || !opps);
>> +
>> +      /* The first entry is a dummy one, loop till we hit
>> terminator */
>> +      while (!IS_OPP_TERMINATOR(opps, i)) {
>> +              if (opps[i].enabled && (opps[i].opp_id == opp_id)) {
>> +                      *freq = opps[i].rate;
>> +                      return 0;
>> +              }
>> +              i++;
>> +      }
>> +
>> +      return -EINVAL;
>> +}
>> +
>> +/**
>> + * freq_to_opp - convert a frequency back to OPP ID (DEPRECATED)
>> + * @opp_id: opp ID returned back to caller
>> + * @opps: opp list
>> + * @freq: frequency we are searching for
>> + *
>> + * return 0 and opp_id is populated if we find the freq, else,
>> + * we return error
>> + *
>> + * NOTE: this function is a standin for the timebeing as
>> opp_id is deprecated
>> + */
>> +static int __deprecated freq_to_opp(u8 *opp_id, const struct
>> omap_opp *opps,
>>               unsigned long freq)
>> {
>> -      struct omap_opp *prcm_config;
>> -      prcm_config = opp_freq_table;
>> -
>> -      if (prcm_config->rate <= freq)
>> -              return prcm_config->opp_id; /* Return the Highest OPP */
>> -      for (; prcm_config->rate; prcm_config--)
>> -              if (prcm_config->rate < freq)
>> -                      return (prcm_config+1)->opp_id;
>> -              else if (prcm_config->rate == freq)
>> -                      return prcm_config->opp_id;
>> -      /* Return the least OPP */
>> -      return (prcm_config+1)->opp_id;
>> +      int i = 1;
>> +
>> +      BUG_ON(!opp_id || !opps);
>> +
>> +      /* The first entry is a dummy one, loop till we hit
>> terminator */
>> +      while (!IS_OPP_TERMINATOR(opps, i)) {
>> +              if (opps[i].enabled && (opps[i].rate == freq)) {
>>     
>
> Here we should check for opps[i].rate >= freq, otherwise resource_refresh() calls will fail with no active users for resources like dsp_freq. This can be tested with:
>
> echo 5 > /sys/power/vdd1_lock
> echo 0 > /sys/power/vdd1_lock
>   

Hmm.. thanks for catching this. (note to self: add 0 and 6 as OPPs in my
test script ;) ).


>   
>> +                      *opp_id = opps[i].opp_id;
>> +                      return 0;
>> +              }
>> +              i++;
>> +      }
>> +
>> +      return -EINVAL;
>> }
>>
>> /**
>> @@ -178,6 +225,8 @@ static unsigned short get_opp(struct
>> omap_opp *opp_freq_table,
>> void init_opp(struct shared_resource *resp)
>> {
>>       struct clk *l3_clk;
>> +      int ret;
>> +      u8 opp_id;
>>       resp->no_of_users = 0;
>>
>>       if (!mpu_opps || !dsp_opps || !l3_opps)
>> @@ -190,17 +239,18 @@ void init_opp(struct shared_resource *resp)
>>               vdd1_resp = resp;
>>               dpll1_clk = clk_get(NULL, "dpll1_ck");
>>               dpll2_clk = clk_get(NULL, "dpll2_ck");
>> -              resp->curr_level = get_opp(mpu_opps + MAX_VDD1_OPP,
>> -                              dpll1_clk->rate);
>> -              curr_vdd1_opp = resp->curr_level;
>> +              ret = freq_to_opp(&opp_id, mpu_opps, dpll1_clk->rate);
>> +              BUG_ON(ret); /* TBD Cleanup handling */
>> +              curr_vdd1_opp = opp_id;
>>       } else if (strcmp(resp->name, "vdd2_opp") == 0) {
>>               vdd2_resp = resp;
>>               dpll3_clk = clk_get(NULL, "dpll3_m2_ck");
>>               l3_clk = clk_get(NULL, "l3_ick");
>> -              resp->curr_level = get_opp(l3_opps + MAX_VDD2_OPP,
>> -                              l3_clk->rate);
>> -              curr_vdd2_opp = resp->curr_level;
>> +              ret = freq_to_opp(&opp_id, l3_opps, l3_clk->rate);
>> +              BUG_ON(ret); /* TBD Cleanup handling */
>> +              curr_vdd2_opp = opp_id;
>>       }
>> +      resp->curr_level = opp_id;
>>       return;
>> }
>>
>> @@ -242,24 +292,40 @@ static int program_opp_freq(int res, int
>> target_level, int current_level)
>> {
>>       int ret = 0, l3_div;
>>       int *curr_opp;
>> +      unsigned long mpu_freq, dsp_freq, l3_freq;
>> +#ifndef CONFIG_CPU_FREQ
>> +      unsigned long mpu_cur_freq
>>     
>
> Missing semicolon.
>
>   
Arrrgghh.. note to self: SHOULD build and check without CPUFREQ and PM
next time.. a.k.a dont send patches at midnight ;)..
thanks for catching it..
>> +#endif
>> +
>> +      /* Check if I can actually switch or not */
>> +      if (res == VDD1_OPP) {
>> +              ret = opp_to_freq(&mpu_freq, mpu_opps, target_level);
>> +              ret |= opp_to_freq(&dsp_freq, dsp_opps, target_level);
>> +#ifndef CONFIG_CPU_FREQ
>> +              ret |= opp_to_freq(&mpu_cur_freq, mpu_opps,
>> current_level);
>> +#endif
>> +      } else {
>> +              ret = opp_to_freq(&l3_freq, l3_opps, target_level);
>> +      }
>> +      /* we would have caught all bad levels earlier.. */
>> +      if (unlikely(ret))
>> +              return ret;
>>
>>       lock_scratchpad_sem();
>>       if (res == VDD1_OPP) {
>>               curr_opp = &curr_vdd1_opp;
>> -              clk_set_rate(dpll1_clk, mpu_opps[target_level].rate);
>> -              clk_set_rate(dpll2_clk, dsp_opps[target_level].rate);
>> +              clk_set_rate(dpll1_clk, mpu_freq);
>> +              clk_set_rate(dpll2_clk, dsp_freq);
>> #ifndef CONFIG_CPU_FREQ
>>               /*Update loops_per_jiffy if processor speed is
>> being changed*/
>>               loops_per_jiffy = compute_lpj(loops_per_jiffy,
>> -                      mpu_opps[current_level].rate/1000,
>> -                      mpu_opps[target_level].rate/1000);
>> +                      mpu_cur_freq / 1000, mpu_freq / 1000);
>> #endif
>>       } else {
>>               curr_opp = &curr_vdd2_opp;
>>               l3_div = cm_read_mod_reg(CORE_MOD, CM_CLKSEL) &
>>                       OMAP3430_CLKSEL_L3_MASK;
>> -              ret = clk_set_rate(dpll3_clk,
>> -                              l3_opps[target_level].rate * l3_div);
>> +              ret = clk_set_rate(dpll3_clk, l3_freq * l3_div);
>>       }
>>       if (ret) {
>>               unlock_scratchpad_sem();
>> @@ -278,6 +344,7 @@ static int program_opp(int res, struct
>> omap_opp *opp, int target_level,
>>               int current_level)
>> {
>>       int i, ret = 0, raise;
>> +      unsigned long freq;
>> #ifdef CONFIG_OMAP_SMARTREFLEX
>>       unsigned long t_opp, c_opp;
>>
>> @@ -285,13 +352,10 @@ static int program_opp(int res, struct
>> omap_opp *opp, int target_level,
>>       c_opp = ID_VDD(res) | ID_OPP_NO(opp[current_level].opp_id);
>> #endif
>>
>> -      /* Only allow enabled OPPs */
>> -      if (!opp[target_level].enabled)
>> -              return -EINVAL;
>> -
>> -      /* Sanity check of the OPP params before attempting to set */
>> -      if (!opp[target_level].rate || !opp[target_level].vsel)
>> -              return -EINVAL;
>> +      /* See if have a freq associated, if not, invalid opp */
>> +      ret = opp_to_freq(&freq, opp, target_level);
>> +      if (unlikely(ret))
>> +              return ret;
>>
>>       if (target_level > current_level)
>>               raise = 1;
>> @@ -303,10 +367,23 @@ static int program_opp(int res, struct
>> omap_opp *opp, int target_level,
>>                       ret = program_opp_freq(res, target_level,
>>                                       current_level);
>> #ifdef CONFIG_OMAP_SMARTREFLEX
>> -              else
>> -                      sr_voltagescale_vcbypass(t_opp, c_opp,
>> -                              opp[target_level].vsel,
>> -                              opp[current_level].vsel);
>> +              else {
>> +                      u8 vc, vt;
>> +                      struct omap_opp *oppx;
>> +                      /*
>> +                       * transitioning from good to good OPP
>> +                       * none of the following should fail..
>> +                       */
>> +                      BUG_ON(opp_is_valid(&oppx, opp, freq));
>> +                      vt = oppx->vsel;
>> +
>> +                      BUG_ON(opp_to_freq(&freq, opp, current_level));
>> +                      BUG_ON(opp_is_valid(&oppx, opp, freq));
>> +                      vc = oppx->vsel;
>> +
>> +                      /* ok to scale.. */
>> +                      sr_voltagescale_vcbypass(t_opp, c_opp, vt, vc);
>> +              }
>> #endif
>>       }
>>
>> @@ -315,7 +392,8 @@ static int program_opp(int res, struct
>> omap_opp *opp, int target_level,
>>
>> int resource_set_opp_level(int res, u32 target_level, int flags)
>> {
>> -      unsigned long mpu_freq, mpu_old_freq;
>> +      unsigned long mpu_freq, mpu_old_freq, l3_freq;
>> +      int ret;
>> #ifdef CONFIG_CPU_FREQ
>>       struct cpufreq_freqs freqs_notify;
>> #endif
>> @@ -334,6 +412,16 @@ int resource_set_opp_level(int res, u32
>> target_level, int flags)
>>       if (!mpu_opps || !dsp_opps || !l3_opps)
>>               return 0;
>>
>> +      /* Check if I can actually switch or not */
>> +      if (res == VDD1_OPP) {
>> +              ret = opp_to_freq(&mpu_freq, mpu_opps, target_level);
>> +              ret |= opp_to_freq(&mpu_old_freq, mpu_opps,
>> resp->curr_level);
>> +      } else {
>> +              ret = opp_to_freq(&l3_freq, l3_opps, target_level);
>> +      }
>> +      if (ret)
>> +              return ret;
>> +
>>       mutex_lock(&dvfs_mutex);
>>
>>       if (res == VDD1_OPP) {
>> @@ -341,9 +429,6 @@ int resource_set_opp_level(int res, u32
>> target_level, int flags)
>>                       mutex_unlock(&dvfs_mutex);
>>                       return 0;
>>               }
>> -              mpu_old_freq = mpu_opps[resp->curr_level].rate;
>> -              mpu_freq = mpu_opps[target_level].rate;
>> -
>> #ifdef CONFIG_CPU_FREQ
>>               freqs_notify.old = mpu_old_freq/1000;
>>               freqs_notify.new = mpu_freq/1000;
>> @@ -371,15 +456,13 @@ int resource_set_opp_level(int res, u32
>> target_level, int flags)
>>
>> int set_opp(struct shared_resource *resp, u32 target_level)
>> {
>> -      unsigned long tput;
>> -      unsigned long req_l3_freq;
>> -      int ind;
>> +      int ret = -EINVAL;
>>
>>       if (resp == vdd1_resp) {
>>               if (target_level < 3)
>>                       resource_release("vdd2_opp", &vdd2_dev);
>>
>> -              resource_set_opp_level(VDD1_OPP, target_level, 0);
>> +              ret = resource_set_opp_level(VDD1_OPP, target_level, 0);
>>               /*
>>                * For VDD1 OPP3 and above, make sure the interconnect
>>                * is at 100Mhz or above.
>> @@ -389,21 +472,33 @@ int set_opp(struct shared_resource
>> *resp, u32 target_level)
>>                       resource_request("vdd2_opp", &vdd2_dev, 400000);
>>
>>       } else if (resp == vdd2_resp) {
>> -              tput = target_level;
>> +              unsigned long req_l3_freq;
>> +              struct omap_opp *oppx = NULL;
>>
>>               /* 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;
>> +              req_l3_freq = (target_level * 1000)/4;
>> +
>> +              /* Do I have an exact match */
>> +              ret = opp_is_valid(&oppx, l3_opps, req_l3_freq);
>> +              if (ret) {
>> +                      /* Do I have a next best match */
>> +                      ret = opp_get_higher_opp(&oppx,
>> &req_l3_freq, l3_opps);
>> +                      if (ret) {
>> +                              /* Give me the best we got */
>> +                              req_l3_freq = ULONG_MAX;
>> +                              ret = opp_get_lower_opp(&oppx,
>> &req_l3_freq,
>> +                                              l3_opps);
>>                       }
>> +              }
>>
>> -              /* Set the highest OPP possible */
>> -              if (ind > MAX_VDD2_OPP)
>> -                      target_level = ind-1;
>> -              resource_set_opp_level(VDD2_OPP, target_level, 0);
>> +              /* uh uh.. no OPPs?? */
>> +              BUG_ON(ret);
>> +
>> +              ret = freq_to_opp((u8 *)&target_level, l3_opps,
>> req_l3_freq);
>> +              /* we dont expect this to fail */
>> +              BUG_ON(ret);
>> +
>> +              ret = resource_set_opp_level(VDD2_OPP, target_level, 0);
>>       }
>>       return 0;
>> }
>> @@ -416,6 +511,11 @@ int set_opp(struct shared_resource *resp,
>> u32 target_level)
>>  */
>> int validate_opp(struct shared_resource *resp, u32 target_level)
>> {
>> +      unsigned long x;
>> +      if (strcmp(resp->name, "mpu_freq") == 0)
>> +              return opp_to_freq(&x, mpu_opps, target_level);
>> +      else if (strcmp(resp->name, "dsp_freq") == 0)
>> +              return opp_to_freq(&x, dsp_opps, target_level);
>>       return 0;
>> }
>>
>> @@ -425,6 +525,8 @@ int validate_opp(struct shared_resource
>> *resp, u32 target_level)
>> void init_freq(struct shared_resource *resp)
>> {
>>       char *linked_res_name;
>> +      int ret = -EINVAL;
>> +      unsigned long freq;
>>       resp->no_of_users = 0;
>>
>>       if (!mpu_opps || !dsp_opps)
>> @@ -436,32 +538,46 @@ void init_freq(struct shared_resource *resp)
>>       */
>>       if (strcmp(resp->name, "mpu_freq") == 0)
>>               /* MPU freq in Mhz */
>> -              resp->curr_level = mpu_opps[curr_vdd1_opp].rate;
>> +              ret = opp_to_freq(&freq, mpu_opps, curr_vdd1_opp);
>>       else if (strcmp(resp->name, "dsp_freq") == 0)
>>               /* DSP freq in Mhz */
>> -              resp->curr_level = dsp_opps[curr_vdd1_opp].rate;
>> +              ret = opp_to_freq(&freq, dsp_opps, curr_vdd1_opp);
>> +      BUG_ON(ret);
>> +
>> +      resp->curr_level = freq;
>>       return;
>> }
>>
>> int set_freq(struct shared_resource *resp, u32 target_level)
>> {
>> -      unsigned int vdd1_opp;
>> +      u8 vdd1_opp;
>> +      int ret = -EINVAL;
>>
>>       if (!mpu_opps || !dsp_opps)
>>               return 0;
>>
>>       if (strcmp(resp->name, "mpu_freq") == 0) {
>> -              vdd1_opp = get_opp(mpu_opps + MAX_VDD1_OPP,
>> target_level);
>> -              resource_request("vdd1_opp", &dummy_mpu_dev, vdd1_opp);
>> +              ret = freq_to_opp(&vdd1_opp, mpu_opps, target_level);
>> +              if (!ret)
>> +                      ret = resource_request("vdd1_opp",
>> &dummy_mpu_dev,
>> +                                      vdd1_opp);
>>       } else if (strcmp(resp->name, "dsp_freq") == 0) {
>> -              vdd1_opp = get_opp(dsp_opps + MAX_VDD1_OPP,
>> target_level);
>> -              resource_request("vdd1_opp", &dummy_dsp_dev, vdd1_opp);
>> +              ret = freq_to_opp(&vdd1_opp, dsp_opps, target_level);
>> +              if (!ret)
>> +                      ret = resource_request("vdd1_opp",
>> &dummy_dsp_dev,
>> +                                      vdd1_opp);
>>       }
>> -      resp->curr_level = target_level;
>> -      return 0;
>> +      if (!ret)
>> +              resp->curr_level = target_level;
>> +      return ret;
>> }
>>
>> int validate_freq(struct shared_resource *resp, u32 target_level)
>> {
>> +      u8 x;
>> +      if (strcmp(resp->name, "mpu_freq") == 0)
>> +              return freq_to_opp(&x, mpu_opps, target_level);
>> +      else if (strcmp(resp->name, "dsp_freq") == 0)
>> +              return freq_to_opp(&x, dsp_opps, target_level);
>>       return 0;
>> }
>> --
>> 1.6.3.3
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe
>> linux-omap" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>     
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>   


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx
  2009-12-07 17:02         ` Tero.Kristo
@ 2009-12-08 11:16           ` Menon, Nishanth
  0 siblings, 0 replies; 36+ messages in thread
From: Menon, Nishanth @ 2009-12-08 11:16 UTC (permalink / raw)
  To: Tero.Kristo; +Cc: khilman, linux-omap

Tero.Kristo@Nokia.com said the following on 12/07/2009 11:02 AM:
> One additional comment to this patch, compilation of board-rx51.c fails unless #include "pm.h" is added to it. This might be true for other boards also seeing it has been added to zoom2 at least.
>   
Huh.. Weird, I did build and test with omap3_pm_defconfig -> rx51 should
have been part of the build.. will check also next time..
>   
>> -----Original Message-----
>> From: linux-omap-owner@vger.kernel.org
>> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of ext Kevin Hilman
>> Sent: 25 November, 2009 19:22
>> To: Nishanth Menon
>> Cc: linux-omap
>> Subject: Re: [PATCH 03/10 V3] omap3: pm: use opp accessor
>> functions for omap34xx
>>
>> Nishanth Menon <nm@ti.com> writes:
>>
>>     
>>> Move the definitions from omap3-opp.h to pm34xx.c. The definitions
>>> are now based on omap_opp_def instead of omap_opp itself.
>>> Since the opp.h has the omap_opp definition, omap-pm.h conflicts and
>>> has been removed in favor of opp.h.
>>>       
>> ok
>>
>>     
>>> omap3_pm_init_opp_table is used to initialize the OPP table and
>>> relevant board files which have omap2_init_common_hw called with opp
>>> arrays have been updated with omap3_pm_init_opp_table.
>>>
>>> This change now allows us to dynamically register OPPs to the system
>>> based on silicon type we detect.
>>>       
>> Nice.
>>
>> With this patch, I would suggest a couple more cleanups in how
>> we are handling
>> the master OPP lists for MPU, DSP and L3.
>>
>> Namely, It's time we could remove the rate_table passing from the OMAP
>> PM layer all together and just keep them as pointers in opp.h.
>>
>> The longer term goal is to remove OPP handling from OMAP PM
>> all together,
>> so this will be a step in that direction.
>>
>> I've attached a patch that applies on top of your series that drops
>> the OPPs from OMAP PM layer.  After doing this, we now have some
>> duplicate global pointers to the various rate tables that could be
>> cleaned up.  In addition, all the rate tables could be dropped from
>> init_common_hw.
>>
>> If you follow my proposal for using opp_add() instead of opp_init()
>> the board files that want to just use default OPPs do not have to do
>> anyting with the rate tables.  Only board files wanting to add OPPs
>> would have to include opp.h and use opp_add().
>>
>> Also, dropping the rate tables from init_common_hw would mean you
>> shouldn't have init sequence issues anymore and you can do the OPP
>> init inside existing PM init.
>>
>> Kevin
>>
>>     
>>> NOTE: This introduces the following warnings highlighting areas we
>>> need to cleanup:
>>> arch/arm/mach-omap2/smartreflex.c: In function 'get_opp':
>>> arch/arm/mach-omap2/smartreflex.c:161: warning: 'opp_id' is
>>>       
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>>     
>>> arch/arm/mach-omap2/smartreflex.c:164: warning: 'opp_id' is
>>>       
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>>     
>>> arch/arm/mach-omap2/smartreflex.c:166: warning: 'opp_id' is
>>>       
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>>     
>>> arch/arm/mach-omap2/smartreflex.c:168: warning: 'opp_id' is
>>>       
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>>     
>>> arch/arm/mach-omap2/resource34xx.c: In function 'get_opp':
>>> arch/arm/mach-omap2/resource34xx.c:165: warning: 'opp_id' is
>>>       
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>>     
>>> arch/arm/mach-omap2/resource34xx.c:168: warning: 'opp_id' is
>>>       
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>>     
>>> arch/arm/mach-omap2/resource34xx.c:170: warning: 'opp_id' is
>>>       
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>>     
>>> arch/arm/mach-omap2/resource34xx.c:172: warning: 'opp_id' is
>>>       
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>>     
>>> arch/arm/mach-omap2/resource34xx.c: In function 'program_opp':
>>> arch/arm/mach-omap2/resource34xx.c:284: warning: 'opp_id' is
>>>       
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>>     
>>> arch/arm/mach-omap2/resource34xx.c:285: warning: 'opp_id' is
>>>       
>> deprecated (declared at arch/arm/plat-omap/include/plat/opp.h:33)
>>     
>>> Signed-off-by: Nishanth Menon <nm@ti.com>
>>> ---
>>>  arch/arm/mach-omap2/board-3430sdp.c       |    1 +
>>>  arch/arm/mach-omap2/board-omap3beagle.c   |    1 +
>>>  arch/arm/mach-omap2/board-omap3evm.c      |    1 +
>>>  arch/arm/mach-omap2/board-rx51.c          |    1 +
>>>  arch/arm/mach-omap2/board-zoom2.c         |    2 +
>>>  arch/arm/mach-omap2/omap3-opp.h           |   58
>>>       
>> +-----------------------
>>     
>>>  arch/arm/mach-omap2/pm.h                  |    6 +++
>>>  arch/arm/mach-omap2/pm34xx.c              |   68
>>>       
>> +++++++++++++++++++++++++++++
>>     
>>>  arch/arm/plat-omap/include/plat/omap-pm.h |   17 +-------
>>>  9 files changed, 84 insertions(+), 71 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-omap2/board-3430sdp.c
>>>       
>> b/arch/arm/mach-omap2/board-3430sdp.c
>>     
>>> index eac529f..0ec8327 100644
>>> --- a/arch/arm/mach-omap2/board-3430sdp.c
>>> +++ b/arch/arm/mach-omap2/board-3430sdp.c
>>> @@ -220,6 +220,7 @@ static void __init omap_3430sdp_init_irq(void)
>>>  {
>>>      omap_board_config = sdp3430_config;
>>>      omap_board_config_size = ARRAY_SIZE(sdp3430_config);
>>> +    omap3_pm_init_opp_table();
>>>      omap3_pm_init_vc(&omap3_setuptime_table);
>>>      omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
>>>      omap2_init_common_hw(hyb18m512160af6_sdrc_params, NULL,
>>>       
>> omap3_mpu_rate_table,
>>     
>>> diff --git a/arch/arm/mach-omap2/board-omap3beagle.c
>>>       
>> b/arch/arm/mach-omap2/board-omap3beagle.c
>>     
>>> index 2ec3520..a937238 100644
>>> --- a/arch/arm/mach-omap2/board-omap3beagle.c
>>> +++ b/arch/arm/mach-omap2/board-omap3beagle.c
>>> @@ -361,6 +361,7 @@ static void __init omap3_beagle_init_irq(void)
>>>  {
>>>      omap_board_config = omap3_beagle_config;
>>>      omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
>>> +    omap3_pm_init_opp_table();
>>>      omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
>>>                           mt46h32m32lf6_sdrc_params,
>>>       
>> omap3_mpu_rate_table,
>>     
>>>                           omap3_dsp_rate_table, omap3_l3_rate_table);
>>> diff --git a/arch/arm/mach-omap2/board-omap3evm.c
>>>       
>> b/arch/arm/mach-omap2/board-omap3evm.c
>>     
>>> index 8130eca..44a5861 100644
>>> --- a/arch/arm/mach-omap2/board-omap3evm.c
>>> +++ b/arch/arm/mach-omap2/board-omap3evm.c
>>> @@ -404,6 +404,7 @@ static void __init omap3_evm_init_irq(void)
>>>  {
>>>      omap_board_config = omap3_evm_config;
>>>      omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
>>> +    omap3_pm_init_opp_table();
>>>      omap2_init_common_hw(mt46h32m32lf6_sdrc_params, NULL,
>>>       
>> omap3_mpu_rate_table,
>>     
>>>                           omap3_dsp_rate_table, omap3_l3_rate_table);
>>>      omap_init_irq();
>>> diff --git a/arch/arm/mach-omap2/board-rx51.c
>>>       
>> b/arch/arm/mach-omap2/board-rx51.c
>>     
>>> index 2f1c2be..997fd1c 100644
>>> --- a/arch/arm/mach-omap2/board-rx51.c
>>> +++ b/arch/arm/mach-omap2/board-rx51.c
>>> @@ -103,6 +103,7 @@ static void __init rx51_init_irq(void)
>>>
>>>      omap_board_config = rx51_config;
>>>      omap_board_config_size = ARRAY_SIZE(rx51_config);
>>> +    omap3_pm_init_opp_table();
>>>      omap3_pm_init_cpuidle(rx51_cpuidle_params);
>>>      sdrc_params = rx51_get_sdram_timings();
>>>      omap2_init_common_hw(sdrc_params, sdrc_params,
>>> diff --git a/arch/arm/mach-omap2/board-zoom2.c
>>>       
>> b/arch/arm/mach-omap2/board-zoom2.c
>>     
>>> index dcc5fb8..9d5b078 100644
>>> --- a/arch/arm/mach-omap2/board-zoom2.c
>>> +++ b/arch/arm/mach-omap2/board-zoom2.c
>>> @@ -24,10 +24,12 @@
>>>  #include <mach/board-zoom.h>
>>>
>>>  #include "sdram-micron-mt46h32m32lf-6.h"
>>> +#include "pm.h"
>>>  #include "omap3-opp.h"
>>>
>>>  static void __init omap_zoom2_init_irq(void)
>>>  {
>>> +    omap3_pm_init_opp_table();
>>>      omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
>>>                               mt46h32m32lf6_sdrc_params,
>>>       
>> omap3_mpu_rate_table,
>>     
>>>                               omap3_dsp_rate_table,
>>>       
>> omap3_l3_rate_table);
>>     
>>> diff --git a/arch/arm/mach-omap2/omap3-opp.h
>>>       
>> b/arch/arm/mach-omap2/omap3-opp.h
>>     
>>> index 42557e1..994d8d4 100644
>>> --- a/arch/arm/mach-omap2/omap3-opp.h
>>> +++ b/arch/arm/mach-omap2/omap3-opp.h
>>> @@ -3,60 +3,8 @@
>>>
>>>  #include <plat/omap-pm.h>
>>>
>>> -/* MPU speeds */
>>> -#define S600M   600000000
>>> -#define S550M   550000000
>>> -#define S500M   500000000
>>> -#define S250M   250000000
>>> -#define S125M   125000000
>>> -
>>> -/* DSP speeds */
>>> -#define S430M   430000000
>>> -#define S400M   400000000
>>> -#define S360M   360000000
>>> -#define S180M   180000000
>>> -#define S90M    90000000
>>> -
>>> -/* L3 speeds */
>>> -#define S83M    83000000
>>> -#define S166M   166000000
>>> -
>>> -static struct omap_opp omap3_mpu_rate_table[] = {
>>> -    {0, 0, 0, 0},
>>> -    /*OPP1*/
>>> -    {true, S125M, VDD1_OPP1, 0x1E},
>>> -    /*OPP2*/
>>> -    {true, S250M, VDD1_OPP2, 0x26},
>>> -    /*OPP3*/
>>> -    {true, S500M, VDD1_OPP3, 0x30},
>>> -    /*OPP4*/
>>> -    {true, S550M, VDD1_OPP4, 0x36},
>>> -    /*OPP5*/
>>> -    {true, S600M, VDD1_OPP5, 0x3C},
>>> -};
>>> -
>>> -static struct omap_opp omap3_l3_rate_table[] = {
>>> -    {0, 0, 0, 0},
>>> -    /*OPP1*/
>>> -    {false, 0, VDD2_OPP1, 0x1E},
>>> -    /*OPP2*/
>>> -    {true, S83M, VDD2_OPP2, 0x24},
>>> -    /*OPP3*/
>>> -    {true, S166M, VDD2_OPP3, 0x2C},
>>> -};
>>> -
>>> -static struct omap_opp omap3_dsp_rate_table[] = {
>>> -    {0, 0, 0, 0},
>>> -    /*OPP1*/
>>> -    {true, S90M, VDD1_OPP1, 0x1E},
>>> -    /*OPP2*/
>>> -    {true, S180M, VDD1_OPP2, 0x26},
>>> -    /*OPP3*/
>>> -    {true, S360M, VDD1_OPP3, 0x30},
>>> -    /*OPP4*/
>>> -    {true, S400M, VDD1_OPP4, 0x36},
>>> -    /*OPP5*/
>>> -    {true, S430M, 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;
>>>
>>>  #endif
>>> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
>>> index 7bc86b6..80a1c1d 100644
>>> --- a/arch/arm/mach-omap2/pm.h
>>> +++ b/arch/arm/mach-omap2/pm.h
>>> @@ -58,6 +58,12 @@ static inline void omap3_pm_init_cpuidle(
>>>  {
>>>  }
>>>  #endif
>>> +/**
>>> + * omap3_pm_init_opp_table - OMAP opp table lookup called
>>>       
>> after cpu is detected.
>>     
>>> + * Initialize the basic opp table here, board files could
>>>       
>> choose to modify opp
>>     
>>> + * table after the basic initialization
>>> + */
>>> +extern void omap3_pm_init_opp_table(void);
>>>
>>>  extern int resource_set_opp_level(int res, u32
>>>       
>> target_level, int flags);
>>     
>>>  extern int resource_access_opp_lock(int res, int delta);
>>> diff --git a/arch/arm/mach-omap2/pm34xx.c
>>>       
>> b/arch/arm/mach-omap2/pm34xx.c
>>     
>>> index 627a509..ad21f5f 100644
>>> --- a/arch/arm/mach-omap2/pm34xx.c
>>> +++ b/arch/arm/mach-omap2/pm34xx.c
>>> @@ -40,6 +40,7 @@
>>>  #include <plat/dmtimer.h>
>>>  #include <plat/usb.h>
>>>
>>> +#include <plat/opp.h>
>>>  #include <plat/resource.h>
>>>
>>>  #include <asm/tlbflush.h>
>>> @@ -52,6 +53,7 @@
>>>  #include "prm.h"
>>>  #include "pm.h"
>>>  #include "sdrc.h"
>>> +#include "omap3-opp.h"
>>>
>>>  static int regset_save_on_suspend;
>>>
>>> @@ -100,6 +102,52 @@ static struct prm_setup_vc prm_setup = {
>>>      .vdd1_off = 0x00,       /* 0.6v */
>>>  };
>>>
>>> +static struct omap_opp_def __initdata omap34xx_mpu_rate_table[] = {
>>> +    /*OPP1 975mV */
>>> +    {.enabled = true, .freq = 125000000, .u_volt = 975000},
>>> +    /*OPP2 1.075V */
>>> +    {.enabled = true, .freq = 250000000, .u_volt = 1075000},
>>> +    /*OPP3 1.2V */
>>> +    {.enabled = true, .freq = 500000000, .u_volt = 1200000},
>>> +    /*OPP4 1.270V */
>>> +    {.enabled = true, .freq = 550000000, .u_volt = 1270000},
>>> +    /*OPP5 1.35V */
>>> +    {.enabled = true, .freq = 600000000, .u_volt = 1350000},
>>> +    /* Terminator */
>>> +    {.enabled = 0, .freq = 0, .u_volt = 0}
>>> +};
>>> +
>>> +static struct omap_opp_def __initdata omap34xx_l3_rate_table[] = {
>>> +    /*OPP1 - 975mV */
>>> +    {.enabled = false, .freq = 0, .u_volt = 975000},
>>> +    /*OPP2 1.05V */
>>> +    {.enabled = true, .freq = 83000000, .u_volt = 1050000},
>>> +    /*OPP3 1.15V*/
>>> +    {.enabled = true, .freq = 166000000, .u_volt = 1150000},
>>> +    /* Terminator */
>>> +    {.enabled = 0, .freq = 0, .u_volt = 0}
>>> +};
>>> +
>>> +static struct omap_opp_def __initdata omap34xx_dsp_rate_table[] = {
>>> +    /*OPP1*/
>>> +    {.enabled = true, .freq = 90000000, .u_volt = 975000},
>>> +    /*OPP2*/
>>> +    {.enabled = true, .freq = 180000000, .u_volt = 1075000},
>>> +    /*OPP3*/
>>> +    {.enabled = true, .freq = 360000000, .u_volt = 1200000},
>>> +    /*OPP4*/
>>> +    {.enabled = true, .freq = 400000000, .u_volt = 1270000},
>>> +    /*OPP5*/
>>> +    {.enabled = true, .freq = 430000000, .u_volt = 1350000},
>>> +    /* Terminator */
>>> +    {.enabled = 0, .freq = 0, .u_volt = 0}
>>> +};
>>> +
>>> +struct omap_opp *omap3_mpu_rate_table;
>>> +struct omap_opp *omap3_dsp_rate_table;
>>> +struct omap_opp *omap3_l3_rate_table;
>>> +
>>> +
>>>  static inline void omap3_per_save_context(void)
>>>  {
>>>      omap_gpio_save_context();
>>> @@ -1248,6 +1296,26 @@ static void __init configure_vc(void)
>>>      pm_dbg_regset_init(2);
>>>  }
>>>
>>> +void __init omap3_pm_init_opp_table(void)
>>> +{
>>> +    int ret, i;
>>> +    struct omap_opp_def *omap34xx_opp_def_list[] = {
>>> +            omap34xx_mpu_rate_table,
>>> +            omap34xx_l3_rate_table,
>>> +            omap34xx_dsp_rate_table
>>> +    };
>>> +    struct omap_opp **omap3_rate_tables[] = {
>>> +            &omap3_mpu_rate_table,
>>> +            &omap3_l3_rate_table,
>>> +            &omap3_dsp_rate_table
>>> +    };
>>> +    for (i = 0; i < ARRAY_SIZE(omap34xx_opp_def_list); i++) {
>>> +            ret = opp_init(omap3_rate_tables[i],
>>>       
>> omap34xx_opp_def_list[i]);
>>     
>>> +            /* We dont want half configured system at the moment */
>>> +            BUG_ON(ret);
>>> +    }
>>> +}
>>> +
>>>  static int __init omap3_pm_early_init(void)
>>>  {
>>>      prm_clear_mod_reg_bits(OMAP3430_OFFMODE_POL, OMAP3430_GR_MOD,
>>> diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h
>>>       
>> b/arch/arm/plat-omap/include/plat/omap-pm.h
>>     
>>> index 5dc2048..aa36339 100644
>>> --- a/arch/arm/plat-omap/include/plat/omap-pm.h
>>> +++ b/arch/arm/plat-omap/include/plat/omap-pm.h
>>> @@ -18,22 +18,7 @@
>>>  #include <linux/cpufreq.h>
>>>
>>>  #include "powerdomain.h"
>>> -
>>> -/**
>>> - * struct omap_opp - clock frequency-to-OPP ID table for DSP, MPU
>>> - * @enabled: enabled if true, disabled if false
>>> - * @rate: target clock rate
>>> - * @opp_id: OPP ID
>>> - * @min_vdd: minimum VDD1 voltage (in millivolts) for this OPP
>>> - *
>>> - * Operating performance point data.  Can vary by OMAP chip
>>>       
>> and board.
>>     
>>> - */
>>> -struct omap_opp {
>>> -    bool enabled;
>>> -    unsigned long rate;
>>> -    u8 opp_id;
>>> -    u16 vsel;
>>> -};
>>> +#include <plat/opp.h>
>>>
>>>  extern struct omap_opp *mpu_opps;
>>>  extern struct omap_opp *dsp_opps;
>>> --
>>> 1.6.3.3
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe
>>>       
>> linux-omap" in
>>     
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>       
>> --
>> To unsubscribe from this list: send the line "unsubscribe
>> linux-omap" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>     
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>   


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 09/10 V3] omap3: pm: introduce 3630 opps
  2009-12-08 10:59                     ` Menon, Nishanth
@ 2009-12-08 11:18                       ` Eduardo Valentin
  2009-12-08 11:31                         ` Menon, Nishanth
  0 siblings, 1 reply; 36+ messages in thread
From: Eduardo Valentin @ 2009-12-08 11:18 UTC (permalink / raw)
  To: ext Menon, Nishanth
  Cc: Valentin Eduardo (Nokia-D/Helsinki),
	linux-omap, Benoit Cousson, Kevin Hilman,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

On Tue, Dec 08, 2009 at 11:59:49AM +0100, ext Nishanth Menon wrote:
> Hi,
> thanks for your comments. few thoughts below.
> 
> Eduardo Valentin said the following on 12/08/2009 01:49 AM:
> > Hello Nishanth,
> >
> > Few comments bellow.
> >
> > On Wed, Nov 25, 2009 at 05:09:18AM +0100, ext Nishanth Menon wrote:
> >   
> >> Introduce the OMAP3630 OPPs including the defined OPP tuples.
> >>
> >> Further information on OMAP3630 can be found here:
> >> http://focus.ti.com/general/docs/wtbu/wtbuproductcontent.tsp?templateId=6123&navigationId=12836&contentId=52606
> >>
> >> OMAP36xx family introduces:
> >> VDD1 with 4 OPPs, of which OPP3 & 4 are available only on devices yet
> >> to be introduced in 36xx family. Meanwhile, VDD2 has 2 opps.
> >>
> >> Device Support of OPPs->
> >>            |<-3630-600->| (default)
> >>            |<-      3630-800    ->| (device: TBD)
> >>            |<-      3630-1000            ->| (device: TBD)
> >> H/w OPP-> OPP50 OPP100       OPP-Turbo   OPP1G-SB
> >> VDD1      OPP1  OPP2         OPP3        OPP4
> >> VDD2      OPP1  OPP2         OPP2        OPP2
> >>
> >> Note:
> >> a) TI h/w naming for OPPs are now standardized in terms of OPP50, 100,
> >>    Turbo and SB. This maps as shown above to the opp IDs (s/w term).
> >> b) For boards which need custom VDD1/2 OPPs, the opp table can be
> >>    updated by the board file on a need basis after the
> >>    omap3_pm_init_opp_table call. The OPPs introduced here are the
> >>    official OPP table at this point in time.
> >>
> >> Cc: Benoit Cousson <b-cousson@ti.com>
> >> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> >> Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
> >> Cc: Paul Walmsley <paul@pwsan.com>
> >> Cc: Romit Dasgupta <romit@ti.com>
> >> Cc: Sanjeev Premi <premi@ti.com>
> >> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> >> Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
> >> Cc: Thara Gopinath <thara@ti.com>
> >> Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
> >>
> >> Signed-off-by: Nishanth Menon <nm@ti.com>
> >> ---
> >>  arch/arm/mach-omap2/pm34xx.c |   49 ++++++++++++++++++++++++++++++++++++++++-
> >>  1 files changed, 47 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> >> index ad21f5f..05ecf02 100644
> >> --- a/arch/arm/mach-omap2/pm34xx.c
> >> +++ b/arch/arm/mach-omap2/pm34xx.c
> >> @@ -143,6 +143,41 @@ static struct omap_opp_def __initdata omap34xx_dsp_rate_table[] = {
> >>  	{.enabled = 0, .freq = 0, .u_volt = 0}
> >>  };
> >>  
> >> +static struct omap_opp_def __initdata omap36xx_mpu_rate_table[] = {
> >> +	/*OPP1 - OPP50*/
> >> +	{.enabled = true,  .freq = 300000000, .u_volt = 930000},
> >> +	/*OPP2 - OPP100*/
> >> +	{.enabled = true,  .freq = 600000000, .u_volt = 1100000},
> >> +	/*OPP3 - OPP-Turbo*/
> >> +	{.enabled = false, .freq = 800000000, .u_volt = 1260000},
> >> +	/*OPP4 - OPP-SB*/
> >> +	{.enabled = false, .freq = 1000000000, .u_volt = 1310000},
> >> +	/* Terminator */
> >> +	{.enabled = 0, .freq = 0, .u_volt = 0}
> >> +};
> >> +
> >> +static struct omap_opp_def __initdata omap36xx_l3_rate_table[] = {
> >> +	/*OPP1 - OPP50 */
> >> +	{.enabled = true, .freq = 100000000, .u_volt = 930000},
> >> +	/*OPP2 - OPP100, OPP-Turbo, OPP-SB*/
> >> +	{.enabled = true, .freq = 200000000, .u_volt = 1137500},
> >> +	/* Terminator */
> >> +	{.enabled = 0, .freq = 0, .u_volt = 0}
> >> +};
> >> +
> >> +static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
> >> +	/*OPP1 - OPP50*/
> >> +	{.enabled = true,  .freq = 260000000, .u_volt = 930000},
> >> +	/*OPP2 - OPP100*/
> >> +	{.enabled = true,  .freq = 520000000, .u_volt = 1100000},
> >> +	/*OPP3 - OPP-Turbo*/
> >> +	{.enabled = false, .freq = 660000000, .u_volt = 1260000},
> >> +	/*OPP4 - OPP-SB*/
> >> +	{.enabled = false, .freq = 875000000, .u_volt = 1310000},
> >> +	/* Terminator */
> >> +	{.enabled = 0, .freq = 0, .u_volt = 0}
> >> +};
> >> +
> >>     
> >
> > Although it is not mandatory, I'd say this way of initializing structure array is more common:
> >
> > static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
> > 	/*OPP1 - OPP50*/
> > 	{
> > 		.enabled	= true,
> > 		.freq		= 260000000,
> > 		.u_volt		= 930000,
> > 	},
> > 	/*OPP2 - OPP100*/
> > 	{
> > 		.enabled	= true,
> > 		.freq		= 520000000,
> > 		.u_volt		= 1100000,
> > 	},
> > 	/*OPP3 - OPP-Turbo*/
> > 	{
> > 		.enabled	= false,
> > 		.freq		= 660000000,
> > 		.u_volt		= 1260000,
> > 	},
> > 	/*OPP4 - OPP-SB*/
> > 	{
> > 		.enabled	= false,
> > 		.freq		= 875000000,
> > 		.u_volt		= 1310000,
> > 	},
> > 	/* Terminator */
> > 	{
> > 		.enabled	= 0,
> > 		.freq		= 0,
> > 		.u_volt		= 0,
> > 	}
> > };
> >
> > and if you thing it is line consuming, you can always define a "INIT" macro:
> > #define	OMAP_OPP_DEF(_enabled, _freq, _uv)	\
> > {						\
> > 	.enabled	= _enabled,		\
> > 	.freq		= _freq,		\
> > 	.u_volt		= _uv,			\
> > }
> >
> > and use it to initialize your array:
> >
> > 	/*OPP1 - OPP50*/
> > static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
> > 	OMAP_OPP_DEF(true, 260000000, 930000),
> > 	OMAP_OPP_DEF(true, 520000000, 1100000),
> > 	OMAP_OPP_DEF(false, 660000000, 1260000),
> > 	OMAP_OPP_DEF(false, 875000000, 1310000},
> > 	OMAP_OPP_DEF(0, 0, 0),
> > };
> >   
> Thanks. yep, I agree this looks cleaner. I vote for this. probably will
> use OMAP_OPP_TERM to denote (0,0,0)

Nice,

> 
> >
> > Beside, although it should not hurt as they are not too big, these tables should
> > be compiled only if omap3630 is the target right?
> >
> >   
> >>  struct omap_opp *omap3_mpu_rate_table;
> >>  struct omap_opp *omap3_dsp_rate_table;
> >>  struct omap_opp *omap3_l3_rate_table;
> >> @@ -1299,18 +1334,28 @@ static void __init configure_vc(void)
> >>  void __init omap3_pm_init_opp_table(void)
> >>  {
> >>  	int ret, i;
> >> +	struct omap_opp_def **omap3_opp_def_list;
> >>  	struct omap_opp_def *omap34xx_opp_def_list[] = {
> >>  		omap34xx_mpu_rate_table,
> >>  		omap34xx_l3_rate_table,
> >>  		omap34xx_dsp_rate_table
> >>  	};
> >> +	struct omap_opp_def *omap36xx_opp_def_list[] = {
> >> +		omap36xx_mpu_rate_table,
> >> +		omap36xx_l3_rate_table,
> >> +		omap36xx_dsp_rate_table
> >> +	};
> >>  	struct omap_opp **omap3_rate_tables[] = {
> >>  		&omap3_mpu_rate_table,
> >>  		&omap3_l3_rate_table,
> >>  		&omap3_dsp_rate_table
> >>  	};
> >> -	for (i = 0; i < ARRAY_SIZE(omap34xx_opp_def_list); i++) {
> >> -		ret = opp_init(omap3_rate_tables[i], omap34xx_opp_def_list[i]);
> >> +
> >> +	omap3_opp_def_list = cpu_is_omap3630() ? omap36xx_opp_def_list :
> >> +				omap34xx_opp_def_list;
> >>     
> >
> > here you cared for runtime target check, but tables above could be avoid if not omap3630.
> >   
> If your concern is memory size: the tables are __initdata, they will get
> freed once kernel boot is complete. the only representation of omap_opp
> will be what the opp layer's definition of the same.
> 
> The intention was to be able to have a single uImage booting across
> multiple boards with multiple silicon -> e.g. today same uImage with
> omap_pm_defconfig will equally boot on sdp3430 as it does on sdp3630..
> which is what we all prefer.. so no ways of a compile time inclusion- it
> has to be runtime determined..

Yeah, but if you have multiple board configuration, at compile time, your check
should add all selected tables.

I just pointed that because it is the way I see in current code. You check at
compile time if you define tables or not, then at runtime you check which table
to use. That should still work for multi board configuration (using same image
for sdp3430 or sdp3630).

Check  arch/arm/mach-omap2/mux.c or arch/arm/mach-omap2/mcbsp.c.

There are other examples.  If you take a look on those you will see that it is
same issue you are dealing, defining static tables for several omap versions and then
just selecting which one to use at runtime. Besides, in mux.c you see that all are
also __initdata_or_module.


> 
> >   
> >> +
> >> +	for (i = 0; i < ARRAY_SIZE(omap3_rate_tables); i++) {
> >> +		ret = opp_init(omap3_rate_tables[i], omap3_opp_def_list[i]);
> >>  		/* We dont want half configured system at the moment */
> >>  		BUG_ON(ret);
> >>  	}
> >> -- 
> >> 1.6.3.3
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>     
> >
> >   

-- 
Eduardo Valentin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 09/10 V3] omap3: pm: introduce 3630 opps
  2009-12-08 11:18                       ` Eduardo Valentin
@ 2009-12-08 11:31                         ` Menon, Nishanth
  2009-12-08 11:40                           ` Eduardo Valentin
  0 siblings, 1 reply; 36+ messages in thread
From: Menon, Nishanth @ 2009-12-08 11:31 UTC (permalink / raw)
  To: eduardo.valentin
  Cc: linux-omap, Benoit Cousson, Kevin Hilman,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

Eduardo Valentin said the following on 12/08/2009 05:18 AM:
> On Tue, Dec 08, 2009 at 11:59:49AM +0100, ext Nishanth Menon wrote:
>   
>> Hi,
>> thanks for your comments. few thoughts below.
>>
>> Eduardo Valentin said the following on 12/08/2009 01:49 AM:
>>     
>>> Hello Nishanth,
>>>
>>> Few comments bellow.
>>>
>>> On Wed, Nov 25, 2009 at 05:09:18AM +0100, ext Nishanth Menon wrote:
>>>   
>>>       
>>>> Introduce the OMAP3630 OPPs including the defined OPP tuples.
>>>>
>>>> Further information on OMAP3630 can be found here:
>>>> http://focus.ti.com/general/docs/wtbu/wtbuproductcontent.tsp?templateId=6123&navigationId=12836&contentId=52606
>>>>
>>>> OMAP36xx family introduces:
>>>> VDD1 with 4 OPPs, of which OPP3 & 4 are available only on devices yet
>>>> to be introduced in 36xx family. Meanwhile, VDD2 has 2 opps.
>>>>
>>>> Device Support of OPPs->
>>>>            |<-3630-600->| (default)
>>>>            |<-      3630-800    ->| (device: TBD)
>>>>            |<-      3630-1000            ->| (device: TBD)
>>>> H/w OPP-> OPP50 OPP100       OPP-Turbo   OPP1G-SB
>>>> VDD1      OPP1  OPP2         OPP3        OPP4
>>>> VDD2      OPP1  OPP2         OPP2        OPP2
>>>>
>>>> Note:
>>>> a) TI h/w naming for OPPs are now standardized in terms of OPP50, 100,
>>>>    Turbo and SB. This maps as shown above to the opp IDs (s/w term).
>>>> b) For boards which need custom VDD1/2 OPPs, the opp table can be
>>>>    updated by the board file on a need basis after the
>>>>    omap3_pm_init_opp_table call. The OPPs introduced here are the
>>>>    official OPP table at this point in time.
>>>>
>>>> Cc: Benoit Cousson <b-cousson@ti.com>
>>>> Cc: Kevin Hilman <khilman@deeprootsystems.com>
>>>> Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
>>>> Cc: Paul Walmsley <paul@pwsan.com>
>>>> Cc: Romit Dasgupta <romit@ti.com>
>>>> Cc: Sanjeev Premi <premi@ti.com>
>>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>> Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
>>>> Cc: Thara Gopinath <thara@ti.com>
>>>> Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
>>>>
>>>> Signed-off-by: Nishanth Menon <nm@ti.com>
>>>> ---
>>>>  arch/arm/mach-omap2/pm34xx.c |   49 ++++++++++++++++++++++++++++++++++++++++-
>>>>  1 files changed, 47 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
>>>> index ad21f5f..05ecf02 100644
>>>> --- a/arch/arm/mach-omap2/pm34xx.c
>>>> +++ b/arch/arm/mach-omap2/pm34xx.c
>>>> @@ -143,6 +143,41 @@ static struct omap_opp_def __initdata omap34xx_dsp_rate_table[] = {
>>>>  	{.enabled = 0, .freq = 0, .u_volt = 0}
>>>>  };
>>>>  
>>>> +static struct omap_opp_def __initdata omap36xx_mpu_rate_table[] = {
>>>> +	/*OPP1 - OPP50*/
>>>> +	{.enabled = true,  .freq = 300000000, .u_volt = 930000},
>>>> +	/*OPP2 - OPP100*/
>>>> +	{.enabled = true,  .freq = 600000000, .u_volt = 1100000},
>>>> +	/*OPP3 - OPP-Turbo*/
>>>> +	{.enabled = false, .freq = 800000000, .u_volt = 1260000},
>>>> +	/*OPP4 - OPP-SB*/
>>>> +	{.enabled = false, .freq = 1000000000, .u_volt = 1310000},
>>>> +	/* Terminator */
>>>> +	{.enabled = 0, .freq = 0, .u_volt = 0}
>>>> +};
>>>> +
>>>> +static struct omap_opp_def __initdata omap36xx_l3_rate_table[] = {
>>>> +	/*OPP1 - OPP50 */
>>>> +	{.enabled = true, .freq = 100000000, .u_volt = 930000},
>>>> +	/*OPP2 - OPP100, OPP-Turbo, OPP-SB*/
>>>> +	{.enabled = true, .freq = 200000000, .u_volt = 1137500},
>>>> +	/* Terminator */
>>>> +	{.enabled = 0, .freq = 0, .u_volt = 0}
>>>> +};
>>>> +
>>>> +static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
>>>> +	/*OPP1 - OPP50*/
>>>> +	{.enabled = true,  .freq = 260000000, .u_volt = 930000},
>>>> +	/*OPP2 - OPP100*/
>>>> +	{.enabled = true,  .freq = 520000000, .u_volt = 1100000},
>>>> +	/*OPP3 - OPP-Turbo*/
>>>> +	{.enabled = false, .freq = 660000000, .u_volt = 1260000},
>>>> +	/*OPP4 - OPP-SB*/
>>>> +	{.enabled = false, .freq = 875000000, .u_volt = 1310000},
>>>> +	/* Terminator */
>>>> +	{.enabled = 0, .freq = 0, .u_volt = 0}
>>>> +};
>>>> +
>>>>     
>>>>         
>>> Although it is not mandatory, I'd say this way of initializing structure array is more common:
>>>
>>> static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
>>> 	/*OPP1 - OPP50*/
>>> 	{
>>> 		.enabled	= true,
>>> 		.freq		= 260000000,
>>> 		.u_volt		= 930000,
>>> 	},
>>> 	/*OPP2 - OPP100*/
>>> 	{
>>> 		.enabled	= true,
>>> 		.freq		= 520000000,
>>> 		.u_volt		= 1100000,
>>> 	},
>>> 	/*OPP3 - OPP-Turbo*/
>>> 	{
>>> 		.enabled	= false,
>>> 		.freq		= 660000000,
>>> 		.u_volt		= 1260000,
>>> 	},
>>> 	/*OPP4 - OPP-SB*/
>>> 	{
>>> 		.enabled	= false,
>>> 		.freq		= 875000000,
>>> 		.u_volt		= 1310000,
>>> 	},
>>> 	/* Terminator */
>>> 	{
>>> 		.enabled	= 0,
>>> 		.freq		= 0,
>>> 		.u_volt		= 0,
>>> 	}
>>> };
>>>
>>> and if you thing it is line consuming, you can always define a "INIT" macro:
>>> #define	OMAP_OPP_DEF(_enabled, _freq, _uv)	\
>>> {						\
>>> 	.enabled	= _enabled,		\
>>> 	.freq		= _freq,		\
>>> 	.u_volt		= _uv,			\
>>> }
>>>
>>> and use it to initialize your array:
>>>
>>> 	/*OPP1 - OPP50*/
>>> static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
>>> 	OMAP_OPP_DEF(true, 260000000, 930000),
>>> 	OMAP_OPP_DEF(true, 520000000, 1100000),
>>> 	OMAP_OPP_DEF(false, 660000000, 1260000),
>>> 	OMAP_OPP_DEF(false, 875000000, 1310000},
>>> 	OMAP_OPP_DEF(0, 0, 0),
>>> };
>>>   
>>>       
>> Thanks. yep, I agree this looks cleaner. I vote for this. probably will
>> use OMAP_OPP_TERM to denote (0,0,0)
>>     
>
> Nice,
>
>   
>>> Beside, although it should not hurt as they are not too big, these tables should
>>> be compiled only if omap3630 is the target right?
>>>
>>>   
>>>       
>>>>  struct omap_opp *omap3_mpu_rate_table;
>>>>  struct omap_opp *omap3_dsp_rate_table;
>>>>  struct omap_opp *omap3_l3_rate_table;
>>>> @@ -1299,18 +1334,28 @@ static void __init configure_vc(void)
>>>>  void __init omap3_pm_init_opp_table(void)
>>>>  {
>>>>  	int ret, i;
>>>> +	struct omap_opp_def **omap3_opp_def_list;
>>>>  	struct omap_opp_def *omap34xx_opp_def_list[] = {
>>>>  		omap34xx_mpu_rate_table,
>>>>  		omap34xx_l3_rate_table,
>>>>  		omap34xx_dsp_rate_table
>>>>  	};
>>>> +	struct omap_opp_def *omap36xx_opp_def_list[] = {
>>>> +		omap36xx_mpu_rate_table,
>>>> +		omap36xx_l3_rate_table,
>>>> +		omap36xx_dsp_rate_table
>>>> +	};
>>>>  	struct omap_opp **omap3_rate_tables[] = {
>>>>  		&omap3_mpu_rate_table,
>>>>  		&omap3_l3_rate_table,
>>>>  		&omap3_dsp_rate_table
>>>>  	};
>>>> -	for (i = 0; i < ARRAY_SIZE(omap34xx_opp_def_list); i++) {
>>>> -		ret = opp_init(omap3_rate_tables[i], omap34xx_opp_def_list[i]);
>>>> +
>>>> +	omap3_opp_def_list = cpu_is_omap3630() ? omap36xx_opp_def_list :
>>>> +				omap34xx_opp_def_list;
>>>>     
>>>>         
>>> here you cared for runtime target check, but tables above could be avoid if not omap3630.
>>>   
>>>       
>> If your concern is memory size: the tables are __initdata, they will get
>> freed once kernel boot is complete. the only representation of omap_opp
>> will be what the opp layer's definition of the same.
>>
>> The intention was to be able to have a single uImage booting across
>> multiple boards with multiple silicon -> e.g. today same uImage with
>> omap_pm_defconfig will equally boot on sdp3430 as it does on sdp3630..
>> which is what we all prefer.. so no ways of a compile time inclusion- it
>> has to be runtime determined..
>>     
>
> Yeah, but if you have multiple board configuration, at compile time, your check
> should add all selected tables.
>
> I just pointed that because it is the way I see in current code. You check at
> compile time if you define tables or not, then at runtime you check which table
> to use. That should still work for multi board configuration (using same image
> for sdp3430 or sdp3630).
>
>   

> Check  arch/arm/mach-omap2/mux.c or arch/arm/mach-omap2/mcbsp.c.
>
> There are other examples.  If you take a look on those you will see that it is
> same issue you are dealing, defining static tables for several omap versions and then
> just selecting which one to use at runtime. Besides, in mux.c you see that all are
> also __initdata_or_module.
>   
I think I still dont understand your intention ->
a) pm34xx.c will not be a module -> it is meant to be built in, so
__module addition to __initdata does not make any sense to it.

b) arch/arm/mach-omap2/pm34xx.c is omap3 series only build ONLY when OMAP3 is defined, there are only two of those families rt now, 34xx (of which 35xx is one), and 36xx series..
so I dont need an enormous array definition like mux.h http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git;a=blob;f=arch/arm/mach-omap2/mux.c;h=c18a94eca641d61826fbad85322bc9f3d2cb4841;hb=HEAD#l257 where it is #ifdef OMAP3..

I am not trying to define for various OMAP versions, I am trying to
define for various OMAP3 versions.. I hope this clarifies.
>
>   
>>>   
>>>       
>>>> +
>>>> +	for (i = 0; i < ARRAY_SIZE(omap3_rate_tables); i++) {
>>>> +		ret = opp_init(omap3_rate_tables[i], omap3_opp_def_list[i]);
>>>>  		/* We dont want half configured system at the moment */
>>>>  		BUG_ON(ret);
>>>>  	}
>>>> -- 
>>>> 1.6.3.3
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>>     
>>>>         
>>>   
>>>       
>
>   


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 09/10 V3] omap3: pm: introduce 3630 opps
  2009-12-08 11:31                         ` Menon, Nishanth
@ 2009-12-08 11:40                           ` Eduardo Valentin
  2009-12-08 14:15                             ` Nishanth Menon
  0 siblings, 1 reply; 36+ messages in thread
From: Eduardo Valentin @ 2009-12-08 11:40 UTC (permalink / raw)
  To: ext Menon, Nishanth
  Cc: Valentin Eduardo (Nokia-D/Helsinki),
	linux-omap, Benoit Cousson, Kevin Hilman,
	Madhusudhan Chikkature Rajashekar, Paul Walmsley, Romit Dasgupta,
	Sanjeev Premi, Santosh Shilimkar,
	Sergio Alberto Aguirre Rodriguez, Thara Gopinath,
	Vishwanath Sripathy

On Tue, Dec 08, 2009 at 12:31:13PM +0100, ext Nishanth Menon wrote:
> Eduardo Valentin said the following on 12/08/2009 05:18 AM:
> > On Tue, Dec 08, 2009 at 11:59:49AM +0100, ext Nishanth Menon wrote:
> >
> >> Hi,
> >> thanks for your comments. few thoughts below.
> >>
> >> Eduardo Valentin said the following on 12/08/2009 01:49 AM:
> >>
> >>> Hello Nishanth,
> >>>
> >>> Few comments bellow.
> >>>
> >>> On Wed, Nov 25, 2009 at 05:09:18AM +0100, ext Nishanth Menon wrote:
> >>>
> >>>
> >>>> Introduce the OMAP3630 OPPs including the defined OPP tuples.
> >>>>
> >>>> Further information on OMAP3630 can be found here:
> >>>> http://focus.ti.com/general/docs/wtbu/wtbuproductcontent.tsp?templateId=6123&navigationId=12836&contentId=52606
> >>>>
> >>>> OMAP36xx family introduces:
> >>>> VDD1 with 4 OPPs, of which OPP3 & 4 are available only on devices yet
> >>>> to be introduced in 36xx family. Meanwhile, VDD2 has 2 opps.
> >>>>
> >>>> Device Support of OPPs->
> >>>>            |<-3630-600->| (default)
> >>>>            |<-      3630-800    ->| (device: TBD)
> >>>>            |<-      3630-1000            ->| (device: TBD)
> >>>> H/w OPP-> OPP50 OPP100       OPP-Turbo   OPP1G-SB
> >>>> VDD1      OPP1  OPP2         OPP3        OPP4
> >>>> VDD2      OPP1  OPP2         OPP2        OPP2
> >>>>
> >>>> Note:
> >>>> a) TI h/w naming for OPPs are now standardized in terms of OPP50, 100,
> >>>>    Turbo and SB. This maps as shown above to the opp IDs (s/w term).
> >>>> b) For boards which need custom VDD1/2 OPPs, the opp table can be
> >>>>    updated by the board file on a need basis after the
> >>>>    omap3_pm_init_opp_table call. The OPPs introduced here are the
> >>>>    official OPP table at this point in time.
> >>>>
> >>>> Cc: Benoit Cousson <b-cousson@ti.com>
> >>>> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> >>>> Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
> >>>> Cc: Paul Walmsley <paul@pwsan.com>
> >>>> Cc: Romit Dasgupta <romit@ti.com>
> >>>> Cc: Sanjeev Premi <premi@ti.com>
> >>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> >>>> Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
> >>>> Cc: Thara Gopinath <thara@ti.com>
> >>>> Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
> >>>>
> >>>> Signed-off-by: Nishanth Menon <nm@ti.com>
> >>>> ---
> >>>>  arch/arm/mach-omap2/pm34xx.c |   49 ++++++++++++++++++++++++++++++++++++++++-
> >>>>  1 files changed, 47 insertions(+), 2 deletions(-)
> >>>>
> >>>> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> >>>> index ad21f5f..05ecf02 100644
> >>>> --- a/arch/arm/mach-omap2/pm34xx.c
> >>>> +++ b/arch/arm/mach-omap2/pm34xx.c
> >>>> @@ -143,6 +143,41 @@ static struct omap_opp_def __initdata omap34xx_dsp_rate_table[] = {
> >>>>    {.enabled = 0, .freq = 0, .u_volt = 0}
> >>>>  };
> >>>>
> >>>> +static struct omap_opp_def __initdata omap36xx_mpu_rate_table[] = {
> >>>> +  /*OPP1 - OPP50*/
> >>>> +  {.enabled = true,  .freq = 300000000, .u_volt = 930000},
> >>>> +  /*OPP2 - OPP100*/
> >>>> +  {.enabled = true,  .freq = 600000000, .u_volt = 1100000},
> >>>> +  /*OPP3 - OPP-Turbo*/
> >>>> +  {.enabled = false, .freq = 800000000, .u_volt = 1260000},
> >>>> +  /*OPP4 - OPP-SB*/
> >>>> +  {.enabled = false, .freq = 1000000000, .u_volt = 1310000},
> >>>> +  /* Terminator */
> >>>> +  {.enabled = 0, .freq = 0, .u_volt = 0}
> >>>> +};
> >>>> +
> >>>> +static struct omap_opp_def __initdata omap36xx_l3_rate_table[] = {
> >>>> +  /*OPP1 - OPP50 */
> >>>> +  {.enabled = true, .freq = 100000000, .u_volt = 930000},
> >>>> +  /*OPP2 - OPP100, OPP-Turbo, OPP-SB*/
> >>>> +  {.enabled = true, .freq = 200000000, .u_volt = 1137500},
> >>>> +  /* Terminator */
> >>>> +  {.enabled = 0, .freq = 0, .u_volt = 0}
> >>>> +};
> >>>> +
> >>>> +static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
> >>>> +  /*OPP1 - OPP50*/
> >>>> +  {.enabled = true,  .freq = 260000000, .u_volt = 930000},
> >>>> +  /*OPP2 - OPP100*/
> >>>> +  {.enabled = true,  .freq = 520000000, .u_volt = 1100000},
> >>>> +  /*OPP3 - OPP-Turbo*/
> >>>> +  {.enabled = false, .freq = 660000000, .u_volt = 1260000},
> >>>> +  /*OPP4 - OPP-SB*/
> >>>> +  {.enabled = false, .freq = 875000000, .u_volt = 1310000},
> >>>> +  /* Terminator */
> >>>> +  {.enabled = 0, .freq = 0, .u_volt = 0}
> >>>> +};
> >>>> +
> >>>>
> >>>>
> >>> Although it is not mandatory, I'd say this way of initializing structure array is more common:
> >>>
> >>> static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
> >>>     /*OPP1 - OPP50*/
> >>>     {
> >>>             .enabled        = true,
> >>>             .freq           = 260000000,
> >>>             .u_volt         = 930000,
> >>>     },
> >>>     /*OPP2 - OPP100*/
> >>>     {
> >>>             .enabled        = true,
> >>>             .freq           = 520000000,
> >>>             .u_volt         = 1100000,
> >>>     },
> >>>     /*OPP3 - OPP-Turbo*/
> >>>     {
> >>>             .enabled        = false,
> >>>             .freq           = 660000000,
> >>>             .u_volt         = 1260000,
> >>>     },
> >>>     /*OPP4 - OPP-SB*/
> >>>     {
> >>>             .enabled        = false,
> >>>             .freq           = 875000000,
> >>>             .u_volt         = 1310000,
> >>>     },
> >>>     /* Terminator */
> >>>     {
> >>>             .enabled        = 0,
> >>>             .freq           = 0,
> >>>             .u_volt         = 0,
> >>>     }
> >>> };
> >>>
> >>> and if you thing it is line consuming, you can always define a "INIT" macro:
> >>> #define     OMAP_OPP_DEF(_enabled, _freq, _uv)      \
> >>> {                                           \
> >>>     .enabled        = _enabled,             \
> >>>     .freq           = _freq,                \
> >>>     .u_volt         = _uv,                  \
> >>> }
> >>>
> >>> and use it to initialize your array:
> >>>
> >>>     /*OPP1 - OPP50*/
> >>> static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
> >>>     OMAP_OPP_DEF(true, 260000000, 930000),
> >>>     OMAP_OPP_DEF(true, 520000000, 1100000),
> >>>     OMAP_OPP_DEF(false, 660000000, 1260000),
> >>>     OMAP_OPP_DEF(false, 875000000, 1310000},
> >>>     OMAP_OPP_DEF(0, 0, 0),
> >>> };
> >>>
> >>>
> >> Thanks. yep, I agree this looks cleaner. I vote for this. probably will
> >> use OMAP_OPP_TERM to denote (0,0,0)
> >>
> >
> > Nice,
> >
> >
> >>> Beside, although it should not hurt as they are not too big, these tables should
> >>> be compiled only if omap3630 is the target right?
> >>>
> >>>
> >>>
> >>>>  struct omap_opp *omap3_mpu_rate_table;
> >>>>  struct omap_opp *omap3_dsp_rate_table;
> >>>>  struct omap_opp *omap3_l3_rate_table;
> >>>> @@ -1299,18 +1334,28 @@ static void __init configure_vc(void)
> >>>>  void __init omap3_pm_init_opp_table(void)
> >>>>  {
> >>>>    int ret, i;
> >>>> +  struct omap_opp_def **omap3_opp_def_list;
> >>>>    struct omap_opp_def *omap34xx_opp_def_list[] = {
> >>>>            omap34xx_mpu_rate_table,
> >>>>            omap34xx_l3_rate_table,
> >>>>            omap34xx_dsp_rate_table
> >>>>    };
> >>>> +  struct omap_opp_def *omap36xx_opp_def_list[] = {
> >>>> +          omap36xx_mpu_rate_table,
> >>>> +          omap36xx_l3_rate_table,
> >>>> +          omap36xx_dsp_rate_table
> >>>> +  };
> >>>>    struct omap_opp **omap3_rate_tables[] = {
> >>>>            &omap3_mpu_rate_table,
> >>>>            &omap3_l3_rate_table,
> >>>>            &omap3_dsp_rate_table
> >>>>    };
> >>>> -  for (i = 0; i < ARRAY_SIZE(omap34xx_opp_def_list); i++) {
> >>>> -          ret = opp_init(omap3_rate_tables[i], omap34xx_opp_def_list[i]);
> >>>> +
> >>>> +  omap3_opp_def_list = cpu_is_omap3630() ? omap36xx_opp_def_list :
> >>>> +                          omap34xx_opp_def_list;
> >>>>
> >>>>
> >>> here you cared for runtime target check, but tables above could be avoid if not omap3630.
> >>>
> >>>
> >> If your concern is memory size: the tables are __initdata, they will get
> >> freed once kernel boot is complete. the only representation of omap_opp
> >> will be what the opp layer's definition of the same.
> >>
> >> The intention was to be able to have a single uImage booting across
> >> multiple boards with multiple silicon -> e.g. today same uImage with
> >> omap_pm_defconfig will equally boot on sdp3430 as it does on sdp3630..
> >> which is what we all prefer.. so no ways of a compile time inclusion- it
> >> has to be runtime determined..
> >>
> >
> > Yeah, but if you have multiple board configuration, at compile time, your check
> > should add all selected tables.
> >
> > I just pointed that because it is the way I see in current code. You check at
> > compile time if you define tables or not, then at runtime you check which table
> > to use. That should still work for multi board configuration (using same image
> > for sdp3430 or sdp3630).
> >
> >
> 
> > Check  arch/arm/mach-omap2/mux.c or arch/arm/mach-omap2/mcbsp.c.
> >
> > There are other examples.  If you take a look on those you will see that it is
> > same issue you are dealing, defining static tables for several omap versions and then
> > just selecting which one to use at runtime. Besides, in mux.c you see that all are
> > also __initdata_or_module.
> >
> I think I still dont understand your intention ->
> a) pm34xx.c will not be a module -> it is meant to be built in, so
> __module addition to __initdata does not make any sense to it.

Well, I just commented that those have the "init" flag you mention earlier.

> 
> b) arch/arm/mach-omap2/pm34xx.c is omap3 series only build ONLY when OMAP3 is defined, there are only two of those families rt now, 34xx (of which 35xx is one), and 36xx series..
> so I dont need an enormous array definition like mux.h http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git;a=blob;f=arch/arm/mach-omap2/mux.c;h=c18a94eca641d61826fbad85322bc9f3d2cb4841;hb=HEAD#l257 where it is #ifdef OMAP3..
> 
> I am not trying to define for various OMAP versions, I am trying to
> define for various OMAP3 versions.. I hope this clarifies.

I still see as "a set of omap versions" support that is compiled in then
and you choose which one to use at run time.


> >
> >
> >>>
> >>>
> >>>> +
> >>>> +  for (i = 0; i < ARRAY_SIZE(omap3_rate_tables); i++) {
> >>>> +          ret = opp_init(omap3_rate_tables[i], omap3_opp_def_list[i]);
> >>>>            /* We dont want half configured system at the moment */
> >>>>            BUG_ON(ret);
> >>>>    }
> >>>> --
> >>>> 1.6.3.3
> >>>>
> >>>> --
> >>>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> >>>> the body of a message to majordomo@vger.kernel.org
> >>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >>>>
> >>>>
> >>>
> >>>
> >
> >

-- 
Eduardo Valentin

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 09/10 V3] omap3: pm: introduce 3630 opps
  2009-12-08 11:40                           ` Eduardo Valentin
@ 2009-12-08 14:15                             ` Nishanth Menon
  0 siblings, 0 replies; 36+ messages in thread
From: Nishanth Menon @ 2009-12-08 14:15 UTC (permalink / raw)
  To: eduardo.valentin
  Cc: linux-omap, Cousson, Benoit, Kevin Hilman, Chikkature Rajashekar,
	Madhusudhan, Paul Walmsley, Dasgupta, Romit, Premi, Sanjeev,
	Shilimkar, Santosh, Aguirre, Sergio, Gopinath, Thara, Sripathy,
	Vishwanath

Eduardo Valentin had written, on 12/08/2009 05:40 AM, the following:
> On Tue, Dec 08, 2009 at 12:31:13PM +0100, ext Nishanth Menon wrote:
>> Eduardo Valentin said the following on 12/08/2009 05:18 AM:
>>> On Tue, Dec 08, 2009 at 11:59:49AM +0100, ext Nishanth Menon wrote:
>>>
>>>> Hi,
>>>> thanks for your comments. few thoughts below.
>>>>
>>>> Eduardo Valentin said the following on 12/08/2009 01:49 AM:
>>>>
>>>>> Hello Nishanth,
>>>>>
>>>>> Few comments bellow.
>>>>>
>>>>> On Wed, Nov 25, 2009 at 05:09:18AM +0100, ext Nishanth Menon wrote:
>>>>>
>>>>>
>>>>>> Introduce the OMAP3630 OPPs including the defined OPP tuples.
>>>>>>
>>>>>> Further information on OMAP3630 can be found here:
>>>>>> http://focus.ti.com/general/docs/wtbu/wtbuproductcontent.tsp?templateId=6123&navigationId=12836&contentId=52606
>>>>>>
>>>>>> OMAP36xx family introduces:
>>>>>> VDD1 with 4 OPPs, of which OPP3 & 4 are available only on devices yet
>>>>>> to be introduced in 36xx family. Meanwhile, VDD2 has 2 opps.
>>>>>>
>>>>>> Device Support of OPPs->
>>>>>>            |<-3630-600->| (default)
>>>>>>            |<-      3630-800    ->| (device: TBD)
>>>>>>            |<-      3630-1000            ->| (device: TBD)
>>>>>> H/w OPP-> OPP50 OPP100       OPP-Turbo   OPP1G-SB
>>>>>> VDD1      OPP1  OPP2         OPP3        OPP4
>>>>>> VDD2      OPP1  OPP2         OPP2        OPP2
>>>>>>
>>>>>> Note:
>>>>>> a) TI h/w naming for OPPs are now standardized in terms of OPP50, 100,
>>>>>>    Turbo and SB. This maps as shown above to the opp IDs (s/w term).
>>>>>> b) For boards which need custom VDD1/2 OPPs, the opp table can be
>>>>>>    updated by the board file on a need basis after the
>>>>>>    omap3_pm_init_opp_table call. The OPPs introduced here are the
>>>>>>    official OPP table at this point in time.
>>>>>>
>>>>>> Cc: Benoit Cousson <b-cousson@ti.com>
>>>>>> Cc: Kevin Hilman <khilman@deeprootsystems.com>
>>>>>> Cc: Madhusudhan Chikkature Rajashekar <madhu.cr@ti.com>
>>>>>> Cc: Paul Walmsley <paul@pwsan.com>
>>>>>> Cc: Romit Dasgupta <romit@ti.com>
>>>>>> Cc: Sanjeev Premi <premi@ti.com>
>>>>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>>>> Cc: Sergio Alberto Aguirre Rodriguez <saaguirre@ti.com>
>>>>>> Cc: Thara Gopinath <thara@ti.com>
>>>>>> Cc: Vishwanath Sripathy <vishwanath.bs@ti.com>
>>>>>>
>>>>>> Signed-off-by: Nishanth Menon <nm@ti.com>
>>>>>> ---
>>>>>>  arch/arm/mach-omap2/pm34xx.c |   49 ++++++++++++++++++++++++++++++++++++++++-
>>>>>>  1 files changed, 47 insertions(+), 2 deletions(-)
>>>>>>
>>>>>> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
>>>>>> index ad21f5f..05ecf02 100644
>>>>>> --- a/arch/arm/mach-omap2/pm34xx.c
>>>>>> +++ b/arch/arm/mach-omap2/pm34xx.c
>>>>>> @@ -143,6 +143,41 @@ static struct omap_opp_def __initdata omap34xx_dsp_rate_table[] = {
>>>>>>    {.enabled = 0, .freq = 0, .u_volt = 0}
>>>>>>  };
>>>>>>
>>>>>> +static struct omap_opp_def __initdata omap36xx_mpu_rate_table[] = {
>>>>>> +  /*OPP1 - OPP50*/
>>>>>> +  {.enabled = true,  .freq = 300000000, .u_volt = 930000},
>>>>>> +  /*OPP2 - OPP100*/
>>>>>> +  {.enabled = true,  .freq = 600000000, .u_volt = 1100000},
>>>>>> +  /*OPP3 - OPP-Turbo*/
>>>>>> +  {.enabled = false, .freq = 800000000, .u_volt = 1260000},
>>>>>> +  /*OPP4 - OPP-SB*/
>>>>>> +  {.enabled = false, .freq = 1000000000, .u_volt = 1310000},
>>>>>> +  /* Terminator */
>>>>>> +  {.enabled = 0, .freq = 0, .u_volt = 0}
>>>>>> +};
>>>>>> +
>>>>>> +static struct omap_opp_def __initdata omap36xx_l3_rate_table[] = {
>>>>>> +  /*OPP1 - OPP50 */
>>>>>> +  {.enabled = true, .freq = 100000000, .u_volt = 930000},
>>>>>> +  /*OPP2 - OPP100, OPP-Turbo, OPP-SB*/
>>>>>> +  {.enabled = true, .freq = 200000000, .u_volt = 1137500},
>>>>>> +  /* Terminator */
>>>>>> +  {.enabled = 0, .freq = 0, .u_volt = 0}
>>>>>> +};
>>>>>> +
>>>>>> +static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
>>>>>> +  /*OPP1 - OPP50*/
>>>>>> +  {.enabled = true,  .freq = 260000000, .u_volt = 930000},
>>>>>> +  /*OPP2 - OPP100*/
>>>>>> +  {.enabled = true,  .freq = 520000000, .u_volt = 1100000},
>>>>>> +  /*OPP3 - OPP-Turbo*/
>>>>>> +  {.enabled = false, .freq = 660000000, .u_volt = 1260000},
>>>>>> +  /*OPP4 - OPP-SB*/
>>>>>> +  {.enabled = false, .freq = 875000000, .u_volt = 1310000},
>>>>>> +  /* Terminator */
>>>>>> +  {.enabled = 0, .freq = 0, .u_volt = 0}
>>>>>> +};
>>>>>> +
>>>>>>
>>>>>>
>>>>> Although it is not mandatory, I'd say this way of initializing structure array is more common:
>>>>>
>>>>> static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
>>>>>     /*OPP1 - OPP50*/
>>>>>     {
>>>>>             .enabled        = true,
>>>>>             .freq           = 260000000,
>>>>>             .u_volt         = 930000,
>>>>>     },
>>>>>     /*OPP2 - OPP100*/
>>>>>     {
>>>>>             .enabled        = true,
>>>>>             .freq           = 520000000,
>>>>>             .u_volt         = 1100000,
>>>>>     },
>>>>>     /*OPP3 - OPP-Turbo*/
>>>>>     {
>>>>>             .enabled        = false,
>>>>>             .freq           = 660000000,
>>>>>             .u_volt         = 1260000,
>>>>>     },
>>>>>     /*OPP4 - OPP-SB*/
>>>>>     {
>>>>>             .enabled        = false,
>>>>>             .freq           = 875000000,
>>>>>             .u_volt         = 1310000,
>>>>>     },
>>>>>     /* Terminator */
>>>>>     {
>>>>>             .enabled        = 0,
>>>>>             .freq           = 0,
>>>>>             .u_volt         = 0,
>>>>>     }
>>>>> };
>>>>>
>>>>> and if you thing it is line consuming, you can always define a "INIT" macro:
>>>>> #define     OMAP_OPP_DEF(_enabled, _freq, _uv)      \
>>>>> {                                           \
>>>>>     .enabled        = _enabled,             \
>>>>>     .freq           = _freq,                \
>>>>>     .u_volt         = _uv,                  \
>>>>> }
>>>>>
>>>>> and use it to initialize your array:
>>>>>
>>>>>     /*OPP1 - OPP50*/
>>>>> static struct omap_opp_def __initdata omap36xx_dsp_rate_table[] = {
>>>>>     OMAP_OPP_DEF(true, 260000000, 930000),
>>>>>     OMAP_OPP_DEF(true, 520000000, 1100000),
>>>>>     OMAP_OPP_DEF(false, 660000000, 1260000),
>>>>>     OMAP_OPP_DEF(false, 875000000, 1310000},
>>>>>     OMAP_OPP_DEF(0, 0, 0),
>>>>> };
>>>>>
>>>>>
>>>> Thanks. yep, I agree this looks cleaner. I vote for this. probably will
>>>> use OMAP_OPP_TERM to denote (0,0,0)
>>>>
>>> Nice,
>>>
>>>
>>>>> Beside, although it should not hurt as they are not too big, these tables should
>>>>> be compiled only if omap3630 is the target right?
>>>>>
>>>>>
>>>>>
>>>>>>  struct omap_opp *omap3_mpu_rate_table;
>>>>>>  struct omap_opp *omap3_dsp_rate_table;
>>>>>>  struct omap_opp *omap3_l3_rate_table;
>>>>>> @@ -1299,18 +1334,28 @@ static void __init configure_vc(void)
>>>>>>  void __init omap3_pm_init_opp_table(void)
>>>>>>  {
>>>>>>    int ret, i;
>>>>>> +  struct omap_opp_def **omap3_opp_def_list;
>>>>>>    struct omap_opp_def *omap34xx_opp_def_list[] = {
>>>>>>            omap34xx_mpu_rate_table,
>>>>>>            omap34xx_l3_rate_table,
>>>>>>            omap34xx_dsp_rate_table
>>>>>>    };
>>>>>> +  struct omap_opp_def *omap36xx_opp_def_list[] = {
>>>>>> +          omap36xx_mpu_rate_table,
>>>>>> +          omap36xx_l3_rate_table,
>>>>>> +          omap36xx_dsp_rate_table
>>>>>> +  };
>>>>>>    struct omap_opp **omap3_rate_tables[] = {
>>>>>>            &omap3_mpu_rate_table,
>>>>>>            &omap3_l3_rate_table,
>>>>>>            &omap3_dsp_rate_table
>>>>>>    };
>>>>>> -  for (i = 0; i < ARRAY_SIZE(omap34xx_opp_def_list); i++) {
>>>>>> -          ret = opp_init(omap3_rate_tables[i], omap34xx_opp_def_list[i]);
>>>>>> +
>>>>>> +  omap3_opp_def_list = cpu_is_omap3630() ? omap36xx_opp_def_list :
>>>>>> +                          omap34xx_opp_def_list;
>>>>>>
>>>>>>
>>>>> here you cared for runtime target check, but tables above could be avoid if not omap3630.
>>>>>
>>>>>
>>>> If your concern is memory size: the tables are __initdata, they will get
>>>> freed once kernel boot is complete. the only representation of omap_opp
>>>> will be what the opp layer's definition of the same.
>>>>
>>>> The intention was to be able to have a single uImage booting across
>>>> multiple boards with multiple silicon -> e.g. today same uImage with
>>>> omap_pm_defconfig will equally boot on sdp3430 as it does on sdp3630..
>>>> which is what we all prefer.. so no ways of a compile time inclusion- it
>>>> has to be runtime determined..
>>>>
>>> Yeah, but if you have multiple board configuration, at compile time, your check
>>> should add all selected tables.
>>>
>>> I just pointed that because it is the way I see in current code. You check at
>>> compile time if you define tables or not, then at runtime you check which table
>>> to use. That should still work for multi board configuration (using same image
>>> for sdp3430 or sdp3630).
>>>
>>>
>>> Check  arch/arm/mach-omap2/mux.c or arch/arm/mach-omap2/mcbsp.c.
>>>
>>> There are other examples.  If you take a look on those you will see that it is
>>> same issue you are dealing, defining static tables for several omap versions and then
>>> just selecting which one to use at runtime. Besides, in mux.c you see that all are
>>> also __initdata_or_module.
>>>
>> I think I still dont understand your intention ->
>> a) pm34xx.c will not be a module -> it is meant to be built in, so
>> __module addition to __initdata does not make any sense to it.
> 
> Well, I just commented that those have the "init" flag you mention earlier.
> 
>> b) arch/arm/mach-omap2/pm34xx.c is omap3 series only build ONLY when OMAP3 is defined, there are only two of those families rt now, 34xx (of which 35xx is one), and 36xx series..
>> so I dont need an enormous array definition like mux.h http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git;a=blob;f=arch/arm/mach-omap2/mux.c;h=c18a94eca641d61826fbad85322bc9f3d2cb4841;hb=HEAD#l257 where it is #ifdef OMAP3..
>>
>> I am not trying to define for various OMAP versions, I am trying to
>> define for various OMAP3 versions.. I hope this clarifies.
> 
> I still see as "a set of omap versions" support that is compiled in then
> and you choose which one to use at run time.
> 
As discussed on irc [1] and in l-o [2] previously, dropping the #ifdef 
proposal.

> 
>>>
>>>>>
>>>>>> +
>>>>>> +  for (i = 0; i < ARRAY_SIZE(omap3_rate_tables); i++) {
>>>>>> +          ret = opp_init(omap3_rate_tables[i], omap3_opp_def_list[i]);
>>>>>>            /* We dont want half configured system at the moment */
>>>>>>            BUG_ON(ret);
>>>>>>    }
>>>>>> --
>>>>>> 1.6.3.3
>>>>>>
>>>>>> --
>>>>>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
>>>>>> the body of a message to majordomo@vger.kernel.org
>>>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>>>>
>>>>>>
>>>>>
>>>
> 
> --
> Eduardo Valentin


-- 
Regards,
Nishanth Menon
Ref:
[1] http://omapzoom.org/ozbotlogs/index.php?date=2009-12-08#T12:58:13
[2] http://marc.info/?t=125343303400003&r=1&w=2

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2009-12-08 14:15 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-25  4:09 [PATCH 00/10 v3] omap3: pm: introduce support for 3630 OPPs Nishanth Menon
2009-11-25  4:09 ` [PATCH 01/10] omap3: pm: introduce enabled flag to omap_opp Nishanth Menon
2009-11-25  4:09   ` [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions Nishanth Menon
2009-11-25  4:09     ` [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx Nishanth Menon
2009-11-25  4:09       ` [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions Nishanth Menon
2009-11-25  4:09         ` [PATCH 05/10 V3] omap3: pm: sr: replace get_opp with freq_to_opp Nishanth Menon
2009-11-25  4:09           ` [PATCH 06/10 V3] omap3: pm: use opp accessor functions for omap-target Nishanth Menon
2009-11-25  4:09             ` [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table Nishanth Menon
2009-11-25  4:09               ` [PATCH 08/10] omap3: pm: remove VDDx_MIN/MAX macros Nishanth Menon
2009-11-25  4:09                 ` [PATCH 09/10 V3] omap3: pm: introduce 3630 opps Nishanth Menon
2009-11-25  4:09                   ` [PATCH 10/10] omap3: pm: omap3630 boards: enable 3630 opp tables Nishanth Menon
2009-12-08  7:49                   ` [PATCH 09/10 V3] omap3: pm: introduce 3630 opps Eduardo Valentin
2009-12-08 10:59                     ` Menon, Nishanth
2009-12-08 11:18                       ` Eduardo Valentin
2009-12-08 11:31                         ` Menon, Nishanth
2009-12-08 11:40                           ` Eduardo Valentin
2009-12-08 14:15                             ` Nishanth Menon
2009-12-07 16:54               ` [PATCH 07/10 V3] omap3: clk: use pm accessor functions for cpufreq table Tero.Kristo
2009-12-08 11:09                 ` Menon, Nishanth
2009-12-08  7:54               ` Eduardo Valentin
2009-11-25 17:56             ` [PATCH 06/10 V3] omap3: pm: use opp accessor functions for omap-target Kevin Hilman
2009-12-08  7:59               ` Eduardo Valentin
2009-12-07 16:59         ` [PATCH 04/10 V3] omap3: pm: srf: use opp accessor functions Tero.Kristo
2009-12-08 11:14           ` Menon, Nishanth
2009-11-25 17:22       ` [PATCH 03/10 V3] omap3: pm: use opp accessor functions for omap34xx Kevin Hilman
2009-11-25 17:27         ` Kevin Hilman
2009-12-07 17:02         ` Tero.Kristo
2009-12-08 11:16           ` Menon, Nishanth
2009-12-08  8:08       ` Eduardo Valentin
2009-11-25 16:30     ` [PATCH 02/10 V3] omap3: pm: introduce opp accessor functions Kevin Hilman
2009-11-25 20:31       ` Nishanth Menon
2009-11-25 23:46         ` Kevin Hilman
2009-11-26  0:22           ` Menon, Nishanth
2009-12-08  8:23             ` Eduardo Valentin
2009-12-08 11:01               ` Menon, Nishanth
2009-11-25 15:24 ` [PATCH 00/10 v3] omap3: pm: introduce support for 3630 OPPs Kevin Hilman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.