All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/16] OMAP3: PM: Smartreflex and voltage revamp.
@ 2010-02-24  9:29 Thara Gopinath
  2010-02-24  9:29 ` [PATCH 01/16] OMAP3: PM: Adding hwmod data for Smartreflex Thara Gopinath
  2010-03-06  0:58 ` [PATCH 00/16] OMAP3: PM: Smartreflex and voltage revamp Kevin Hilman
  0 siblings, 2 replies; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant,
	Thara Gopinath (none)

From: Thara Gopinath <thara@omaplbp.(none)>

This main motivations behind this patch series are the following
1. Making smartreflex a platform driver with omap-device layer.
2. Separating voltage specific code from smartreflex.c and other
   locations and consolidating them into voltage.c and voltage.h.
3. Smartreflex module can have Class 3 or Class 2 implementations
   depending on the PMIC in use. Making smartreflex.c capable
   of handling both the class implementaions and separating out
   class specific code into a separate class driver.
4. Implementating  latest TI recommended register settings for
  Smartreflex and Voltage processor module as well as recommended
  sequences for enabling and disabling of Smartreflex and Voltage
  processor modules.
5. Implementing VP force update method of voltage scaling which is
   again TI hardware recommended.

What this patch series does not address are
1. Separating PMIC specific portions from smartreflex and voltage code.
2. OMAP3630 and OMP4 smartreflex support.

This patch series is based on Kevin's PM tree origin/pm-wip-opp branch
and is dependent on the following patches not yet applied onto this branch.

http://patchwork.kernel.org/patch/79523/
http://patchwork.kernel.org/patch/81504/
http://patchwork.kernel.org/patch/81606/

This patch series has been tested on OMAP3430 SDP with basic power
management tests including the dvfs scripts.

Thara Gopinath (16):
  OMAP3: PM: Adding hwmod data for Smartreflex
  OMAP3: PM: Create list to keep track of various smartreflex
    instances.
  OMAP3: PM: Convert smartreflex driver into a platform driver using
    hwmods and omap-device layer
  OMAP3: PM: Move smartreflex autocompensation enable disable hooks to
    PM debugfs.
  OMAP3: PM: Export get_vdd1_opp and get_vdd2_opp from shared resource
    framework
  OMAP3: PM: Smartreflex class related changes for smartreflex.c
  OMAP3: PM: Adding smartreflex class 3 driver.
  OMAP3: PM: Disabling Smartreflex across both frequency and voltage
    scaling during DVFS.
  OMAP3: PM: Creating separate files for handling OMAP3 voltage related
    operations.
  OMAP3: PM: Cleaning up of smartreflex header file.
  OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex
    Class 3
  OMAP3: PM: Support for enabling smartreflex autocompensation by
    default.
  OMAP3: PM: Correcting accessing of ERRCONFIG register in
    smartreflex.c
  OMAP3: PM: Implement latest h/w recommendations for SR and VP
    registers and SR VP enable disable sequence.
  OMAP3: PM: VP force update method of voltage scaling
  OMAP3: PM: Enabling Smartreflex Class 3 driver by default in pm
    defconfig

 arch/arm/configs/omap3_pm_defconfig      |    1 +
 arch/arm/mach-omap2/Makefile             |    4 +-
 arch/arm/mach-omap2/board-3430sdp.c      |    3 +-
 arch/arm/mach-omap2/omap_hwmod_34xx.h    |   92 ++
 arch/arm/mach-omap2/pm-debug.c           |    4 +-
 arch/arm/mach-omap2/pm.h                 |    7 -
 arch/arm/mach-omap2/pm34xx.c             |   95 +--
 arch/arm/mach-omap2/resource34xx.c       |   28 +-
 arch/arm/mach-omap2/resource34xx.h       |    1 -
 arch/arm/mach-omap2/smartreflex-class3.c |   54 ++
 arch/arm/mach-omap2/smartreflex.c        | 1431 +++++++++++++-----------------
 arch/arm/mach-omap2/smartreflex.h        |  319 +++----
 arch/arm/mach-omap2/voltage.c            |  748 ++++++++++++++++
 arch/arm/mach-omap2/voltage.h            |   77 ++
 arch/arm/plat-omap/Kconfig               |   30 +-
 15 files changed, 1805 insertions(+), 1089 deletions(-)
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
 create mode 100644 arch/arm/mach-omap2/voltage.c
 create mode 100644 arch/arm/mach-omap2/voltage.h


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

* [PATCH 01/16] OMAP3: PM: Adding hwmod data for Smartreflex
  2010-02-24  9:29 [PATCH 00/16] OMAP3: PM: Smartreflex and voltage revamp Thara Gopinath
@ 2010-02-24  9:29 ` Thara Gopinath
  2010-02-24  9:29   ` [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances Thara Gopinath
                     ` (2 more replies)
  2010-03-06  0:58 ` [PATCH 00/16] OMAP3: PM: Smartreflex and voltage revamp Kevin Hilman
  1 sibling, 3 replies; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

This patch adds the hwmod strucutres and other hwmod data for
OMAP3 Smartreflex IP's.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_34xx.h |   92 +++++++++++++++++++++++++++++++++
 1 files changed, 92 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_34xx.h b/arch/arm/mach-omap2/omap_hwmod_34xx.h
index 2e629dc..dccb4a4 100644
--- a/arch/arm/mach-omap2/omap_hwmod_34xx.h
+++ b/arch/arm/mach-omap2/omap_hwmod_34xx.h
@@ -25,6 +25,8 @@ static struct omap_hwmod omap34xx_mpu_hwmod;
 static struct omap_hwmod omap34xx_l3_hwmod;
 static struct omap_hwmod omap34xx_l4_core_hwmod;
 static struct omap_hwmod omap34xx_l4_per_hwmod;
+static struct omap_hwmod omap34xx_sr1_hwmod;
+static struct omap_hwmod omap34xx_sr2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap34xx_l3__l4_core = {
@@ -77,9 +79,49 @@ static struct omap_hwmod_ocp_if omap34xx_l4_core__l4_wkup = {
 	.user	= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> SR1 interface */
+static struct omap_hwmod_addr_space omap34xx_sr1_addr_space[] = {
+	{
+		.pa_start	= OMAP34XX_SR1_BASE,
+		.pa_end		= OMAP34XX_SR1_BASE + SZ_1K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__sr1 = {
+	.master		= &omap34xx_l4_core_hwmod,
+	.slave		= &omap34xx_sr1_hwmod,
+	.clkdev_dev_id	= NULL,
+	.clkdev_con_id  = NULL,
+	.addr		= omap34xx_sr1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap34xx_sr1_addr_space),
+	.user		= OCP_USER_MPU,
+};
+
+/* L4 CORE -> SR1 interface */
+static struct omap_hwmod_addr_space omap34xx_sr2_addr_space[] = {
+	{
+		.pa_start	= OMAP34XX_SR2_BASE,
+		.pa_end		= OMAP34XX_SR2_BASE + SZ_1K - 1,
+		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__sr2 = {
+	.master		= &omap34xx_l4_core_hwmod,
+	.slave		= &omap34xx_sr2_hwmod,
+	.clkdev_dev_id	= NULL,
+	.clkdev_con_id  = NULL,
+	.addr		= omap34xx_sr2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap34xx_sr2_addr_space),
+	.user		= OCP_USER_MPU,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap34xx_l4_core_slaves[] = {
 	&omap34xx_l3__l4_core,
+	&omap3_l4_core__sr1,
+	&omap3_l4_core__sr2,
 };
 
 /* Master interfaces on the L4_CORE interconnect */
@@ -150,12 +192,62 @@ static struct omap_hwmod omap34xx_mpu_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
+/* SR common */
+static struct omap_hwmod_sysc_fields sr_sysc_fields = {
+	.clkact_shift	= 20,
+};
+
+static struct omap_hwmod_sysconfig sr_if_ctrl = {
+	.sysc_offs	= 0x24,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_NO_CACHE),
+	.clockact	= CLOCKACT_TEST_ICLK,
+	.sysc_fields	= &sr_sysc_fields,
+};
+
+/* SR1 */
+static struct omap_hwmod_ocp_if *omap34xx_sr1_slaves[] = {
+	&omap3_l4_core__sr1,
+};
+
+static struct omap_hwmod omap34xx_sr1_hwmod = {
+	.name		= "sr1_hwmod",
+	.mpu_irqs	= NULL,
+	.sdma_chs	= NULL,
+	.clkdev_dev_id	= NULL,
+	.clkdev_con_id	= "sr1_fck",
+	.slaves		= omap34xx_sr1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap34xx_sr1_slaves),
+	.sysconfig	= &sr_if_ctrl,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
+};
+
+/* SR2 */
+static struct omap_hwmod_ocp_if *omap34xx_sr2_slaves[] = {
+	&omap3_l4_core__sr2,
+};
+
+static struct omap_hwmod omap34xx_sr2_hwmod = {
+	.name		= "sr2_hwmod",
+	.mpu_irqs	= NULL,
+	.sdma_chs	= NULL,
+	.clkdev_dev_id	= NULL,
+	.clkdev_con_id	= "sr2_fck",
+	.slaves		= omap34xx_sr2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap34xx_sr2_slaves),
+	.sysconfig	= &sr_if_ctrl,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
+};
+
 static __initdata struct omap_hwmod *omap34xx_hwmods[] = {
 	&omap34xx_l3_hwmod,
 	&omap34xx_l4_core_hwmod,
 	&omap34xx_l4_per_hwmod,
 	&omap34xx_l4_wkup_hwmod,
 	&omap34xx_mpu_hwmod,
+	&omap34xx_sr1_hwmod,
+	&omap34xx_sr2_hwmod,
 	NULL,
 };
 
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances.
  2010-02-24  9:29 ` [PATCH 01/16] OMAP3: PM: Adding hwmod data for Smartreflex Thara Gopinath
@ 2010-02-24  9:29   ` Thara Gopinath
  2010-02-24  9:29     ` [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer Thara Gopinath
                       ` (2 more replies)
  2010-02-24 16:52   ` [PATCH 01/16] OMAP3: PM: Adding hwmod data for Smartreflex Mike Turquette
  2010-03-06  0:45   ` Kevin Hilman
  2 siblings, 3 replies; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

This patch removes the pointer sr1, sr2 in smartreflex.c and
instead creatse a list for keeping track of multiple smartreflex
instances.. This makes it scalable for next gen OMAPs where there
are more than two smartreflex modules.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/smartreflex.c |  114 ++++++++++++++++++++++++------------
 1 files changed, 76 insertions(+), 38 deletions(-)

diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 1c5ec37..4a9c2e2 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -26,6 +26,7 @@
 #include <linux/kobject.h>
 #include <linux/i2c/twl.h>
 #include <linux/io.h>
+#include <linux/list.h>
 
 #include <plat/omap34xx.h>
 #include <plat/control.h>
@@ -51,9 +52,12 @@ struct omap_sr {
 	u32		opp5_nvalue;
 	u32		senp_mod, senn_mod;
 	void __iomem	*srbase_addr;
-	void __iomem	*vpbase_addr;
+	struct list_head 	node;
 };
 
+/* sr_list contains all the instances of smartreflex module */
+static LIST_HEAD(sr_list);
+
 #define SR_REGADDR(offs)	(sr->srbase_addr + offset)
 
 static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
@@ -78,6 +82,20 @@ static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
 	return __raw_readl(SR_REGADDR(offset));
 }
 
+static struct omap_sr *_sr_lookup(int srid)
+{
+	struct omap_sr *sr_info, *temp_sr_info;
+
+	sr_info = NULL;
+	list_for_each_entry(temp_sr_info, &sr_list, node) {
+		if (srid == temp_sr_info->srid) {
+			sr_info = temp_sr_info;
+			break;
+		}
+	}
+	return sr_info;
+}
+
 static int sr_clk_enable(struct omap_sr *sr)
 {
 	if (clk_enable(sr->clk) != 0) {
@@ -151,11 +169,17 @@ static u8 get_vdd1_opp(void)
 {
 	struct omap_opp *opp;
 	unsigned long freq;
+	struct omap_sr *sr_info = _sr_lookup(SR1);
 
-	if (sr1.vdd_opp_clk == NULL || IS_ERR(sr1.vdd_opp_clk))
+	if (!sr_info) {
+		pr_warning("omap_sr struct corresponding to SR1 not found\n");
+		return 0;
+	}
+
+	if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
 		return 0;
 
-	freq = sr1.vdd_opp_clk->rate;
+	freq = sr_info->vdd_opp_clk->rate;
 	opp = opp_find_freq_ceil(OPP_MPU, &freq);
 	if (IS_ERR(opp))
 		return 0;
@@ -163,9 +187,9 @@ static u8 get_vdd1_opp(void)
 	 * Use higher freq voltage even if an exact match is not available
 	 * we are probably masking a clock framework bug, so warn
 	 */
-	if (unlikely(freq != sr1.vdd_opp_clk->rate))
+	if (unlikely(freq != sr_info->vdd_opp_clk->rate))
 		pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
-			   __func__, freq, sr1.vdd_opp_clk->rate);
+			   __func__, freq, sr_info->vdd_opp_clk->rate);
 
 	return opp_get_opp_id(opp);
 }
@@ -174,11 +198,17 @@ static u8 get_vdd2_opp(void)
 {
 	struct omap_opp *opp;
 	unsigned long freq;
+	struct omap_sr *sr_info = _sr_lookup(SR2);
+
+	if (!sr_info) {
+		pr_warning("omap_sr struct corresponding to SR2 not found\n");
+		return 0;
+	}
 
-	if (sr2.vdd_opp_clk == NULL || IS_ERR(sr2.vdd_opp_clk))
+	if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
 		return 0;
 
-	freq = sr2.vdd_opp_clk->rate;
+	freq = sr_info->vdd_opp_clk->rate;
 	opp = opp_find_freq_ceil(OPP_L3, &freq);
 	if (IS_ERR(opp))
 		return 0;
@@ -187,9 +217,9 @@ static u8 get_vdd2_opp(void)
 	 * Use higher freq voltage even if an exact match is not available
 	 * we are probably masking a clock framework bug, so warn
 	 */
-	if (unlikely(freq != sr2.vdd_opp_clk->rate))
+	if (unlikely(freq != sr_info->vdd_opp_clk->rate))
 		pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
-			   __func__, freq, sr2.vdd_opp_clk->rate);
+			   __func__, freq, sr_info->vdd_opp_clk->rate);
 	return opp_get_opp_id(opp);
 }
 
@@ -694,14 +724,13 @@ static void sr_disable(struct omap_sr *sr)
 
 void sr_start_vddautocomap(int srid, u32 target_opp_no)
 {
-	struct omap_sr *sr = NULL;
+	struct omap_sr *sr = _sr_lookup(srid);
 
-	if (srid == SR1)
-		sr = &sr1;
-	else if (srid == SR2)
-		sr = &sr2;
-	else
+	if (!sr) {
+		pr_warning("omap_sr struct corresponding to SR%d not found\n",
+								srid);
 		return;
+	}
 
 	if (sr->is_sr_reset == 1) {
 		sr_clk_enable(sr);
@@ -719,14 +748,13 @@ EXPORT_SYMBOL(sr_start_vddautocomap);
 
 int sr_stop_vddautocomap(int srid)
 {
-	struct omap_sr *sr = NULL;
+	struct omap_sr *sr = _sr_lookup(srid);
 
-	if (srid == SR1)
-		sr = &sr1;
-	else if (srid == SR2)
-		sr = &sr2;
-	else
-		return -EINVAL;
+	if (!sr) {
+		pr_warning("omap_sr struct corresponding to SR%d not found\n",
+								srid);
+		return false;
+	}
 
 	if (sr->is_autocomp_active == 1) {
 		sr_disable(sr);
@@ -744,14 +772,13 @@ EXPORT_SYMBOL(sr_stop_vddautocomap);
 void enable_smartreflex(int srid)
 {
 	u32 target_opp_no = 0;
-	struct omap_sr *sr = NULL;
+	struct omap_sr *sr = _sr_lookup(srid);
 
-	if (srid == SR1)
-		sr = &sr1;
-	else if (srid == SR2)
-		sr = &sr2;
-	else
+	if (!sr) {
+		pr_warning("omap_sr struct corresponding to SR%d not found\n",
+								srid);
 		return;
+	}
 
 	if (sr->is_autocomp_active == 1) {
 		if (sr->is_sr_reset == 1) {
@@ -779,15 +806,13 @@ void enable_smartreflex(int srid)
 void disable_smartreflex(int srid)
 {
 	u32 i = 0;
+	struct omap_sr *sr = _sr_lookup(srid);
 
-	struct omap_sr *sr = NULL;
-
-	if (srid == SR1)
-		sr = &sr1;
-	else if (srid == SR2)
-		sr = &sr2;
-	else
+	if (!sr) {
+		pr_warning("omap_sr struct corresponding to SR%d not found\n",
+								srid);
 		return;
+	}
 
 	if (sr->is_autocomp_active == 1) {
 		if (sr->is_sr_reset == 0) {
@@ -920,7 +945,13 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
 static ssize_t omap_sr_vdd1_autocomp_show(struct kobject *kobj,
 					struct kobj_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", sr1.is_autocomp_active);
+	struct omap_sr *sr_info = _sr_lookup(SR1);
+
+	if (!sr_info) {
+		pr_warning("omap_sr struct corresponding to SR1 not found\n");
+		return 0;
+	}
+	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
 }
 
 static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj,
@@ -960,7 +991,13 @@ static struct kobj_attribute sr_vdd1_autocomp = {
 static ssize_t omap_sr_vdd2_autocomp_show(struct kobject *kobj,
 					struct kobj_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", sr2.is_autocomp_active);
+	struct omap_sr *sr_info = _sr_lookup(SR2);
+
+	if (!sr_info) {
+		pr_warning("omap_sr struct corresponding to SR2 not found\n");
+		return 0;
+	}
+	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
 }
 
 static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj,
@@ -1010,7 +1047,6 @@ static int __init omap3_sr_init(void)
 	RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
 	ret |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
 				R_DCDC_GLOBAL_CFG);
-
 	if (cpu_is_omap34xx()) {
 		sr1.clk = clk_get(NULL, "sr1_fck");
 		sr2.clk = clk_get(NULL, "sr2_fck");
@@ -1036,6 +1072,8 @@ static int __init omap3_sr_init(void)
 	ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
 	if (ret)
 		pr_err("sysfs_create_file failed: %d\n", ret);
+	list_add(&sr1.node, &sr_list);
+	list_add(&sr2.node, &sr_list);
 
 	return 0;
 }
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer
  2010-02-24  9:29   ` [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances Thara Gopinath
@ 2010-02-24  9:29     ` Thara Gopinath
  2010-02-24  9:29       ` [PATCH 04/16] OMAP3: PM: Move smartreflex autocompensation enable disable hooks to PM debugfs Thara Gopinath
                         ` (3 more replies)
  2010-02-25  1:42     ` [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances ambresh
  2010-02-26 23:21     ` Mike Turquette
  2 siblings, 4 replies; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

This patch converts the exisitng smartreflex library into a
platform driver with device , driver registrations using hardware mods.
As part of this Ntarget values are passed as platform data.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/smartreflex.c |  470 +++++++++++++++++++++----------------
 arch/arm/mach-omap2/smartreflex.h |   27 ++
 2 files changed, 293 insertions(+), 204 deletions(-)

diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 4a9c2e2..05c72b2 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -14,7 +14,6 @@
  * published by the Free Software Foundation.
  */
 
-
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -33,6 +32,8 @@
 #include <plat/clock.h>
 #include <plat/opp.h>
 #include <plat/opp_twl_tps.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 
 #include "prm.h"
 #include "smartreflex.h"
@@ -41,17 +42,14 @@
 #define MAX_TRIES 100
 
 struct omap_sr {
-	int		srid;
-	int		is_sr_reset;
-	int		is_autocomp_active;
-	struct clk	*clk;
-	struct clk	*vdd_opp_clk;
-	u32		clk_length;
-	u32		req_opp_no;
-	u32		opp1_nvalue, opp2_nvalue, opp3_nvalue, opp4_nvalue;
-	u32		opp5_nvalue;
-	u32		senp_mod, senn_mod;
-	void __iomem	*srbase_addr;
+	int			srid;
+	int			is_sr_reset;
+	int			is_autocomp_active;
+	struct clk		*vdd_opp_clk;
+	u32			clk_length;
+	void __iomem		*srbase_addr;
+	unsigned int		irq;
+	struct platform_device 	*pdev;
 	struct list_head 	node;
 };
 
@@ -98,71 +96,22 @@ static struct omap_sr *_sr_lookup(int srid)
 
 static int sr_clk_enable(struct omap_sr *sr)
 {
-	if (clk_enable(sr->clk) != 0) {
-		pr_err("Could not enable %s\n", sr->clk->name);
-		return -1;
-	}
+	struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
 
-	/* set fclk- active , iclk- idle */
-	sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
-		      SR_CLKACTIVITY_IOFF_FON);
+	if (pdata->device_enable)
+		pdata->device_enable(sr->pdev);
 
 	return 0;
 }
 
 static void sr_clk_disable(struct omap_sr *sr)
 {
-	/* set fclk, iclk- idle */
-	sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
-		      SR_CLKACTIVITY_IOFF_FOFF);
-
-	clk_disable(sr->clk);
-	sr->is_sr_reset = 1;
-}
+	struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
 
-static struct omap_sr sr1 = {
-	.srid			= SR1,
-	.is_sr_reset		= 1,
-	.is_autocomp_active	= 0,
-	.clk_length		= 0,
-	.srbase_addr		= OMAP2_L4_IO_ADDRESS(OMAP34XX_SR1_BASE),
-};
-
-static struct omap_sr sr2 = {
-	.srid			= SR2,
-	.is_sr_reset		= 1,
-	.is_autocomp_active	= 0,
-	.clk_length		= 0,
-	.srbase_addr		= OMAP2_L4_IO_ADDRESS(OMAP34XX_SR2_BASE),
-};
+	if (pdata->device_idle)
+		pdata->device_idle(sr->pdev);
 
-static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen)
-{
-	u32 gn, rn, mul;
-
-	for (gn = 0; gn < GAIN_MAXLIMIT; gn++) {
-		mul = 1 << (gn + 8);
-		rn = mul / sensor;
-		if (rn < R_MAXLIMIT) {
-			*sengain = gn;
-			*rnsen = rn;
-		}
-	}
-}
-
-static u32 cal_test_nvalue(u32 sennval, u32 senpval)
-{
-	u32 senpgain, senngain;
-	u32 rnsenp, rnsenn;
-
-	/* Calculating the gain and reciprocal of the SenN and SenP values */
-	cal_reciprocal(senpval, &senpgain, &rnsenp);
-	cal_reciprocal(sennval, &senngain, &rnsenn);
-
-	return (senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |
-		(senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |
-		(rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |
-		(rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT);
+	sr->is_sr_reset = 1;
 }
 
 static u8 get_vdd1_opp(void)
@@ -255,76 +204,6 @@ static void sr_set_clk_length(struct omap_sr *sr)
 	}
 }
 
-static void sr_set_efuse_nvalues(struct omap_sr *sr)
-{
-	if (sr->srid == SR1) {
-		sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
-					OMAP343X_SR1_SENNENABLE_MASK) >>
-					OMAP343X_SR1_SENNENABLE_SHIFT;
-		sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
-					OMAP343X_SR1_SENPENABLE_MASK) >>
-					OMAP343X_SR1_SENPENABLE_SHIFT;
-
-		sr->opp5_nvalue = omap_ctrl_readl(
-					OMAP343X_CONTROL_FUSE_OPP5_VDD1);
-		sr->opp4_nvalue = omap_ctrl_readl(
-					OMAP343X_CONTROL_FUSE_OPP4_VDD1);
-		sr->opp3_nvalue = omap_ctrl_readl(
-					OMAP343X_CONTROL_FUSE_OPP3_VDD1);
-		sr->opp2_nvalue = omap_ctrl_readl(
-					OMAP343X_CONTROL_FUSE_OPP2_VDD1);
-		sr->opp1_nvalue = omap_ctrl_readl(
-					OMAP343X_CONTROL_FUSE_OPP1_VDD1);
-	} else if (sr->srid == SR2) {
-		sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
-					OMAP343X_SR2_SENNENABLE_MASK) >>
-					OMAP343X_SR2_SENNENABLE_SHIFT;
-
-		sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
-					OMAP343X_SR2_SENPENABLE_MASK) >>
-					OMAP343X_SR2_SENPENABLE_SHIFT;
-
-		sr->opp3_nvalue = omap_ctrl_readl(
-					OMAP343X_CONTROL_FUSE_OPP3_VDD2);
-		sr->opp2_nvalue = omap_ctrl_readl(
-					OMAP343X_CONTROL_FUSE_OPP2_VDD2);
-		sr->opp1_nvalue = omap_ctrl_readl(
-					OMAP343X_CONTROL_FUSE_OPP1_VDD2);
-	}
-}
-
-/* Hard coded nvalues for testing purposes, may cause device to hang! */
-static void sr_set_testing_nvalues(struct omap_sr *sr)
-{
-	if (sr->srid == SR1) {
-		sr->senp_mod = 0x03;	/* SenN-M5 enabled */
-		sr->senn_mod = 0x03;
-
-		/* calculate nvalues for each opp */
-		sr->opp5_nvalue = cal_test_nvalue(0xacd + 0x330, 0x848 + 0x330);
-		sr->opp4_nvalue = cal_test_nvalue(0x964 + 0x2a0, 0x727 + 0x2a0);
-		sr->opp3_nvalue = cal_test_nvalue(0x85b + 0x200, 0x655 + 0x200);
-		sr->opp2_nvalue = cal_test_nvalue(0x506 + 0x1a0, 0x3be + 0x1a0);
-		sr->opp1_nvalue = cal_test_nvalue(0x373 + 0x100, 0x28c + 0x100);
-	} else if (sr->srid == SR2) {
-		sr->senp_mod = 0x03;
-		sr->senn_mod = 0x03;
-
-		sr->opp3_nvalue = cal_test_nvalue(0x76f + 0x200, 0x579 + 0x200);
-		sr->opp2_nvalue = cal_test_nvalue(0x4f5 + 0x1c0, 0x390 + 0x1c0);
-		sr->opp1_nvalue = cal_test_nvalue(0x359, 0x25d);
-	}
-
-}
-
-static void sr_set_nvalues(struct omap_sr *sr)
-{
-	if (SR_TESTING_NVALUES)
-		sr_set_testing_nvalues(sr);
-	else
-		sr_set_efuse_nvalues(sr);
-}
-
 static void sr_configure_vp(int srid)
 {
 	u32 vpconfig;
@@ -438,12 +317,13 @@ static void sr_configure(struct omap_sr *sr)
 {
 	u32 sr_config;
 	u32 senp_en , senn_en;
+	struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
 
 	if (sr->clk_length == 0)
 		sr_set_clk_length(sr);
 
-	senp_en = sr->senp_mod;
-	senn_en = sr->senn_mod;
+	senp_en = pdata->senp_mod;
+	senn_en = pdata->senn_mod;
 	if (sr->srid == SR1) {
 		sr_config = SR1_SRCONFIG_ACCUMDATA |
 			(sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
@@ -571,57 +451,33 @@ static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
 {
 	u32 nvalue_reciprocal, v;
 	struct omap_opp *opp;
+	struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
 	int uvdc;
 	char vsel;
 
-	sr->req_opp_no = target_opp_no;
-
 	if (sr->srid == SR1) {
-		switch (target_opp_no) {
-		case 5:
-			nvalue_reciprocal = sr->opp5_nvalue;
-			break;
-		case 4:
-			nvalue_reciprocal = sr->opp4_nvalue;
-			break;
-		case 3:
-			nvalue_reciprocal = sr->opp3_nvalue;
-			break;
-		case 2:
-			nvalue_reciprocal = sr->opp2_nvalue;
-			break;
-		case 1:
-			nvalue_reciprocal = sr->opp1_nvalue;
-			break;
-		default:
-			nvalue_reciprocal = sr->opp3_nvalue;
-			break;
-		}
-
 		opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
 		if (!opp)
 			return false;
 	} else {
-		switch (target_opp_no) {
-		case 3:
-			nvalue_reciprocal = sr->opp3_nvalue;
-			break;
-		case 2:
-			nvalue_reciprocal = sr->opp2_nvalue;
-			break;
-		case 1:
-			nvalue_reciprocal = sr->opp1_nvalue;
-			break;
-		default:
-			nvalue_reciprocal = sr->opp3_nvalue;
-			break;
-		}
-
 		opp = opp_find_by_opp_id(OPP_L3, target_opp_no);
 		if (!opp)
 			return false;
 	}
 
+	if (target_opp_no > pdata->no_opp) {
+		pr_notice("Wrong target opp\n");
+		return false;
+	}
+
+	if (!pdata->sr_nvalue) {
+		pr_notice("N target values does not exist for SR%d\n",
+								sr->srid);
+		return false;
+	}
+
+	nvalue_reciprocal = pdata->sr_nvalue[target_opp_no - 1];
+
 	if (nvalue_reciprocal == 0) {
 		pr_notice("OPP%d doesn't support SmartReflex\n",
 								target_opp_no);
@@ -1033,49 +889,255 @@ static struct kobj_attribute sr_vdd2_autocomp = {
 	.store = omap_sr_vdd2_autocomp_store,
 };
 
+static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
+{
+	struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
+	struct omap_device *odev = to_omap_device(pdev);
+	int ret = 0;
+
+	if (WARN_ON(!sr_info))
+		return -ENOMEM;
+	sr_info->pdev = pdev;
+	sr_info->srid = pdev->id + 1;
+	sr_info->is_sr_reset = 1,
+	sr_info->is_autocomp_active = 0;
+	sr_info->clk_length = 0;
+	sr_info->srbase_addr = odev->hwmods[0]->_rt_va;
+	if (odev->hwmods[0]->mpu_irqs)
+		sr_info->irq = odev->hwmods[0]->mpu_irqs[0].irq;
+	sr_set_clk_length(sr_info);
+
+	if (sr_info->srid == SR1) {
+		sr_info->vdd_opp_clk = clk_get(NULL, "dpll1_ck");
+		ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
+		if (ret)
+			pr_err("sysfs_create_file failed: %d\n", ret);
+	} else {
+		sr_info->vdd_opp_clk = clk_get(NULL, "l3_ick");
+		ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
+		if (ret)
+			pr_err("sysfs_create_file failed: %d\n", ret);
+	}
+
+	/* Call the VPConfig */
+	sr_configure_vp(sr_info->srid);
+	odev->hwmods[0]->dev_attr = sr_info;
+	list_add(&sr_info->node, &sr_list);
+	pr_info("SmartReflex driver initialized\n");
+
+	return ret;
+}
+
+static int __devexit omap_smartreflex_remove(struct platform_device *pdev)
+{
+	struct omap_device *odev = to_omap_device(pdev);
+	struct omap_sr *sr_info = odev->hwmods[0]->dev_attr;
+
+	/* Disable Autocompensation if enabled before removing the module */
+	if (sr_info->is_autocomp_active == 1)
+		sr_stop_vddautocomap(sr_info->srid);
+	list_del(&sr_info->node);
+	return 0;
+}
 
+static struct platform_driver smartreflex_driver = {
+	.probe          = omap_smartreflex_probe,
+	.remove         = omap_smartreflex_remove,
+	.driver		= {
+		.name	= "smartreflex",
+	},
+};
 
-static int __init omap3_sr_init(void)
+static int __init sr_init(void)
 {
 	int ret = 0;
 	u8 RdReg;
 
+	/* TODO: Find an appropriate place for this */
 	/* Enable SR on T2 */
 	ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &RdReg,
 			      R_DCDC_GLOBAL_CFG);
-
 	RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
 	ret |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
 				R_DCDC_GLOBAL_CFG);
-	if (cpu_is_omap34xx()) {
-		sr1.clk = clk_get(NULL, "sr1_fck");
-		sr2.clk = clk_get(NULL, "sr2_fck");
-	}
-	sr1.vdd_opp_clk = clk_get(NULL, "dpll1_ck");
-	sr2.vdd_opp_clk = clk_get(NULL, "l3_ick");
-	sr_set_clk_length(&sr1);
-	sr_set_clk_length(&sr2);
 
-	/* Call the VPConfig, VCConfig, set N Values. */
-	sr_set_nvalues(&sr1);
-	sr_configure_vp(SR1);
+	ret = platform_driver_probe(&smartreflex_driver,
+				omap_smartreflex_probe);
 
-	sr_set_nvalues(&sr2);
-	sr_configure_vp(SR2);
+	if (ret)
+		pr_err("platform driver register failed for smartreflex");
+	return 0;
+}
 
-	pr_info("SmartReflex driver initialized\n");
+void __exit sr_exit(void)
+{
+	platform_driver_unregister(&smartreflex_driver);
+}
+late_initcall(sr_init);
+module_exit(sr_exit);
 
-	ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
-	if (ret)
-		pr_err("sysfs_create_file failed: %d\n", ret);
+MODULE_DESCRIPTION("OMAP SMARTREFLEX DRIVER");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
 
-	ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
-	if (ret)
-		pr_err("sysfs_create_file failed: %d\n", ret);
-	list_add(&sr1.node, &sr_list);
-	list_add(&sr2.node, &sr_list);
+/* Device registrations for smartreflex instances */
 
-	return 0;
+#define MAX_HWMOD_NAME_LEN	16
+
+struct omap_device_pm_latency omap_sr_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func	 = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST
+	},
+};
+
+/* Read EFUSE values from control registers */
+static void __init omap3_sr_read_efuse(struct omap_smartreflex_data *sr_data,
+						int sr_id)
+{
+	if (sr_id == SR1) {
+		/*
+		 * TODO: When opp framework come into picture use appropriate
+		 * API's to find out number of opp's.
+		 */
+		sr_data->no_opp = 5;
+		sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
+					sr_data->no_opp , GFP_KERNEL);
+		if (WARN_ON(!sr_data->sr_nvalue))
+			return;
+
+		sr_data->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
+					OMAP343X_SR1_SENNENABLE_MASK) >>
+					OMAP343X_SR1_SENNENABLE_SHIFT;
+		sr_data->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
+					OMAP343X_SR1_SENPENABLE_MASK) >>
+					OMAP343X_SR1_SENPENABLE_SHIFT;
+		sr_data->sr_nvalue[4] = omap_ctrl_readl(
+					OMAP343X_CONTROL_FUSE_OPP5_VDD1);
+		sr_data->sr_nvalue[3] = omap_ctrl_readl(
+					OMAP343X_CONTROL_FUSE_OPP4_VDD1);
+		sr_data->sr_nvalue[2] = omap_ctrl_readl(
+					OMAP343X_CONTROL_FUSE_OPP3_VDD1);
+		sr_data->sr_nvalue[1] = omap_ctrl_readl(
+					OMAP343X_CONTROL_FUSE_OPP2_VDD1);
+		sr_data->sr_nvalue[0] = omap_ctrl_readl(
+					OMAP343X_CONTROL_FUSE_OPP1_VDD1);
+	} else if (sr_id == SR2) {
+		/*
+		 * TODO: When opp framework come into picture use appropriate
+		 * API's to find out number of opp's.
+		 */
+		sr_data->no_opp = 3;
+		sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
+					sr_data->no_opp , GFP_KERNEL);
+		if (WARN_ON(!sr_data->sr_nvalue))
+			return;
+
+		sr_data->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
+					OMAP343X_SR2_SENNENABLE_MASK) >>
+					OMAP343X_SR2_SENNENABLE_SHIFT;
+		sr_data->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
+					OMAP343X_SR2_SENPENABLE_MASK) >>
+					OMAP343X_SR2_SENPENABLE_SHIFT;
+		sr_data->sr_nvalue[2] = omap_ctrl_readl(
+					OMAP343X_CONTROL_FUSE_OPP3_VDD2);
+		sr_data->sr_nvalue[1] = omap_ctrl_readl(
+					OMAP343X_CONTROL_FUSE_OPP2_VDD2);
+		sr_data->sr_nvalue[0] = omap_ctrl_readl(
+					OMAP343X_CONTROL_FUSE_OPP1_VDD2);
+	}
 }
 
-late_initcall(omap3_sr_init);
+/* Hard coded nvalues for testing purposes, may cause device to hang! */
+static void __init omap3_sr_set_testing_nvalues(
+				struct omap_smartreflex_data *sr_data, int srid)
+{
+	if (srid == SR1) {
+		/*
+		 * TODO: When opp framework come into picture use appropriate
+		 * API's to find out number of opp's.
+		 */
+		sr_data->no_opp = 5;
+		sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
+				sr_data->no_opp , GFP_KERNEL);
+		if (WARN_ON(!sr_data->sr_nvalue))
+			return;
+
+		sr_data->senp_mod = 0x03;	/* SenN-M5 enabled */
+		sr_data->senn_mod = 0x03;
+		/* calculate nvalues for each opp */
+		sr_data->sr_nvalue[4] = 0x0;
+		sr_data->sr_nvalue[3] = 0x0;
+		sr_data->sr_nvalue[2] = 0x0;
+		sr_data->sr_nvalue[1] = 0x0;
+		sr_data->sr_nvalue[0] = 0x0;
+	} else if (srid == SR2) {
+		/*
+		 * TODO: When opp framework come into picture use appropriate
+		 * API's to find out number of opp's.
+		 */
+		sr_data->no_opp = 3;
+		sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
+					sr_data->no_opp , GFP_KERNEL);
+		if (WARN_ON(!sr_data->sr_nvalue))
+			return;
+
+		sr_data->senp_mod = 0x03;	/* SenN-M5 enabled */
+		sr_data->senn_mod = 0x03;
+		sr_data->sr_nvalue[2] = 0x0;
+		sr_data->sr_nvalue[1] = 0x0;
+		sr_data->sr_nvalue[0] = 0x0;
+	}
+}
+
+static void __init sr_set_nvalues(struct omap_smartreflex_data *sr_data,
+						int srid)
+{
+	if (cpu_is_omap343x()) {
+		if (SR_TESTING_NVALUES)
+			omap3_sr_set_testing_nvalues(sr_data, srid);
+		else
+			omap3_sr_read_efuse(sr_data, srid);
+	}
+}
+
+static int __init omap_devinit_smartreflex(void)
+{
+	int i = 0;
+	char *name = "smartreflex";
+
+	do {
+		struct omap_smartreflex_data *sr_data;
+		struct omap_device *od;
+		struct omap_hwmod *oh;
+		char oh_name[MAX_HWMOD_NAME_LEN];
+
+		snprintf(oh_name, MAX_HWMOD_NAME_LEN, "sr%d_hwmod", i + 1);
+		oh = omap_hwmod_lookup(oh_name);
+		if (!oh)
+			break;
+
+		sr_data = kzalloc(sizeof(struct omap_smartreflex_data),
+								GFP_KERNEL);
+		if (WARN_ON(!sr_data))
+			return -ENOMEM;
+
+		sr_data->init_enable = false;
+		sr_data->device_enable = omap_device_enable;
+		sr_data->device_shutdown = omap_device_shutdown;
+		sr_data->device_idle = omap_device_idle;
+		sr_set_nvalues(sr_data, i + 1);
+
+		od = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
+				       omap_sr_latency,
+				       ARRAY_SIZE(omap_sr_latency));
+		WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
+		     name, oh->name);
+		i++;
+	} while (1);
+
+	return 0;
+}
+arch_initcall(omap_devinit_smartreflex);
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 2a0e823..f1e8676 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -14,6 +14,8 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/platform_device.h>
+
 #define PHY_TO_OFF_PM_MASTER(p)		(p - 0x36)
 #define PHY_TO_OFF_PM_RECIEVER(p)	(p - 0x5b)
 #define PHY_TO_OFF_PM_INT(p)		(p - 0x2e)
@@ -243,6 +245,31 @@ extern u32 current_vdd2_opp;
  * do anything.
  */
 #ifdef CONFIG_OMAP_SMARTREFLEX
+/*
+ * omap_smartreflex_data - Smartreflex platform data
+ *
+ * @senp_mod	: SENPENABLE value for the sr
+ * @senn_mod	: SENNENABLE value for sr
+ * @sr_nvalue	: array of n target values for sr
+ * @no_opp	: number of opp's for this SR
+ * @init_enable	: whether this sr module needs to enabled at boot up or not
+ * @device_enable	: fn pointer to be populated with omap_device
+ * 			enable API
+ * @device_shutdown	: fn pointer to be populated with omap_device
+ * 			shutdown API
+ * @device_idle		: fn pointer to be pouplated with omap_device idle API
+ */
+struct omap_smartreflex_data {
+	u32		senp_mod;
+	u32		senn_mod;
+	u32		*sr_nvalue;
+	int		no_opp;
+	bool		init_enable;
+	int (*device_enable)(struct platform_device *pdev);
+	int (*device_shutdown)(struct platform_device *pdev);
+	int (*device_idle)(struct platform_device *pdev);
+};
+
 void enable_smartreflex(int srid);
 void disable_smartreflex(int srid);
 int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel);
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 04/16] OMAP3: PM: Move smartreflex autocompensation enable disable hooks to PM debugfs.
  2010-02-24  9:29     ` [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer Thara Gopinath
@ 2010-02-24  9:29       ` Thara Gopinath
  2010-02-24  9:29         ` [PATCH 05/16] OMAP3: PM: Export get_vdd1_opp and get_vdd2_opp from shared resource framework Thara Gopinath
  2010-03-02 18:28         ` [PATCH 04/16] OMAP3: PM: Move smartreflex autocompensation enable disable hooks to PM debugfs Kevin Hilman
  2010-02-25  2:39       ` [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer ambresh
                         ` (2 subsequent siblings)
  3 siblings, 2 replies; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

This patch moves the hooks to enable disable smartreflex
autocompensation to pm debugfs from the /sys/power/.

To enable autocompensation for smartreflex SR<n> do
        echo 1 > <path>/pm_debug/sr<n>_autocomp
To disable autocompensation for smartreflex SR<n> do
        echo 0 > <path>/pm_debug/sr<n>_autocomp

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/pm-debug.c    |    4 +-
 arch/arm/mach-omap2/smartreflex.c |  114 ++++++++++--------------------------
 arch/arm/mach-omap2/smartreflex.h |    2 +
 3 files changed, 36 insertions(+), 84 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index ec76f3b..7931bad 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -162,7 +162,7 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
 
 static void pm_dbg_regset_store(u32 *ptr);
 
-struct dentry *pm_dbg_dir;
+struct dentry *pm_dbg_dir, *pm_dbg_main_dir;
 
 static int pm_dbg_init_done;
 
@@ -608,7 +608,7 @@ static int __init pm_dbg_init(void)
 					   S_IRUGO | S_IWUGO, d,
 					   &voltage_off_while_idle,
 					   &pm_dbg_option_fops);
-
+	pm_dbg_main_dir = d;
 	pm_dbg_init_done = 1;
 
 	return 0;
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 05c72b2..db2e9bf 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -21,11 +21,11 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/clk.h>
-#include <linux/sysfs.h>
 #include <linux/kobject.h>
 #include <linux/i2c/twl.h>
 #include <linux/io.h>
 #include <linux/list.h>
+#include <linux/debugfs.h>
 
 #include <plat/omap34xx.h>
 #include <plat/control.h>
@@ -40,6 +40,7 @@
 #include "prm-regbits-34xx.h"
 
 #define MAX_TRIES 100
+#define SMARTREFLEX_NAME_LEN	16
 
 struct omap_sr {
 	int			srid;
@@ -797,103 +798,53 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
 	return 0;
 }
 
-/* Sysfs interface to select SR VDD1 auto compensation */
-static ssize_t omap_sr_vdd1_autocomp_show(struct kobject *kobj,
-					struct kobj_attribute *attr, char *buf)
+/* PM Debug Fs enteries to enable disable smartreflex.*/
+
+static int omap_sr_autocomp_show(void *data, u64 *val)
 {
-	struct omap_sr *sr_info = _sr_lookup(SR1);
+	struct omap_sr *sr_info = (struct omap_sr *) data;
 
 	if (!sr_info) {
-		pr_warning("omap_sr struct corresponding to SR1 not found\n");
+		pr_warning("omap_sr struct corresponding to SR%d not found\n",
+							sr_info->srid);
 		return 0;
 	}
-	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
-}
-
-static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj,
-					struct kobj_attribute *attr,
-					const char *buf, size_t n)
-{
-	unsigned short value;
-
-	if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
-		pr_err("sr_vdd1_autocomp: Invalid value\n");
-		return -EINVAL;
-	}
-
-	if (value == 0) {
-		sr_stop_vddautocomap(SR1);
-	} else {
-		u32 current_vdd1opp_no = get_vdd1_opp();
-		if (!current_vdd1opp_no) {
-			pr_err("sr_vdd1_autocomp: Current VDD1 opp unknown\n");
-			return -EINVAL;
-		}
-		sr_start_vddautocomap(SR1, current_vdd1opp_no);
-	}
-	return n;
+	*val = sr_info->is_autocomp_active;
+	return 0;
 }
 
-static struct kobj_attribute sr_vdd1_autocomp = {
-	.attr = {
-	.name = __stringify(sr_vdd1_autocomp),
-	.mode = 0644,
-	},
-	.show = omap_sr_vdd1_autocomp_show,
-	.store = omap_sr_vdd1_autocomp_store,
-};
-
-/* Sysfs interface to select SR VDD2 auto compensation */
-static ssize_t omap_sr_vdd2_autocomp_show(struct kobject *kobj,
-					struct kobj_attribute *attr, char *buf)
+static int omap_sr_autocomp_store(void *data, u64 val)
 {
-	struct omap_sr *sr_info = _sr_lookup(SR2);
+	struct omap_sr *sr_info = (struct omap_sr *) data;
 
 	if (!sr_info) {
-		pr_warning("omap_sr struct corresponding to SR2 not found\n");
+		pr_warning("omap_sr struct corresponding to SR%d not found\n",
+							sr_info->srid);
 		return 0;
 	}
-	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
-}
-
-static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj,
-					struct kobj_attribute *attr,
-					const char *buf, size_t n)
-{
-	unsigned short value;
-
-	if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
-		pr_err("sr_vdd2_autocomp: Invalid value\n");
-		return -EINVAL;
-	}
-
-	if (value == 0) {
-		sr_stop_vddautocomap(SR2);
+	if (val == 0) {
+		sr_stop_vddautocomap(sr_info->srid);
 	} else {
-		u32 current_vdd2opp_no = get_vdd2_opp();
-		if (!current_vdd2opp_no) {
-			pr_err("sr_vdd2_autocomp: Current VDD2 opp unknown\n");
-			return -EINVAL;
-		}
-		sr_start_vddautocomap(SR2, current_vdd2opp_no);
+		u32 current_opp;
+
+		if (sr_info->srid == SR1)
+			current_opp = get_vdd1_opp();
+		else
+			current_opp = get_vdd2_opp();
+		sr_start_vddautocomap(sr_info->srid, current_opp);
 	}
-	return n;
+	return 0;
 }
 
-static struct kobj_attribute sr_vdd2_autocomp = {
-	.attr = {
-	.name = __stringify(sr_vdd2_autocomp),
-	.mode = 0644,
-	},
-	.show = omap_sr_vdd2_autocomp_show,
-	.store = omap_sr_vdd2_autocomp_store,
-};
+DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
+		omap_sr_autocomp_store, "%llu\n");
 
 static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
 {
 	struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
 	struct omap_device *odev = to_omap_device(pdev);
 	int ret = 0;
+	char name[SMARTREFLEX_NAME_LEN];
 
 	if (WARN_ON(!sr_info))
 		return -ENOMEM;
@@ -909,16 +860,15 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
 
 	if (sr_info->srid == SR1) {
 		sr_info->vdd_opp_clk = clk_get(NULL, "dpll1_ck");
-		ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
-		if (ret)
-			pr_err("sysfs_create_file failed: %d\n", ret);
 	} else {
 		sr_info->vdd_opp_clk = clk_get(NULL, "l3_ick");
-		ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
-		if (ret)
-			pr_err("sysfs_create_file failed: %d\n", ret);
 	}
 
+	/* Create the debug fs enteries */
+	sprintf(name, "sr%d_autocomp", sr_info->srid);
+	(void) debugfs_create_file(name, S_IRUGO | S_IWUGO, pm_dbg_main_dir,
+				(void *)sr_info, &pm_sr_fops);
+
 	/* Call the VPConfig */
 	sr_configure_vp(sr_info->srid);
 	odev->hwmods[0]->dev_attr = sr_info;
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index f1e8676..20fc128 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -16,6 +16,8 @@
 
 #include <linux/platform_device.h>
 
+extern struct dentry *pm_dbg_main_dir;
+
 #define PHY_TO_OFF_PM_MASTER(p)		(p - 0x36)
 #define PHY_TO_OFF_PM_RECIEVER(p)	(p - 0x5b)
 #define PHY_TO_OFF_PM_INT(p)		(p - 0x2e)
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 05/16] OMAP3: PM: Export get_vdd1_opp and get_vdd2_opp from shared resource framework
  2010-02-24  9:29       ` [PATCH 04/16] OMAP3: PM: Move smartreflex autocompensation enable disable hooks to PM debugfs Thara Gopinath
@ 2010-02-24  9:29         ` Thara Gopinath
  2010-02-24  9:29           ` [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c Thara Gopinath
  2010-03-02 18:28         ` [PATCH 04/16] OMAP3: PM: Move smartreflex autocompensation enable disable hooks to PM debugfs Kevin Hilman
  1 sibling, 1 reply; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

get_vdd1_opp and get_vdd2_opp APIs will be needed by voltage.c
and smartreflex-class3.c which will get added in the later patches
in this patch series. So it is very clumsy to declare these API's
in each of these files and employ the mechanism of getting the opp
from mpu and l3 clocks.
This patch removes get_vdd1_opp and get_vdd2_opp from smartreflex.c.
To keep the implementaion clean these functions are exported out
in resource34xx.c.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/resource34xx.c |   10 +++++
 arch/arm/mach-omap2/smartreflex.c  |   66 ------------------------------------
 arch/arm/mach-omap2/smartreflex.h  |    2 +
 3 files changed, 12 insertions(+), 66 deletions(-)

diff --git a/arch/arm/mach-omap2/resource34xx.c b/arch/arm/mach-omap2/resource34xx.c
index c6cce8b..db5f40e 100644
--- a/arch/arm/mach-omap2/resource34xx.c
+++ b/arch/arm/mach-omap2/resource34xx.c
@@ -560,3 +560,13 @@ int validate_freq(struct shared_resource *resp, u32 target_level)
 		return freq_to_opp(&x, OPP_DSP, target_level);
 	return 0;
 }
+
+int get_vdd1_opp(void)
+{
+	return curr_vdd1_opp;
+}
+
+int get_vdd2_opp(void)
+{
+	return curr_vdd2_opp;
+}
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index db2e9bf..c00925d 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -46,7 +46,6 @@ struct omap_sr {
 	int			srid;
 	int			is_sr_reset;
 	int			is_autocomp_active;
-	struct clk		*vdd_opp_clk;
 	u32			clk_length;
 	void __iomem		*srbase_addr;
 	unsigned int		irq;
@@ -115,65 +114,6 @@ static void sr_clk_disable(struct omap_sr *sr)
 	sr->is_sr_reset = 1;
 }
 
-static u8 get_vdd1_opp(void)
-{
-	struct omap_opp *opp;
-	unsigned long freq;
-	struct omap_sr *sr_info = _sr_lookup(SR1);
-
-	if (!sr_info) {
-		pr_warning("omap_sr struct corresponding to SR1 not found\n");
-		return 0;
-	}
-
-	if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
-		return 0;
-
-	freq = sr_info->vdd_opp_clk->rate;
-	opp = opp_find_freq_ceil(OPP_MPU, &freq);
-	if (IS_ERR(opp))
-		return 0;
-	/*
-	 * Use higher freq voltage even if an exact match is not available
-	 * we are probably masking a clock framework bug, so warn
-	 */
-	if (unlikely(freq != sr_info->vdd_opp_clk->rate))
-		pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
-			   __func__, freq, sr_info->vdd_opp_clk->rate);
-
-	return opp_get_opp_id(opp);
-}
-
-static u8 get_vdd2_opp(void)
-{
-	struct omap_opp *opp;
-	unsigned long freq;
-	struct omap_sr *sr_info = _sr_lookup(SR2);
-
-	if (!sr_info) {
-		pr_warning("omap_sr struct corresponding to SR2 not found\n");
-		return 0;
-	}
-
-	if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
-		return 0;
-
-	freq = sr_info->vdd_opp_clk->rate;
-	opp = opp_find_freq_ceil(OPP_L3, &freq);
-	if (IS_ERR(opp))
-		return 0;
-
-	/*
-	 * Use higher freq voltage even if an exact match is not available
-	 * we are probably masking a clock framework bug, so warn
-	 */
-	if (unlikely(freq != sr_info->vdd_opp_clk->rate))
-		pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
-			   __func__, freq, sr_info->vdd_opp_clk->rate);
-	return opp_get_opp_id(opp);
-}
-
-
 static void sr_set_clk_length(struct omap_sr *sr)
 {
 	struct clk *sys_ck;
@@ -858,12 +798,6 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
 		sr_info->irq = odev->hwmods[0]->mpu_irqs[0].irq;
 	sr_set_clk_length(sr_info);
 
-	if (sr_info->srid == SR1) {
-		sr_info->vdd_opp_clk = clk_get(NULL, "dpll1_ck");
-	} else {
-		sr_info->vdd_opp_clk = clk_get(NULL, "l3_ick");
-	}
-
 	/* Create the debug fs enteries */
 	sprintf(name, "sr%d_autocomp", sr_info->srid);
 	(void) debugfs_create_file(name, S_IRUGO | S_IWUGO, pm_dbg_main_dir,
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 20fc128..572cdca 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -17,6 +17,8 @@
 #include <linux/platform_device.h>
 
 extern struct dentry *pm_dbg_main_dir;
+extern int get_vdd1_opp(void);
+extern int get_vdd2_opp(void);
 
 #define PHY_TO_OFF_PM_MASTER(p)		(p - 0x36)
 #define PHY_TO_OFF_PM_RECIEVER(p)	(p - 0x5b)
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c
  2010-02-24  9:29         ` [PATCH 05/16] OMAP3: PM: Export get_vdd1_opp and get_vdd2_opp from shared resource framework Thara Gopinath
@ 2010-02-24  9:29           ` Thara Gopinath
  2010-02-24  9:29             ` [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver Thara Gopinath
                               ` (3 more replies)
  0 siblings, 4 replies; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

OMAP3 smartreflex modules are capable of two different classes
of implementaion -
	Class-2: Continuous Software Calibration
	Class-3: Continuous Hardware Calibration.
OMAP3 along with T2/Gaia supports the Class 3 implementaion.
With a different PMIC it can support Class 2 implementaion also.

The idea behind this patch is that smartreflex.c should be able
to support both the classes of Smartreflex and the class specific
details for smartreflex should stay out of this file in a separate
class file.
This patch introduces smartreflex class specific hooks in
smartreflex.c. This patch only takes care of smartreflex enable
disable hooks which differ between Class 2 and Class 3. There
are some register setting changes between both the classes which
will be taken care of in a later patch.
This will form the base for adding class specific
drivers in later patches.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/pm34xx.c      |    8 +-
 arch/arm/mach-omap2/smartreflex.c |  251 ++++++++++++++++++++----------------
 arch/arm/mach-omap2/smartreflex.h |   48 ++++++--
 3 files changed, 182 insertions(+), 125 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index cf9ca23..ece5195 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -430,9 +430,9 @@ void omap_sram_idle(void)
 	 * Only needed if we are going to enter retention or off.
 	 */
 	if (mpu_next_state <= PWRDM_POWER_RET)
-		disable_smartreflex(SR1);
+		omap_smartreflex_disable(SR1);
 	if (core_next_state <= PWRDM_POWER_RET)
-		disable_smartreflex(SR2);
+		omap_smartreflex_disable(SR2);
 
 	/* CORE */
 	if (core_next_state < PWRDM_POWER_ON) {
@@ -531,9 +531,9 @@ void omap_sram_idle(void)
 	 * retention or off
 	 */
 	if (mpu_next_state <= PWRDM_POWER_RET)
-		enable_smartreflex(SR1);
+		omap_smartreflex_enable(SR1);
 	if (core_next_state <= PWRDM_POWER_RET)
-		enable_smartreflex(SR2);
+		omap_smartreflex_enable(SR2);
 
 	/* PER */
 	if (per_next_state < PWRDM_POWER_ON) {
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index c00925d..ba9f899 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -55,6 +55,7 @@ struct omap_sr {
 
 /* sr_list contains all the instances of smartreflex module */
 static LIST_HEAD(sr_list);
+static struct omap_smartreflex_class_data *sr_class;
 
 #define SR_REGADDR(offs)	(sr->srbase_addr + offset)
 
@@ -388,14 +389,86 @@ static int sr_reset_voltage(int srid)
 	return 0;
 }
 
-static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
+static void sr_start_vddautocomap(int srid)
+{
+	struct omap_sr *sr = _sr_lookup(srid);
+
+	if (!sr) {
+		pr_warning("omap_sr struct corresponding to SR%d not found\n",
+								srid);
+		return;
+	}
+
+	if (!sr_class || !(sr_class->enable)) {
+		pr_warning("smartreflex class driver not registered\n");
+		return;
+	}
+
+	if (sr->is_sr_reset == 1) {
+		sr_clk_enable(sr);
+		sr_configure(sr);
+	}
+
+	sr->is_autocomp_active = 1;
+	if (!sr_class->enable(srid)) {
+		sr->is_autocomp_active = 0;
+		if (sr->is_sr_reset == 1)
+			sr_clk_disable(sr);
+	}
+}
+
+static void sr_stop_vddautocomap(int srid)
+{
+	struct omap_sr *sr = _sr_lookup(srid);
+
+	if (!sr) {
+		pr_warning("omap_sr struct corresponding to SR%d not found\n",
+								srid);
+		return;
+	}
+	if (!sr_class || !(sr_class->disable)) {
+		pr_warning("smartreflex class driver not registered\n");
+		return;
+	}
+
+	if (sr->is_autocomp_active == 1) {
+		sr_class->disable(srid);
+		sr_clk_disable(sr);
+		sr->is_autocomp_active = 0;
+		/* Reset the volatage for current OPP */
+		sr_reset_voltage(srid);
+	}
+
+}
+
+/* Public Functions */
+
+/**
+ * sr_enable : Enables the smartreflex module.
+ * @srid - The id of the sr module to be enabled.
+ * @target_opp_no - The OPP at which the Voltage domain associated with
+ * the smartreflex module is operating at. This is required only to program
+ * the correct Ntarget value.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * enable a smartreflex module. Returns true on success.Returns false if the
+ * target opp id passed is wrong or if ntarget value is wrong.
+ */
+int sr_enable(int srid, u32 target_opp_no)
 {
 	u32 nvalue_reciprocal, v;
+	struct omap_sr *sr = _sr_lookup(srid);
 	struct omap_opp *opp;
 	struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
 	int uvdc;
 	char vsel;
 
+	if (!sr) {
+		pr_warning("omap_sr struct corresponding to SR%d not found\n",
+								srid);
+		return false;
+	}
+
 	if (sr->srid == SR1) {
 		opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
 		if (!opp)
@@ -477,8 +550,16 @@ static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
 	return true;
 }
 
-static void sr_disable(struct omap_sr *sr)
+/**
+ * sr_disable : Disables the smartreflex module.
+ * @srid - The id of the sr module to be disabled.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * disable a smartreflex module.
+ */
+void sr_disable(int srid)
 {
+	struct omap_sr *sr = _sr_lookup(srid);
 	u32 i = 0;
 
 	sr->is_sr_reset = 1;
@@ -518,9 +599,19 @@ static void sr_disable(struct omap_sr *sr)
 	}
 }
 
-
-void sr_start_vddautocomap(int srid, u32 target_opp_no)
+/**
+ * omap_smartreflex_enable : API to enable SR clocks and to call into the
+ * registered smartreflex class enable API.
+ * @srid - The id of the sr module to be enabled.
+ *
+ * This API is to be called from the kernel in order to enable
+ * a particular smartreflex module. This API will do the initial
+ * configurations to turn on the smartreflex module and in turn call
+ * into the registered smartreflex class enable API.
+ */
+void omap_smartreflex_enable(int srid)
 {
+	u32 target_opp_no = 0;
 	struct omap_sr *sr = _sr_lookup(srid);
 
 	if (!sr) {
@@ -528,52 +619,8 @@ void sr_start_vddautocomap(int srid, u32 target_opp_no)
 								srid);
 		return;
 	}
-
-	if (sr->is_sr_reset == 1) {
-		sr_clk_enable(sr);
-		sr_configure(sr);
-	}
-
-	sr->is_autocomp_active = 1;
-	if (!sr_enable(sr, target_opp_no)) {
-		sr->is_autocomp_active = 0;
-		if (sr->is_sr_reset == 1)
-			sr_clk_disable(sr);
-	}
-}
-EXPORT_SYMBOL(sr_start_vddautocomap);
-
-int sr_stop_vddautocomap(int srid)
-{
-	struct omap_sr *sr = _sr_lookup(srid);
-
-	if (!sr) {
-		pr_warning("omap_sr struct corresponding to SR%d not found\n",
-								srid);
-		return false;
-	}
-
-	if (sr->is_autocomp_active == 1) {
-		sr_disable(sr);
-		sr_clk_disable(sr);
-		sr->is_autocomp_active = 0;
-		/* Reset the volatage for current OPP */
-		sr_reset_voltage(srid);
-		return true;
-	} else
-		return false;
-
-}
-EXPORT_SYMBOL(sr_stop_vddautocomap);
-
-void enable_smartreflex(int srid)
-{
-	u32 target_opp_no = 0;
-	struct omap_sr *sr = _sr_lookup(srid);
-
-	if (!sr) {
-		pr_warning("omap_sr struct corresponding to SR%d not found\n",
-								srid);
+	if (!sr_class || !(sr_class->enable)) {
+		pr_warning("smartreflex class driver not registered\n");
 		return;
 	}
 
@@ -581,26 +628,24 @@ void enable_smartreflex(int srid)
 		if (sr->is_sr_reset == 1) {
 			/* Enable SR clks */
 			sr_clk_enable(sr);
-
-			if (srid == SR1)
-				target_opp_no = get_vdd1_opp();
-			else if (srid == SR2)
-				target_opp_no = get_vdd2_opp();
-
-			if (!target_opp_no) {
-				pr_info("Current OPP unknown \
-						 Cannot configure SR\n");
-			}
-
 			sr_configure(sr);
 
-			if (!sr_enable(sr, target_opp_no))
+			if (!sr_class->enable(srid))
 				sr_clk_disable(sr);
 		}
 	}
 }
 
-void disable_smartreflex(int srid)
+/**
+ * omap_smartreflex_disable : API to disable SR clocks and to call into the
+ * registered smartreflex class disable API.
+ * @srid - The id of the sr module to be disabled.
+ *
+ * This API is to be called from the kernel in order to disable
+ * a particular smartreflex module. This API will in turn call
+ * into the registered smartreflex class disable API.
+ */
+void omap_smartreflex_disable(int srid)
 {
 	u32 i = 0;
 	struct omap_sr *sr = _sr_lookup(srid);
@@ -610,54 +655,43 @@ void disable_smartreflex(int srid)
 								srid);
 		return;
 	}
+	if (!sr_class || !(sr_class->disable)) {
+		pr_warning("smartreflex class driver not registered\n");
+		return;
+	}
 
 	if (sr->is_autocomp_active == 1) {
 		if (sr->is_sr_reset == 0) {
-
-			sr->is_sr_reset = 1;
-			/* SRCONFIG - disable SR */
-			sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
-							~SRCONFIG_SRENABLE);
-
+			sr_class->disable(srid);
 			/* Disable SR clk */
 			sr_clk_disable(sr);
-			if (sr->srid == SR1) {
-				/* Wait for VP idle before disabling VP */
-				while ((!prm_read_mod_reg(OMAP3430_GR_MOD,
-						OMAP3_PRM_VP1_STATUS_OFFSET))
-						&& i++ < MAX_TRIES)
-					udelay(1);
-
-				if (i >= MAX_TRIES)
-					pr_warning("VP1 not idle, still going \
-						ahead with VP1 disable\n");
-
-				/* Disable VP1 */
-				prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE,
-						OMAP3430_GR_MOD,
-						OMAP3_PRM_VP1_CONFIG_OFFSET);
-			} else if (sr->srid == SR2) {
-				/* Wait for VP idle before disabling VP */
-				while ((!prm_read_mod_reg(OMAP3430_GR_MOD,
-						OMAP3_PRM_VP2_STATUS_OFFSET))
-						&& i++ < MAX_TRIES)
-					udelay(1);
-
-				if (i >= MAX_TRIES)
-					pr_warning("VP2 not idle, still going \
-						 ahead with VP2 disable\n");
-
-				/* Disable VP2 */
-				prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE,
-						OMAP3430_GR_MOD,
-						OMAP3_PRM_VP2_CONFIG_OFFSET);
-			}
 			/* Reset the volatage for current OPP */
 			sr_reset_voltage(srid);
 		}
 	}
 }
 
+/**
+ * omap_sr_register_class : API to register a smartreflex class parameters.
+ * @class_data - The structure containing various sr class specific data.
+ *
+ * This API is to be called by the smartreflex class driver to register itself
+ * with the smartreflex driver during init.
+ */
+void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
+{
+	if (!class_data) {
+		pr_warning("Smartreflex class data passed is NULL\n");
+		return;
+	}
+
+	if (sr_class) {
+		pr_warning("Smartreflex class driver already registered\n");
+		return;
+	}
+	sr_class = class_data;
+}
+
 /* Voltage Scaling using SR VCBYPASS */
 int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
 					u8 target_vsel, u8 current_vsel)
@@ -730,9 +764,9 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
 
 	if (sr_status) {
 		if (vdd == VDD1_OPP)
-			sr_start_vddautocomap(SR1, target_opp_no);
+			sr_start_vddautocomap(SR1);
 		else if (vdd == VDD2_OPP)
-			sr_start_vddautocomap(SR2, target_opp_no);
+			sr_start_vddautocomap(SR2);
 	}
 
 	return 0;
@@ -762,17 +796,10 @@ static int omap_sr_autocomp_store(void *data, u64 val)
 							sr_info->srid);
 		return 0;
 	}
-	if (val == 0) {
+	if (val == 0)
 		sr_stop_vddautocomap(sr_info->srid);
-	} else {
-		u32 current_opp;
-
-		if (sr_info->srid == SR1)
-			current_opp = get_vdd1_opp();
-		else
-			current_opp = get_vdd2_opp();
-		sr_start_vddautocomap(sr_info->srid, current_opp);
-	}
+	else
+		sr_start_vddautocomap(sr_info->srid);
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 572cdca..a59a073 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -243,12 +243,27 @@ extern u32 current_vdd2_opp;
 #define SR_TESTING_NVALUES 	0
 #endif
 
-/*
- * Smartreflex module enable/disable interface.
- * NOTE: if smartreflex is not enabled from sysfs, these functions will not
- * do anything.
- */
 #ifdef CONFIG_OMAP_SMARTREFLEX
+/**
+ * omap_smartreflex_class_data : Structure to be populated by
+ * Smartreflex class driver with corresponding class enable disable API's
+ *
+ * @enable - API to enable a particular class smaartreflex.
+ * @disable - API to disable a particular class smartreflex.
+ * @notify - API to notify the class driver about an event in SR. Not needed
+ *		for class3.
+ * @notify_flags - specify the events to be notified to the class driver
+ * @class_type - specify which smartreflex class. Can be used by the SR driver
+ * 		to tkae any class based decisions.
+ */
+struct omap_smartreflex_class_data {
+	int (*enable)(int sr_id);
+	int (*disable)(int sr_id);
+	int (*notify)(int sr_id, u32 status);
+	u8 notify_flags;
+	u8 class_type;
+};
+
 /*
  * omap_smartreflex_data - Smartreflex platform data
  *
@@ -274,11 +289,26 @@ struct omap_smartreflex_data {
 	int (*device_idle)(struct platform_device *pdev);
 };
 
-void enable_smartreflex(int srid);
-void disable_smartreflex(int srid);
+/*
+ * Smartreflex module enable/disable interface.
+ * NOTE: if smartreflex is not enabled from sysfs, these functions will not
+ * do anything.
+ */
+void omap_smartreflex_enable(int srid);
+void omap_smartreflex_disable(int srid);
+
+/**
+ * Smartreflex driver hooks to be called from Smartreflex class driver
+ */
+int sr_enable(int srid, u32 target_opp_no);
+void sr_disable(int srid);
+
+/**
+ * API to register the smartreflex class driver with the smartreflex driver
+ */
+void omap_sr_register_class(struct omap_smartreflex_class_data *class_data);
+
 int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel);
-void sr_start_vddautocomap(int srid, u32 target_opp_no);
-int sr_stop_vddautocomap(int srid);
 #else
 static inline void enable_smartreflex(int srid) {}
 static inline void disable_smartreflex(int srid) {}
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver.
  2010-02-24  9:29           ` [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c Thara Gopinath
@ 2010-02-24  9:29             ` Thara Gopinath
  2010-02-24  9:29               ` [PATCH 08/16] OMAP3: PM: Disabling Smartreflex across both frequency and voltage scaling during DVFS Thara Gopinath
  2010-03-02 19:36               ` [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver Kevin Hilman
  2010-03-02 18:44             ` [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c Kevin Hilman
                               ` (2 subsequent siblings)
  3 siblings, 2 replies; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

This patch adds smartreflex class 3 driver. This driver hooks
up with the generic smartreflex driver smartreflex.c to abstract
out class specific implementations out of the generic driver.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/Makefile             |    1 +
 arch/arm/mach-omap2/smartreflex-class3.c |   49 ++++++++++++++++++++++++++++++
 arch/arm/plat-omap/Kconfig               |   11 ++++++-
 3 files changed, 60 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index f6f901f..cd8ab86 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o cpuidle34xx.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 obj-$(CONFIG_OMAP_SMARTREFLEX)	+= smartreflex.o
+obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)	+= smartreflex-class3.o
 
 AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
 AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
new file mode 100644
index 0000000..d2e98a5
--- /dev/null
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -0,0 +1,49 @@
+/*
+ * Smart reflex Class 3 specific implementations
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * 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 "smartreflex.h"
+
+static int sr_class3_enable(int id)
+{
+	int target_opp_no = 0;
+	if (id == SR1)
+		target_opp_no = get_vdd1_opp();
+	else if (id == SR2)
+		target_opp_no = get_vdd2_opp();
+	if (!target_opp_no) {
+		pr_warning("Targetopp not known.Cannot enable SR%d\n", id);
+		return false;
+	}
+	return sr_enable(id, target_opp_no);
+}
+
+static int sr_class3_disable(int id)
+{
+	int target_opp_no = 0;
+	if (id == SR1)
+		target_opp_no = get_vdd1_opp();
+	else if (id == SR2)
+		target_opp_no = get_vdd2_opp();
+	sr_disable(id);
+	return true;
+}
+/* SR class3 structure */
+struct omap_smartreflex_class_data class3_data = {
+	.enable = sr_class3_enable,
+	.disable = sr_class3_disable,
+};
+
+static int __init sr_class3_init(void)
+{
+	omap_sr_register_class(&class3_data);
+	return 0;
+}
+late_initcall(sr_class3_init);
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index cef67f3..9d286e6 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -54,7 +54,7 @@ config OMAP_DEBUG_LEDS
 
 config OMAP_SMARTREFLEX
 	bool "SmartReflex support"
-	depends on ARCH_OMAP3 && TWL4030_CORE && PM
+	depends on ARCH_OMAP3 && PM
 	help
 	  Say Y if you want to enable SmartReflex.
 
@@ -69,6 +69,15 @@ config OMAP_SMARTREFLEX
 	  compensation for VDD1 and VDD2, user must write 1 to
 	  /sys/power/sr_vddX_autocomp, where X is 1 or 2.
 
+config OMAP_SMARTREFLEX_CLASS3
+	bool "Class 3 mode of Smartreflex Implementation"
+	depends on OMAP_SMARTREFLEX && TWL4030_CORE
+	help
+	  Say Y to enable Class 3 implementation of Smartreflex
+
+	  Class 3 implementation of Smartreflex employs continuous hardware
+	  voltage caliberation.
+
 config OMAP_SMARTREFLEX_TESTING
 	bool "Smartreflex testing support"
 	depends on OMAP_SMARTREFLEX
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 08/16] OMAP3: PM: Disabling Smartreflex across both frequency and voltage scaling during DVFS.
  2010-02-24  9:29             ` [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver Thara Gopinath
@ 2010-02-24  9:29               ` Thara Gopinath
  2010-02-24  9:29                 ` [PATCH 09/16] OMAP3: PM: Creating separate files for handling OMAP3 voltage related operations Thara Gopinath
  2010-03-02 19:36               ` [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver Kevin Hilman
  1 sibling, 1 reply; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

This patch disables smartreflex across both frequency and voltage
scaling instead of just across voltage scaling as before.
This is the hardware recommended practice.
This bug was first reported and solved on Nokia Rover
code base by Nishanth Menon and Paul Walmsley.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/resource34xx.c |    3 +++
 arch/arm/mach-omap2/smartreflex.c  |   10 ----------
 2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-omap2/resource34xx.c b/arch/arm/mach-omap2/resource34xx.c
index db5f40e..7c0bb0e 100644
--- a/arch/arm/mach-omap2/resource34xx.c
+++ b/arch/arm/mach-omap2/resource34xx.c
@@ -348,6 +348,8 @@ static int program_opp(int res, enum opp_t opp_type, int target_level,
 	else
 		raise = 0;
 
+	omap_smartreflex_disable(res);
+
 	for (i = 0; i < 2; i++) {
 		if (i == raise)
 			ret = program_opp_freq(res, target_level,
@@ -379,6 +381,7 @@ static int program_opp(int res, enum opp_t opp_type, int target_level,
 #endif
 	}
 
+	omap_smartreflex_enable(res);
 	return ret;
 }
 
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index ba9f899..ac935e2 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -696,7 +696,6 @@ void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
 int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
 					u8 target_vsel, u8 current_vsel)
 {
-	int sr_status = 0;
 	u32 vdd, target_opp_no, current_opp_no;
 	u32 vc_bypass_value;
 	u32 reg_addr = 0;
@@ -709,7 +708,6 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
 	current_opp_no = get_opp_no(current_opp);
 
 	if (vdd == VDD1_OPP) {
-		sr_status = sr_stop_vddautocomap(SR1);
 		t2_smps_steps = abs(target_vsel - current_vsel);
 
 		prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
@@ -719,7 +717,6 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
 		reg_addr = R_VDD1_SR_CONTROL;
 
 	} else if (vdd == VDD2_OPP) {
-		sr_status = sr_stop_vddautocomap(SR2);
 		t2_smps_steps =  abs(target_vsel - current_vsel);
 
 		prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
@@ -762,13 +759,6 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
 	t2_smps_delay = ((t2_smps_steps * 125) / 40) + 2;
 	udelay(t2_smps_delay);
 
-	if (sr_status) {
-		if (vdd == VDD1_OPP)
-			sr_start_vddautocomap(SR1);
-		else if (vdd == VDD2_OPP)
-			sr_start_vddautocomap(SR2);
-	}
-
 	return 0;
 }
 
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 09/16] OMAP3: PM: Creating separate files for handling OMAP3 voltage related operations.
  2010-02-24  9:29               ` [PATCH 08/16] OMAP3: PM: Disabling Smartreflex across both frequency and voltage scaling during DVFS Thara Gopinath
@ 2010-02-24  9:29                 ` Thara Gopinath
  2010-02-24  9:29                   ` [PATCH 10/16] OMAP3: PM: Cleaning up of smartreflex header file Thara Gopinath
  2010-03-02 20:02                   ` [PATCH 09/16] OMAP3: PM: Creating separate files for handling OMAP3 voltage related operations Kevin Hilman
  0 siblings, 2 replies; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

This patch creates voltage.c and voltage.h files and
moves all voltage processor and voltage controller specific code
from smartreflex.c and other places in the OMAP3 codebase into
these two files.
This along with smartreflex class driver addition will make
smartreflex.c a generic driver to support both Class 2 and
Class 3 smartreflex implementaions.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/Makefile             |    3 +-
 arch/arm/mach-omap2/board-3430sdp.c      |    3 +-
 arch/arm/mach-omap2/pm.h                 |    7 -
 arch/arm/mach-omap2/pm34xx.c             |   87 +-----
 arch/arm/mach-omap2/resource34xx.c       |   15 +-
 arch/arm/mach-omap2/resource34xx.h       |    1 -
 arch/arm/mach-omap2/smartreflex-class3.c |    4 +
 arch/arm/mach-omap2/smartreflex.c        |  370 +--------------------
 arch/arm/mach-omap2/smartreflex.h        |  139 --------
 arch/arm/mach-omap2/voltage.c            |  550 ++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/voltage.h            |   74 ++++
 11 files changed, 640 insertions(+), 613 deletions(-)
 create mode 100644 arch/arm/mach-omap2/voltage.c
 create mode 100644 arch/arm/mach-omap2/voltage.h

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index cd8ab86..efaff8d 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -49,7 +49,8 @@ obj-$(CONFIG_ARCH_OMAP2)		+= sdrc2xxx.o
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
 obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o
-obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o cpuidle34xx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o cpuidle34xx.o \
+					   voltage.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 obj-$(CONFIG_OMAP_SMARTREFLEX)	+= smartreflex.o
 obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)	+= smartreflex-class3.o
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index e069032..2e0e78f 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -49,6 +49,7 @@
 #include "sdram-qimonda-hyb18m512160af-6.h"
 #include "hsmmc.h"
 #include "pm.h"
+#include "voltage.h"
 #include "omap3-opp.h"
 
 #define SDP3430_TS_GPIO_IRQ_SDPV1	3
@@ -346,7 +347,7 @@ static void __init omap_3430sdp_init_irq(void)
 	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
 	omap3_pm_init_opp_table();
 	omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
-	omap3_pm_init_vc(&omap3_setuptime_table);
+	omap_voltage_init_vc(&omap3_setuptime_table);
 	omap2_init_common_hw(hyb18m512160af6_sdrc_params, NULL);
 	omap_init_irq();
 	omap_gpio_init();
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index b761be5..55bde0d 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -57,13 +57,6 @@ struct prm_setup_vc {
 	u16 vdd1_ret;
 	u16 vdd1_off;
 };
-#ifdef CONFIG_PM
-extern void omap3_pm_init_vc(struct prm_setup_vc *setup_vc);
-#else
-static inline void omap3_pm_init_vc(struct prm_setup_vc *setup_vc)
-{
-}
-#endif
 
 extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm);
 extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index ece5195..0d1b3af 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -49,6 +49,7 @@
 #include "prm-regbits-34xx.h"
 
 #include "smartreflex.h"
+#include "voltage.h"
 #include "prm.h"
 #include "pm.h"
 #include "sdrc.h"
@@ -96,22 +97,6 @@ static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
 static struct powerdomain *cam_pwrdm;
 
-static struct prm_setup_vc prm_setup = {
-	.clksetup = 0xff,
-	.voltsetup_time1 = 0xfff,
-	.voltsetup_time2 = 0xfff,
-	.voltoffset = 0xff,
-	.voltsetup2 = 0xff,
-	.vdd0_on = 0x30,	/* 1.2v */
-	.vdd0_onlp = 0x20,	/* 1.0v */
-	.vdd0_ret = 0x1e,	/* 0.975v */
-	.vdd0_off = 0x00,	/* 0.6v */
-	.vdd1_on = 0x2c,	/* 1.15v */
-	.vdd1_onlp = 0x20,	/* 1.0v */
-	.vdd1_ret = 0x1e,	/* .975v */
-	.vdd1_off = 0x00,	/* 0.6v */
-};
-
 static inline void omap3_per_save_context(void)
 {
 	omap_gpio_save_context();
@@ -1077,26 +1062,6 @@ int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state)
 	return -EINVAL;
 }
 
-void omap3_pm_init_vc(struct prm_setup_vc *setup_vc)
-{
-	if (!setup_vc)
-		return;
-
-	prm_setup.clksetup = setup_vc->clksetup;
-	prm_setup.voltsetup_time1 = setup_vc->voltsetup_time1;
-	prm_setup.voltsetup_time2 = setup_vc->voltsetup_time2;
-	prm_setup.voltoffset = setup_vc->voltoffset;
-	prm_setup.voltsetup2 = setup_vc->voltsetup2;
-	prm_setup.vdd0_on = setup_vc->vdd0_on;
-	prm_setup.vdd0_onlp = setup_vc->vdd0_onlp;
-	prm_setup.vdd0_ret = setup_vc->vdd0_ret;
-	prm_setup.vdd0_off = setup_vc->vdd0_off;
-	prm_setup.vdd1_on = setup_vc->vdd1_on;
-	prm_setup.vdd1_onlp = setup_vc->vdd1_onlp;
-	prm_setup.vdd1_ret = setup_vc->vdd1_ret;
-	prm_setup.vdd1_off = setup_vc->vdd1_off;
-}
-
 static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 {
 	struct power_state *pwrst;
@@ -1242,58 +1207,12 @@ err2:
 	return ret;
 }
 
-static void __init configure_vc(void)
-{
-
-	prm_write_mod_reg((R_SRI2C_SLAVE_ADDR << OMAP3430_SMPS_SA1_SHIFT) |
-			  (R_SRI2C_SLAVE_ADDR << OMAP3430_SMPS_SA0_SHIFT),
-			  OMAP3430_GR_MOD, OMAP3_PRM_VC_SMPS_SA_OFFSET);
-	prm_write_mod_reg((R_VDD2_SR_CONTROL << OMAP3430_VOLRA1_SHIFT) |
-			  (R_VDD1_SR_CONTROL << OMAP3430_VOLRA0_SHIFT),
-			  OMAP3430_GR_MOD, OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET);
-
-	prm_write_mod_reg((prm_setup.vdd0_on << OMAP3430_VC_CMD_ON_SHIFT) |
-		(prm_setup.vdd0_onlp << OMAP3430_VC_CMD_ONLP_SHIFT) |
-		(prm_setup.vdd0_ret << OMAP3430_VC_CMD_RET_SHIFT) |
-		(prm_setup.vdd0_off << OMAP3430_VC_CMD_OFF_SHIFT),
-		OMAP3430_GR_MOD, OMAP3_PRM_VC_CMD_VAL_0_OFFSET);
-
-	prm_write_mod_reg((prm_setup.vdd1_on << OMAP3430_VC_CMD_ON_SHIFT) |
-		(prm_setup.vdd1_onlp << OMAP3430_VC_CMD_ONLP_SHIFT) |
-		(prm_setup.vdd1_ret << OMAP3430_VC_CMD_RET_SHIFT) |
-		(prm_setup.vdd1_off << OMAP3430_VC_CMD_OFF_SHIFT),
-		OMAP3430_GR_MOD, OMAP3_PRM_VC_CMD_VAL_1_OFFSET);
-
-	prm_write_mod_reg(OMAP3430_CMD1 | OMAP3430_RAV1, OMAP3430_GR_MOD,
-			  OMAP3_PRM_VC_CH_CONF_OFFSET);
-
-	prm_write_mod_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN,
-			  OMAP3430_GR_MOD,
-			  OMAP3_PRM_VC_I2C_CFG_OFFSET);
-
-	/* Write setup times */
-	prm_write_mod_reg(prm_setup.clksetup, OMAP3430_GR_MOD,
-			OMAP3_PRM_CLKSETUP_OFFSET);
-	prm_write_mod_reg((prm_setup.voltsetup_time2 <<
-			OMAP3430_SETUP_TIME2_SHIFT) |
-			(prm_setup.voltsetup_time1 <<
-			OMAP3430_SETUP_TIME1_SHIFT),
-			OMAP3430_GR_MOD, OMAP3_PRM_VOLTSETUP1_OFFSET);
-
-	prm_write_mod_reg(prm_setup.voltoffset, OMAP3430_GR_MOD,
-			OMAP3_PRM_VOLTOFFSET_OFFSET);
-	prm_write_mod_reg(prm_setup.voltsetup2, OMAP3430_GR_MOD,
-			OMAP3_PRM_VOLTSETUP2_OFFSET);
-}
-
-
 static int __init omap3_pm_early_init(void)
 {
 	prm_clear_mod_reg_bits(OMAP3430_OFFMODE_POL, OMAP3430_GR_MOD,
 				OMAP3_PRM_POLCTRL_OFFSET);
-
-	configure_vc();
-
+	/* Initializes OMAP3 voltage modules */
+	omap_voltage_init();
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/resource34xx.c b/arch/arm/mach-omap2/resource34xx.c
index 7c0bb0e..7496b2d 100644
--- a/arch/arm/mach-omap2/resource34xx.c
+++ b/arch/arm/mach-omap2/resource34xx.c
@@ -28,6 +28,7 @@
 #include <plat/opp_twl_tps.h>
 
 #include "smartreflex.h"
+#include "voltage.h"
 #include "resource34xx.h"
 #include "pm.h"
 #include "cm.h"
@@ -331,12 +332,6 @@ static int program_opp(int res, enum opp_t opp_type, int target_level,
 {
 	int i, ret = 0, raise;
 	unsigned long freq;
-#ifdef CONFIG_OMAP_SMARTREFLEX
-	unsigned long t_opp, c_opp;
-
-	t_opp = ID_VDD(res) | ID_OPP_NO(target_level);
-	c_opp = ID_VDD(res) | ID_OPP_NO(current_level);
-#endif
 
 	/* See if have a freq associated, if not, invalid opp */
 	ret = opp_to_freq(&freq, opp_type, target_level);
@@ -351,11 +346,10 @@ static int program_opp(int res, enum opp_t opp_type, int target_level,
 	omap_smartreflex_disable(res);
 
 	for (i = 0; i < 2; i++) {
-		if (i == raise)
+		if (i == raise) {
 			ret = program_opp_freq(res, target_level,
 					current_level);
-#ifdef CONFIG_OMAP_SMARTREFLEX
-		else {
+		} else {
 			u8 vc, vt;
 			struct omap_opp *oppx;
 			unsigned long uvdc;
@@ -376,9 +370,8 @@ static int program_opp(int res, enum opp_t opp_type, int target_level,
 			vc = omap_twl_uv_to_vsel(uvdc);
 
 			/* ok to scale.. */
-			sr_voltagescale_vcbypass(t_opp, c_opp, vt, vc);
+			omap_voltage_scale(res, vt, vc);
 		}
-#endif
 	}
 
 	omap_smartreflex_enable(res);
diff --git a/arch/arm/mach-omap2/resource34xx.h b/arch/arm/mach-omap2/resource34xx.h
index 0b4e76e..b56d2df 100644
--- a/arch/arm/mach-omap2/resource34xx.h
+++ b/arch/arm/mach-omap2/resource34xx.h
@@ -30,7 +30,6 @@
 #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);
 extern void lock_scratchpad_sem(void);
 extern void unlock_scratchpad_sem(void);
 
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index d2e98a5..8e3b530 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -10,6 +10,7 @@
  */
 
 #include "smartreflex.h"
+#include "voltage.h"
 
 static int sr_class3_enable(int id)
 {
@@ -22,6 +23,7 @@ static int sr_class3_enable(int id)
 		pr_warning("Targetopp not known.Cannot enable SR%d\n", id);
 		return false;
 	}
+	omap_voltageprocessor_enable(id);
 	return sr_enable(id, target_opp_no);
 }
 
@@ -32,7 +34,9 @@ static int sr_class3_disable(int id)
 		target_opp_no = get_vdd1_opp();
 	else if (id == SR2)
 		target_opp_no = get_vdd2_opp();
+	omap_voltageprocessor_disable(id);
 	sr_disable(id);
+	omap_reset_voltage(id);
 	return true;
 }
 /* SR class3 structure */
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index ac935e2..f7c1182 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -14,11 +14,9 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/kobject.h>
@@ -27,19 +25,12 @@
 #include <linux/list.h>
 #include <linux/debugfs.h>
 
-#include <plat/omap34xx.h>
 #include <plat/control.h>
-#include <plat/clock.h>
-#include <plat/opp.h>
-#include <plat/opp_twl_tps.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 
-#include "prm.h"
 #include "smartreflex.h"
-#include "prm-regbits-34xx.h"
 
-#define MAX_TRIES 100
 #define SMARTREFLEX_NAME_LEN	16
 
 struct omap_sr {
@@ -146,115 +137,6 @@ static void sr_set_clk_length(struct omap_sr *sr)
 	}
 }
 
-static void sr_configure_vp(int srid)
-{
-	u32 vpconfig;
-	u32 vsel;
-	int uvdc;
-	u32 target_opp_no;
-	struct omap_opp *opp;
-
-	if (srid == SR1) {
-		target_opp_no = get_vdd1_opp();
-		if (!target_opp_no)
-			target_opp_no = VDD1_OPP3;
-
-		opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
-		BUG_ON(!opp); /* XXX ugh */
-
-		uvdc = opp_get_voltage(opp);
-		vsel = omap_twl_uv_to_vsel(uvdc);
-
-		vpconfig = PRM_VP1_CONFIG_ERROROFFSET |
-			PRM_VP1_CONFIG_ERRORGAIN |
-			PRM_VP1_CONFIG_TIMEOUTEN |
-			vsel << OMAP3430_INITVOLTAGE_SHIFT;
-
-		prm_write_mod_reg(vpconfig, OMAP3430_GR_MOD,
-					OMAP3_PRM_VP1_CONFIG_OFFSET);
-		prm_write_mod_reg(PRM_VP1_VSTEPMIN_SMPSWAITTIMEMIN |
-					PRM_VP1_VSTEPMIN_VSTEPMIN,
-					OMAP3430_GR_MOD,
-					OMAP3_PRM_VP1_VSTEPMIN_OFFSET);
-
-		prm_write_mod_reg(PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX |
-					PRM_VP1_VSTEPMAX_VSTEPMAX,
-					OMAP3430_GR_MOD,
-					OMAP3_PRM_VP1_VSTEPMAX_OFFSET);
-
-		prm_write_mod_reg(PRM_VP1_VLIMITTO_VDDMAX |
-					PRM_VP1_VLIMITTO_VDDMIN |
-					PRM_VP1_VLIMITTO_TIMEOUT,
-					OMAP3430_GR_MOD,
-					OMAP3_PRM_VP1_VLIMITTO_OFFSET);
-
-		/* Trigger initVDD value copy to voltage processor */
-		prm_set_mod_reg_bits(PRM_VP1_CONFIG_INITVDD, OMAP3430_GR_MOD,
-				     OMAP3_PRM_VP1_CONFIG_OFFSET);
-
-		/* Clear initVDD copy trigger bit */
-		prm_clear_mod_reg_bits(PRM_VP1_CONFIG_INITVDD, OMAP3430_GR_MOD,
-				       OMAP3_PRM_VP1_CONFIG_OFFSET);
-
-		/* Force update of voltage */
-		prm_set_mod_reg_bits(OMAP3430_FORCEUPDATE, OMAP3430_GR_MOD,
-				     OMAP3_PRM_VP1_CONFIG_OFFSET);
-		/* Clear force bit */
-		prm_clear_mod_reg_bits(OMAP3430_FORCEUPDATE, OMAP3430_GR_MOD,
-				       OMAP3_PRM_VP1_CONFIG_OFFSET);
-
-	} else if (srid == SR2) {
-		target_opp_no = get_vdd2_opp();
-		if (!target_opp_no)
-			target_opp_no = VDD2_OPP3;
-
-		opp = opp_find_by_opp_id(OPP_L3, target_opp_no);
-		BUG_ON(!opp); /* XXX ugh */
-
-		uvdc = opp_get_voltage(opp);
-		vsel = omap_twl_uv_to_vsel(uvdc);
-
-		vpconfig = PRM_VP2_CONFIG_ERROROFFSET |
-			PRM_VP2_CONFIG_ERRORGAIN |
-			PRM_VP2_CONFIG_TIMEOUTEN |
-			vsel << OMAP3430_INITVOLTAGE_SHIFT;
-
-		prm_write_mod_reg(vpconfig, OMAP3430_GR_MOD,
-					OMAP3_PRM_VP2_CONFIG_OFFSET);
-		prm_write_mod_reg(PRM_VP2_VSTEPMIN_SMPSWAITTIMEMIN |
-					PRM_VP2_VSTEPMIN_VSTEPMIN,
-					OMAP3430_GR_MOD,
-					OMAP3_PRM_VP2_VSTEPMIN_OFFSET);
-
-		prm_write_mod_reg(PRM_VP2_VSTEPMAX_SMPSWAITTIMEMAX |
-					PRM_VP2_VSTEPMAX_VSTEPMAX,
-					OMAP3430_GR_MOD,
-					OMAP3_PRM_VP2_VSTEPMAX_OFFSET);
-
-		prm_write_mod_reg(PRM_VP2_VLIMITTO_VDDMAX |
-					PRM_VP2_VLIMITTO_VDDMIN |
-					PRM_VP2_VLIMITTO_TIMEOUT,
-					OMAP3430_GR_MOD,
-					OMAP3_PRM_VP2_VLIMITTO_OFFSET);
-
-		/* Trigger initVDD value copy to voltage processor */
-		prm_set_mod_reg_bits(PRM_VP1_CONFIG_INITVDD, OMAP3430_GR_MOD,
-				     OMAP3_PRM_VP2_CONFIG_OFFSET);
-
-		/* Clear initVDD copy trigger bit */
-		prm_clear_mod_reg_bits(PRM_VP1_CONFIG_INITVDD, OMAP3430_GR_MOD,
-				       OMAP3_PRM_VP2_CONFIG_OFFSET);
-
-		/* Force update of voltage */
-		prm_set_mod_reg_bits(OMAP3430_FORCEUPDATE, OMAP3430_GR_MOD,
-				     OMAP3_PRM_VP2_CONFIG_OFFSET);
-		/* Clear force bit */
-		prm_clear_mod_reg_bits(OMAP3430_FORCEUPDATE, OMAP3430_GR_MOD,
-				       OMAP3_PRM_VP2_CONFIG_OFFSET);
-
-	}
-}
-
 static void sr_configure(struct omap_sr *sr)
 {
 	u32 sr_config;
@@ -303,92 +185,6 @@ static void sr_configure(struct omap_sr *sr)
 	sr->is_sr_reset = 0;
 }
 
-static int sr_reset_voltage(int srid)
-{
-	struct omap_opp *opp;
-	unsigned long uvdc;
-	u32 target_opp_no, vsel = 0;
-	u32 reg_addr = 0;
-	u32 loop_cnt = 0, retries_cnt = 0;
-	u32 vc_bypass_value;
-	u32 t2_smps_steps = 0;
-	u32 t2_smps_delay = 0;
-	u32 prm_vp1_voltage, prm_vp2_voltage;
-
-	if (srid == SR1) {
-		target_opp_no = get_vdd1_opp();
-		if (!target_opp_no) {
-			pr_info("Current OPP unknown: Cannot reset voltage\n");
-			return 1;
-		}
-
-		opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
-		if (!opp)
-			return 1;
-
-		uvdc = opp_get_voltage(opp);
-		vsel = omap_twl_uv_to_vsel(uvdc);
-
-		reg_addr = R_VDD1_SR_CONTROL;
-		prm_vp1_voltage = prm_read_mod_reg(OMAP3430_GR_MOD,
-						OMAP3_PRM_VP1_VOLTAGE_OFFSET);
-		t2_smps_steps = abs(vsel - prm_vp1_voltage);
-	} else if (srid == SR2) {
-		target_opp_no = get_vdd2_opp();
-		if (!target_opp_no) {
-			pr_info("Current OPP unknown: Cannot reset voltage\n");
-			return 1;
-		}
-
-		opp = opp_find_by_opp_id(OPP_L3, target_opp_no);
-		if (!opp)
-			return 1;
-
-		uvdc = opp_get_voltage(opp);
-		vsel = omap_twl_uv_to_vsel(uvdc);
-
-		reg_addr = R_VDD2_SR_CONTROL;
-		prm_vp2_voltage = prm_read_mod_reg(OMAP3430_GR_MOD,
-						OMAP3_PRM_VP2_VOLTAGE_OFFSET);
-		t2_smps_steps = abs(vsel - prm_vp2_voltage);
-	}
-
-	vc_bypass_value = (vsel << OMAP3430_DATA_SHIFT) |
-			(reg_addr << OMAP3430_REGADDR_SHIFT) |
-			(R_SRI2C_SLAVE_ADDR << OMAP3430_SLAVEADDR_SHIFT);
-
-	prm_write_mod_reg(vc_bypass_value, OMAP3430_GR_MOD,
-			OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
-
-	vc_bypass_value = prm_set_mod_reg_bits(OMAP3430_VALID, OMAP3430_GR_MOD,
-					OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
-
-	while ((vc_bypass_value & OMAP3430_VALID) != 0x0) {
-		loop_cnt++;
-		if (retries_cnt > 10) {
-			pr_info("Loop count exceeded in check SR I2C"
-								"write\n");
-			return 1;
-		}
-		if (loop_cnt > 50) {
-			retries_cnt++;
-			loop_cnt = 0;
-			udelay(10);
-		}
-		vc_bypass_value = prm_read_mod_reg(OMAP3430_GR_MOD,
-					OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
-	}
-
-	/*
-	 *  T2 SMPS slew rate (min) 4mV/uS, step size 12.5mV,
-	 *  2us added as buffer.
-	 */
-	t2_smps_delay = ((t2_smps_steps * 125) / 40) + 2;
-	udelay(t2_smps_delay);
-
-	return 0;
-}
-
 static void sr_start_vddautocomap(int srid)
 {
 	struct omap_sr *sr = _sr_lookup(srid);
@@ -435,8 +231,6 @@ static void sr_stop_vddautocomap(int srid)
 		sr_class->disable(srid);
 		sr_clk_disable(sr);
 		sr->is_autocomp_active = 0;
-		/* Reset the volatage for current OPP */
-		sr_reset_voltage(srid);
 	}
 
 }
@@ -456,12 +250,9 @@ static void sr_stop_vddautocomap(int srid)
  */
 int sr_enable(int srid, u32 target_opp_no)
 {
-	u32 nvalue_reciprocal, v;
+	u32 nvalue_reciprocal;
 	struct omap_sr *sr = _sr_lookup(srid);
-	struct omap_opp *opp;
 	struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
-	int uvdc;
-	char vsel;
 
 	if (!sr) {
 		pr_warning("omap_sr struct corresponding to SR%d not found\n",
@@ -469,16 +260,6 @@ int sr_enable(int srid, u32 target_opp_no)
 		return false;
 	}
 
-	if (sr->srid == SR1) {
-		opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
-		if (!opp)
-			return false;
-	} else {
-		opp = opp_find_by_opp_id(OPP_L3, target_opp_no);
-		if (!opp)
-			return false;
-	}
-
 	if (target_opp_no > pdata->no_opp) {
 		pr_notice("Wrong target opp\n");
 		return false;
@@ -505,46 +286,6 @@ int sr_enable(int srid, u32 target_opp_no)
 			(ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST),
 			(ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST));
 
-	uvdc = opp_get_voltage(opp);
-	vsel = omap_twl_uv_to_vsel(uvdc);
-
-	if (sr->srid == SR1) {
-		/* set/latch init voltage */
-		v = prm_read_mod_reg(OMAP3430_GR_MOD,
-				     OMAP3_PRM_VP1_CONFIG_OFFSET);
-		v &= ~(OMAP3430_INITVOLTAGE_MASK | OMAP3430_INITVDD);
-
-		v |= vsel << OMAP3430_INITVOLTAGE_SHIFT;
-		prm_write_mod_reg(v, OMAP3430_GR_MOD,
-				  OMAP3_PRM_VP1_CONFIG_OFFSET);
-		/* write1 to latch */
-		prm_set_mod_reg_bits(OMAP3430_INITVDD, OMAP3430_GR_MOD,
-				     OMAP3_PRM_VP1_CONFIG_OFFSET);
-		/* write2 clear */
-		prm_clear_mod_reg_bits(OMAP3430_INITVDD, OMAP3430_GR_MOD,
-				       OMAP3_PRM_VP1_CONFIG_OFFSET);
-		/* Enable VP1 */
-		prm_set_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE, OMAP3430_GR_MOD,
-				     OMAP3_PRM_VP1_CONFIG_OFFSET);
-	} else if (sr->srid == SR2) {
-		/* set/latch init voltage */
-		v = prm_read_mod_reg(OMAP3430_GR_MOD,
-				     OMAP3_PRM_VP2_CONFIG_OFFSET);
-		v &= ~(OMAP3430_INITVOLTAGE_MASK | OMAP3430_INITVDD);
-		v |= vsel << OMAP3430_INITVOLTAGE_SHIFT;
-		prm_write_mod_reg(v, OMAP3430_GR_MOD,
-				  OMAP3_PRM_VP2_CONFIG_OFFSET);
-		/* write1 to latch */
-		prm_set_mod_reg_bits(OMAP3430_INITVDD, OMAP3430_GR_MOD,
-				     OMAP3_PRM_VP2_CONFIG_OFFSET);
-		/* write2 clear */
-		prm_clear_mod_reg_bits(OMAP3430_INITVDD, OMAP3430_GR_MOD,
-				       OMAP3_PRM_VP2_CONFIG_OFFSET);
-		/* Enable VP2 */
-		prm_set_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, OMAP3430_GR_MOD,
-				     OMAP3_PRM_VP2_CONFIG_OFFSET);
-	}
-
 	/* SRCONFIG - enable SR */
 	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
 	return true;
@@ -560,43 +301,10 @@ int sr_enable(int srid, u32 target_opp_no)
 void sr_disable(int srid)
 {
 	struct omap_sr *sr = _sr_lookup(srid);
-	u32 i = 0;
 
 	sr->is_sr_reset = 1;
-
 	/* SRCONFIG - disable SR */
 	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, ~SRCONFIG_SRENABLE);
-
-	if (sr->srid == SR1) {
-		/* Wait for VP idle before disabling VP */
-		while ((!prm_read_mod_reg(OMAP3430_GR_MOD,
-					OMAP3_PRM_VP1_STATUS_OFFSET))
-					&& i++ < MAX_TRIES)
-			udelay(1);
-
-		if (i >= MAX_TRIES)
-			pr_warning("VP1 not idle, still going ahead with \
-							VP1 disable\n");
-
-		/* Disable VP1 */
-		prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE, OMAP3430_GR_MOD,
-					OMAP3_PRM_VP1_CONFIG_OFFSET);
-
-	} else if (sr->srid == SR2) {
-		/* Wait for VP idle before disabling VP */
-		while ((!prm_read_mod_reg(OMAP3430_GR_MOD,
-					OMAP3_PRM_VP2_STATUS_OFFSET))
-					&& i++ < MAX_TRIES)
-			udelay(1);
-
-		if (i >= MAX_TRIES)
-			pr_warning("VP2 not idle, still going ahead with \
-							 VP2 disable\n");
-
-		/* Disable VP2 */
-		prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, OMAP3430_GR_MOD,
-					OMAP3_PRM_VP2_CONFIG_OFFSET);
-	}
 }
 
 /**
@@ -611,7 +319,6 @@ void sr_disable(int srid)
  */
 void omap_smartreflex_enable(int srid)
 {
-	u32 target_opp_no = 0;
 	struct omap_sr *sr = _sr_lookup(srid);
 
 	if (!sr) {
@@ -647,7 +354,6 @@ void omap_smartreflex_enable(int srid)
  */
 void omap_smartreflex_disable(int srid)
 {
-	u32 i = 0;
 	struct omap_sr *sr = _sr_lookup(srid);
 
 	if (!sr) {
@@ -665,8 +371,6 @@ void omap_smartreflex_disable(int srid)
 			sr_class->disable(srid);
 			/* Disable SR clk */
 			sr_clk_disable(sr);
-			/* Reset the volatage for current OPP */
-			sr_reset_voltage(srid);
 		}
 	}
 }
@@ -692,76 +396,6 @@ void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
 	sr_class = class_data;
 }
 
-/* Voltage Scaling using SR VCBYPASS */
-int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
-					u8 target_vsel, u8 current_vsel)
-{
-	u32 vdd, target_opp_no, current_opp_no;
-	u32 vc_bypass_value;
-	u32 reg_addr = 0;
-	u32 loop_cnt = 0, retries_cnt = 0;
-	u32 t2_smps_steps = 0;
-	u32 t2_smps_delay = 0;
-
-	vdd = get_vdd(target_opp);
-	target_opp_no = get_opp_no(target_opp);
-	current_opp_no = get_opp_no(current_opp);
-
-	if (vdd == VDD1_OPP) {
-		t2_smps_steps = abs(target_vsel - current_vsel);
-
-		prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
-				(target_vsel << OMAP3430_VC_CMD_ON_SHIFT),
-				OMAP3430_GR_MOD,
-				OMAP3_PRM_VC_CMD_VAL_0_OFFSET);
-		reg_addr = R_VDD1_SR_CONTROL;
-
-	} else if (vdd == VDD2_OPP) {
-		t2_smps_steps =  abs(target_vsel - current_vsel);
-
-		prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
-				(target_vsel << OMAP3430_VC_CMD_ON_SHIFT),
-				OMAP3430_GR_MOD,
-				OMAP3_PRM_VC_CMD_VAL_1_OFFSET);
-		reg_addr = R_VDD2_SR_CONTROL;
-	}
-
-	vc_bypass_value = (target_vsel << OMAP3430_DATA_SHIFT) |
-			(reg_addr << OMAP3430_REGADDR_SHIFT) |
-			(R_SRI2C_SLAVE_ADDR << OMAP3430_SLAVEADDR_SHIFT);
-
-	prm_write_mod_reg(vc_bypass_value, OMAP3430_GR_MOD,
-			OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
-
-	vc_bypass_value = prm_set_mod_reg_bits(OMAP3430_VALID, OMAP3430_GR_MOD,
-					OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
-
-	while ((vc_bypass_value & OMAP3430_VALID) != 0x0) {
-		loop_cnt++;
-		if (retries_cnt > 10) {
-			pr_info("Loop count exceeded in check SR I2C"
-								"write\n");
-			return 1;
-		}
-		if (loop_cnt > 50) {
-			retries_cnt++;
-			loop_cnt = 0;
-			udelay(10);
-		}
-		vc_bypass_value = prm_read_mod_reg(OMAP3430_GR_MOD,
-					OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
-	}
-
-	/*
-	 *  T2 SMPS slew rate (min) 4mV/uS, step size 12.5mV,
-	 *  2us added as buffer.
-	 */
-	t2_smps_delay = ((t2_smps_steps * 125) / 40) + 2;
-	udelay(t2_smps_delay);
-
-	return 0;
-}
-
 /* PM Debug Fs enteries to enable disable smartreflex.*/
 
 static int omap_sr_autocomp_show(void *data, u64 *val)
@@ -820,8 +454,6 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
 	(void) debugfs_create_file(name, S_IRUGO | S_IWUGO, pm_dbg_main_dir,
 				(void *)sr_info, &pm_sr_fops);
 
-	/* Call the VPConfig */
-	sr_configure_vp(sr_info->srid);
 	odev->hwmods[0]->dev_attr = sr_info;
 	list_add(&sr_info->node, &sr_list);
 	pr_info("SmartReflex driver initialized\n");
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index a59a073..986f4df 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -17,12 +17,8 @@
 #include <linux/platform_device.h>
 
 extern struct dentry *pm_dbg_main_dir;
-extern int get_vdd1_opp(void);
-extern int get_vdd2_opp(void);
 
-#define PHY_TO_OFF_PM_MASTER(p)		(p - 0x36)
 #define PHY_TO_OFF_PM_RECIEVER(p)	(p - 0x5b)
-#define PHY_TO_OFF_PM_INT(p)		(p - 0x2e)
 
 /* SMART REFLEX REG ADDRESS OFFSET */
 #define SRCONFIG	0x00
@@ -40,64 +36,12 @@ extern int get_vdd2_opp(void);
 #define SR1		1
 #define SR2		2
 
-#define SR_FAIL		1
-#define SR_PASS		0
-
-#define SR_TRUE		1
-#define SR_FALSE	0
-
 #define GAIN_MAXLIMIT	16
 #define R_MAXLIMIT	256
 
 #define SR1_CLK_ENABLE	BIT(6)
 #define SR2_CLK_ENABLE	BIT(7)
 
-/* PRM_VP1_CONFIG */
-#define PRM_VP1_CONFIG_ERROROFFSET	(0x00 << 24)
-#define PRM_VP1_CONFIG_ERRORGAIN	(0x20 << 16)
-
-#define PRM_VP1_CONFIG_INITVOLTAGE	(0x30 << 8) /* 1.2 volt */
-#define PRM_VP1_CONFIG_TIMEOUTEN	BIT(3)
-#define PRM_VP1_CONFIG_INITVDD		BIT(2)
-#define PRM_VP1_CONFIG_FORCEUPDATE	BIT(1)
-#define PRM_VP1_CONFIG_VPENABLE		BIT(0)
-
-/* PRM_VP1_VSTEPMIN */
-#define PRM_VP1_VSTEPMIN_SMPSWAITTIMEMIN	(0x01F4 << 8)
-#define PRM_VP1_VSTEPMIN_VSTEPMIN		BIT(0)
-
-/* PRM_VP1_VSTEPMAX */
-#define PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX	(0x01F4 << 8)
-#define PRM_VP1_VSTEPMAX_VSTEPMAX		(0x04 << 0)
-
-/* PRM_VP1_VLIMITTO */
-#define PRM_VP1_VLIMITTO_VDDMAX		(0x3C << 24)
-#define PRM_VP1_VLIMITTO_VDDMIN		(0x0 << 16)
-#define PRM_VP1_VLIMITTO_TIMEOUT	(0xFFFF << 0)
-
-/* PRM_VP2_CONFIG */
-#define PRM_VP2_CONFIG_ERROROFFSET	(0x00 << 24)
-#define PRM_VP2_CONFIG_ERRORGAIN	(0x20 << 16)
-
-#define PRM_VP2_CONFIG_INITVOLTAGE	(0x30 << 8) /* 1.2 volt */
-#define PRM_VP2_CONFIG_TIMEOUTEN	BIT(3)
-#define PRM_VP2_CONFIG_INITVDD		BIT(2)
-#define PRM_VP2_CONFIG_FORCEUPDATE	BIT(1)
-#define PRM_VP2_CONFIG_VPENABLE		BIT(0)
-
-/* PRM_VP2_VSTEPMIN */
-#define PRM_VP2_VSTEPMIN_SMPSWAITTIMEMIN	(0x01F4 << 8)
-#define PRM_VP2_VSTEPMIN_VSTEPMIN		BIT(0)
-
-/* PRM_VP2_VSTEPMAX */
-#define PRM_VP2_VSTEPMAX_SMPSWAITTIMEMAX	(0x01F4 << 8)
-#define PRM_VP2_VSTEPMAX_VSTEPMAX		(0x04 << 0)
-
-/* PRM_VP2_VLIMITTO */
-#define PRM_VP2_VLIMITTO_VDDMAX		(0x2C << 24)
-#define PRM_VP2_VLIMITTO_VDDMIN		(0x0 << 16)
-#define PRM_VP2_VLIMITTO_TIMEOUT	(0xFFFF << 0)
-
 /* SRCONFIG */
 #define SR1_SRCONFIG_ACCUMDATA		(0x1F4 << 22)
 #define SR2_SRCONFIG_ACCUMDATA		(0x1F4 << 22)
@@ -139,9 +83,6 @@ extern int get_vdd2_opp(void);
 #define SR_ERRMAXLIMIT_MASK		(0xFF << 8)
 #define SR_ERRMINLIMIT_MASK		(0xFF << 0)
 
-#define SR_CLKACTIVITY_IOFF_FOFF	(0x00 << 20)
-#define SR_CLKACTIVITY_IOFF_FON		(0x02 << 20)
-
 #define ERRCONFIG_VPBOUNDINTEN		BIT(31)
 #define ERRCONFIG_VPBOUNDINTST		BIT(30)
 
@@ -153,90 +94,12 @@ extern int get_vdd2_opp(void);
 #define SR2_ERRMAXLIMIT			(0x02 << 8)
 #define SR2_ERRMINLIMIT			(0xF9 << 0)
 
-/* T2 SMART REFLEX */
-#define R_SRI2C_SLAVE_ADDR		0x12
-#define R_VDD1_SR_CONTROL		0x00
-#define R_VDD2_SR_CONTROL		0x01
-#define T2_SMPS_UPDATE_DELAY		360	/* In uSec */
-
 /* Vmode control */
 #define R_DCDC_GLOBAL_CFG	PHY_TO_OFF_PM_RECIEVER(0x61)
 
-#define R_VDD1_VSEL		PHY_TO_OFF_PM_RECIEVER(0xb9)
-#define R_VDD1_VMODE_CFG	PHY_TO_OFF_PM_RECIEVER(0xba)
-#define R_VDD1_VFLOOR		PHY_TO_OFF_PM_RECIEVER(0xbb)
-#define R_VDD1_VROOF		PHY_TO_OFF_PM_RECIEVER(0xbc)
-#define R_VDD1_STEP		PHY_TO_OFF_PM_RECIEVER(0xbd)
-
-#define R_VDD2_VSEL		PHY_TO_OFF_PM_RECIEVER(0xc7)
-#define R_VDD2_VMODE_CFG	PHY_TO_OFF_PM_RECIEVER(0xc8)
-#define R_VDD2_VFLOOR		PHY_TO_OFF_PM_RECIEVER(0xc9)
-#define R_VDD2_VROOF		PHY_TO_OFF_PM_RECIEVER(0xca)
-#define R_VDD2_STEP		PHY_TO_OFF_PM_RECIEVER(0xcb)
-
 /* R_DCDC_GLOBAL_CFG register, SMARTREFLEX_ENABLE values */
 #define DCDC_GLOBAL_CFG_ENABLE_SRFLX	0x08
 
-#define PRCM_MAX_SYSC_REGS 30
-
-/*
- * XXX: These should be removed/moved from here once we have a working DVFS
- * implementation in place
- */
-#define AT_3430		1	/*3430 ES 1.0 */
-#define AT_3430_ES2	2	/*3430 ES 2.0 */
-
-#define ID_OPP			0xE2 	/*OPP*/
-
-/* DEVICE ID/DPLL ID/CLOCK ID: bits 28-31 for OMAP type */
-#define OMAP_TYPE_SHIFT		28
-#define OMAP_TYPE_MASK		0xF
-/* OPP ID: bits: 0-4 for OPP number */
-#define OPP_NO_POS		0
-#define OPP_NO_MASK		0x1F
-/* OPP ID: bits: 5-6 for VDD */
-#define VDD_NO_POS		5
-#define VDD_NO_MASK		0x3
-/* Other IDs: bits 20-27 for ID type */
-/* These IDs have bits 25,26,27 as 1 */
-#define OTHER_ID_TYPE_SHIFT		20
-#define OTHER_ID_TYPE_MASK		0xFF
-
-#define OTHER_ID_TYPE(X) ((X & OTHER_ID_TYPE_MASK) << OTHER_ID_TYPE_SHIFT)
-#define ID_OPP_NO(X)	 ((X & OPP_NO_MASK) << OPP_NO_POS)
-#define ID_VDD(X)	 ((X & VDD_NO_MASK) << VDD_NO_POS)
-#define OMAP(X)		 ((X >> OMAP_TYPE_SHIFT) & OMAP_TYPE_MASK)
-#define get_opp_no(X)	 ((X >> OPP_NO_POS) & OPP_NO_MASK)
-#define get_vdd(X)	 ((X >> VDD_NO_POS) & VDD_NO_MASK)
-
-/* VDD1 OPPs */
-#define PRCM_VDD1_OPP1		(OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
-					ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x1))
-#define PRCM_VDD1_OPP2		(OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
-					ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x2))
-#define PRCM_VDD1_OPP3		(OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
-					ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x3))
-#define PRCM_VDD1_OPP4		(OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
-					ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x4))
-#define PRCM_VDD1_OPP5		(OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
-					ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x5))
-#define PRCM_NO_VDD1_OPPS	5
-
-
-/* VDD2 OPPs */
-#define PRCM_VDD2_OPP1		(OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
-					ID_VDD(PRCM_VDD2) | ID_OPP_NO(0x1))
-#define PRCM_VDD2_OPP2		(OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
-					ID_VDD(PRCM_VDD2) | ID_OPP_NO(0x2))
-#define PRCM_VDD2_OPP3		(OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
-					ID_VDD(PRCM_VDD2) | ID_OPP_NO(0x3))
-#define PRCM_NO_VDD2_OPPS	3
-/* XXX: end remove/move */
-
-/* XXX: find more appropriate place for these once DVFS is in place */
-extern u32 current_vdd1_opp;
-extern u32 current_vdd2_opp;
-
 #ifdef CONFIG_OMAP_SMARTREFLEX_TESTING
 #define SR_TESTING_NVALUES 	1
 #else
@@ -307,8 +170,6 @@ void sr_disable(int srid);
  * API to register the smartreflex class driver with the smartreflex driver
  */
 void omap_sr_register_class(struct omap_smartreflex_class_data *class_data);
-
-int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel);
 #else
 static inline void enable_smartreflex(int srid) {}
 static inline void disable_smartreflex(int srid) {}
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
new file mode 100644
index 0000000..c0c2c17
--- /dev/null
+++ b/arch/arm/mach-omap2/voltage.c
@@ -0,0 +1,550 @@
+/*
+ * OMAP3/OMAP4 Voltage Management Routines
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * 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/pm.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <plat/omap-pm.h>
+#include <plat/omap34xx.h>
+#include <plat/opp.h>
+#include <plat/opp_twl_tps.h>
+
+#include "prm-regbits-34xx.h"
+#include "voltage.h"
+
+#define MAX_TRIES 100
+
+/**
+ * OMAP3 Voltage controller SR parameters. TODO: Pass this info as part of
+ * board data or PMIC data
+ */
+#define R_SRI2C_SLAVE_ADDR              0x12
+#define R_VDD1_SR_CONTROL               0x00
+#define R_VDD2_SR_CONTROL		0x01
+
+
+/* Voltage processor register offsets */
+struct vp_reg_offs {
+	void __iomem *vp_vpconfig_reg;
+	void __iomem *vp_vstepmin_reg;
+	void __iomem *vp_vstepmax_reg;
+	void __iomem *vp_vlimitto_reg;
+	void __iomem *vp_status_reg;
+	void __iomem *vp_voltage_reg;
+};
+
+/*
+ * Voltage processor structure conttaining info about
+ * the various register offsets and the bit field values
+ * for a particular instance of voltage processor.
+ */
+struct vp_reg_info {
+	struct vp_reg_offs vp_offs;
+	/* Bit fields for VPx_VPCONFIG */
+	u32 vp_erroroffset;
+	u32 vp_errorgain;
+	/* Bit fields for VPx_VSTEPMIN */
+	u32 vp_stepmin;
+	u32 vp_smpswaittimemin;
+	/* Bit fields for VPx_VSTEPMAX */
+	u32 vp_stepmax;
+	u32 vp_smpswaittimemax;
+	/* Bit fields for VPx_VLIMITTO */
+	u32 vp_vddmin;
+	u32 vp_vddmax;
+	u32 vp_timeout;
+};
+static struct vp_reg_info *vp_reg;
+/*
+ * Number of scalable voltage domains that has an independent
+ * Voltage processor
+ */
+static int no_scalable_vdd;
+
+/* OMAP3 VP register offsets and other definitions */
+struct __init vp_reg_offs omap3_vp_offs[] = {
+	/* VP1 */
+	{
+		.vp_vpconfig_reg = OMAP3430_PRM_VP1_CONFIG,
+		.vp_vstepmin_reg = OMAP3430_PRM_VP1_VSTEPMIN,
+		.vp_vstepmax_reg = OMAP3430_PRM_VP1_VSTEPMAX,
+		.vp_vlimitto_reg = OMAP3430_PRM_VP1_VLIMITTO,
+		.vp_status_reg = OMAP3430_PRM_VP1_STATUS,
+		.vp_voltage_reg = OMAP3430_PRM_VP1_VOLTAGE,
+	},
+	/* VP2 */
+	{	.vp_vpconfig_reg = OMAP3430_PRM_VP2_CONFIG,
+		.vp_vstepmin_reg = OMAP3430_PRM_VP2_VSTEPMIN,
+		.vp_vstepmax_reg = OMAP3430_PRM_VP2_VSTEPMAX,
+		.vp_vlimitto_reg = OMAP3430_PRM_VP2_VLIMITTO,
+		.vp_status_reg = OMAP3430_PRM_VP2_STATUS,
+		.vp_voltage_reg = OMAP3430_PRM_VP2_VOLTAGE,
+	},
+};
+
+#define OMAP3_NO_SCALABLE_VDD ARRAY_SIZE(omap3_vp_offs)
+static struct vp_reg_info omap3_vp_reg[OMAP3_NO_SCALABLE_VDD];
+
+
+/* TODO: OMAP4 register offsets */
+
+/**
+ * Voltage controller register offsets
+ */
+struct vc_reg_info {
+	void __iomem *vc_cmdval0_reg;
+	void __iomem *vc_cmdval1_reg;
+	void __iomem *vc_bypass_val_reg;
+} vc_reg;
+
+/*
+ * Default voltage controller settings for OMAP3
+ */
+static struct prm_setup_vc vc_config = {
+	.clksetup = 0xff,
+	.voltsetup_time1 = 0xfff,
+	.voltsetup_time2 = 0xfff,
+	.voltoffset = 0xff,
+	.voltsetup2 = 0xff,
+	.vdd0_on = 0x30,        /* 1.2v */
+	.vdd0_onlp = 0x20,      /* 1.0v */
+	.vdd0_ret = 0x1e,       /* 0.975v */
+	.vdd0_off = 0x00,       /* 0.6v */
+	.vdd1_on = 0x2c,        /* 1.15v */
+	.vdd1_onlp = 0x20,      /* 1.0v */
+	.vdd1_ret = 0x1e,       /* .975v */
+	.vdd1_off = 0x00,       /* 0.6v */
+};
+
+static inline u32 voltage_read_reg(void __iomem *offset)
+{
+	return __raw_readl(offset);
+}
+
+static inline void voltage_write_reg(void __iomem *offset, u32 value)
+{
+	__raw_writel(value, offset);
+}
+
+/**
+ * voltagecontroller_init - initializes the voltage controller.
+ *
+ * Intializes the voltage controller registers with the PMIC and board
+ * specific parameters and voltage setup times. If the board file does not
+ * populate the voltage controller parameters through omap3_pm_init_vc,
+ * default values specified in vc_config is used.
+ */
+static void __init init_voltagecontroller(void)
+{
+
+	void __iomem *vc_ch_conf_reg, *vc_i2c_cfg_reg, *vc_smps_sa_reg;
+	void __iomem *vc_smps_vol_ra_reg;
+	void __iomem *prm_clksetup_reg, *prm_voltsetup1_reg;
+	void __iomem *prm_voltsetup2_reg, *prm_voltoffset_reg;
+
+	if (cpu_is_omap34xx()) {
+		vc_reg.vc_cmdval0_reg = OMAP3430_PRM_VC_CMD_VAL_0;
+		vc_reg.vc_cmdval1_reg = OMAP3430_PRM_VC_CMD_VAL_1;
+		vc_reg.vc_bypass_val_reg = OMAP3430_PRM_VC_BYPASS_VAL;
+		vc_ch_conf_reg = OMAP3430_PRM_VC_CH_CONF;
+		vc_i2c_cfg_reg = OMAP3430_PRM_VC_I2C_CFG;
+		vc_smps_sa_reg = OMAP3430_PRM_VC_SMPS_SA;
+		vc_smps_vol_ra_reg = OMAP3430_PRM_VC_SMPS_VOL_RA;
+		prm_clksetup_reg = OMAP3430_PRM_CLKSETUP;
+		prm_voltoffset_reg = OMAP3430_PRM_VOLTOFFSET;
+		prm_voltsetup1_reg = OMAP3430_PRM_VOLTSETUP1;
+		prm_voltsetup2_reg = OMAP3430_PRM_VOLTSETUP2;
+	} else {
+		pr_warning("support for voltage controller not added\n");
+		return;
+	}
+	voltage_write_reg(vc_smps_sa_reg, (R_SRI2C_SLAVE_ADDR <<
+			VC_SMPS_SA1_SHIFT) | (R_SRI2C_SLAVE_ADDR <<
+			VC_SMPS_SA0_SHIFT));
+
+	voltage_write_reg(vc_smps_vol_ra_reg, (R_VDD2_SR_CONTROL <<
+			VC_VOLRA1_SHIFT) | (R_VDD1_SR_CONTROL <<
+			VC_VOLRA0_SHIFT));
+
+	voltage_write_reg(vc_reg.vc_cmdval0_reg,
+			(vc_config.vdd0_on << VC_CMD_ON_SHIFT) |
+			(vc_config.vdd0_onlp << VC_CMD_ONLP_SHIFT) |
+			(vc_config.vdd0_ret << VC_CMD_RET_SHIFT) |
+			(vc_config.vdd0_off << VC_CMD_OFF_SHIFT));
+
+	voltage_write_reg(vc_reg.vc_cmdval1_reg,
+			(vc_config.vdd1_on << VC_CMD_ON_SHIFT) |
+			(vc_config.vdd1_onlp << VC_CMD_ONLP_SHIFT) |
+			(vc_config.vdd1_ret << VC_CMD_RET_SHIFT) |
+			(vc_config.vdd1_off << VC_CMD_OFF_SHIFT));
+
+	voltage_write_reg(vc_ch_conf_reg, VC_CMD1 | VC_RAV1);
+
+	voltage_write_reg(vc_i2c_cfg_reg, VC_MCODE_SHIFT | VC_HSEN);
+
+	/* Write setup times */
+	voltage_write_reg(prm_clksetup_reg, vc_config.clksetup);
+	voltage_write_reg(prm_voltsetup1_reg,
+			(vc_config.voltsetup_time2 << VC_SETUP_TIME2_SHIFT) |
+			(vc_config.voltsetup_time1 << VC_SETUP_TIME1_SHIFT));
+	voltage_write_reg(prm_voltoffset_reg, vc_config.voltoffset);
+	voltage_write_reg(prm_voltsetup2_reg, vc_config.voltsetup2);
+}
+
+static void vp_latch_vsel(int vp_id)
+{
+	u32 vpconfig, target_opp_no;
+	struct omap_opp *opp;
+	int uvdc;
+	char vsel;
+
+	/* Should remove this once OPP framework is fixed */
+	if (vp_id == VP1) {
+		target_opp_no = get_vdd1_opp();
+		opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
+		if (!opp)
+			return;
+	} else if (vp_id == VP2) {
+		target_opp_no = get_vdd2_opp();
+		opp = opp_find_by_opp_id(OPP_L3, target_opp_no);
+		if (!opp)
+			return;
+	} else {
+		pr_warning("Voltage processor%d does not exisit", vp_id);
+		return;
+	}
+
+	uvdc = opp_get_voltage(opp);
+	vsel = omap_twl_uv_to_vsel(uvdc);
+	vpconfig = voltage_read_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg);
+	vpconfig &= ~(VP_INITVOLTAGE_MASK | VP_CONFIG_INITVDD);
+	vpconfig |= vsel << VP_INITVOLTAGE_SHIFT;
+
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
+
+	/* Trigger initVDD value copy to voltage processor */
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg,
+			(vpconfig | VP_CONFIG_INITVDD));
+
+	/* Clear initVDD copy trigger bit */
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
+}
+
+static void __init vp_configure(int vp_id)
+{
+	u32 vpconfig;
+
+	vpconfig = vp_reg[vp_id].vp_erroroffset | vp_reg[vp_id].vp_errorgain |
+			VP_CONFIG_TIMEOUTEN;
+
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
+
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vstepmin_reg,
+			(vp_reg[vp_id].vp_smpswaittimemin |
+			vp_reg[vp_id].vp_stepmin));
+
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vstepmax_reg,
+			(vp_reg[vp_id].vp_smpswaittimemax |
+			vp_reg[vp_id].vp_stepmax));
+
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vlimitto_reg,
+			(vp_reg[vp_id].vp_vddmax | vp_reg[vp_id].vp_vddmin |
+			vp_reg[vp_id].vp_timeout));
+
+	/* Set the init voltage */
+	vp_latch_vsel(vp_id);
+
+	vpconfig = voltage_read_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg);
+	/* Force update of voltage */
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg,
+			(vpconfig | VP_FORCEUPDATE));
+	/* Clear force bit */
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
+}
+
+static void __init vp_reg_configure(int vp_id)
+{
+	if (cpu_is_omap34xx()) {
+		vp_reg[vp_id].vp_offs = omap3_vp_offs[vp_id];
+		if (vp_id == VP1) {
+			vp_reg[vp_id].vp_vddmin = (OMAP3_VP1_VLIMITTO_VDDMIN <<
+					OMAP3430_VDDMIN_SHIFT);
+			vp_reg[vp_id].vp_vddmax = (OMAP3_VP1_VLIMITTO_VDDMAX <<
+					OMAP3430_VDDMAX_SHIFT);
+		} else if (vp_id == VP2) {
+			vp_reg[vp_id].vp_vddmin = (OMAP3_VP2_VLIMITTO_VDDMIN <<
+					OMAP3430_VDDMIN_SHIFT);
+			vp_reg[vp_id].vp_vddmax = (OMAP3_VP2_VLIMITTO_VDDMAX <<
+					OMAP3430_VDDMAX_SHIFT);
+		} else {
+			pr_warning("Voltage processor%d does not exisit\
+					in OMAP3 \n", vp_id);
+			return;
+		}
+		vp_reg[vp_id].vp_erroroffset = (OMAP3_VP_CONFIG_ERROROFFSET <<
+					OMAP3430_INITVOLTAGE_SHIFT);
+		vp_reg[vp_id].vp_errorgain = (OMAP3_VP_CONFIG_ERRORGAIN <<
+					OMAP3430_ERRORGAIN_SHIFT);
+		vp_reg[vp_id].vp_smpswaittimemin =
+					(OMAP3_VP_VSTEPMIN_SMPSWAITTIMEMIN <<
+					OMAP3430_SMPSWAITTIMEMIN_SHIFT);
+		vp_reg[vp_id].vp_smpswaittimemax =
+					(OMAP3_VP_VSTEPMAX_SMPSWAITTIMEMAX <<
+					OMAP3430_SMPSWAITTIMEMAX_SHIFT);
+		vp_reg[vp_id].vp_stepmin = (OMAP3_VP_VSTEPMIN_VSTEPMIN <<
+					OMAP3430_VSTEPMIN_SHIFT);
+		vp_reg[vp_id].vp_stepmax = (OMAP3_VP_VSTEPMAX_VSTEPMAX <<
+					OMAP3430_VSTEPMAX_SHIFT);
+		vp_reg[vp_id].vp_timeout = (OMAP3_VP_VLIMITTO_TIMEOUT <<
+					OMAP3430_TIMEOUT_SHIFT);
+	}
+	/* TODO Extend this for OMAP4 ?? Or need a separate file  */
+}
+
+/**
+ * vc_bypass_scale_voltage - VC bypass method of voltage scaling
+ */
+static int vc_bypass_scale_voltage(u32 vdd, u8 target_vsel, u8 current_vsel)
+{
+	u32 vc_bypass_value;
+	u32 reg_addr = 0;
+	u32 loop_cnt = 0, retries_cnt = 0;
+	u32 smps_steps = 0;
+	u32 smps_delay = 0;
+
+	smps_steps = abs(target_vsel - current_vsel);
+
+	if (vdd == VDD1_OPP) {
+		u32 vc_cmdval0;
+
+		vc_cmdval0 = voltage_read_reg(vc_reg.vc_cmdval0_reg);
+		vc_cmdval0 &= ~VC_CMD_ON_MASK;
+		vc_cmdval0 |= (target_vsel << VC_CMD_ON_SHIFT);
+		voltage_write_reg(vc_reg.vc_cmdval0_reg, vc_cmdval0);
+		reg_addr = R_VDD1_SR_CONTROL;
+
+	} else if (vdd == VDD2_OPP) {
+		u32 vc_cmdval1;
+
+		vc_cmdval1 = voltage_read_reg(vc_reg.vc_cmdval1_reg);
+		vc_cmdval1 &= ~VC_CMD_ON_MASK;
+		vc_cmdval1 |= (target_vsel << VC_CMD_ON_SHIFT);
+		voltage_write_reg(vc_reg.vc_cmdval1_reg, vc_cmdval1);
+		reg_addr = R_VDD2_SR_CONTROL;
+	} else {
+		pr_warning("Wrong VDD passed in vc_bypass_scale_voltage %d\n",
+				vdd);
+		return false;
+	}
+
+	vc_bypass_value = (target_vsel << VC_DATA_SHIFT) |
+			(reg_addr << VC_REGADDR_SHIFT) |
+			(R_SRI2C_SLAVE_ADDR << VC_SLAVEADDR_SHIFT);
+
+	voltage_write_reg(vc_reg.vc_bypass_val_reg, vc_bypass_value);
+
+	voltage_write_reg(vc_reg.vc_bypass_val_reg,
+			vc_bypass_value | VC_VALID);
+	vc_bypass_value = voltage_read_reg(vc_reg.vc_bypass_val_reg);
+
+	while ((vc_bypass_value & VC_VALID) != 0x0) {
+		loop_cnt++;
+		if (retries_cnt > 10) {
+			pr_warning("Loop count exceeded in check SR I2C write\
+						during voltgae scaling\n");
+			return false;
+		}
+		if (loop_cnt > 50) {
+			retries_cnt++;
+			loop_cnt = 0;
+			udelay(10);
+		}
+		vc_bypass_value = voltage_read_reg(vc_reg.vc_bypass_val_reg);
+	}
+
+	/*
+	 *  T2 SMPS slew rate (min) 4mV/uS, step size 12.5mV,
+	 *  2us added as buffer.
+	 */
+	smps_delay = ((smps_steps * 125) / 40) + 2;
+	udelay(smps_delay);
+	return true;
+}
+
+
+static void __init init_voltageprocessors(void)
+{
+	int i;
+
+	if (cpu_is_omap34xx()) {
+		vp_reg = omap3_vp_reg;
+		no_scalable_vdd = OMAP3_NO_SCALABLE_VDD;
+	} else {
+		/* TODO: Add support for OMAP4 */
+		pr_warning("Voltage processor support not yet added \n");
+		return;
+	}
+	for (i = 0; i < no_scalable_vdd; i++) {
+		vp_reg_configure(i);
+		vp_configure(i);
+	}
+}
+
+/* Public functions */
+
+/**
+ * omap_voltageprocessor_enable : API to enable a particular VP
+ * @vp_id : The id of the VP to be enable.
+ *
+ * This API enables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_voltageprocessor_enable(int vp_id)
+{
+	u32 vpconfig;
+
+	/*
+	 * This latching is required only if VC bypass method is used for
+	 * voltage scaling during dvfs.
+	 */
+	vp_latch_vsel(vp_id - 1);
+	vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
+	/* Enable VP */
+	voltage_write_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg,
+				vpconfig | VP_CONFIG_VPENABLE);
+}
+
+/**
+ * omap_voltageprocessor_disable : API to disable a particular VP
+ * @vp_id : The id of the VP to be disable.
+ *
+ * This API disables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_voltageprocessor_disable(int vp_id)
+{
+	int i = 0;
+	u32 vpconfig;
+
+	/* Wait for VP idle before disabling VP */
+	while ((!voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_status_reg)) &&
+				i++ < MAX_TRIES)
+		udelay(1);
+
+	if (i >= MAX_TRIES)
+		pr_warning("VP1 not idle, still going ahead with \
+						VP1 disable\n");
+	/* Disable VP1 */
+	vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
+	vpconfig &= ~VP_CONFIG_VPENABLE;
+	voltage_write_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg, vpconfig);
+}
+
+/**
+ * omap_voltage_scale : API to scale voltage of a particular voltage domain.
+ * @vdd : the voltage domain whose voltage is to be scaled
+ * @target_vsel : The target voltage of the voltage domain
+ * @current_vsel : the current voltage of the voltage domain.
+ *
+ * This API should be called by the kernel to do the voltage scaling
+ * for a particular voltage domain during dvfs or any other situation.
+ */
+int omap_voltage_scale(int vdd, u8 target_vsel, u8 current_vsel)
+{	/*
+	 * TODO add VP force update method of voltage scaling
+	 * and choose btw the two
+	 */
+	return vc_bypass_scale_voltage(vdd, target_vsel, current_vsel);
+}
+
+/**
+ * omap_reset_voltage : Resets the voltage of a particular voltage domain
+ * to that of the current OPP.
+ * @vdd : the voltage domain whose voltage is to be reset.
+ *
+ * This API finds out the correct voltage the voltage domain is supposed
+ * to be at and resets the voltage to that level. Should be used expecially
+ * while disabling any voltage compensation modules.
+ */
+void omap_reset_voltage(int vdd)
+{
+	u32 target_opp_no;
+	struct omap_opp *opp;
+	int uvdc;
+	char vsel;
+
+	/* Should remove this once OPP framework is fixed */
+	if ((vdd - 1) == VP1) {
+		target_opp_no = get_vdd1_opp();
+		opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
+		if (!opp)
+			return;
+	} else if ((vdd - 1) == VP2) {
+		target_opp_no = get_vdd2_opp();
+		opp = opp_find_by_opp_id(OPP_L3, target_opp_no);
+		if (!opp)
+			return;
+	} else {
+		pr_warning("Wrong VDD passed in omap_reset_voltage %d\n", vdd);
+		return;
+	}
+	uvdc = opp_get_voltage(opp);
+	vsel = omap_twl_uv_to_vsel(uvdc);
+	omap_voltage_scale(vdd, vsel, voltage_read_reg(
+				vp_reg[vdd - 1].vp_offs.vp_voltage_reg));
+}
+
+/**
+ * omap3_pm_init_vc - polpulates vc_config with values specified in board file
+ * @setup_vc - the structure with various vc parameters
+ *
+ * Updates vc_config with the voltage setup times and other parameters as
+ * specified in setup_vc. vc_config is later used in init_voltagecontroller
+ * to initialize the voltage controller registers. Board files should call
+ * this function with the correct volatge settings corresponding
+ * the particular PMIC and chip.
+ */
+void __init omap_voltage_init_vc(struct prm_setup_vc *setup_vc)
+{
+	if (!setup_vc)
+		return;
+
+	vc_config.clksetup = setup_vc->clksetup;
+	vc_config.voltsetup_time1 = setup_vc->voltsetup_time1;
+	vc_config.voltsetup_time2 = setup_vc->voltsetup_time2;
+	vc_config.voltoffset = setup_vc->voltoffset;
+	vc_config.voltsetup2 = setup_vc->voltsetup2;
+	vc_config.vdd0_on = setup_vc->vdd0_on;
+	vc_config.vdd0_onlp = setup_vc->vdd0_onlp;
+	vc_config.vdd0_ret = setup_vc->vdd0_ret;
+	vc_config.vdd0_off = setup_vc->vdd0_off;
+	vc_config.vdd1_on = setup_vc->vdd1_on;
+	vc_config.vdd1_onlp = setup_vc->vdd1_onlp;
+	vc_config.vdd1_ret = setup_vc->vdd1_ret;
+	vc_config.vdd1_off = setup_vc->vdd1_off;
+}
+
+/**
+ * omap_voltage_init : Volatage init API which does VP and VC init.
+ */
+void __init omap_voltage_init(void)
+{
+	init_voltagecontroller();
+	init_voltageprocessors();
+}
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
new file mode 100644
index 0000000..64c506c
--- /dev/null
+++ b/arch/arm/mach-omap2/voltage.h
@@ -0,0 +1,74 @@
+/*
+ * OMAP3 Voltage Management Routines
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * 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 "pm.h"
+
+/* Voltageprocessor instances */
+#define VP1	0
+#define VP2	1
+
+extern int get_vdd1_opp(void);
+extern int get_vdd2_opp(void);
+
+/* Generic VP definitions. Need to be redefined for OMAP4 */
+#define VP_CONFIG_TIMEOUTEN	OMAP3430_TIMEOUTEN
+#define VP_CONFIG_INITVDD	OMAP3430_INITVDD
+#define VP_FORCEUPDATE		OMAP3430_FORCEUPDATE
+#define VP_CONFIG_VPENABLE	OMAP3430_VPENABLE
+#define VP_INITVOLTAGE_MASK	OMAP3430_INITVOLTAGE_MASK
+#define VP_INITVOLTAGE_SHIFT	OMAP3430_INITVOLTAGE_SHIFT
+
+/* Generic VC definitions. Need to be redefined for OMAP4 */
+#define VC_SMPS_SA1_SHIFT	OMAP3430_SMPS_SA1_SHIFT
+#define VC_SMPS_SA0_SHIFT	OMAP3430_SMPS_SA0_SHIFT
+#define VC_VOLRA1_SHIFT		OMAP3430_VOLRA1_SHIFT
+#define VC_VOLRA0_SHIFT		OMAP3430_VOLRA0_SHIFT
+#define VC_CMD_ON_SHIFT		OMAP3430_VC_CMD_ON_SHIFT
+#define VC_CMD_ONLP_SHIFT	OMAP3430_VC_CMD_ONLP_SHIFT
+#define VC_CMD_RET_SHIFT	OMAP3430_VC_CMD_RET_SHIFT
+#define VC_CMD_OFF_SHIFT	OMAP3430_VC_CMD_OFF_SHIFT
+#define VC_SETUP_TIME2_SHIFT	OMAP3430_SETUP_TIME2_SHIFT
+#define VC_SETUP_TIME1_SHIFT	OMAP3430_SETUP_TIME1_SHIFT
+#define VC_DATA_SHIFT		OMAP3430_DATA_SHIFT
+#define VC_REGADDR_SHIFT	OMAP3430_REGADDR_SHIFT
+#define VC_SLAVEADDR_SHIFT	OMAP3430_SLAVEADDR_SHIFT
+#define VC_CMD_ON_MASK		OMAP3430_VC_CMD_ON_MASK
+#define VC_CMD1			OMAP3430_CMD1
+#define VC_RAV1			OMAP3430_RAV1
+#define VC_MCODE_SHIFT		OMAP3430_MCODE_SHIFT
+#define VC_HSEN			OMAP3430_HSEN
+#define VC_VALID		OMAP3430_VALID
+
+
+/*
+ * Omap 3430 VP registerspecific values. Maybe these need to come from
+ * board file or PMIC data structure
+ */
+#define OMAP3_VP_CONFIG_ERROROFFSET		0x00
+#define OMAP3_VP_CONFIG_ERRORGAIN		0x20
+#define	OMAP3_VP_VSTEPMIN_SMPSWAITTIMEMIN	0x01F4
+#define OMAP3_VP_VSTEPMIN_VSTEPMIN		0x1
+#define OMAP3_VP_VSTEPMAX_SMPSWAITTIMEMAX	0x01F4
+#define OMAP3_VP_VSTEPMAX_VSTEPMAX		0x04
+#define OMAP3_VP1_VLIMITTO_VDDMIN		0x0
+#define OMAP3_VP1_VLIMITTO_VDDMAX		0x3C
+#define OMAP3_VP2_VLIMITTO_VDDMAX		0x2C
+#define OMAP3_VP2_VLIMITTO_VDDMIN		0x0
+#define OMAP3_VP_VLIMITTO_TIMEOUT		0xFFFF
+
+#define VOLTAGE_MOD	OMAP3430_GR_MOD
+/* TODO OMAP4 VP register values if the same file is used for OMAP4*/
+
+void omap_voltageprocessor_enable(int vp_id);
+void omap_voltageprocessor_disable(int vp_id);
+void omap_voltage_init_vc(struct prm_setup_vc *setup_vc);
+void omap_voltage_init(void);
+int omap_voltage_scale(int vdd, u8 target_vsel, u8 current_vsel);
+void omap_reset_voltage(int vdd);
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 10/16] OMAP3: PM: Cleaning up of smartreflex header file.
  2010-02-24  9:29                 ` [PATCH 09/16] OMAP3: PM: Creating separate files for handling OMAP3 voltage related operations Thara Gopinath
@ 2010-02-24  9:29                   ` Thara Gopinath
  2010-02-24  9:29                     ` [PATCH 11/16] OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3 Thara Gopinath
  2010-03-02 20:02                   ` [PATCH 09/16] OMAP3: PM: Creating separate files for handling OMAP3 voltage related operations Kevin Hilman
  1 sibling, 1 reply; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

This patch cleans up smartreflex.h removing all unnecessary and
duplicate definitions.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/smartreflex.h |   99 +++++++++++++++++++++---------------
 1 files changed, 58 insertions(+), 41 deletions(-)

diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 986f4df..7a1f0c7 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -18,20 +18,6 @@
 
 extern struct dentry *pm_dbg_main_dir;
 
-#define PHY_TO_OFF_PM_RECIEVER(p)	(p - 0x5b)
-
-/* SMART REFLEX REG ADDRESS OFFSET */
-#define SRCONFIG	0x00
-#define SRSTATUS	0x04
-#define SENVAL		0x08
-#define SENMIN		0x0C
-#define SENMAX		0x10
-#define SENAVG		0x14
-#define AVGWEIGHT	0x18
-#define NVALUERECIPROCAL	0x1C
-#define SENERROR	0x20
-#define ERRCONFIG	0x24
-
 /* SR Modules */
 #define SR1		1
 #define SR2		2
@@ -39,37 +25,38 @@ extern struct dentry *pm_dbg_main_dir;
 #define GAIN_MAXLIMIT	16
 #define R_MAXLIMIT	256
 
-#define SR1_CLK_ENABLE	BIT(6)
-#define SR2_CLK_ENABLE	BIT(7)
+/* SMART REFLEX REG ADDRESS OFFSET */
+#define SRCONFIG		0x00
+#define SRSTATUS		0x04
+#define SENVAL			0x08
+#define SENMIN			0x0C
+#define SENMAX			0x10
+#define SENAVG			0x14
+#define AVGWEIGHT		0x18
+#define NVALUERECIPROCAL	0x1C
+#define SENERROR		0x20
+#define ERRCONFIG		0x24
 
-/* SRCONFIG */
-#define SR1_SRCONFIG_ACCUMDATA		(0x1F4 << 22)
-#define SR2_SRCONFIG_ACCUMDATA		(0x1F4 << 22)
-
-#define SRCLKLENGTH_12MHZ_SYSCLK	0x3C
-#define SRCLKLENGTH_13MHZ_SYSCLK	0x41
-#define SRCLKLENGTH_19MHZ_SYSCLK	0x60
-#define SRCLKLENGTH_26MHZ_SYSCLK	0x82
-#define SRCLKLENGTH_38MHZ_SYSCLK	0xC0
+/* Bit/Shift Positions */
 
+/* SRCONFIG */
+#define SRCONFIG_ACCUMDATA_SHIFT	22
 #define SRCONFIG_SRCLKLENGTH_SHIFT	12
 #define SRCONFIG_SENNENABLE_SHIFT	5
 #define SRCONFIG_SENPENABLE_SHIFT	3
+#define SRCONFIG_CLKCTRL_SHIFT		0
+
+#define SRCONFIG_ACCUMDATA_MASK		(0x3FF << 22)
 
 #define SRCONFIG_SRENABLE		BIT(11)
 #define SRCONFIG_SENENABLE		BIT(10)
 #define SRCONFIG_ERRGEN_EN		BIT(9)
 #define SRCONFIG_MINMAXAVG_EN		BIT(8)
-
 #define SRCONFIG_DELAYCTRL		BIT(2)
-#define SRCONFIG_CLKCTRL		(0x00 << 0)
 
 /* AVGWEIGHT */
-#define SR1_AVGWEIGHT_SENPAVGWEIGHT	(0x03 << 2)
-#define SR1_AVGWEIGHT_SENNAVGWEIGHT	(0x03 << 0)
-
-#define SR2_AVGWEIGHT_SENPAVGWEIGHT	BIT(2)
-#define SR2_AVGWEIGHT_SENNAVGWEIGHT	BIT(0)
+#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT	2
+#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT	0
 
 /* NVALUERECIPROCAL */
 #define NVALUERECIPROCAL_SENPGAIN_SHIFT	20
@@ -78,25 +65,55 @@ extern struct dentry *pm_dbg_main_dir;
 #define NVALUERECIPROCAL_RNSENN_SHIFT	0
 
 /* ERRCONFIG */
-#define SR_CLKACTIVITY_MASK		(0x03 << 20)
+#define ERRCONFIG_ERRWEIGHT_SHIFT	16
+#define ERRCONFIG_ERRMAXLIMIT_SHIFT	8
+#define ERRCONFIG_ERRMiNLIMIT_SHIFT	0
+
 #define SR_ERRWEIGHT_MASK		(0x07 << 16)
 #define SR_ERRMAXLIMIT_MASK		(0xFF << 8)
 #define SR_ERRMINLIMIT_MASK		(0xFF << 0)
 
 #define ERRCONFIG_VPBOUNDINTEN		BIT(31)
 #define ERRCONFIG_VPBOUNDINTST		BIT(30)
+#define	ERRCONFIG_MCUACCUMINTEN		BIT(29)
+#define ERRCONFIG_MCUACCUMINTST		BIT(28)
+#define	ERRCONFIG_MCUVALIDINTEN		BIT(27)
+#define ERRCONFIG_MCUVALIDINTST		BIT(26)
+#define ERRCONFIG_MCUBOUNDINTEN		BIT(25)
+#define	ERRCONFIG_MCUBOUNDINTST		BIT(24)
+#define	ERRCONFIG_MCUDISACKINTEN	BIT(23)
+#define ERRCONFIG_MCUDISACKINTST	BIT(22)
 
-#define SR1_ERRWEIGHT			(0x07 << 16)
-#define SR1_ERRMAXLIMIT			(0x02 << 8)
-#define SR1_ERRMINLIMIT			(0xFA << 0)
+/* Common Bit values */
 
-#define SR2_ERRWEIGHT			(0x07 << 16)
-#define SR2_ERRMAXLIMIT			(0x02 << 8)
-#define SR2_ERRMINLIMIT			(0xF9 << 0)
+#define SRCLKLENGTH_12MHZ_SYSCLK	0x3C
+#define SRCLKLENGTH_13MHZ_SYSCLK	0x41
+#define SRCLKLENGTH_19MHZ_SYSCLK	0x60
+#define SRCLKLENGTH_26MHZ_SYSCLK	0x82
+#define SRCLKLENGTH_38MHZ_SYSCLK	0xC0
 
-/* Vmode control */
-#define R_DCDC_GLOBAL_CFG	PHY_TO_OFF_PM_RECIEVER(0x61)
+/*
+ * 3430 specific values. Maybe these should be passed from board file or
+ * pmic structures.
+ */
+#define OMAP3430_SR_ACCUMDATA		0x1F4
+
+#define OMAP3430_SR1_SENPAVGWEIGHT	0x03
+#define OMAP3430_SR1_SENNAVGWEIGHT	0x03
+
+#define OMAP3430_SR2_SENPAVGWEIGHT	0x01
+#define OMAP3430_SR2_SENNAVGWEIGHT	0x01
 
+#define OMAP3430_SR_ERRWEIGHT		0x07
+#define OMAP3430_SR_ERRMAXLIMIT		0x02
+#define OMAP3430_SR1_ERRMINLIMIT	0xFA
+#define OMAP3430_SR2_ERRMINLIMIT	0xF9
+
+/* TODO:3630/OMAP4 values if it has to come from this file */
+
+/* Info for enabling SR in T2/gaia. ToDo: Move it to twl4030_power.c */
+#define PHY_TO_OFF_PM_RECIEVER(p)	(p - 0x5b)
+#define R_DCDC_GLOBAL_CFG	PHY_TO_OFF_PM_RECIEVER(0x61)
 /* R_DCDC_GLOBAL_CFG register, SMARTREFLEX_ENABLE values */
 #define DCDC_GLOBAL_CFG_ENABLE_SRFLX	0x08
 
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 11/16] OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3
  2010-02-24  9:29                   ` [PATCH 10/16] OMAP3: PM: Cleaning up of smartreflex header file Thara Gopinath
@ 2010-02-24  9:29                     ` Thara Gopinath
  2010-02-24  9:29                       ` [PATCH 12/16] OMAP3: PM: Support for enabling smartreflex autocompensation by default Thara Gopinath
  2010-03-03  0:37                       ` [PATCH 11/16] OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3 Kevin Hilman
  0 siblings, 2 replies; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

There are two separate modules in SmartReflex-AVS :
MinMaxAvg module and Error module. Class3 uses the Error module only.
In Class2 you can choose between either module since it is software based.
The registers are mapped to the modules as followed:

MinMaxAvg module: AccumData, MinMaxAvgEnable, MinMaxAvgValid,
        MinMaxAvgAccumValid, SenVal, SenMin, SenMax, SenAverage,
        AverageWeight, MCUAccum, MCUValid, MCUBounds.

Error module: SenNGain, SenPGain, SenPRN, SenNRN, AvgError,
        SenError, VPBounds, ErrWeight, ErrMaxLimit, ErrMinLimit.

Shared between both: SRClkLength, SREnable, SenEnable, SenNEnable,
        SenPEnable, DelayCtrl, MCUDisableAck, ClkActivity.

This patch introduces class specific configuration of registers in smartreflex.c
This also allows for choosing between Error module and Minmaxavg module
for Class 2 SR. This patch allows allows for registering for smartreflex
interrupt handler and notification of interrupts in case requested by
the smartreflex class driver.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/smartreflex-class3.c |    1 +
 arch/arm/mach-omap2/smartreflex.c        |  199 ++++++++++++++++++++++++------
 arch/arm/mach-omap2/smartreflex.h        |   24 ++++-
 3 files changed, 186 insertions(+), 38 deletions(-)

diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index 8e3b530..aae88b6 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -43,6 +43,7 @@ static int sr_class3_disable(int id)
 struct omap_smartreflex_class_data class3_data = {
 	.enable = sr_class3_enable,
 	.disable = sr_class3_disable,
+	.class_type = SR_CLASS3,
 };
 
 static int __init sr_class3_init(void)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index f7c1182..96dc76b 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -38,6 +38,12 @@ struct omap_sr {
 	int			is_sr_reset;
 	int			is_autocomp_active;
 	u32			clk_length;
+	u32			err_weight;
+	u32			err_minlimit;
+	u32			err_maxlimit;
+	u32			accum_data;
+	u32			senn_avgweight;
+	u32			senp_avgweight;
 	void __iomem		*srbase_addr;
 	unsigned int		irq;
 	struct platform_device 	*pdev;
@@ -106,6 +112,24 @@ static void sr_clk_disable(struct omap_sr *sr)
 	sr->is_sr_reset = 1;
 }
 
+static irqreturn_t sr_omap_isr(int irq, void *data)
+{
+	struct omap_sr *sr_info = (struct omap_sr *)data;
+	u32 status;
+
+	/* Read the status bits */
+	status = sr_read_reg(sr_info, ERRCONFIG);
+
+	/* Clear them by writing back */
+	sr_write_reg(sr_info, ERRCONFIG, status);
+
+	/* Call the class driver notify function if registered*/
+	if (sr_class->class_type == SR_CLASS2 && sr_class->notify)
+		sr_class->notify(sr_info->srid, status);
+
+	return IRQ_HANDLED;
+}
+
 static void sr_set_clk_length(struct omap_sr *sr)
 {
 	struct clk *sys_ck;
@@ -137,50 +161,96 @@ static void sr_set_clk_length(struct omap_sr *sr)
 	}
 }
 
+static void sr_set_regfields(struct omap_sr *sr)
+{
+	/*
+	 * For time being these values are defined in smartreflex.h
+	 * and populated during init. May be they can be moved to board
+	 * file or pmic specific data structure. In that case these structure
+	 * fields will have to be populated using the pdata or pmic structure.
+	 */
+	if (cpu_is_omap343x()) {
+		sr->err_weight = OMAP3430_SR_ERRWEIGHT;
+		sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
+		sr->accum_data = OMAP3430_SR_ACCUMDATA;
+		if (sr->srid == SR1) {
+			sr->err_minlimit = OMAP3430_SR1_ERRMINLIMIT;
+			sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
+			sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
+		} else {
+			sr->err_minlimit = OMAP3430_SR2_ERRMINLIMIT;
+			sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
+			sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
+		}
+	}
+	/* TODO: 3630 and Omap4 specific bit field values */
+}
+
 static void sr_configure(struct omap_sr *sr)
 {
 	u32 sr_config;
 	u32 senp_en , senn_en;
 	struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
 
+	/* Common settings for SR Class3 and SR Class2 */
 	if (sr->clk_length == 0)
 		sr_set_clk_length(sr);
 
 	senp_en = pdata->senp_mod;
 	senn_en = pdata->senn_mod;
-	if (sr->srid == SR1) {
-		sr_config = SR1_SRCONFIG_ACCUMDATA |
-			(sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
-			SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN |
-			SRCONFIG_MINMAXAVG_EN |
-			(senn_en << SRCONFIG_SENNENABLE_SHIFT) |
-			(senp_en << SRCONFIG_SENPENABLE_SHIFT) |
-			SRCONFIG_DELAYCTRL;
-
-		sr_write_reg(sr, SRCONFIG, sr_config);
-		sr_write_reg(sr, AVGWEIGHT, SR1_AVGWEIGHT_SENPAVGWEIGHT |
-					SR1_AVGWEIGHT_SENNAVGWEIGHT);
 
+	sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
+		SRCONFIG_SENENABLE | (senn_en << SRCONFIG_SENNENABLE_SHIFT) |
+		(senp_en << SRCONFIG_SENPENABLE_SHIFT) | SRCONFIG_DELAYCTRL;
+	sr_write_reg(sr, SRCONFIG, sr_config);
+
+	if ((sr_class->class_type == SR_CLASS3) || (sr_class->class_type ==
+		SR_CLASS2 && sr_class->mod_use == SR_USE_ERROR_MOD)) {
+		/*
+		 * SR settings if using the ERROR module inside Smartreflex.
+		 * SR CLASS 3 by default uses only the ERROR module where as
+		 * SR CLASS 2 can choose between ERROR module and MINMAXAVG
+		 * module.
+		 */
+		u32 sr_errconfig;
+
+		sr_modify_reg(sr, SRCONFIG, SRCONFIG_ERRGEN_EN,
+			SRCONFIG_ERRGEN_EN);
+		sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
+			(sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
+			(sr->err_minlimit <<  ERRCONFIG_ERRMiNLIMIT_SHIFT);
 		sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |
 			SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
-			(SR1_ERRWEIGHT | SR1_ERRMAXLIMIT | SR1_ERRMINLIMIT));
-
-	} else if (sr->srid == SR2) {
-		sr_config = SR2_SRCONFIG_ACCUMDATA |
-			(sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
-			SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN |
-			SRCONFIG_MINMAXAVG_EN |
-			(senn_en << SRCONFIG_SENNENABLE_SHIFT) |
-			(senp_en << SRCONFIG_SENPENABLE_SHIFT) |
-			SRCONFIG_DELAYCTRL;
-
-		sr_write_reg(sr, SRCONFIG, sr_config);
-		sr_write_reg(sr, AVGWEIGHT, SR2_AVGWEIGHT_SENPAVGWEIGHT |
-					SR2_AVGWEIGHT_SENNAVGWEIGHT);
-		sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |
-			SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
-			(SR2_ERRWEIGHT | SR2_ERRMAXLIMIT | SR2_ERRMINLIMIT));
+			sr_errconfig);
+		/* Enabling the interrupts if the ERROR module is used */
+		sr_modify_reg(sr, ERRCONFIG,
+			(ERRCONFIG_VPBOUNDINTEN),
+			(ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST));
+	} else if ((sr_class->class_type == SR_CLASS2) &&
+			(sr_class->mod_use == SR_USE_ERROR_MOD)) {
+		/*
+		 * SR settings if using the MINMAXAVG module inside
+		 * Smartreflex. SR CLASS 3 does not use this module where as
+		 * SR CLASS 2 can choose between ERROR module and MINMAXAVG
+		 * module.
+		 */
+		u32 avgwt;
 
+		sr_modify_reg(sr, SRCONFIG, SRCONFIG_ACCUMDATA_MASK,
+			sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
+		avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
+			(sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT);
+		sr_write_reg(sr, AVGWEIGHT, avgwt);
+		/*
+		 * Enabling the interrupts if MINMAXAVG module is used.
+		 * TODO: check if all the interrupts are mandatory
+		 */
+		sr_modify_reg(sr, ERRCONFIG,
+			(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
+			ERRCONFIG_MCUBOUNDINTEN),
+			(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST |
+			 ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST |
+			 ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST));
 	}
 	sr->is_sr_reset = 0;
 }
@@ -280,12 +350,6 @@ int sr_enable(int srid, u32 target_opp_no)
 	}
 
 	sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
-
-	/* Enable the interrupt */
-	sr_modify_reg(sr, ERRCONFIG,
-			(ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST),
-			(ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST));
-
 	/* SRCONFIG - enable SR */
 	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
 	return true;
@@ -384,6 +448,8 @@ void omap_smartreflex_disable(int srid)
  */
 void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
 {
+	struct omap_sr *sr_info;
+
 	if (!class_data) {
 		pr_warning("Smartreflex class data passed is NULL\n");
 		return;
@@ -393,7 +459,44 @@ void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
 		pr_warning("Smartreflex class driver already registered\n");
 		return;
 	}
+
+	if ((class_data->class_type != SR_CLASS2) &&
+			(class_data->class_type != SR_CLASS3)) {
+		pr_warning("SR Class type passed is invalid. So cannot \
+				register the class structure\n");
+		return;
+	}
+
+	if ((class_data->class_type == SR_CLASS2) &&
+			!((class_data->mod_use == SR_USE_MINMAXAVG_MOD) ||
+			(class_data->mod_use == SR_USE_ERROR_MOD))) {
+		pr_warning("SR Class 2 specified but whether to use error \
+				module or minmaxavg module not specified\n");
+		return;
+	}
+
 	sr_class = class_data;
+	/*
+	 * Register the interrupt handler incase requested by the class driver
+	 */
+	list_for_each_entry(sr_info, &sr_list, node) {
+		if (sr_class->class_type == SR_CLASS2 &&
+				sr_class->notify_flags && sr_info->irq) {
+			char name[SMARTREFLEX_NAME_LEN];
+			int ret;
+
+			sprintf(name, "sr%d", sr_info->srid);
+			ret = request_irq(sr_info->irq, sr_omap_isr,
+					IRQF_DISABLED, name, (void *)sr_info);
+			if (ret < 0) {
+				pr_warning("ERROR in registering interrupt \
+					handler for SR%d Smartreflex will \
+					not function as desired\n",
+					sr_info->srid);
+				return;
+			}
+		}
+	}
 }
 
 /* PM Debug Fs enteries to enable disable smartreflex.*/
@@ -448,6 +551,7 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
 	if (odev->hwmods[0]->mpu_irqs)
 		sr_info->irq = odev->hwmods[0]->mpu_irqs[0].irq;
 	sr_set_clk_length(sr_info);
+	sr_set_regfields(sr_info);
 
 	/* Create the debug fs enteries */
 	sprintf(name, "sr%d_autocomp", sr_info->srid);
@@ -456,8 +560,29 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
 
 	odev->hwmods[0]->dev_attr = sr_info;
 	list_add(&sr_info->node, &sr_list);
-	pr_info("SmartReflex driver initialized\n");
 
+	/*
+	 * Register interrrupt handler if smartreflex class driver is already
+	 * registered and has requested for interrupts. This will be attempted
+	 * in the class driver register again if it does not happen here.
+	 */
+	if (sr_class) {
+		if (sr_class->class_type == SR_CLASS2 &&
+				sr_class->notify_flags && sr_info->irq) {
+			sprintf(name, "sr%d", sr_info->srid);
+			ret = request_irq(sr_info->irq, sr_omap_isr,
+					IRQF_DISABLED, name, (void *)sr_info);
+			if (ret < 0) {
+				pr_warning("ERROR in registering interrupt \
+					handler for SR%d. Smartreflex will \
+					not function as desired\n",
+					sr_info->srid);
+				return ret;
+			}
+		}
+	}
+
+	pr_info("SmartReflex driver initialized\n");
 	return ret;
 }
 
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 7a1f0c7..f8fc8a4 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -124,6 +124,24 @@ extern struct dentry *pm_dbg_main_dir;
 #endif
 
 #ifdef CONFIG_OMAP_SMARTREFLEX
+/*
+ * The smart reflex driver supports both CLASS2 and CLASS3 SR.
+ * The smartreflex class driver should pass the class type.
+ * Should be used to populate the class_type field of the
+ * omap_smartreflex_class_data structure.
+ */
+#define SR_CLASS2	0x1
+#define SR_CLASS3	0x2
+
+/*
+ * CLASS2 SR can use either the MINMAXAVG module or the ERROR module
+ * of the Smartreflex. Should be used to populate the mod_use field
+ * of omap_smartreflex_class_data structure is class_type is chosen
+ * as SR_CLASS2.
+ */
+#define SR_USE_MINMAXAVG_MOD	0x1
+#define SR_USE_ERROR_MOD	0x2
+
 /**
  * omap_smartreflex_class_data : Structure to be populated by
  * Smartreflex class driver with corresponding class enable disable API's
@@ -134,7 +152,10 @@ extern struct dentry *pm_dbg_main_dir;
  *		for class3.
  * @notify_flags - specify the events to be notified to the class driver
  * @class_type - specify which smartreflex class. Can be used by the SR driver
- * 		to tkae any class based decisions.
+ * 		to take any class based decisions.
+ * @mod_use - specify whether to use the error module or minmaxavg module for
+ *		smartreflex caliberations in case of class2 SR. In case of
+ *		class 3 SR only error module is used.
  */
 struct omap_smartreflex_class_data {
 	int (*enable)(int sr_id);
@@ -142,6 +163,7 @@ struct omap_smartreflex_class_data {
 	int (*notify)(int sr_id, u32 status);
 	u8 notify_flags;
 	u8 class_type;
+	u8 mod_use;
 };
 
 /*
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 12/16] OMAP3: PM: Support for enabling smartreflex autocompensation by default.
  2010-02-24  9:29                     ` [PATCH 11/16] OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3 Thara Gopinath
@ 2010-02-24  9:29                       ` Thara Gopinath
  2010-02-24  9:29                         ` [PATCH 13/16] OMAP3: PM: Correcting accessing of ERRCONFIG register in smartreflex.c Thara Gopinath
  2010-03-03  0:48                         ` [PATCH 12/16] OMAP3: PM: Support for enabling smartreflex autocompensation by default Kevin Hilman
  2010-03-03  0:37                       ` [PATCH 11/16] OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3 Kevin Hilman
  1 sibling, 2 replies; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

This patch adds support to pdata enable smartreflex autocompenstion
during init based on init_enable flag passed as pdata.

This patch also adds enabling of autocompensation by
default (setting init_enable flag to true) in case of ES3.1
OMAP3430 chip. In the current implementation
this step is kept in smartreflex.c itself.Later an API can be added
so that the decision to enable autocompensation by default
can be passed from the corresponding board files.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/smartreflex.c |   32 ++++++++++++++++++++++++++++----
 1 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 96dc76b..085dd05 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -477,9 +477,15 @@ void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
 
 	sr_class = class_data;
 	/*
-	 * Register the interrupt handler incase requested by the class driver
+	 * Check if any SR module needs to be enabled as part of init.
+	 * In case the probe for the SR module is not yet called the enable
+	 * will not be done here but will be done in the probe whenever
+	 * it gets called. Also register the interrupt handler incase
+	 * requested by the class driver.
 	 */
 	list_for_each_entry(sr_info, &sr_list, node) {
+		struct omap_smartreflex_data *pdata =
+				sr_info->pdev->dev.platform_data;
 		if (sr_class->class_type == SR_CLASS2 &&
 				sr_class->notify_flags && sr_info->irq) {
 			char name[SMARTREFLEX_NAME_LEN];
@@ -496,6 +502,8 @@ void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
 				return;
 			}
 		}
+		if (pdata->init_enable)
+			sr_start_vddautocomap(sr_info->srid);
 	}
 }
 
@@ -562,11 +570,15 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
 	list_add(&sr_info->node, &sr_list);
 
 	/*
-	 * Register interrrupt handler if smartreflex class driver is already
-	 * registered and has requested for interrupts. This will be attempted
+	 * Enable the smartreflex module if init_enable flag is set and
+	 * if the class driver is registered. Also Register interrrupt handler
+	 * if smartreflex class driver is already registered and has
+	 * requested for interrupts. This will be attempted
 	 * in the class driver register again if it does not happen here.
 	 */
 	if (sr_class) {
+		struct omap_smartreflex_data *pdata = pdev->dev.platform_data;
+
 		if (sr_class->class_type == SR_CLASS2 &&
 				sr_class->notify_flags && sr_info->irq) {
 			sprintf(name, "sr%d", sr_info->srid);
@@ -580,6 +592,8 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
 				return ret;
 			}
 		}
+		if (pdata->init_enable)
+			sr_start_vddautocomap(sr_info->srid);
 	}
 
 	pr_info("SmartReflex driver initialized\n");
@@ -782,7 +796,17 @@ static int __init omap_devinit_smartreflex(void)
 		if (WARN_ON(!sr_data))
 			return -ENOMEM;
 
-		sr_data->init_enable = false;
+		/*
+		 * Enable the SR module by default if it is a OMAP3430
+		 * ES3.1 chip
+		 */
+		if (cpu_is_omap343x()) {
+			if (omap_rev() == OMAP3430_REV_ES3_1)
+				sr_data->init_enable = true;
+			else
+				sr_data->init_enable = false;
+		} else
+			sr_data->init_enable = false;
 		sr_data->device_enable = omap_device_enable;
 		sr_data->device_shutdown = omap_device_shutdown;
 		sr_data->device_idle = omap_device_idle;
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 13/16] OMAP3: PM: Correcting accessing of ERRCONFIG register in smartreflex.c
  2010-02-24  9:29                       ` [PATCH 12/16] OMAP3: PM: Support for enabling smartreflex autocompensation by default Thara Gopinath
@ 2010-02-24  9:29                         ` Thara Gopinath
  2010-02-24  9:29                           ` [PATCH 14/16] OMAP3: PM: Implement latest h/w recommendations for SR and VP registers and SR VP enable disable sequence Thara Gopinath
  2010-03-03  0:48                         ` [PATCH 12/16] OMAP3: PM: Support for enabling smartreflex autocompensation by default Kevin Hilman
  1 sibling, 1 reply; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

Smartreflex error config register is special as it contains
certain status bits which if written a 1 into means a clear
of those bits. This patch takes special care during modify of
this register that no status bits in this register are accidently
set to 1.

This issue was first reported by Nishanth Menon.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/smartreflex.c |   12 +++++++++++-
 arch/arm/mach-omap2/smartreflex.h |    6 ++++++
 2 files changed, 17 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 085dd05..8a4c48b 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -68,8 +68,18 @@ static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
 
 	reg_val = __raw_readl(SR_REGADDR(offset));
 	reg_val &= ~mask;
-	reg_val |= value;
+	/*
+	 * Smartreflex error config register is special as it contains
+	 * certain status bits which if written a 1 into means a clear
+	 * of those bits. So in order to make sure no accidental write of
+	 * 1 happens to those status bits, do a clear of them in the read
+	 * value. Now if there is an actual reguest to write to these bits
+	 * they will be set in the nex step.
+	 */
+	if (offset == ERRCONFIG)
+		reg_val &= ~ERRCONFIG_STATUS_MASK;
 
+	reg_val |= value;
 	__raw_writel(reg_val, SR_REGADDR(offset));
 }
 
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index f8fc8a4..fbb6bf4 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -84,6 +84,12 @@ extern struct dentry *pm_dbg_main_dir;
 #define	ERRCONFIG_MCUDISACKINTEN	BIT(23)
 #define ERRCONFIG_MCUDISACKINTST	BIT(22)
 
+#define ERRCONFIG_STATUS_MASK		(ERRCONFIG_VPBOUNDINTST | \
+					ERRCONFIG_MCUACCUMINTST | \
+					ERRCONFIG_MCUVALIDINTST | \
+					ERRCONFIG_MCUBOUNDINTST | \
+					ERRCONFIG_MCUDISACKINTST)
+
 /* Common Bit values */
 
 #define SRCLKLENGTH_12MHZ_SYSCLK	0x3C
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 14/16] OMAP3: PM: Implement latest h/w recommendations for SR and VP registers and SR VP enable disable sequence.
  2010-02-24  9:29                         ` [PATCH 13/16] OMAP3: PM: Correcting accessing of ERRCONFIG register in smartreflex.c Thara Gopinath
@ 2010-02-24  9:29                           ` Thara Gopinath
  2010-02-24  9:29                             ` [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling Thara Gopinath
  2010-03-03  0:54                             ` [PATCH 14/16] OMAP3: PM: Implement latest h/w recommendations for SR and VP registers and SR VP enable disable sequence Kevin Hilman
  0 siblings, 2 replies; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

This patch introduces OMAP3 specific values for Smartreflex and
Voltage processor registers as per the latest TI recommendations.
This patch also improves the smartreflex and voltage processor
enable disable sequences as per the latest recommendations.

These recommendations were first formed based on experimentations
on Nokia Rover platform  and were implemented in the Rover code
base first by Nishanth Menon and Paul Walmsley.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/smartreflex.c |   65 ++++++++++++++++++++-----
 arch/arm/mach-omap2/smartreflex.h |    6 +-
 arch/arm/mach-omap2/voltage.c     |   95 ++++++++++++++++++++++++++++++------
 arch/arm/mach-omap2/voltage.h     |   16 ++++---
 4 files changed, 142 insertions(+), 40 deletions(-)

diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 8a4c48b..ca2223d 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/list.h>
 #include <linux/debugfs.h>
+#include <linux/delay.h>
 
 #include <plat/control.h>
 #include <plat/omap_hwmod.h>
@@ -32,6 +33,7 @@
 #include "smartreflex.h"
 
 #define SMARTREFLEX_NAME_LEN	16
+#define SR_DISABLE_TIMEOUT	200
 
 struct omap_sr {
 	int			srid;
@@ -184,11 +186,9 @@ static void sr_set_regfields(struct omap_sr *sr)
 		sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
 		sr->accum_data = OMAP3430_SR_ACCUMDATA;
 		if (sr->srid == SR1) {
-			sr->err_minlimit = OMAP3430_SR1_ERRMINLIMIT;
 			sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
 			sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
 		} else {
-			sr->err_minlimit = OMAP3430_SR2_ERRMINLIMIT;
 			sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
 			sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
 		}
@@ -280,11 +280,6 @@ static void sr_start_vddautocomap(int srid)
 		return;
 	}
 
-	if (sr->is_sr_reset == 1) {
-		sr_clk_enable(sr);
-		sr_configure(sr);
-	}
-
 	sr->is_autocomp_active = 1;
 	if (!sr_class->enable(srid)) {
 		sr->is_autocomp_active = 0;
@@ -351,8 +346,20 @@ int sr_enable(int srid, u32 target_opp_no)
 		return false;
 	}
 
-	nvalue_reciprocal = pdata->sr_nvalue[target_opp_no - 1];
+	/*
+	 * For OMAP3430 errminlimit is dependent on opp. So choose
+	 * it appropriately
+	 */
+	if (cpu_is_omap343x())
+		sr->err_minlimit = (target_opp_no > 2) ?
+			OMAP3430_SR_ERRMINLIMIT_HIGHOPP :
+			OMAP3430_SR_ERRMINLIMIT_LOWOPP;
+
+	/* Enable the clocks and configure SR */
+	sr_clk_enable(sr);
+	sr_configure(sr);
 
+	nvalue_reciprocal = pdata->sr_nvalue[target_opp_no - 1];
 	if (nvalue_reciprocal == 0) {
 		pr_notice("OPP%d doesn't support SmartReflex\n",
 								target_opp_no);
@@ -375,10 +382,44 @@ int sr_enable(int srid, u32 target_opp_no)
 void sr_disable(int srid)
 {
 	struct omap_sr *sr = _sr_lookup(srid);
+	int timeout = 0;
+
+	/* Check if SR is already disabled. If yes do nothing */
+	if (!(sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE))
+		return;
+
+	/* Enable MCUDisableAcknowledge interrupt */
+	sr_modify_reg(sr, ERRCONFIG,
+			ERRCONFIG_MCUDISACKINTEN, ERRCONFIG_MCUDISACKINTEN);
 
-	sr->is_sr_reset = 1;
 	/* SRCONFIG - disable SR */
-	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, ~SRCONFIG_SRENABLE);
+	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
+
+	/* Disable all other SR interrupts and clear the status */
+	sr_modify_reg(sr, ERRCONFIG,
+			(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
+			ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN),
+			(ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
+			ERRCONFIG_MCUBOUNDINTST | ERRCONFIG_VPBOUNDINTST));
+
+	/* Wait for SR to be disabled.
+	 * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us.
+	 */
+	while ((timeout < SR_DISABLE_TIMEOUT) &&
+		(!(sr_read_reg(sr, ERRCONFIG) & ERRCONFIG_MCUDISACKINTST))) {
+
+		udelay(1);
+		timeout++;
+	}
+
+	if (timeout == SR_DISABLE_TIMEOUT)
+		pr_warning("SR%d disable timedout\n", srid);
+
+	/* Disable MCUDisableAcknowledge interrupt & clear pending interrupt
+	 * Also enable VPBOUND interrrupt
+	 */
+	sr_modify_reg(sr, ERRCONFIG, ERRCONFIG_MCUDISACKINTEN,
+			ERRCONFIG_MCUDISACKINTST);
 }
 
 /**
@@ -407,10 +448,6 @@ void omap_smartreflex_enable(int srid)
 
 	if (sr->is_autocomp_active == 1) {
 		if (sr->is_sr_reset == 1) {
-			/* Enable SR clks */
-			sr_clk_enable(sr);
-			sr_configure(sr);
-
 			if (!sr_class->enable(srid))
 				sr_clk_disable(sr);
 		}
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index fbb6bf4..ae8d5db 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -110,10 +110,10 @@ extern struct dentry *pm_dbg_main_dir;
 #define OMAP3430_SR2_SENPAVGWEIGHT	0x01
 #define OMAP3430_SR2_SENNAVGWEIGHT	0x01
 
-#define OMAP3430_SR_ERRWEIGHT		0x07
+#define OMAP3430_SR_ERRWEIGHT		0x04
 #define OMAP3430_SR_ERRMAXLIMIT		0x02
-#define OMAP3430_SR1_ERRMINLIMIT	0xFA
-#define OMAP3430_SR2_ERRMINLIMIT	0xF9
+#define OMAP3430_SR_ERRMINLIMIT_HIGHOPP	0xF9
+#define OMAP3430_SR_ERRMINLIMIT_LOWOPP	0xF4
 
 /* TODO:3630/OMAP4 values if it has to come from this file */
 
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index c0c2c17..49167c0 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -19,6 +19,7 @@
 #include <linux/pm.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 
 #include <plat/omap-pm.h>
 #include <plat/omap34xx.h>
@@ -28,9 +29,9 @@
 #include "prm-regbits-34xx.h"
 #include "voltage.h"
 
-#define MAX_TRIES 100
+#define VP_IDLE_TIMEOUT 200
 
-/**
+/*
  * OMAP3 Voltage controller SR parameters. TODO: Pass this info as part of
  * board data or PMIC data
  */
@@ -281,13 +282,32 @@ static void __init vp_configure(int vp_id)
 static void __init vp_reg_configure(int vp_id)
 {
 	if (cpu_is_omap34xx()) {
+		struct clk *sys_ck;
+		u32 sys_clk_speed, timeout_val;
+
 		vp_reg[vp_id].vp_offs = omap3_vp_offs[vp_id];
 		if (vp_id == VP1) {
+			/*
+			 * OMAP3430 has error gain varying btw higher and
+			 * lower opp's
+			 */
+			vp_reg[vp_id].vp_errorgain = (((get_vdd1_opp() > 2) ?
+					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
+					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
+					OMAP3430_ERRORGAIN_SHIFT);
 			vp_reg[vp_id].vp_vddmin = (OMAP3_VP1_VLIMITTO_VDDMIN <<
 					OMAP3430_VDDMIN_SHIFT);
 			vp_reg[vp_id].vp_vddmax = (OMAP3_VP1_VLIMITTO_VDDMAX <<
 					OMAP3430_VDDMAX_SHIFT);
 		} else if (vp_id == VP2) {
+			/*
+			 * OMAP3430 has error gain varying btw higher and
+			 * lower opp's
+			 */
+			vp_reg[vp_id].vp_errorgain = (((get_vdd2_opp() > 2) ?
+					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
+					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
+					OMAP3430_ERRORGAIN_SHIFT);
 			vp_reg[vp_id].vp_vddmin = (OMAP3_VP2_VLIMITTO_VDDMIN <<
 					OMAP3430_VDDMIN_SHIFT);
 			vp_reg[vp_id].vp_vddmax = (OMAP3_VP2_VLIMITTO_VDDMAX <<
@@ -299,8 +319,6 @@ static void __init vp_reg_configure(int vp_id)
 		}
 		vp_reg[vp_id].vp_erroroffset = (OMAP3_VP_CONFIG_ERROROFFSET <<
 					OMAP3430_INITVOLTAGE_SHIFT);
-		vp_reg[vp_id].vp_errorgain = (OMAP3_VP_CONFIG_ERRORGAIN <<
-					OMAP3430_ERRORGAIN_SHIFT);
 		vp_reg[vp_id].vp_smpswaittimemin =
 					(OMAP3_VP_VSTEPMIN_SMPSWAITTIMEMIN <<
 					OMAP3430_SMPSWAITTIMEMIN_SHIFT);
@@ -311,7 +329,18 @@ static void __init vp_reg_configure(int vp_id)
 					OMAP3430_VSTEPMIN_SHIFT);
 		vp_reg[vp_id].vp_stepmax = (OMAP3_VP_VSTEPMAX_VSTEPMAX <<
 					OMAP3430_VSTEPMAX_SHIFT);
-		vp_reg[vp_id].vp_timeout = (OMAP3_VP_VLIMITTO_TIMEOUT <<
+		/*
+		 * Use sys clk speed to convet the VP timeout in us to no of
+		 * clock cycles
+		 */
+		sys_ck = clk_get(NULL, "sys_ck");
+		sys_clk_speed = clk_get_rate(sys_ck);
+		clk_put(sys_ck);
+		/* Divide to avoid overflow */
+		sys_clk_speed /= 1000;
+		timeout_val = (sys_clk_speed * OMAP3_VP_VLIMITTO_TIMEOUT_US) /
+					1000;
+		vp_reg[vp_id].vp_timeout = (timeout_val <<
 					OMAP3430_TIMEOUT_SHIFT);
 	}
 	/* TODO Extend this for OMAP4 ?? Or need a separate file  */
@@ -338,7 +367,12 @@ static int vc_bypass_scale_voltage(u32 vdd, u8 target_vsel, u8 current_vsel)
 		vc_cmdval0 |= (target_vsel << VC_CMD_ON_SHIFT);
 		voltage_write_reg(vc_reg.vc_cmdval0_reg, vc_cmdval0);
 		reg_addr = R_VDD1_SR_CONTROL;
-
+		/* OMAP3430 has errorgain varying btw higher and lower opp's */
+		if (cpu_is_omap34xx())
+			vp_reg[vdd].vp_errorgain = (((get_vdd1_opp() > 2) ?
+					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
+					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
+					OMAP3430_ERRORGAIN_SHIFT);
 	} else if (vdd == VDD2_OPP) {
 		u32 vc_cmdval1;
 
@@ -347,12 +381,29 @@ static int vc_bypass_scale_voltage(u32 vdd, u8 target_vsel, u8 current_vsel)
 		vc_cmdval1 |= (target_vsel << VC_CMD_ON_SHIFT);
 		voltage_write_reg(vc_reg.vc_cmdval1_reg, vc_cmdval1);
 		reg_addr = R_VDD2_SR_CONTROL;
+		/* OMAP3430 has errorgain varying btw higher and lower opp's */
+		if (cpu_is_omap34xx())
+			vp_reg[vdd].vp_errorgain = (((get_vdd2_opp() > 2) ?
+					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
+					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
+					OMAP3430_ERRORGAIN_SHIFT);
 	} else {
 		pr_warning("Wrong VDD passed in vc_bypass_scale_voltage %d\n",
 				vdd);
 		return false;
 	}
 
+	/* OMAP3430 has errorgain varying btw higher and lower opp's */
+	if (cpu_is_omap34xx()) {
+		u32 errorgain =
+			voltage_read_reg(vp_reg[vdd - 1].vp_offs.
+				vp_vpconfig_reg);
+		errorgain &= ~VP_ERRORGAIN_MASK;
+		errorgain |= vp_reg[vdd].vp_errorgain;
+
+		voltage_write_reg(vp_reg[vdd - 1].vp_offs.vp_vpconfig_reg,
+				errorgain);
+	}
 	vc_bypass_value = (target_vsel << VC_DATA_SHIFT) |
 			(reg_addr << VC_REGADDR_SHIFT) |
 			(R_SRI2C_SLAVE_ADDR << VC_SLAVEADDR_SHIFT);
@@ -419,6 +470,10 @@ void omap_voltageprocessor_enable(int vp_id)
 {
 	u32 vpconfig;
 
+	/* If VP is already enabled, do nothing. Return */
+	if (voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg) &
+				VP_CONFIG_VPENABLE)
+		return;
 	/*
 	 * This latching is required only if VC bypass method is used for
 	 * voltage scaling during dvfs.
@@ -439,21 +494,29 @@ void omap_voltageprocessor_enable(int vp_id)
  */
 void omap_voltageprocessor_disable(int vp_id)
 {
-	int i = 0;
 	u32 vpconfig;
+	int timeout = 0;
 
-	/* Wait for VP idle before disabling VP */
-	while ((!voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_status_reg)) &&
-				i++ < MAX_TRIES)
-		udelay(1);
-
-	if (i >= MAX_TRIES)
-		pr_warning("VP1 not idle, still going ahead with \
-						VP1 disable\n");
-	/* Disable VP1 */
+	/* If VP is already disabled, do nothing. Return */
+	if (!(voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg) &
+				VP_CONFIG_VPENABLE))
+		return;
+	/* Disable VP */
 	vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
 	vpconfig &= ~VP_CONFIG_VPENABLE;
 	voltage_write_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg, vpconfig);
+
+	/*
+	 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
+	 */
+	while ((timeout++ < VP_IDLE_TIMEOUT) &&
+			(!(voltage_read_reg(vp_reg[vp_id - 1].vp_offs
+			.vp_status_reg))))
+		udelay(1);
+
+	if (timeout >= VP_IDLE_TIMEOUT)
+		pr_warning("VP%d idle timedout\n", vp_id);
+	return;
 }
 
 /**
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index 64c506c..c3203c9 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -22,6 +22,7 @@ extern int get_vdd2_opp(void);
 #define VP_CONFIG_INITVDD	OMAP3430_INITVDD
 #define VP_FORCEUPDATE		OMAP3430_FORCEUPDATE
 #define VP_CONFIG_VPENABLE	OMAP3430_VPENABLE
+#define VP_ERRORGAIN_MASK	OMAP3430_ERRORGAIN_MASK
 #define VP_INITVOLTAGE_MASK	OMAP3430_INITVOLTAGE_MASK
 #define VP_INITVOLTAGE_SHIFT	OMAP3430_INITVOLTAGE_SHIFT
 
@@ -52,16 +53,17 @@ extern int get_vdd2_opp(void);
  * board file or PMIC data structure
  */
 #define OMAP3_VP_CONFIG_ERROROFFSET		0x00
-#define OMAP3_VP_CONFIG_ERRORGAIN		0x20
-#define	OMAP3_VP_VSTEPMIN_SMPSWAITTIMEMIN	0x01F4
+#define OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP	0x0C
+#define OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP	0x18
+#define	OMAP3_VP_VSTEPMIN_SMPSWAITTIMEMIN	0x3C
 #define OMAP3_VP_VSTEPMIN_VSTEPMIN		0x1
-#define OMAP3_VP_VSTEPMAX_SMPSWAITTIMEMAX	0x01F4
+#define OMAP3_VP_VSTEPMAX_SMPSWAITTIMEMAX	0x3C
 #define OMAP3_VP_VSTEPMAX_VSTEPMAX		0x04
-#define OMAP3_VP1_VLIMITTO_VDDMIN		0x0
-#define OMAP3_VP1_VLIMITTO_VDDMAX		0x3C
+#define OMAP3_VP1_VLIMITTO_VDDMIN		0x14
+#define OMAP3_VP1_VLIMITTO_VDDMAX		0x42
 #define OMAP3_VP2_VLIMITTO_VDDMAX		0x2C
-#define OMAP3_VP2_VLIMITTO_VDDMIN		0x0
-#define OMAP3_VP_VLIMITTO_TIMEOUT		0xFFFF
+#define OMAP3_VP2_VLIMITTO_VDDMIN		0x18
+#define OMAP3_VP_VLIMITTO_TIMEOUT_US		0x200
 
 #define VOLTAGE_MOD	OMAP3430_GR_MOD
 /* TODO OMAP4 VP register values if the same file is used for OMAP4*/
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling
  2010-02-24  9:29                           ` [PATCH 14/16] OMAP3: PM: Implement latest h/w recommendations for SR and VP registers and SR VP enable disable sequence Thara Gopinath
@ 2010-02-24  9:29                             ` Thara Gopinath
  2010-02-24  9:29                               ` [PATCH 16/16] OMAP3: PM: Enabling Smartreflex Class 3 driver by default in pm defconfig Thara Gopinath
  2010-03-03  0:58                               ` [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling Kevin Hilman
  2010-03-03  0:54                             ` [PATCH 14/16] OMAP3: PM: Implement latest h/w recommendations for SR and VP registers and SR VP enable disable sequence Kevin Hilman
  1 sibling, 2 replies; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

This patch introduces VP force update method of voltage scaling
and enables it by default. The older method of vc bypass is now
configuratble through a menu config option. VP force update is the
hardware recommended method of voltage scaling.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/mach-omap2/voltage.c |  149 +++++++++++++++++++++++++++++++++++++++--
 arch/arm/mach-omap2/voltage.h |    1 +
 arch/arm/plat-omap/Kconfig    |   19 +++++
 3 files changed, 162 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 49167c0..4f325af 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -29,7 +29,8 @@
 #include "prm-regbits-34xx.h"
 #include "voltage.h"
 
-#define VP_IDLE_TIMEOUT 200
+#define VP_IDLE_TIMEOUT 	200
+#define VP_TRANXDONE_TIMEOUT	300
 
 /*
  * OMAP3 Voltage controller SR parameters. TODO: Pass this info as part of
@@ -70,6 +71,7 @@ struct vp_reg_info {
 	u32 vp_vddmin;
 	u32 vp_vddmax;
 	u32 vp_timeout;
+	u32 vp_tranxdone_status;
 };
 static struct vp_reg_info *vp_reg;
 /*
@@ -299,6 +301,8 @@ static void __init vp_reg_configure(int vp_id)
 					OMAP3430_VDDMIN_SHIFT);
 			vp_reg[vp_id].vp_vddmax = (OMAP3_VP1_VLIMITTO_VDDMAX <<
 					OMAP3430_VDDMAX_SHIFT);
+			vp_reg[vp_id].vp_tranxdone_status =
+					OMAP3430_VP1_TRANXDONE_ST;
 		} else if (vp_id == VP2) {
 			/*
 			 * OMAP3430 has error gain varying btw higher and
@@ -312,6 +316,8 @@ static void __init vp_reg_configure(int vp_id)
 					OMAP3430_VDDMIN_SHIFT);
 			vp_reg[vp_id].vp_vddmax = (OMAP3_VP2_VLIMITTO_VDDMAX <<
 					OMAP3430_VDDMAX_SHIFT);
+			vp_reg[vp_id].vp_tranxdone_status =
+					OMAP3430_VP2_TRANXDONE_ST;
 		} else {
 			pr_warning("Voltage processor%d does not exisit\
 					in OMAP3 \n", vp_id);
@@ -346,6 +352,131 @@ static void __init vp_reg_configure(int vp_id)
 	/* TODO Extend this for OMAP4 ?? Or need a separate file  */
 }
 
+#ifdef CONFIG_OMAP_VOLT_VPFORCEUPDATE
+/* VP force update method of voltage scaling */
+static int vp_forceupdate_scale_voltage(u32 vdd, u8 target_vsel,
+				u8 current_vsel)
+{
+	u32 smps_steps = 0, smps_delay = 0;
+	u32 vpconfig;
+	int timeout = 0;
+	int vp_id = vdd - 1;
+
+	if (!((vdd == VDD1_OPP) || (vdd == VDD2_OPP))) {
+		pr_warning("Wrong vdd id passed to vp forceupdate\n");
+		return false;
+	}
+
+	smps_steps = abs(target_vsel - current_vsel);
+
+	/* OMAP3430 has errorgain varying btw higher and lower opp's */
+	if (cpu_is_omap34xx()) {
+		if (vdd == VDD1_OPP) {
+			u32 vc_cmdval0;
+
+			vc_cmdval0 = voltage_read_reg(vc_reg.vc_cmdval0_reg);
+			vc_cmdval0 &= ~VC_CMD_ON_MASK;
+			vc_cmdval0 |= (target_vsel << VC_CMD_ON_SHIFT);
+			voltage_write_reg(vc_reg.vc_cmdval0_reg, vc_cmdval0);
+			vp_reg[vp_id].vp_errorgain = (((get_vdd1_opp() > 2) ?
+					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
+					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
+					OMAP3430_ERRORGAIN_SHIFT);
+		} else if (vdd == VDD2_OPP) {
+			u32 vc_cmdval1;
+
+			vc_cmdval1 = voltage_read_reg(vc_reg.vc_cmdval1_reg);
+			vc_cmdval1 &= ~VC_CMD_ON_MASK;
+			vc_cmdval1 |= (target_vsel << VC_CMD_ON_SHIFT);
+			voltage_write_reg(vc_reg.vc_cmdval1_reg, vc_cmdval1);
+			vp_reg[vp_id].vp_errorgain = (((get_vdd2_opp() > 2) ?
+					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
+					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
+					OMAP3430_ERRORGAIN_SHIFT);
+		}
+	}
+
+	/* Clear all pending TransactionDone interrupt/status. Typical latency
+	 * is <3us
+	 */
+	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+		voltage_write_reg(PRM_IRQSTATUS_REG,
+				vp_reg[vp_id].vp_tranxdone_status);
+		if (!(voltage_read_reg(PRM_IRQSTATUS_REG) &
+				vp_reg[vp_id].vp_tranxdone_status))
+				break;
+		udelay(1);
+	}
+
+	if (timeout >= VP_TRANXDONE_TIMEOUT) {
+		pr_warning("VP%d TRANXDONE timeout exceeded. Voltage change \
+				aborted", vdd);
+		return false;
+	}
+
+	/* Configure for VP-Force Update */
+	vpconfig = voltage_read_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg);
+	vpconfig &= ~(VP_CONFIG_INITVDD | VP_FORCEUPDATE |
+			VP_INITVOLTAGE_MASK | VP_ERRORGAIN_MASK);
+	vpconfig |= ((target_vsel << VP_INITVOLTAGE_SHIFT) |
+			vp_reg[vp_id].vp_errorgain);
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
+
+	/* Trigger initVDD value copy to voltage processor */
+	vpconfig |= VP_CONFIG_INITVDD;
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
+
+	/* Force update of voltage */
+	vpconfig |= VP_FORCEUPDATE;
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
+
+	timeout = 0;
+	/* Wait for TransactionDone. Typical latency is <200us.
+	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
+	 */
+	while ((timeout++ < VP_TRANXDONE_TIMEOUT) &&
+			(!(voltage_read_reg(PRM_IRQSTATUS_REG) &
+			vp_reg[vp_id].vp_tranxdone_status)))
+		udelay(1);
+
+	if (timeout >= VP_TRANXDONE_TIMEOUT)
+		pr_warning("VP%d TRANXDONE timeout exceeded. TRANXDONE never \
+			got set after the voltage update.Serious error!!!!\n",
+			vdd);
+
+	/* Wait for voltage to settle with SW wait-loop */
+	smps_delay = ((smps_steps * 125) / 40) + 2;
+	udelay(smps_delay);
+
+	/* Disable TransactionDone interrupt , clear all status, clear
+	 * control registers
+	 */
+	timeout = 0;
+	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+		voltage_write_reg(PRM_IRQSTATUS_REG,
+				vp_reg[vp_id].vp_tranxdone_status);
+		if (!(voltage_read_reg(PRM_IRQSTATUS_REG) &
+				vp_reg[vp_id].vp_tranxdone_status))
+				break;
+		udelay(1);
+	}
+	if (timeout >= VP_TRANXDONE_TIMEOUT)
+		pr_warning("VP%d TRANXDONE timeout exceeded while trying to \
+			clear the TRANXDONE status\n", vdd);
+
+	vpconfig = voltage_read_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg);
+	/* Clear initVDD copy trigger bit */
+	vpconfig &= ~VP_CONFIG_INITVDD;
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
+	/* Clear force bit */
+	vpconfig &= ~VP_FORCEUPDATE;
+	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
+
+	return true;
+}
+#endif
+
+#ifdef CONFIG_OMAP_VOLT_VCBYPASS
 /**
  * vc_bypass_scale_voltage - VC bypass method of voltage scaling
  */
@@ -437,7 +568,7 @@ static int vc_bypass_scale_voltage(u32 vdd, u8 target_vsel, u8 current_vsel)
 	udelay(smps_delay);
 	return true;
 }
-
+#endif
 
 static void __init init_voltageprocessors(void)
 {
@@ -474,13 +605,16 @@ void omap_voltageprocessor_enable(int vp_id)
 	if (voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg) &
 				VP_CONFIG_VPENABLE)
 		return;
+
+#ifdef CONFIG_OMAP_VOLT_VCBYPASS
 	/*
 	 * This latching is required only if VC bypass method is used for
 	 * voltage scaling during dvfs.
 	 */
 	vp_latch_vsel(vp_id - 1);
-	vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
+#endif
 	/* Enable VP */
+	vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
 	voltage_write_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg,
 				vpconfig | VP_CONFIG_VPENABLE);
 }
@@ -529,11 +663,12 @@ void omap_voltageprocessor_disable(int vp_id)
  * for a particular voltage domain during dvfs or any other situation.
  */
 int omap_voltage_scale(int vdd, u8 target_vsel, u8 current_vsel)
-{	/*
-	 * TODO add VP force update method of voltage scaling
-	 * and choose btw the two
-	 */
+{
+#ifdef CONFIG_OMAP_VOLT_VCBYPASS
 	return vc_bypass_scale_voltage(vdd, target_vsel, current_vsel);
+#elif CONFIG_OMAP_VOLT_VPFORCEUPDATE
+	return vp_forceupdate_scale_voltage(vdd, target_vsel, current_vsel);
+#endif
 }
 
 /**
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index c3203c9..615bde6 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -17,6 +17,7 @@
 extern int get_vdd1_opp(void);
 extern int get_vdd2_opp(void);
 
+#define PRM_IRQSTATUS_REG	OMAP3430_PRM_IRQSTATUS_MPU
 /* Generic VP definitions. Need to be redefined for OMAP4 */
 #define VP_CONFIG_TIMEOUTEN	OMAP3430_TIMEOUTEN
 #define VP_CONFIG_INITVDD	OMAP3430_INITVDD
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 9d286e6..1a611a9 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -92,6 +92,25 @@ config OMAP_SMARTREFLEX_TESTING
 
 	  WARNING: Enabling this option may cause your device to hang!
 
+choice
+	prompt "Choose Voltage Scale method"
+	depends on ARCH_OMAP3 && PM
+	default OMAP_VOLT_VPFORCEUPDATE
+
+config OMAP_VOLT_VPFORCEUPDATE
+	bool "Voltage scaling via VP force update method"
+	help
+	 Say Y if you want to enable VP force update method
+	 of voltage scaling. This is the h/w recomended way
+	 of voltage scaling in OMAP3.
+
+config OMAP_VOLT_VCBYPASS
+	bool "Voltage Scale via Voltage controller in bypass"
+	help
+	 Say Y if you want to enable VC Bypass method of voltage scaling.
+	 Not the default recommended method.
+endchoice
+
 config OMAP_RESET_CLOCKS
 	bool "Reset unused clocks during boot"
 	depends on ARCH_OMAP
-- 
1.7.0.rc1.33.g07cf0f


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

* [PATCH 16/16] OMAP3: PM: Enabling Smartreflex Class 3 driver by default in pm defconfig
  2010-02-24  9:29                             ` [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling Thara Gopinath
@ 2010-02-24  9:29                               ` Thara Gopinath
  2010-03-03  0:58                               ` [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling Kevin Hilman
  1 sibling, 0 replies; 61+ messages in thread
From: Thara Gopinath @ 2010-02-24  9:29 UTC (permalink / raw)
  To: linux-omap
  Cc: khilman, paul, nm, b-cousson, vishwanath.bs, sawant, Thara Gopinath

This patch enables smartreflex class 3 driver in omap3_pm_defconfig.

Signed-off-by: Thara Gopinath <thara@ti.com>
---
 arch/arm/configs/omap3_pm_defconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/configs/omap3_pm_defconfig b/arch/arm/configs/omap3_pm_defconfig
index c7fa3e1..61410b6 100644
--- a/arch/arm/configs/omap3_pm_defconfig
+++ b/arch/arm/configs/omap3_pm_defconfig
@@ -231,6 +231,7 @@ CONFIG_ARCH_OMAP3=y
 # OMAP Feature Selections
 #
 CONFIG_OMAP_SMARTREFLEX=y
+CONFIG_OMAP_SMARTREFLEX_CLASS3=y
 # CONFIG_OMAP_SMARTREFLEX_TESTING is not set
 CONFIG_OMAP_RESET_CLOCKS=y
 CONFIG_OMAP_MUX=y
-- 
1.7.0.rc1.33.g07cf0f


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

* Re: [PATCH 01/16] OMAP3: PM: Adding hwmod data for Smartreflex
  2010-02-24  9:29 ` [PATCH 01/16] OMAP3: PM: Adding hwmod data for Smartreflex Thara Gopinath
  2010-02-24  9:29   ` [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances Thara Gopinath
@ 2010-02-24 16:52   ` Mike Turquette
  2010-03-06  0:45   ` Kevin Hilman
  2 siblings, 0 replies; 61+ messages in thread
From: Mike Turquette @ 2010-02-24 16:52 UTC (permalink / raw)
  To: Thara Gopinath
  Cc: linux-omap, khilman, paul, Menon, Nishanth, Cousson, Benoit,
	Sripathy, Vishwanath, Sawant, Anand

Thara Gopinath wrote:
> This patch adds the hwmod strucutres and other hwmod data for
> OMAP3 Smartreflex IP's.
> 
> Signed-off-by: Thara Gopinath <thara@ti.com>
> ---
>  arch/arm/mach-omap2/omap_hwmod_34xx.h |   92 +++++++++++++++++++++++++++++++++
>  1 files changed, 92 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/omap_hwmod_34xx.h b/arch/arm/mach-omap2/omap_hwmod_34xx.h
> index 2e629dc..dccb4a4 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_34xx.h
> +++ b/arch/arm/mach-omap2/omap_hwmod_34xx.h
> @@ -25,6 +25,8 @@ static struct omap_hwmod omap34xx_mpu_hwmod;
>  static struct omap_hwmod omap34xx_l3_hwmod;
>  static struct omap_hwmod omap34xx_l4_core_hwmod;
>  static struct omap_hwmod omap34xx_l4_per_hwmod;
> +static struct omap_hwmod omap34xx_sr1_hwmod;
> +static struct omap_hwmod omap34xx_sr2_hwmod;
>  
>  /* L3 -> L4_CORE interface */
>  static struct omap_hwmod_ocp_if omap34xx_l3__l4_core = {
> @@ -77,9 +79,49 @@ static struct omap_hwmod_ocp_if omap34xx_l4_core__l4_wkup = {
>  	.user	= OCP_USER_MPU | OCP_USER_SDMA,
>  };
>  
> +/* L4 CORE -> SR1 interface */
> +static struct omap_hwmod_addr_space omap34xx_sr1_addr_space[] = {
> +	{
> +		.pa_start	= OMAP34XX_SR1_BASE,
> +		.pa_end		= OMAP34XX_SR1_BASE + SZ_1K - 1,
> +		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
> +	},
> +};
> +
> +static struct omap_hwmod_ocp_if omap3_l4_core__sr1 = {
> +	.master		= &omap34xx_l4_core_hwmod,
> +	.slave		= &omap34xx_sr1_hwmod,
> +	.clkdev_dev_id	= NULL,
> +	.clkdev_con_id  = NULL,
> +	.addr		= omap34xx_sr1_addr_space,
> +	.addr_cnt	= ARRAY_SIZE(omap34xx_sr1_addr_space),
> +	.user		= OCP_USER_MPU,
> +};
> +
> +/* L4 CORE -> SR1 interface */

Comment above should be "SR2 interface"

Regards,
Mike

> +static struct omap_hwmod_addr_space omap34xx_sr2_addr_space[] = {
> +	{
> +		.pa_start	= OMAP34XX_SR2_BASE,
> +		.pa_end		= OMAP34XX_SR2_BASE + SZ_1K - 1,
> +		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
> +	},
> +};
> +
> +static struct omap_hwmod_ocp_if omap3_l4_core__sr2 = {
> +	.master		= &omap34xx_l4_core_hwmod,
> +	.slave		= &omap34xx_sr2_hwmod,
> +	.clkdev_dev_id	= NULL,
> +	.clkdev_con_id  = NULL,
> +	.addr		= omap34xx_sr2_addr_space,
> +	.addr_cnt	= ARRAY_SIZE(omap34xx_sr2_addr_space),
> +	.user		= OCP_USER_MPU,
> +};
> +
>  /* Slave interfaces on the L4_CORE interconnect */
>  static struct omap_hwmod_ocp_if *omap34xx_l4_core_slaves[] = {
>  	&omap34xx_l3__l4_core,
> +	&omap3_l4_core__sr1,
> +	&omap3_l4_core__sr2,
>  };
>  
>  /* Master interfaces on the L4_CORE interconnect */
> @@ -150,12 +192,62 @@ static struct omap_hwmod omap34xx_mpu_hwmod = {
>  	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
>  };
>  
> +/* SR common */
> +static struct omap_hwmod_sysc_fields sr_sysc_fields = {
> +	.clkact_shift	= 20,
> +};
> +
> +static struct omap_hwmod_sysconfig sr_if_ctrl = {
> +	.sysc_offs	= 0x24,
> +	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_NO_CACHE),
> +	.clockact	= CLOCKACT_TEST_ICLK,
> +	.sysc_fields	= &sr_sysc_fields,
> +};
> +
> +/* SR1 */
> +static struct omap_hwmod_ocp_if *omap34xx_sr1_slaves[] = {
> +	&omap3_l4_core__sr1,
> +};
> +
> +static struct omap_hwmod omap34xx_sr1_hwmod = {
> +	.name		= "sr1_hwmod",
> +	.mpu_irqs	= NULL,
> +	.sdma_chs	= NULL,
> +	.clkdev_dev_id	= NULL,
> +	.clkdev_con_id	= "sr1_fck",
> +	.slaves		= omap34xx_sr1_slaves,
> +	.slaves_cnt	= ARRAY_SIZE(omap34xx_sr1_slaves),
> +	.sysconfig	= &sr_if_ctrl,
> +	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
> +	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
> +};
> +
> +/* SR2 */
> +static struct omap_hwmod_ocp_if *omap34xx_sr2_slaves[] = {
> +	&omap3_l4_core__sr2,
> +};
> +
> +static struct omap_hwmod omap34xx_sr2_hwmod = {
> +	.name		= "sr2_hwmod",
> +	.mpu_irqs	= NULL,
> +	.sdma_chs	= NULL,
> +	.clkdev_dev_id	= NULL,
> +	.clkdev_con_id	= "sr2_fck",
> +	.slaves		= omap34xx_sr2_slaves,
> +	.slaves_cnt	= ARRAY_SIZE(omap34xx_sr2_slaves),
> +	.sysconfig	= &sr_if_ctrl,
> +	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
> +	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
> +};
> +
>  static __initdata struct omap_hwmod *omap34xx_hwmods[] = {
>  	&omap34xx_l3_hwmod,
>  	&omap34xx_l4_core_hwmod,
>  	&omap34xx_l4_per_hwmod,
>  	&omap34xx_l4_wkup_hwmod,
>  	&omap34xx_mpu_hwmod,
> +	&omap34xx_sr1_hwmod,
> +	&omap34xx_sr2_hwmod,
>  	NULL,
>  };
>  


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

* Re: [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances.
  2010-02-24  9:29   ` [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances Thara Gopinath
  2010-02-24  9:29     ` [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer Thara Gopinath
@ 2010-02-25  1:42     ` ambresh
  2010-03-02 17:40       ` Kevin Hilman
  2010-02-26 23:21     ` Mike Turquette
  2 siblings, 1 reply; 61+ messages in thread
From: ambresh @ 2010-02-25  1:42 UTC (permalink / raw)
  To: Gopinath, Thara
  Cc: linux-omap, khilman, paul, Menon, Nishanth, Cousson, Benoit,
	Sripathy, Vishwanath, Sawant, Anand

Gopinath, Thara wrote:
> This patch removes the pointer sr1, sr2 in smartreflex.c and
> instead creatse a list for keeping track of multiple smartreflex
> instances.. This makes it scalable for next gen OMAPs where there
> are more than two smartreflex modules.
> 
> Signed-off-by: Thara Gopinath <thara@ti.com>
> ---
>  arch/arm/mach-omap2/smartreflex.c |  114 ++++++++++++++++++++++++------------
>  1 files changed, 76 insertions(+), 38 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
> index 1c5ec37..4a9c2e2 100644
> --- a/arch/arm/mach-omap2/smartreflex.c
> +++ b/arch/arm/mach-omap2/smartreflex.c
> @@ -26,6 +26,7 @@
>  #include <linux/kobject.h>
>  #include <linux/i2c/twl.h>
>  #include <linux/io.h>
> +#include <linux/list.h>
>  
>  #include <plat/omap34xx.h>
>  #include <plat/control.h>
> @@ -51,9 +52,12 @@ struct omap_sr {
>  	u32		opp5_nvalue;
>  	u32		senp_mod, senn_mod;
>  	void __iomem	*srbase_addr;
> -	void __iomem	*vpbase_addr;
> +	struct list_head 	node;
>  };
>  
> +/* sr_list contains all the instances of smartreflex module */
> +static LIST_HEAD(sr_list);
> +
>  #define SR_REGADDR(offs)	(sr->srbase_addr + offset)
>  
>  static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
> @@ -78,6 +82,20 @@ static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
>  	return __raw_readl(SR_REGADDR(offset));
>  }
>  
> +static struct omap_sr *_sr_lookup(int srid)
> +{
> +	struct omap_sr *sr_info, *temp_sr_info;
> +
> +	sr_info = NULL;
> +	list_for_each_entry(temp_sr_info, &sr_list, node) {
> +		if (srid == temp_sr_info->srid) {
> +			sr_info = temp_sr_info;
> +			break;
> +		}
> +	}
> +	return sr_info;
> +}
> +
>  static int sr_clk_enable(struct omap_sr *sr)
>  {
>  	if (clk_enable(sr->clk) != 0) {
> @@ -151,11 +169,17 @@ static u8 get_vdd1_opp(void)
>  {
>  	struct omap_opp *opp;
>  	unsigned long freq;
> +	struct omap_sr *sr_info = _sr_lookup(SR1);
>  
> -	if (sr1.vdd_opp_clk == NULL || IS_ERR(sr1.vdd_opp_clk))
> +	if (!sr_info) {
> +		pr_warning("omap_sr struct corresponding to SR1 not found\n");
> +		return 0;
> +	}
> +
> +	if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
>  		return 0;
>  
> -	freq = sr1.vdd_opp_clk->rate;
> +	freq = sr_info->vdd_opp_clk->rate;
>  	opp = opp_find_freq_ceil(OPP_MPU, &freq);
>  	if (IS_ERR(opp))
>  		return 0;
> @@ -163,9 +187,9 @@ static u8 get_vdd1_opp(void)
>  	 * Use higher freq voltage even if an exact match is not available
>  	 * we are probably masking a clock framework bug, so warn
>  	 */
> -	if (unlikely(freq != sr1.vdd_opp_clk->rate))
> +	if (unlikely(freq != sr_info->vdd_opp_clk->rate))
>  		pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
> -			   __func__, freq, sr1.vdd_opp_clk->rate);
> +			   __func__, freq, sr_info->vdd_opp_clk->rate);
>  
>  	return opp_get_opp_id(opp);
>  }
> @@ -174,11 +198,17 @@ static u8 get_vdd2_opp(void)
>  {
>  	struct omap_opp *opp;
>  	unsigned long freq;
> +	struct omap_sr *sr_info = _sr_lookup(SR2);
> +
> +	if (!sr_info) {
> +		pr_warning("omap_sr struct corresponding to SR2 not found\n");
> +		return 0;
> +	}
>  
> -	if (sr2.vdd_opp_clk == NULL || IS_ERR(sr2.vdd_opp_clk))
> +	if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
>  		return 0;
>  
> -	freq = sr2.vdd_opp_clk->rate;
> +	freq = sr_info->vdd_opp_clk->rate;
>  	opp = opp_find_freq_ceil(OPP_L3, &freq);
>  	if (IS_ERR(opp))
>  		return 0;
> @@ -187,9 +217,9 @@ static u8 get_vdd2_opp(void)
>  	 * Use higher freq voltage even if an exact match is not available
>  	 * we are probably masking a clock framework bug, so warn
>  	 */
> -	if (unlikely(freq != sr2.vdd_opp_clk->rate))
> +	if (unlikely(freq != sr_info->vdd_opp_clk->rate))
>  		pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
> -			   __func__, freq, sr2.vdd_opp_clk->rate);
> +			   __func__, freq, sr_info->vdd_opp_clk->rate);
>  	return opp_get_opp_id(opp);
>  }
>  
> @@ -694,14 +724,13 @@ static void sr_disable(struct omap_sr *sr)
>  
>  void sr_start_vddautocomap(int srid, u32 target_opp_no)
>  {
> -	struct omap_sr *sr = NULL;
> +	struct omap_sr *sr = _sr_lookup(srid);
>  
> -	if (srid == SR1)
> -		sr = &sr1;
> -	else if (srid == SR2)
> -		sr = &sr2;
> -	else
> +	if (!sr) {
> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> +								srid);
>  		return;
> +	}
>  
>  	if (sr->is_sr_reset == 1) {
>  		sr_clk_enable(sr);
> @@ -719,14 +748,13 @@ EXPORT_SYMBOL(sr_start_vddautocomap);
>  
>  int sr_stop_vddautocomap(int srid)
>  {
> -	struct omap_sr *sr = NULL;
> +	struct omap_sr *sr = _sr_lookup(srid);
>  
> -	if (srid == SR1)
> -		sr = &sr1;
> -	else if (srid == SR2)
> -		sr = &sr2;
> -	else
> -		return -EINVAL;
> +	if (!sr) {
> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> +								srid);
> +		return false;
> +	}
>  
>  	if (sr->is_autocomp_active == 1) {
>  		sr_disable(sr);
> @@ -744,14 +772,13 @@ EXPORT_SYMBOL(sr_stop_vddautocomap);
>  void enable_smartreflex(int srid)
>  {
>  	u32 target_opp_no = 0;
> -	struct omap_sr *sr = NULL;
> +	struct omap_sr *sr = _sr_lookup(srid);
>  
> -	if (srid == SR1)
> -		sr = &sr1;
> -	else if (srid == SR2)
> -		sr = &sr2;
> -	else
> +	if (!sr) {
> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> +								srid);
>  		return;
> +	}
>  
>  	if (sr->is_autocomp_active == 1) {
>  		if (sr->is_sr_reset == 1) {
> @@ -779,15 +806,13 @@ void enable_smartreflex(int srid)
>  void disable_smartreflex(int srid)
>  {
>  	u32 i = 0;
> +	struct omap_sr *sr = _sr_lookup(srid);
>  
> -	struct omap_sr *sr = NULL;
> -
> -	if (srid == SR1)
> -		sr = &sr1;
> -	else if (srid == SR2)
> -		sr = &sr2;
> -	else
> +	if (!sr) {
> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> +								srid);
>  		return;
> +	}
>  
>  	if (sr->is_autocomp_active == 1) {
>  		if (sr->is_sr_reset == 0) {
> @@ -920,7 +945,13 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
>  static ssize_t omap_sr_vdd1_autocomp_show(struct kobject *kobj,
>  					struct kobj_attribute *attr, char *buf)
>  {
> -	return sprintf(buf, "%d\n", sr1.is_autocomp_active);
> +	struct omap_sr *sr_info = _sr_lookup(SR1);
> +
> +	if (!sr_info) {
> +		pr_warning("omap_sr struct corresponding to SR1 not found\n");
> +		return 0;
> +	}
> +	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
>  }
>  
>  static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj,
> @@ -960,7 +991,13 @@ static struct kobj_attribute sr_vdd1_autocomp = {
>  static ssize_t omap_sr_vdd2_autocomp_show(struct kobject *kobj,
>  					struct kobj_attribute *attr, char *buf)
>  {
> -	return sprintf(buf, "%d\n", sr2.is_autocomp_active);
> +	struct omap_sr *sr_info = _sr_lookup(SR2);
> +
> +	if (!sr_info) {
> +		pr_warning("omap_sr struct corresponding to SR2 not found\n");
> +		return 0;
> +	}
> +	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
>  }
>  
>  static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj,
> @@ -1010,7 +1047,6 @@ static int __init omap3_sr_init(void)
>  	RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
>  	ret |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
>  				R_DCDC_GLOBAL_CFG);
> -
>  	if (cpu_is_omap34xx()) {
>  		sr1.clk = clk_get(NULL, "sr1_fck");
>  		sr2.clk = clk_get(NULL, "sr2_fck");
> @@ -1036,6 +1072,8 @@ static int __init omap3_sr_init(void)
>  	ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
>  	if (ret)
>  		pr_err("sysfs_create_file failed: %d\n", ret);
> +	list_add(&sr1.node, &sr_list);
> +	list_add(&sr2.node, &sr_list);
>  
 From scaling perspective for Next Gen Omap, I guess it would be better 
to add list through a loop and the info related to, no of sr's can be 
passed through SR platform structure?

>  	return 0;
>  }


Regards,
Ambresh

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

* Re: [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer
  2010-02-24  9:29     ` [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer Thara Gopinath
  2010-02-24  9:29       ` [PATCH 04/16] OMAP3: PM: Move smartreflex autocompensation enable disable hooks to PM debugfs Thara Gopinath
@ 2010-02-25  2:39       ` ambresh
  2010-03-02 18:28       ` Kevin Hilman
  2010-03-03  0:02       ` Kevin Hilman
  3 siblings, 0 replies; 61+ messages in thread
From: ambresh @ 2010-02-25  2:39 UTC (permalink / raw)
  To: Gopinath, Thara
  Cc: linux-omap, khilman, paul, Menon, Nishanth, Cousson, Benoit,
	Sripathy, Vishwanath, Sawant, Anand

Gopinath, Thara wrote:
> This patch converts the exisitng smartreflex library into a
> platform driver with device , driver registrations using hardware mods.
> As part of this Ntarget values are passed as platform data.
> 
> Signed-off-by: Thara Gopinath <thara@ti.com>
> ---
>  arch/arm/mach-omap2/smartreflex.c |  470 +++++++++++++++++++++----------------
>  arch/arm/mach-omap2/smartreflex.h |   27 ++
>  2 files changed, 293 insertions(+), 204 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
> index 4a9c2e2..05c72b2 100644
> --- a/arch/arm/mach-omap2/smartreflex.c
> +++ b/arch/arm/mach-omap2/smartreflex.c
> @@ -14,7 +14,6 @@
>   * published by the Free Software Foundation.
>   */
> 
> -
>  #include <linux/kernel.h>
>  #include <linux/init.h>
>  #include <linux/interrupt.h>
> @@ -33,6 +32,8 @@
>  #include <plat/clock.h>
>  #include <plat/opp.h>
>  #include <plat/opp_twl_tps.h>
> +#include <plat/omap_hwmod.h>
> +#include <plat/omap_device.h>
> 
>  #include "prm.h"
>  #include "smartreflex.h"
> @@ -41,17 +42,14 @@
>  #define MAX_TRIES 100
> 
>  struct omap_sr {
> -       int             srid;
> -       int             is_sr_reset;
> -       int             is_autocomp_active;
> -       struct clk      *clk;
> -       struct clk      *vdd_opp_clk;
> -       u32             clk_length;
> -       u32             req_opp_no;
> -       u32             opp1_nvalue, opp2_nvalue, opp3_nvalue, opp4_nvalue;
> -       u32             opp5_nvalue;
> -       u32             senp_mod, senn_mod;
> -       void __iomem    *srbase_addr;
> +       int                     srid;
> +       int                     is_sr_reset;
> +       int                     is_autocomp_active;
> +       struct clk              *vdd_opp_clk;
> +       u32                     clk_length;
> +       void __iomem            *srbase_addr;
> +       unsigned int            irq;
> +       struct platform_device  *pdev;
>         struct list_head        node;
>  };
> 
> @@ -98,71 +96,22 @@ static struct omap_sr *_sr_lookup(int srid)
> 
>  static int sr_clk_enable(struct omap_sr *sr)
>  {
> -       if (clk_enable(sr->clk) != 0) {
> -               pr_err("Could not enable %s\n", sr->clk->name);
> -               return -1;
> -       }
> +       struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
> 
> -       /* set fclk- active , iclk- idle */
> -       sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
> -                     SR_CLKACTIVITY_IOFF_FON);
> +       if (pdata->device_enable)
> +               pdata->device_enable(sr->pdev);
> 
>         return 0;
>  }
> 
>  static void sr_clk_disable(struct omap_sr *sr)
>  {
> -       /* set fclk, iclk- idle */
> -       sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
> -                     SR_CLKACTIVITY_IOFF_FOFF);
> -
> -       clk_disable(sr->clk);
> -       sr->is_sr_reset = 1;
> -}
> +       struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
> 
> -static struct omap_sr sr1 = {
> -       .srid                   = SR1,
> -       .is_sr_reset            = 1,
> -       .is_autocomp_active     = 0,
> -       .clk_length             = 0,
> -       .srbase_addr            = OMAP2_L4_IO_ADDRESS(OMAP34XX_SR1_BASE),
> -};
> -
> -static struct omap_sr sr2 = {
> -       .srid                   = SR2,
> -       .is_sr_reset            = 1,
> -       .is_autocomp_active     = 0,
> -       .clk_length             = 0,
> -       .srbase_addr            = OMAP2_L4_IO_ADDRESS(OMAP34XX_SR2_BASE),
> -};
> +       if (pdata->device_idle)
	> +               pdata->device_idle(sr->pdev);
> 
> -static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen)
> -{
> -       u32 gn, rn, mul;
> -
> -       for (gn = 0; gn < GAIN_MAXLIMIT; gn++) {
> -               mul = 1 << (gn + 8);
> -               rn = mul / sensor;
> -               if (rn < R_MAXLIMIT) {
> -                       *sengain = gn;
> -                       *rnsen = rn;
> -               }
> -       }
> -}
> -
> -static u32 cal_test_nvalue(u32 sennval, u32 senpval)
> -{
> -       u32 senpgain, senngain;
> -       u32 rnsenp, rnsenn;
> -
> -       /* Calculating the gain and reciprocal of the SenN and SenP values */
> -       cal_reciprocal(senpval, &senpgain, &rnsenp);
> -       cal_reciprocal(sennval, &senngain, &rnsenn);
> -
> -       return (senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |
> -               (senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |
> -               (rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |
> -               (rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT);
> +       sr->is_sr_reset = 1;
>  }
> 
>  static u8 get_vdd1_opp(void)
> @@ -255,76 +204,6 @@ static void sr_set_clk_length(struct omap_sr *sr)
>         }
>  }
> 
> -static void sr_set_efuse_nvalues(struct omap_sr *sr)
> -{
> -       if (sr->srid == SR1) {
> -               sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> -                                       OMAP343X_SR1_SENNENABLE_MASK) >>
> -                                       OMAP343X_SR1_SENNENABLE_SHIFT;
> -               sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> -                                       OMAP343X_SR1_SENPENABLE_MASK) >>
> -                                       OMAP343X_SR1_SENPENABLE_SHIFT;
> -
> -               sr->opp5_nvalue = omap_ctrl_readl(
> -                                       OMAP343X_CONTROL_FUSE_OPP5_VDD1);
> -               sr->opp4_nvalue = omap_ctrl_readl(
> -                                       OMAP343X_CONTROL_FUSE_OPP4_VDD1);
> -               sr->opp3_nvalue = omap_ctrl_readl(
> -                                       OMAP343X_CONTROL_FUSE_OPP3_VDD1);
> -               sr->opp2_nvalue = omap_ctrl_readl(
> -                                       OMAP343X_CONTROL_FUSE_OPP2_VDD1);
> -               sr->opp1_nvalue = omap_ctrl_readl(
> -                                       OMAP343X_CONTROL_FUSE_OPP1_VDD1);
> -       } else if (sr->srid == SR2) {
> -               sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> -                                       OMAP343X_SR2_SENNENABLE_MASK) >>
> -                                       OMAP343X_SR2_SENNENABLE_SHIFT;
> -
> -               sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> -                                       OMAP343X_SR2_SENPENABLE_MASK) >>
> -                                       OMAP343X_SR2_SENPENABLE_SHIFT;
> -
> -               sr->opp3_nvalue = omap_ctrl_readl(
> -                                       OMAP343X_CONTROL_FUSE_OPP3_VDD2);
> -               sr->opp2_nvalue = omap_ctrl_readl(
> -                                       OMAP343X_CONTROL_FUSE_OPP2_VDD2);
> -               sr->opp1_nvalue = omap_ctrl_readl(
> -                                       OMAP343X_CONTROL_FUSE_OPP1_VDD2);
> -       }
> -}
> -
> -/* Hard coded nvalues for testing purposes, may cause device to hang! */
> -static void sr_set_testing_nvalues(struct omap_sr *sr)
> -{
> -       if (sr->srid == SR1) {
> -               sr->senp_mod = 0x03;    /* SenN-M5 enabled */
> -               sr->senn_mod = 0x03;
> -
> -               /* calculate nvalues for each opp */
> -               sr->opp5_nvalue = cal_test_nvalue(0xacd + 0x330, 0x848 + 0x330);
> -               sr->opp4_nvalue = cal_test_nvalue(0x964 + 0x2a0, 0x727 + 0x2a0);
> -               sr->opp3_nvalue = cal_test_nvalue(0x85b + 0x200, 0x655 + 0x200);
> -               sr->opp2_nvalue = cal_test_nvalue(0x506 + 0x1a0, 0x3be + 0x1a0);
> -               sr->opp1_nvalue = cal_test_nvalue(0x373 + 0x100, 0x28c + 0x100);
> -       } else if (sr->srid == SR2) {
> -               sr->senp_mod = 0x03;
> -               sr->senn_mod = 0x03;
> -
> -               sr->opp3_nvalue = cal_test_nvalue(0x76f + 0x200, 0x579 + 0x200);
> -               sr->opp2_nvalue = cal_test_nvalue(0x4f5 + 0x1c0, 0x390 + 0x1c0);
> -               sr->opp1_nvalue = cal_test_nvalue(0x359, 0x25d);
> -       }
> -
> -}
> -
> -static void sr_set_nvalues(struct omap_sr *sr)
> -{
> -       if (SR_TESTING_NVALUES)
> -               sr_set_testing_nvalues(sr);
> -       else
> -               sr_set_efuse_nvalues(sr);
> -}
> -
>  static void sr_configure_vp(int srid)
>  {
>         u32 vpconfig;
> @@ -438,12 +317,13 @@ static void sr_configure(struct omap_sr *sr)
>  {
>         u32 sr_config;
>         u32 senp_en , senn_en;
> +       struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
> 
>         if (sr->clk_length == 0)
>                 sr_set_clk_length(sr);
> 
> -       senp_en = sr->senp_mod;
> -       senn_en = sr->senn_mod;
> +       senp_en = pdata->senp_mod;
> +       senn_en = pdata->senn_mod;
>         if (sr->srid == SR1) {
>                 sr_config = SR1_SRCONFIG_ACCUMDATA |
>                         (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
> @@ -571,57 +451,33 @@ static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
>  {
>         u32 nvalue_reciprocal, v;
>         struct omap_opp *opp;
> +       struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>         int uvdc;
>         char vsel;
> 
> -       sr->req_opp_no = target_opp_no;
> -
>         if (sr->srid == SR1) {
> -               switch (target_opp_no) {
> -               case 5:
> -                       nvalue_reciprocal = sr->opp5_nvalue;
> -                       break;
> -               case 4:
> -                       nvalue_reciprocal = sr->opp4_nvalue;
> -                       break;
> -               case 3:
> -                       nvalue_reciprocal = sr->opp3_nvalue;
> -                       break;
> -               case 2:
> -                       nvalue_reciprocal = sr->opp2_nvalue;
> -                       break;
> -               case 1:
> -                       nvalue_reciprocal = sr->opp1_nvalue;
> -                       break;
> -               default:
> -                       nvalue_reciprocal = sr->opp3_nvalue;
> -                       break;
> -               }
> -
>                 opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
>                 if (!opp)
>                         return false;
>         } else {
> -               switch (target_opp_no) {
> -               case 3:
> -                       nvalue_reciprocal = sr->opp3_nvalue;
> -                       break;
> -               case 2:
> -                       nvalue_reciprocal = sr->opp2_nvalue;
> -                       break;
> -               case 1:
> -                       nvalue_reciprocal = sr->opp1_nvalue;
> -                       break;
> -               default:
> -                       nvalue_reciprocal = sr->opp3_nvalue;
> -                       break;
> -               }
> -
>                 opp = opp_find_by_opp_id(OPP_L3, target_opp_no);
>                 if (!opp)
>                         return false;
>         }
> 
> +       if (target_opp_no > pdata->no_opp) {
> +               pr_notice("Wrong target opp\n");
> +               return false;
> +       }
> +
> +       if (!pdata->sr_nvalue) {
> +               pr_notice("N target values does not exist for SR%d\n",
> +                                                               sr->srid);
> +               return false;
> +       }
> +
> +       nvalue_reciprocal = pdata->sr_nvalue[target_opp_no - 1];
> +
>         if (nvalue_reciprocal == 0) {
>                 pr_notice("OPP%d doesn't support SmartReflex\n",
>                                                                 target_opp_no);
> @@ -1033,49 +889,255 @@ static struct kobj_attribute sr_vdd2_autocomp = {
>         .store = omap_sr_vdd2_autocomp_store,
>  };
> 
> +static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
> +{
> +       struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
> +       struct omap_device *odev = to_omap_device(pdev);
> +       int ret = 0;
> +
> +       if (WARN_ON(!sr_info))
> +               return -ENOMEM;
> +       sr_info->pdev = pdev;
> +       sr_info->srid = pdev->id + 1;
> +       sr_info->is_sr_reset = 1,
> +       sr_info->is_autocomp_active = 0;
> +       sr_info->clk_length = 0;
> +       sr_info->srbase_addr = odev->hwmods[0]->_rt_va;
> +       if (odev->hwmods[0]->mpu_irqs)
> +               sr_info->irq = odev->hwmods[0]->mpu_irqs[0].irq;
> +       sr_set_clk_length(sr_info);
> +
> +       if (sr_info->srid == SR1) {
> +               sr_info->vdd_opp_clk = clk_get(NULL, "dpll1_ck");
> +               ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
> +               if (ret)
> +                       pr_err("sysfs_create_file failed: %d\n", ret);
> +       } else {
> +               sr_info->vdd_opp_clk = clk_get(NULL, "l3_ick");
> +               ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
> +               if (ret)
> +                       pr_err("sysfs_create_file failed: %d\n", ret);
> +       }
> +

 From scalable perspective for Next Gen Omap, above code can be split 
into two sets ;  one for acquiring all the required clocks (May be In 
another function) and creation of attribute files in a loop for 'x' no 
of SR's





> +       /* Call the VPConfig */
> +       sr_configure_vp(sr_info->srid);
> +       odev->hwmods[0]->dev_attr = sr_info;
> +       list_add(&sr_info->node, &sr_list);
> +       pr_info("SmartReflex driver initialized\n");
> +
> +       return ret;
> +}
> +
> +static int __devexit omap_smartreflex_remove(struct platform_device *pdev)
> +{
> +       struct omap_device *odev = to_omap_device(pdev);
> +       struct omap_sr *sr_info = odev->hwmods[0]->dev_attr;
> +
> +       /* Disable Autocompensation if enabled before removing the module */
> +       if (sr_info->is_autocomp_active == 1)
> +               sr_stop_vddautocomap(sr_info->srid);
> +       list_del(&sr_info->node);
> +       return 0;
> +}
> 
> +static struct platform_driver smartreflex_driver = {
> +       .probe          = omap_smartreflex_probe,
> +       .remove         = omap_smartreflex_remove,
> +       .driver         = {
> +               .name   = "smartreflex",
> +       },
> +};
> 
> -static int __init omap3_sr_init(void)
> +static int __init sr_init(void)
>  {
>         int ret = 0;
>         u8 RdReg;
> 
> +       /* TODO: Find an appropriate place for this */
>         /* Enable SR on T2 */
>         ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &RdReg,
>                               R_DCDC_GLOBAL_CFG);
> -
>         RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
>         ret |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
>                                 R_DCDC_GLOBAL_CFG);
> -       if (cpu_is_omap34xx()) {
> -               sr1.clk = clk_get(NULL, "sr1_fck");
> -               sr2.clk = clk_get(NULL, "sr2_fck");
> -       }
> -       sr1.vdd_opp_clk = clk_get(NULL, "dpll1_ck");
> -       sr2.vdd_opp_clk = clk_get(NULL, "l3_ick");
> -       sr_set_clk_length(&sr1);
> -       sr_set_clk_length(&sr2);
> 
> -       /* Call the VPConfig, VCConfig, set N Values. */
> -       sr_set_nvalues(&sr1);
> -       sr_configure_vp(SR1);
> +       ret = platform_driver_probe(&smartreflex_driver,
> +                               omap_smartreflex_probe);
> 
> -       sr_set_nvalues(&sr2);
> -       sr_configure_vp(SR2);
> +       if (ret)
> +               pr_err("platform driver register failed for smartreflex");
> +       return 0;
> +}
> 
> -       pr_info("SmartReflex driver initialized\n");
> +void __exit sr_exit(void)
> +{
> +       platform_driver_unregister(&smartreflex_driver);
> +}
> +late_initcall(sr_init);
> +module_exit(sr_exit);
> 
> -       ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
> -       if (ret)
> -               pr_err("sysfs_create_file failed: %d\n", ret);
> +MODULE_DESCRIPTION("OMAP SMARTREFLEX DRIVER");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:" DRIVER_NAME);
> +MODULE_AUTHOR("Texas Instruments Inc");
> 
> -       ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
> -       if (ret)
> -               pr_err("sysfs_create_file failed: %d\n", ret);
> -       list_add(&sr1.node, &sr_list);
> -       list_add(&sr2.node, &sr_list);
> +/* Device registrations for smartreflex instances */
> 
> -       return 0;
> +#define MAX_HWMOD_NAME_LEN     16
> +
> +struct omap_device_pm_latency omap_sr_latency[] = {
> +       {
> +               .deactivate_func = omap_device_idle_hwmods,
> +               .activate_func   = omap_device_enable_hwmods,
> +               .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST
> +       },
> +};
> +
> +/* Read EFUSE values from control registers */
> +static void __init omap3_sr_read_efuse(struct omap_smartreflex_data *sr_data,
> +                                               int sr_id)
> +{
> +       if (sr_id == SR1) {
> +               /*
> +                * TODO: When opp framework come into picture use appropriate
> +                * API's to find out number of opp's.
> +                */
> +               sr_data->no_opp = 5;
> +               sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
> +                                       sr_data->no_opp , GFP_KERNEL);
> +               if (WARN_ON(!sr_data->sr_nvalue))
> +                       return;
> +
> +               sr_data->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> +                                       OMAP343X_SR1_SENNENABLE_MASK) >>
> +                                       OMAP343X_SR1_SENNENABLE_SHIFT;
> +               sr_data->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> +                                       OMAP343X_SR1_SENPENABLE_MASK) >>
> +                                       OMAP343X_SR1_SENPENABLE_SHIFT;
> +               sr_data->sr_nvalue[4] = omap_ctrl_readl(
> +                                       OMAP343X_CONTROL_FUSE_OPP5_VDD1);
> +               sr_data->sr_nvalue[3] = omap_ctrl_readl(
> +                                       OMAP343X_CONTROL_FUSE_OPP4_VDD1);
> +               sr_data->sr_nvalue[2] = omap_ctrl_readl(
> +                                       OMAP343X_CONTROL_FUSE_OPP3_VDD1);
> +               sr_data->sr_nvalue[1] = omap_ctrl_readl(
> +                                       OMAP343X_CONTROL_FUSE_OPP2_VDD1);
> +               sr_data->sr_nvalue[0] = omap_ctrl_readl(
> +                                       OMAP343X_CONTROL_FUSE_OPP1_VDD1);
> +       } else if (sr_id == SR2) {
> +               /*
> +                * TODO: When opp framework come into picture use appropriate
> +                * API's to find out number of opp's.
> +                */
> +               sr_data->no_opp = 3;
> +               sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
> +                                       sr_data->no_opp , GFP_KERNEL);
> +               if (WARN_ON(!sr_data->sr_nvalue))
> +                       return;
> +
> +               sr_data->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> +                                       OMAP343X_SR2_SENNENABLE_MASK) >>
> +                                       OMAP343X_SR2_SENNENABLE_SHIFT;
> +               sr_data->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> +                                       OMAP343X_SR2_SENPENABLE_MASK) >>
> +                                       OMAP343X_SR2_SENPENABLE_SHIFT;
> +               sr_data->sr_nvalue[2] = omap_ctrl_readl(
> +                                       OMAP343X_CONTROL_FUSE_OPP3_VDD2);
> +               sr_data->sr_nvalue[1] = omap_ctrl_readl(
> +                                       OMAP343X_CONTROL_FUSE_OPP2_VDD2);
> +               sr_data->sr_nvalue[0] = omap_ctrl_readl(
> +                                       OMAP343X_CONTROL_FUSE_OPP1_VDD2);
> +       }
>  }
> 
> -late_initcall(omap3_sr_init);
> +/* Hard coded nvalues for testing purposes, may cause device to hang! */
> +static void __init omap3_sr_set_testing_nvalues(
> +                               struct omap_smartreflex_data *sr_data, int srid)
> +{
> +       if (srid == SR1) {
> +               /*
> +                * TODO: When opp framework come into picture use appropriate
> +                * API's to find out number of opp's.
> +                */
> +               sr_data->no_opp = 5;
> +               sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
> +                               sr_data->no_opp , GFP_KERNEL);
> +               if (WARN_ON(!sr_data->sr_nvalue))
> +                       return;
> +
> +               sr_data->senp_mod = 0x03;       /* SenN-M5 enabled */
> +               sr_data->senn_mod = 0x03;
> +               /* calculate nvalues for each opp */
> +               sr_data->sr_nvalue[4] = 0x0;
> +               sr_data->sr_nvalue[3] = 0x0;
> +               sr_data->sr_nvalue[2] = 0x0;
> +               sr_data->sr_nvalue[1] = 0x0;
> +               sr_data->sr_nvalue[0] = 0x0;
> +       } else if (srid == SR2) {
> +               /*
> +                * TODO: When opp framework come into picture use appropriate
> +                * API's to find out number of opp's.
> +                */
> +               sr_data->no_opp = 3;
> +               sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
> +                                       sr_data->no_opp , GFP_KERNEL);
> +               if (WARN_ON(!sr_data->sr_nvalue))
> +                       return;
> +
> +               sr_data->senp_mod = 0x03;       /* SenN-M5 enabled */
> +               sr_data->senn_mod = 0x03;
> +               sr_data->sr_nvalue[2] = 0x0;
> +               sr_data->sr_nvalue[1] = 0x0;
> +               sr_data->sr_nvalue[0] = 0x0;
> +       }
> +}
> +
> +static void __init sr_set_nvalues(struct omap_smartreflex_data *sr_data,
> +                                               int srid)
> +{
> +       if (cpu_is_omap343x()) {
> +               if (SR_TESTING_NVALUES)
> +                       omap3_sr_set_testing_nvalues(sr_data, srid);
> +               else
> +                       omap3_sr_read_efuse(sr_data, srid);
> +       }
> +}
> +
> +static int __init omap_devinit_smartreflex(void)
> +{
> +       int i = 0;
> +       char *name = "smartreflex";
> +
> +       do {
> +               struct omap_smartreflex_data *sr_data;
> +               struct omap_device *od;
> +               struct omap_hwmod *oh;
> +               char oh_name[MAX_HWMOD_NAME_LEN];
> +
> +               snprintf(oh_name, MAX_HWMOD_NAME_LEN, "sr%d_hwmod", i + 1);
> +               oh = omap_hwmod_lookup(oh_name);
> +               if (!oh)
> +                       break;
> +
> +               sr_data = kzalloc(sizeof(struct omap_smartreflex_data),
> +                                                               GFP_KERNEL);
> +               if (WARN_ON(!sr_data))
> +                       return -ENOMEM;
> +
> +               sr_data->init_enable = false;
> +               sr_data->device_enable = omap_device_enable;
> +               sr_data->device_shutdown = omap_device_shutdown;
> +               sr_data->device_idle = omap_device_idle;
> +               sr_set_nvalues(sr_data, i + 1);
> +
> +               od = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
> +                                      omap_sr_latency,
> +                                      ARRAY_SIZE(omap_sr_latency));
> +               WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
> +                    name, oh->name);
> +               i++;
> +       } while (1);
> +
> +       return 0;
> +}
> +arch_initcall(omap_devinit_smartreflex);
> diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
> index 2a0e823..f1e8676 100644
> --- a/arch/arm/mach-omap2/smartreflex.h
> +++ b/arch/arm/mach-omap2/smartreflex.h
> @@ -14,6 +14,8 @@
>   * published by the Free Software Foundation.
>   */
> 
> +#include <linux/platform_device.h>
> +
>  #define PHY_TO_OFF_PM_MASTER(p)                (p - 0x36)
>  #define PHY_TO_OFF_PM_RECIEVER(p)      (p - 0x5b)
>  #define PHY_TO_OFF_PM_INT(p)           (p - 0x2e)
> @@ -243,6 +245,31 @@ extern u32 current_vdd2_opp;
>   * do anything.
>   */
>  #ifdef CONFIG_OMAP_SMARTREFLEX
> +/*
> + * omap_smartreflex_data - Smartreflex platform data
> + *
> + * @senp_mod   : SENPENABLE value for the sr
> + * @senn_mod   : SENNENABLE value for sr
> + * @sr_nvalue  : array of n target values for sr
> + * @no_opp     : number of opp's for this SR
> + * @init_enable        : whether this sr module needs to enabled at boot up or not
> + * @device_enable      : fn pointer to be populated with omap_device
> + *                     enable API
> + * @device_shutdown    : fn pointer to be populated with omap_device
> + *                     shutdown API
> + * @device_idle                : fn pointer to be pouplated with omap_device idle API
> + */
> +struct omap_smartreflex_data {
> +       u32             senp_mod;
> +       u32             senn_mod;
> +       u32             *sr_nvalue;
> +       int             no_opp;
> +       bool            init_enable;
> +       int (*device_enable)(struct platform_device *pdev);
> +       int (*device_shutdown)(struct platform_device *pdev);
> +       int (*device_idle)(struct platform_device *pdev);
> +};
> +
>  void enable_smartreflex(int srid);
>  void disable_smartreflex(int srid);
>  int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel);
> --
> 1.7.0.rc1.33.g07cf0f
> 
> --
> 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] 61+ messages in thread

* Re: [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances.
  2010-02-24  9:29   ` [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances Thara Gopinath
  2010-02-24  9:29     ` [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer Thara Gopinath
  2010-02-25  1:42     ` [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances ambresh
@ 2010-02-26 23:21     ` Mike Turquette
  2010-03-02 17:39       ` Kevin Hilman
  2 siblings, 1 reply; 61+ messages in thread
From: Mike Turquette @ 2010-02-26 23:21 UTC (permalink / raw)
  To: Gopinath, Thara
  Cc: linux-omap, khilman, paul, Menon, Nishanth, Cousson, Benoit,
	Sripathy, Vishwanath, Sawant, Anand

Gopinath, Thara wrote:
> This patch removes the pointer sr1, sr2 in smartreflex.c and
> instead creatse a list for keeping track of multiple smartreflex
> instances.. This makes it scalable for next gen OMAPs where there
> are more than two smartreflex modules.
> 
> Signed-off-by: Thara Gopinath <thara@ti.com>
> ---
>  arch/arm/mach-omap2/smartreflex.c |  114 ++++++++++++++++++++++++------------
>  1 files changed, 76 insertions(+), 38 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
> index 1c5ec37..4a9c2e2 100644
> --- a/arch/arm/mach-omap2/smartreflex.c
> +++ b/arch/arm/mach-omap2/smartreflex.c
> @@ -26,6 +26,7 @@
>  #include <linux/kobject.h>
>  #include <linux/i2c/twl.h>
>  #include <linux/io.h>
> +#include <linux/list.h>
>  
>  #include <plat/omap34xx.h>
>  #include <plat/control.h>
> @@ -51,9 +52,12 @@ struct omap_sr {
>  	u32		opp5_nvalue;
>  	u32		senp_mod, senn_mod;
>  	void __iomem	*srbase_addr;
> -	void __iomem	*vpbase_addr;
> +	struct list_head 	node;
>  };
>  
> +/* sr_list contains all the instances of smartreflex module */
> +static LIST_HEAD(sr_list);
> +
>  #define SR_REGADDR(offs)	(sr->srbase_addr + offset)
>  
>  static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
> @@ -78,6 +82,20 @@ static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
>  	return __raw_readl(SR_REGADDR(offset));
>  }
>  
> +static struct omap_sr *_sr_lookup(int srid)
> +{
> +	struct omap_sr *sr_info, *temp_sr_info;
> +
> +	sr_info = NULL;
> +	list_for_each_entry(temp_sr_info, &sr_list, node) {
> +		if (srid == temp_sr_info->srid) {
> +			sr_info = temp_sr_info;
> +			break;
> +		}
> +	}
> +	return sr_info;
> +}
> +
>  static int sr_clk_enable(struct omap_sr *sr)
>  {
>  	if (clk_enable(sr->clk) != 0) {
> @@ -151,11 +169,17 @@ static u8 get_vdd1_opp(void)
>  {
>  	struct omap_opp *opp;
>  	unsigned long freq;
> +	struct omap_sr *sr_info = _sr_lookup(SR1);

Why has the list implementation been chosen over individually registered 
platform devices?  There seems to be a trend lately in device drivers to 
have a single platform device with either an array of pointers or a list 
implementation to track the multiple instances of the same device on a 
board.  McBSP is another example of this approach.

Why is that?  Is it a bad idea to have each SR instance be a separate 
platform device?  Please let me know if my question is nuts.

Mike

>  
> -	if (sr1.vdd_opp_clk == NULL || IS_ERR(sr1.vdd_opp_clk))
> +	if (!sr_info) {
> +		pr_warning("omap_sr struct corresponding to SR1 not found\n");
> +		return 0;
> +	}
> +
> +	if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
>  		return 0;
>  
> -	freq = sr1.vdd_opp_clk->rate;
> +	freq = sr_info->vdd_opp_clk->rate;
>  	opp = opp_find_freq_ceil(OPP_MPU, &freq);
>  	if (IS_ERR(opp))
>  		return 0;
> @@ -163,9 +187,9 @@ static u8 get_vdd1_opp(void)
>  	 * Use higher freq voltage even if an exact match is not available
>  	 * we are probably masking a clock framework bug, so warn
>  	 */
> -	if (unlikely(freq != sr1.vdd_opp_clk->rate))
> +	if (unlikely(freq != sr_info->vdd_opp_clk->rate))
>  		pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
> -			   __func__, freq, sr1.vdd_opp_clk->rate);
> +			   __func__, freq, sr_info->vdd_opp_clk->rate);
>  
>  	return opp_get_opp_id(opp);
>  }
> @@ -174,11 +198,17 @@ static u8 get_vdd2_opp(void)
>  {
>  	struct omap_opp *opp;
>  	unsigned long freq;
> +	struct omap_sr *sr_info = _sr_lookup(SR2);
> +
> +	if (!sr_info) {
> +		pr_warning("omap_sr struct corresponding to SR2 not found\n");
> +		return 0;
> +	}
>  
> -	if (sr2.vdd_opp_clk == NULL || IS_ERR(sr2.vdd_opp_clk))
> +	if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
>  		return 0;
>  
> -	freq = sr2.vdd_opp_clk->rate;
> +	freq = sr_info->vdd_opp_clk->rate;
>  	opp = opp_find_freq_ceil(OPP_L3, &freq);
>  	if (IS_ERR(opp))
>  		return 0;
> @@ -187,9 +217,9 @@ static u8 get_vdd2_opp(void)
>  	 * Use higher freq voltage even if an exact match is not available
>  	 * we are probably masking a clock framework bug, so warn
>  	 */
> -	if (unlikely(freq != sr2.vdd_opp_clk->rate))
> +	if (unlikely(freq != sr_info->vdd_opp_clk->rate))
>  		pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
> -			   __func__, freq, sr2.vdd_opp_clk->rate);
> +			   __func__, freq, sr_info->vdd_opp_clk->rate);
>  	return opp_get_opp_id(opp);
>  }
>  
> @@ -694,14 +724,13 @@ static void sr_disable(struct omap_sr *sr)
>  
>  void sr_start_vddautocomap(int srid, u32 target_opp_no)
>  {
> -	struct omap_sr *sr = NULL;
> +	struct omap_sr *sr = _sr_lookup(srid);
>  
> -	if (srid == SR1)
> -		sr = &sr1;
> -	else if (srid == SR2)
> -		sr = &sr2;
> -	else
> +	if (!sr) {
> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> +								srid);
>  		return;
> +	}
>  
>  	if (sr->is_sr_reset == 1) {
>  		sr_clk_enable(sr);
> @@ -719,14 +748,13 @@ EXPORT_SYMBOL(sr_start_vddautocomap);
>  
>  int sr_stop_vddautocomap(int srid)
>  {
> -	struct omap_sr *sr = NULL;
> +	struct omap_sr *sr = _sr_lookup(srid);
>  
> -	if (srid == SR1)
> -		sr = &sr1;
> -	else if (srid == SR2)
> -		sr = &sr2;
> -	else
> -		return -EINVAL;
> +	if (!sr) {
> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> +								srid);
> +		return false;
> +	}
>  
>  	if (sr->is_autocomp_active == 1) {
>  		sr_disable(sr);
> @@ -744,14 +772,13 @@ EXPORT_SYMBOL(sr_stop_vddautocomap);
>  void enable_smartreflex(int srid)
>  {
>  	u32 target_opp_no = 0;
> -	struct omap_sr *sr = NULL;
> +	struct omap_sr *sr = _sr_lookup(srid);
>  
> -	if (srid == SR1)
> -		sr = &sr1;
> -	else if (srid == SR2)
> -		sr = &sr2;
> -	else
> +	if (!sr) {
> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> +								srid);
>  		return;
> +	}
>  
>  	if (sr->is_autocomp_active == 1) {
>  		if (sr->is_sr_reset == 1) {
> @@ -779,15 +806,13 @@ void enable_smartreflex(int srid)
>  void disable_smartreflex(int srid)
>  {
>  	u32 i = 0;
> +	struct omap_sr *sr = _sr_lookup(srid);
>  
> -	struct omap_sr *sr = NULL;
> -
> -	if (srid == SR1)
> -		sr = &sr1;
> -	else if (srid == SR2)
> -		sr = &sr2;
> -	else
> +	if (!sr) {
> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> +								srid);
>  		return;
> +	}
>  
>  	if (sr->is_autocomp_active == 1) {
>  		if (sr->is_sr_reset == 0) {
> @@ -920,7 +945,13 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
>  static ssize_t omap_sr_vdd1_autocomp_show(struct kobject *kobj,
>  					struct kobj_attribute *attr, char *buf)
>  {
> -	return sprintf(buf, "%d\n", sr1.is_autocomp_active);
> +	struct omap_sr *sr_info = _sr_lookup(SR1);
> +
> +	if (!sr_info) {
> +		pr_warning("omap_sr struct corresponding to SR1 not found\n");
> +		return 0;
> +	}
> +	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
>  }
>  
>  static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj,
> @@ -960,7 +991,13 @@ static struct kobj_attribute sr_vdd1_autocomp = {
>  static ssize_t omap_sr_vdd2_autocomp_show(struct kobject *kobj,
>  					struct kobj_attribute *attr, char *buf)
>  {
> -	return sprintf(buf, "%d\n", sr2.is_autocomp_active);
> +	struct omap_sr *sr_info = _sr_lookup(SR2);
> +
> +	if (!sr_info) {
> +		pr_warning("omap_sr struct corresponding to SR2 not found\n");
> +		return 0;
> +	}
> +	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
>  }
>  
>  static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj,
> @@ -1010,7 +1047,6 @@ static int __init omap3_sr_init(void)
>  	RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
>  	ret |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
>  				R_DCDC_GLOBAL_CFG);
> -
>  	if (cpu_is_omap34xx()) {
>  		sr1.clk = clk_get(NULL, "sr1_fck");
>  		sr2.clk = clk_get(NULL, "sr2_fck");
> @@ -1036,6 +1072,8 @@ static int __init omap3_sr_init(void)
>  	ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
>  	if (ret)
>  		pr_err("sysfs_create_file failed: %d\n", ret);
> +	list_add(&sr1.node, &sr_list);
> +	list_add(&sr2.node, &sr_list);
>  
>  	return 0;
>  }


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

* Re: [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances.
  2010-02-26 23:21     ` Mike Turquette
@ 2010-03-02 17:39       ` Kevin Hilman
  0 siblings, 0 replies; 61+ messages in thread
From: Kevin Hilman @ 2010-03-02 17:39 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Gopinath, Thara, linux-omap, paul, Menon, Nishanth, Cousson,
	Benoit, Sripathy, Vishwanath, Sawant, Anand

Mike Turquette <mturquette@ti.com> writes:

> Gopinath, Thara wrote:
>> This patch removes the pointer sr1, sr2 in smartreflex.c and
>> instead creatse a list for keeping track of multiple smartreflex
>> instances.. This makes it scalable for next gen OMAPs where there
>> are more than two smartreflex modules.
>>
>> Signed-off-by: Thara Gopinath <thara@ti.com>
>> ---
>>  arch/arm/mach-omap2/smartreflex.c |  114 ++++++++++++++++++++++++------------
>>  1 files changed, 76 insertions(+), 38 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
>> index 1c5ec37..4a9c2e2 100644
>> --- a/arch/arm/mach-omap2/smartreflex.c
>> +++ b/arch/arm/mach-omap2/smartreflex.c
>> @@ -26,6 +26,7 @@
>>  #include <linux/kobject.h>
>>  #include <linux/i2c/twl.h>
>>  #include <linux/io.h>
>> +#include <linux/list.h>
>>   #include <plat/omap34xx.h>
>>  #include <plat/control.h>
>> @@ -51,9 +52,12 @@ struct omap_sr {
>>  	u32		opp5_nvalue;
>>  	u32		senp_mod, senn_mod;
>>  	void __iomem	*srbase_addr;
>> -	void __iomem	*vpbase_addr;
>> +	struct list_head 	node;
>>  };
>>  +/* sr_list contains all the instances of smartreflex module */
>> +static LIST_HEAD(sr_list);
>> +
>>  #define SR_REGADDR(offs)	(sr->srbase_addr + offset)
>>   static inline void sr_write_reg(struct omap_sr *sr, unsigned
>> offset, u32 value)
>> @@ -78,6 +82,20 @@ static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
>>  	return __raw_readl(SR_REGADDR(offset));
>>  }
>>  +static struct omap_sr *_sr_lookup(int srid)
>> +{
>> +	struct omap_sr *sr_info, *temp_sr_info;
>> +
>> +	sr_info = NULL;
>> +	list_for_each_entry(temp_sr_info, &sr_list, node) {
>> +		if (srid == temp_sr_info->srid) {
>> +			sr_info = temp_sr_info;
>> +			break;
>> +		}
>> +	}
>> +	return sr_info;
>> +}
>> +
>>  static int sr_clk_enable(struct omap_sr *sr)
>>  {
>>  	if (clk_enable(sr->clk) != 0) {
>> @@ -151,11 +169,17 @@ static u8 get_vdd1_opp(void)
>>  {
>>  	struct omap_opp *opp;
>>  	unsigned long freq;
>> +	struct omap_sr *sr_info = _sr_lookup(SR1);
>
> Why has the list implementation been chosen over individually
> registered platform devices?  

Not sure I follow your question exactly here, but IIUC, Thara converts
to individually registered platform_devices in the next patch.  This
is a preliminary one to prepare for that.  In PATCH 03/16, the devices
are found via hwmod then registered via omap_device_build() (which in
turn does the platform_device_register())

Kevin


> There seems to be a trend lately in
> device drivers to have a single platform device with either an array
> of pointers or a list implementation to track the multiple instances
> of the same device on a board.  McBSP is another example of this
> approach.
>
> Why is that?  Is it a bad idea to have each SR instance be a separate
> platform device?  Please let me know if my question is nuts.
>
> Mike
>
>>  -	if (sr1.vdd_opp_clk == NULL || IS_ERR(sr1.vdd_opp_clk))
>> +	if (!sr_info) {
>> +		pr_warning("omap_sr struct corresponding to SR1 not found\n");
>> +		return 0;
>> +	}
>> +
>> +	if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
>>  		return 0;
>>  -	freq = sr1.vdd_opp_clk->rate;
>> +	freq = sr_info->vdd_opp_clk->rate;
>>  	opp = opp_find_freq_ceil(OPP_MPU, &freq);
>>  	if (IS_ERR(opp))
>>  		return 0;
>> @@ -163,9 +187,9 @@ static u8 get_vdd1_opp(void)
>>  	 * Use higher freq voltage even if an exact match is not available
>>  	 * we are probably masking a clock framework bug, so warn
>>  	 */
>> -	if (unlikely(freq != sr1.vdd_opp_clk->rate))
>> +	if (unlikely(freq != sr_info->vdd_opp_clk->rate))
>>  		pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
>> -			   __func__, freq, sr1.vdd_opp_clk->rate);
>> +			   __func__, freq, sr_info->vdd_opp_clk->rate);
>>   	return opp_get_opp_id(opp);
>>  }
>> @@ -174,11 +198,17 @@ static u8 get_vdd2_opp(void)
>>  {
>>  	struct omap_opp *opp;
>>  	unsigned long freq;
>> +	struct omap_sr *sr_info = _sr_lookup(SR2);
>> +
>> +	if (!sr_info) {
>> +		pr_warning("omap_sr struct corresponding to SR2 not found\n");
>> +		return 0;
>> +	}
>>  -	if (sr2.vdd_opp_clk == NULL || IS_ERR(sr2.vdd_opp_clk))
>> +	if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
>>  		return 0;
>>  -	freq = sr2.vdd_opp_clk->rate;
>> +	freq = sr_info->vdd_opp_clk->rate;
>>  	opp = opp_find_freq_ceil(OPP_L3, &freq);
>>  	if (IS_ERR(opp))
>>  		return 0;
>> @@ -187,9 +217,9 @@ static u8 get_vdd2_opp(void)
>>  	 * Use higher freq voltage even if an exact match is not available
>>  	 * we are probably masking a clock framework bug, so warn
>>  	 */
>> -	if (unlikely(freq != sr2.vdd_opp_clk->rate))
>> +	if (unlikely(freq != sr_info->vdd_opp_clk->rate))
>>  		pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
>> -			   __func__, freq, sr2.vdd_opp_clk->rate);
>> +			   __func__, freq, sr_info->vdd_opp_clk->rate);
>>  	return opp_get_opp_id(opp);
>>  }
>>  @@ -694,14 +724,13 @@ static void sr_disable(struct omap_sr *sr)
>>   void sr_start_vddautocomap(int srid, u32 target_opp_no)
>>  {
>> -	struct omap_sr *sr = NULL;
>> +	struct omap_sr *sr = _sr_lookup(srid);
>>  -	if (srid == SR1)
>> -		sr = &sr1;
>> -	else if (srid == SR2)
>> -		sr = &sr2;
>> -	else
>> +	if (!sr) {
>> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
>> +								srid);
>>  		return;
>> +	}
>>   	if (sr->is_sr_reset == 1) {
>>  		sr_clk_enable(sr);
>> @@ -719,14 +748,13 @@ EXPORT_SYMBOL(sr_start_vddautocomap);
>>   int sr_stop_vddautocomap(int srid)
>>  {
>> -	struct omap_sr *sr = NULL;
>> +	struct omap_sr *sr = _sr_lookup(srid);
>>  -	if (srid == SR1)
>> -		sr = &sr1;
>> -	else if (srid == SR2)
>> -		sr = &sr2;
>> -	else
>> -		return -EINVAL;
>> +	if (!sr) {
>> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
>> +								srid);
>> +		return false;
>> +	}
>>   	if (sr->is_autocomp_active == 1) {
>>  		sr_disable(sr);
>> @@ -744,14 +772,13 @@ EXPORT_SYMBOL(sr_stop_vddautocomap);
>>  void enable_smartreflex(int srid)
>>  {
>>  	u32 target_opp_no = 0;
>> -	struct omap_sr *sr = NULL;
>> +	struct omap_sr *sr = _sr_lookup(srid);
>>  -	if (srid == SR1)
>> -		sr = &sr1;
>> -	else if (srid == SR2)
>> -		sr = &sr2;
>> -	else
>> +	if (!sr) {
>> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
>> +								srid);
>>  		return;
>> +	}
>>   	if (sr->is_autocomp_active == 1) {
>>  		if (sr->is_sr_reset == 1) {
>> @@ -779,15 +806,13 @@ void enable_smartreflex(int srid)
>>  void disable_smartreflex(int srid)
>>  {
>>  	u32 i = 0;
>> +	struct omap_sr *sr = _sr_lookup(srid);
>>  -	struct omap_sr *sr = NULL;
>> -
>> -	if (srid == SR1)
>> -		sr = &sr1;
>> -	else if (srid == SR2)
>> -		sr = &sr2;
>> -	else
>> +	if (!sr) {
>> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
>> +								srid);
>>  		return;
>> +	}
>>   	if (sr->is_autocomp_active == 1) {
>>  		if (sr->is_sr_reset == 0) {
>> @@ -920,7 +945,13 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
>>  static ssize_t omap_sr_vdd1_autocomp_show(struct kobject *kobj,
>>  					struct kobj_attribute *attr, char *buf)
>>  {
>> -	return sprintf(buf, "%d\n", sr1.is_autocomp_active);
>> +	struct omap_sr *sr_info = _sr_lookup(SR1);
>> +
>> +	if (!sr_info) {
>> +		pr_warning("omap_sr struct corresponding to SR1 not found\n");
>> +		return 0;
>> +	}
>> +	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
>>  }
>>   static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj,
>> @@ -960,7 +991,13 @@ static struct kobj_attribute sr_vdd1_autocomp = {
>>  static ssize_t omap_sr_vdd2_autocomp_show(struct kobject *kobj,
>>  					struct kobj_attribute *attr, char *buf)
>>  {
>> -	return sprintf(buf, "%d\n", sr2.is_autocomp_active);
>> +	struct omap_sr *sr_info = _sr_lookup(SR2);
>> +
>> +	if (!sr_info) {
>> +		pr_warning("omap_sr struct corresponding to SR2 not found\n");
>> +		return 0;
>> +	}
>> +	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
>>  }
>>   static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj,
>> @@ -1010,7 +1047,6 @@ static int __init omap3_sr_init(void)
>>  	RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
>>  	ret |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
>>  				R_DCDC_GLOBAL_CFG);
>> -
>>  	if (cpu_is_omap34xx()) {
>>  		sr1.clk = clk_get(NULL, "sr1_fck");
>>  		sr2.clk = clk_get(NULL, "sr2_fck");
>> @@ -1036,6 +1072,8 @@ static int __init omap3_sr_init(void)
>>  	ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
>>  	if (ret)
>>  		pr_err("sysfs_create_file failed: %d\n", ret);
>> +	list_add(&sr1.node, &sr_list);
>> +	list_add(&sr2.node, &sr_list);
>>   	return 0;
>>  }

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

* Re: [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances.
  2010-02-25  1:42     ` [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances ambresh
@ 2010-03-02 17:40       ` Kevin Hilman
  0 siblings, 0 replies; 61+ messages in thread
From: Kevin Hilman @ 2010-03-02 17:40 UTC (permalink / raw)
  To: ambresh
  Cc: Gopinath, Thara, linux-omap, paul, Menon, Nishanth, Cousson,
	Benoit, Sripathy, Vishwanath, Sawant, Anand

ambresh <a0393775@ti.com> writes:

> Gopinath, Thara wrote:
>> This patch removes the pointer sr1, sr2 in smartreflex.c and
>> instead creatse a list for keeping track of multiple smartreflex
>> instances.. This makes it scalable for next gen OMAPs where there
>> are more than two smartreflex modules.
>>
>> Signed-off-by: Thara Gopinath <thara@ti.com>
>> ---
>>  arch/arm/mach-omap2/smartreflex.c |  114 ++++++++++++++++++++++++------------
>>  1 files changed, 76 insertions(+), 38 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
>> index 1c5ec37..4a9c2e2 100644
>> --- a/arch/arm/mach-omap2/smartreflex.c
>> +++ b/arch/arm/mach-omap2/smartreflex.c
>> @@ -26,6 +26,7 @@
>>  #include <linux/kobject.h>
>>  #include <linux/i2c/twl.h>
>>  #include <linux/io.h>
>> +#include <linux/list.h>
>>   #include <plat/omap34xx.h>
>>  #include <plat/control.h>
>> @@ -51,9 +52,12 @@ struct omap_sr {
>>  	u32		opp5_nvalue;
>>  	u32		senp_mod, senn_mod;
>>  	void __iomem	*srbase_addr;
>> -	void __iomem	*vpbase_addr;
>> +	struct list_head 	node;
>>  };
>>  +/* sr_list contains all the instances of smartreflex module */
>> +static LIST_HEAD(sr_list);
>> +
>>  #define SR_REGADDR(offs)	(sr->srbase_addr + offset)
>>   static inline void sr_write_reg(struct omap_sr *sr, unsigned
>> offset, u32 value)
>> @@ -78,6 +82,20 @@ static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
>>  	return __raw_readl(SR_REGADDR(offset));
>>  }
>>  +static struct omap_sr *_sr_lookup(int srid)
>> +{
>> +	struct omap_sr *sr_info, *temp_sr_info;
>> +
>> +	sr_info = NULL;
>> +	list_for_each_entry(temp_sr_info, &sr_list, node) {
>> +		if (srid == temp_sr_info->srid) {
>> +			sr_info = temp_sr_info;
>> +			break;
>> +		}
>> +	}
>> +	return sr_info;
>> +}
>> +
>>  static int sr_clk_enable(struct omap_sr *sr)
>>  {
>>  	if (clk_enable(sr->clk) != 0) {
>> @@ -151,11 +169,17 @@ static u8 get_vdd1_opp(void)
>>  {
>>  	struct omap_opp *opp;
>>  	unsigned long freq;
>> +	struct omap_sr *sr_info = _sr_lookup(SR1);
>>  -	if (sr1.vdd_opp_clk == NULL || IS_ERR(sr1.vdd_opp_clk))
>> +	if (!sr_info) {
>> +		pr_warning("omap_sr struct corresponding to SR1 not found\n");
>> +		return 0;
>> +	}
>> +
>> +	if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
>>  		return 0;
>>  -	freq = sr1.vdd_opp_clk->rate;
>> +	freq = sr_info->vdd_opp_clk->rate;
>>  	opp = opp_find_freq_ceil(OPP_MPU, &freq);
>>  	if (IS_ERR(opp))
>>  		return 0;
>> @@ -163,9 +187,9 @@ static u8 get_vdd1_opp(void)
>>  	 * Use higher freq voltage even if an exact match is not available
>>  	 * we are probably masking a clock framework bug, so warn
>>  	 */
>> -	if (unlikely(freq != sr1.vdd_opp_clk->rate))
>> +	if (unlikely(freq != sr_info->vdd_opp_clk->rate))
>>  		pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
>> -			   __func__, freq, sr1.vdd_opp_clk->rate);
>> +			   __func__, freq, sr_info->vdd_opp_clk->rate);
>>   	return opp_get_opp_id(opp);
>>  }
>> @@ -174,11 +198,17 @@ static u8 get_vdd2_opp(void)
>>  {
>>  	struct omap_opp *opp;
>>  	unsigned long freq;
>> +	struct omap_sr *sr_info = _sr_lookup(SR2);
>> +
>> +	if (!sr_info) {
>> +		pr_warning("omap_sr struct corresponding to SR2 not found\n");
>> +		return 0;
>> +	}
>>  -	if (sr2.vdd_opp_clk == NULL || IS_ERR(sr2.vdd_opp_clk))
>> +	if (sr_info->vdd_opp_clk == NULL || IS_ERR(sr_info->vdd_opp_clk))
>>  		return 0;
>>  -	freq = sr2.vdd_opp_clk->rate;
>> +	freq = sr_info->vdd_opp_clk->rate;
>>  	opp = opp_find_freq_ceil(OPP_L3, &freq);
>>  	if (IS_ERR(opp))
>>  		return 0;
>> @@ -187,9 +217,9 @@ static u8 get_vdd2_opp(void)
>>  	 * Use higher freq voltage even if an exact match is not available
>>  	 * we are probably masking a clock framework bug, so warn
>>  	 */
>> -	if (unlikely(freq != sr2.vdd_opp_clk->rate))
>> +	if (unlikely(freq != sr_info->vdd_opp_clk->rate))
>>  		pr_warning("%s: Available freq %ld != dpll freq %ld.\n",
>> -			   __func__, freq, sr2.vdd_opp_clk->rate);
>> +			   __func__, freq, sr_info->vdd_opp_clk->rate);
>>  	return opp_get_opp_id(opp);
>>  }
>>  @@ -694,14 +724,13 @@ static void sr_disable(struct omap_sr *sr)
>>   void sr_start_vddautocomap(int srid, u32 target_opp_no)
>>  {
>> -	struct omap_sr *sr = NULL;
>> +	struct omap_sr *sr = _sr_lookup(srid);
>>  -	if (srid == SR1)
>> -		sr = &sr1;
>> -	else if (srid == SR2)
>> -		sr = &sr2;
>> -	else
>> +	if (!sr) {
>> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
>> +								srid);
>>  		return;
>> +	}
>>   	if (sr->is_sr_reset == 1) {
>>  		sr_clk_enable(sr);
>> @@ -719,14 +748,13 @@ EXPORT_SYMBOL(sr_start_vddautocomap);
>>   int sr_stop_vddautocomap(int srid)
>>  {
>> -	struct omap_sr *sr = NULL;
>> +	struct omap_sr *sr = _sr_lookup(srid);
>>  -	if (srid == SR1)
>> -		sr = &sr1;
>> -	else if (srid == SR2)
>> -		sr = &sr2;
>> -	else
>> -		return -EINVAL;
>> +	if (!sr) {
>> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
>> +								srid);
>> +		return false;
>> +	}
>>   	if (sr->is_autocomp_active == 1) {
>>  		sr_disable(sr);
>> @@ -744,14 +772,13 @@ EXPORT_SYMBOL(sr_stop_vddautocomap);
>>  void enable_smartreflex(int srid)
>>  {
>>  	u32 target_opp_no = 0;
>> -	struct omap_sr *sr = NULL;
>> +	struct omap_sr *sr = _sr_lookup(srid);
>>  -	if (srid == SR1)
>> -		sr = &sr1;
>> -	else if (srid == SR2)
>> -		sr = &sr2;
>> -	else
>> +	if (!sr) {
>> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
>> +								srid);
>>  		return;
>> +	}
>>   	if (sr->is_autocomp_active == 1) {
>>  		if (sr->is_sr_reset == 1) {
>> @@ -779,15 +806,13 @@ void enable_smartreflex(int srid)
>>  void disable_smartreflex(int srid)
>>  {
>>  	u32 i = 0;
>> +	struct omap_sr *sr = _sr_lookup(srid);
>>  -	struct omap_sr *sr = NULL;
>> -
>> -	if (srid == SR1)
>> -		sr = &sr1;
>> -	else if (srid == SR2)
>> -		sr = &sr2;
>> -	else
>> +	if (!sr) {
>> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
>> +								srid);
>>  		return;
>> +	}
>>   	if (sr->is_autocomp_active == 1) {
>>  		if (sr->is_sr_reset == 0) {
>> @@ -920,7 +945,13 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
>>  static ssize_t omap_sr_vdd1_autocomp_show(struct kobject *kobj,
>>  					struct kobj_attribute *attr, char *buf)
>>  {
>> -	return sprintf(buf, "%d\n", sr1.is_autocomp_active);
>> +	struct omap_sr *sr_info = _sr_lookup(SR1);
>> +
>> +	if (!sr_info) {
>> +		pr_warning("omap_sr struct corresponding to SR1 not found\n");
>> +		return 0;
>> +	}
>> +	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
>>  }
>>   static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj,
>> @@ -960,7 +991,13 @@ static struct kobj_attribute sr_vdd1_autocomp = {
>>  static ssize_t omap_sr_vdd2_autocomp_show(struct kobject *kobj,
>>  					struct kobj_attribute *attr, char *buf)
>>  {
>> -	return sprintf(buf, "%d\n", sr2.is_autocomp_active);
>> +	struct omap_sr *sr_info = _sr_lookup(SR2);
>> +
>> +	if (!sr_info) {
>> +		pr_warning("omap_sr struct corresponding to SR2 not found\n");
>> +		return 0;
>> +	}
>> +	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
>>  }
>>   static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj,
>> @@ -1010,7 +1047,6 @@ static int __init omap3_sr_init(void)
>>  	RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
>>  	ret |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
>>  				R_DCDC_GLOBAL_CFG);
>> -
>>  	if (cpu_is_omap34xx()) {
>>  		sr1.clk = clk_get(NULL, "sr1_fck");
>>  		sr2.clk = clk_get(NULL, "sr2_fck");
>> @@ -1036,6 +1072,8 @@ static int __init omap3_sr_init(void)
>>  	ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
>>  	if (ret)
>>  		pr_err("sysfs_create_file failed: %d\n", ret);
>> +	list_add(&sr1.node, &sr_list);
>> +	list_add(&sr2.node, &sr_list);
>>  
> From scaling perspective for Next Gen Omap, I guess it would be better
> to add list through a loop and the info related to, no of sr's can be
> passed through SR platform structure?

This is handled by omap_hwmod + omap_device registration in PATCH 03/16.

Kevin

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

* Re: [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer
  2010-02-24  9:29     ` [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer Thara Gopinath
  2010-02-24  9:29       ` [PATCH 04/16] OMAP3: PM: Move smartreflex autocompensation enable disable hooks to PM debugfs Thara Gopinath
  2010-02-25  2:39       ` [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer ambresh
@ 2010-03-02 18:28       ` Kevin Hilman
  2010-03-05 14:26         ` Gopinath, Thara
  2010-03-12  9:48         ` Gopinath, Thara
  2010-03-03  0:02       ` Kevin Hilman
  3 siblings, 2 replies; 61+ messages in thread
From: Kevin Hilman @ 2010-03-02 18:28 UTC (permalink / raw)
  To: Thara Gopinath; +Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant

Thara Gopinath <thara@ti.com> writes:

> This patch converts the exisitng smartreflex library into a
> platform driver with device , driver registrations using hardware mods.
> As part of this Ntarget values are passed as platform data.
>
> Signed-off-by: Thara Gopinath <thara@ti.com>

Nice work Thara.  This is good.  Some minor comments below, but some
general comments first.

As discussed, eventually (longer term) we'll want to move the driver
parts of this to a regulator driver.  To ease that transition, I think
it would be nice to start now by separating the driver portions of
this file from the device portions.

You've already done a good job of keeping them separate in this file
(most of the device stuff is at the end) but I think having a separate
file is probably even better.  Maybe move driver stuff to sr_driver.c
and leave device stuff in smartreflex.c?  I don't care much about the
names at this point.

> ---
>  arch/arm/mach-omap2/smartreflex.c |  470 +++++++++++++++++++++----------------
>  arch/arm/mach-omap2/smartreflex.h |   27 ++
>  2 files changed, 293 insertions(+), 204 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
> index 4a9c2e2..05c72b2 100644
> --- a/arch/arm/mach-omap2/smartreflex.c
> +++ b/arch/arm/mach-omap2/smartreflex.c
> @@ -14,7 +14,6 @@
>   * published by the Free Software Foundation.
>   */
>  
> -
>  #include <linux/kernel.h>
>  #include <linux/init.h>
>  #include <linux/interrupt.h>
> @@ -33,6 +32,8 @@
>  #include <plat/clock.h>
>  #include <plat/opp.h>
>  #include <plat/opp_twl_tps.h>
> +#include <plat/omap_hwmod.h>
> +#include <plat/omap_device.h>
>  
>  #include "prm.h"
>  #include "smartreflex.h"
> @@ -41,17 +42,14 @@
>  #define MAX_TRIES 100
>  
>  struct omap_sr {
> -	int		srid;
> -	int		is_sr_reset;
> -	int		is_autocomp_active;
> -	struct clk	*clk;
> -	struct clk	*vdd_opp_clk;
> -	u32		clk_length;
> -	u32		req_opp_no;
> -	u32		opp1_nvalue, opp2_nvalue, opp3_nvalue, opp4_nvalue;
> -	u32		opp5_nvalue;
> -	u32		senp_mod, senn_mod;
> -	void __iomem	*srbase_addr;
> +	int			srid;
> +	int			is_sr_reset;
> +	int			is_autocomp_active;
> +	struct clk		*vdd_opp_clk;
> +	u32			clk_length;
> +	void __iomem		*srbase_addr;
> +	unsigned int		irq;
> +	struct platform_device 	*pdev;
>  	struct list_head 	node;
>  };
>  
> @@ -98,71 +96,22 @@ static struct omap_sr *_sr_lookup(int srid)
>  
>  static int sr_clk_enable(struct omap_sr *sr)
>  {
> -	if (clk_enable(sr->clk) != 0) {
> -		pr_err("Could not enable %s\n", sr->clk->name);
> -		return -1;
> -	}
> +	struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>  
> -	/* set fclk- active , iclk- idle */
> -	sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
> -		      SR_CLKACTIVITY_IOFF_FON);
> +	if (pdata->device_enable)
> +		pdata->device_enable(sr->pdev);
>  	return 0;
>  }
>  
>  static void sr_clk_disable(struct omap_sr *sr)
>  {
> -	/* set fclk, iclk- idle */
> -	sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
> -		      SR_CLKACTIVITY_IOFF_FOFF);
> -
> -	clk_disable(sr->clk);
> -	sr->is_sr_reset = 1;
> -}
> +	struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>  
> -static struct omap_sr sr1 = {
> -	.srid			= SR1,
> -	.is_sr_reset		= 1,
> -	.is_autocomp_active	= 0,
> -	.clk_length		= 0,
> -	.srbase_addr		= OMAP2_L4_IO_ADDRESS(OMAP34XX_SR1_BASE),
> -};
> -
> -static struct omap_sr sr2 = {
> -	.srid			= SR2,
> -	.is_sr_reset		= 1,
> -	.is_autocomp_active	= 0,
> -	.clk_length		= 0,
> -	.srbase_addr		= OMAP2_L4_IO_ADDRESS(OMAP34XX_SR2_BASE),
> -};
> +	if (pdata->device_idle)
> +		pdata->device_idle(sr->pdev);
>  
> -static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen)
> -{
> -	u32 gn, rn, mul;
> -
> -	for (gn = 0; gn < GAIN_MAXLIMIT; gn++) {
> -		mul = 1 << (gn + 8);
> -		rn = mul / sensor;
> -		if (rn < R_MAXLIMIT) {
> -			*sengain = gn;
> -			*rnsen = rn;
> -		}
> -	}
> -}
> -
> -static u32 cal_test_nvalue(u32 sennval, u32 senpval)
> -{
> -	u32 senpgain, senngain;
> -	u32 rnsenp, rnsenn;
> -
> -	/* Calculating the gain and reciprocal of the SenN and SenP values */
> -	cal_reciprocal(senpval, &senpgain, &rnsenp);
> -	cal_reciprocal(sennval, &senngain, &rnsenn);
> -
> -	return (senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |
> -		(senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |
> -		(rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |
> -		(rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT);
> +	sr->is_sr_reset = 1;
>  }
>  
>  static u8 get_vdd1_opp(void)
> @@ -255,76 +204,6 @@ static void sr_set_clk_length(struct omap_sr *sr)
>  	}
>  }
>  
> -static void sr_set_efuse_nvalues(struct omap_sr *sr)
> -{
> -	if (sr->srid == SR1) {
> -		sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> -					OMAP343X_SR1_SENNENABLE_MASK) >>
> -					OMAP343X_SR1_SENNENABLE_SHIFT;
> -		sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> -					OMAP343X_SR1_SENPENABLE_MASK) >>
> -					OMAP343X_SR1_SENPENABLE_SHIFT;
> -
> -		sr->opp5_nvalue = omap_ctrl_readl(
> -					OMAP343X_CONTROL_FUSE_OPP5_VDD1);
> -		sr->opp4_nvalue = omap_ctrl_readl(
> -					OMAP343X_CONTROL_FUSE_OPP4_VDD1);
> -		sr->opp3_nvalue = omap_ctrl_readl(
> -					OMAP343X_CONTROL_FUSE_OPP3_VDD1);
> -		sr->opp2_nvalue = omap_ctrl_readl(
> -					OMAP343X_CONTROL_FUSE_OPP2_VDD1);
> -		sr->opp1_nvalue = omap_ctrl_readl(
> -					OMAP343X_CONTROL_FUSE_OPP1_VDD1);
> -	} else if (sr->srid == SR2) {
> -		sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> -					OMAP343X_SR2_SENNENABLE_MASK) >>
> -					OMAP343X_SR2_SENNENABLE_SHIFT;
> -
> -		sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> -					OMAP343X_SR2_SENPENABLE_MASK) >>
> -					OMAP343X_SR2_SENPENABLE_SHIFT;
> -
> -		sr->opp3_nvalue = omap_ctrl_readl(
> -					OMAP343X_CONTROL_FUSE_OPP3_VDD2);
> -		sr->opp2_nvalue = omap_ctrl_readl(
> -					OMAP343X_CONTROL_FUSE_OPP2_VDD2);
> -		sr->opp1_nvalue = omap_ctrl_readl(
> -					OMAP343X_CONTROL_FUSE_OPP1_VDD2);
> -	}
> -}
> -
> -/* Hard coded nvalues for testing purposes, may cause device to hang! */
> -static void sr_set_testing_nvalues(struct omap_sr *sr)
> -{
> -	if (sr->srid == SR1) {
> -		sr->senp_mod = 0x03;	/* SenN-M5 enabled */
> -		sr->senn_mod = 0x03;
> -
> -		/* calculate nvalues for each opp */
> -		sr->opp5_nvalue = cal_test_nvalue(0xacd + 0x330, 0x848 + 0x330);
> -		sr->opp4_nvalue = cal_test_nvalue(0x964 + 0x2a0, 0x727 + 0x2a0);
> -		sr->opp3_nvalue = cal_test_nvalue(0x85b + 0x200, 0x655 + 0x200);
> -		sr->opp2_nvalue = cal_test_nvalue(0x506 + 0x1a0, 0x3be + 0x1a0);
> -		sr->opp1_nvalue = cal_test_nvalue(0x373 + 0x100, 0x28c + 0x100);
> -	} else if (sr->srid == SR2) {
> -		sr->senp_mod = 0x03;
> -		sr->senn_mod = 0x03;
> -
> -		sr->opp3_nvalue = cal_test_nvalue(0x76f + 0x200, 0x579 + 0x200);
> -		sr->opp2_nvalue = cal_test_nvalue(0x4f5 + 0x1c0, 0x390 + 0x1c0);
> -		sr->opp1_nvalue = cal_test_nvalue(0x359, 0x25d);
> -	}
> -
> -}
> -
> -static void sr_set_nvalues(struct omap_sr *sr)
> -{
> -	if (SR_TESTING_NVALUES)
> -		sr_set_testing_nvalues(sr);
> -	else
> -		sr_set_efuse_nvalues(sr);
> -}
> -
>  static void sr_configure_vp(int srid)
>  {
>  	u32 vpconfig;
> @@ -438,12 +317,13 @@ static void sr_configure(struct omap_sr *sr)
>  {
>  	u32 sr_config;
>  	u32 senp_en , senn_en;
> +	struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>  
>  	if (sr->clk_length == 0)
>  		sr_set_clk_length(sr);
>  
> -	senp_en = sr->senp_mod;
> -	senn_en = sr->senn_mod;
> +	senp_en = pdata->senp_mod;
> +	senn_en = pdata->senn_mod;
>  	if (sr->srid == SR1) {
>  		sr_config = SR1_SRCONFIG_ACCUMDATA |
>  			(sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
> @@ -571,57 +451,33 @@ static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
>  {
>  	u32 nvalue_reciprocal, v;
>  	struct omap_opp *opp;
> +	struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>  	int uvdc;
>  	char vsel;
>  
> -	sr->req_opp_no = target_opp_no;
> -
>  	if (sr->srid == SR1) {
> -		switch (target_opp_no) {
> -		case 5:
> -			nvalue_reciprocal = sr->opp5_nvalue;
> -			break;
> -		case 4:
> -			nvalue_reciprocal = sr->opp4_nvalue;
> -			break;
> -		case 3:
> -			nvalue_reciprocal = sr->opp3_nvalue;
> -			break;
> -		case 2:
> -			nvalue_reciprocal = sr->opp2_nvalue;
> -			break;
> -		case 1:
> -			nvalue_reciprocal = sr->opp1_nvalue;
> -			break;
> -		default:
> -			nvalue_reciprocal = sr->opp3_nvalue;
> -			break;
> -		}
> -
>  		opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
>  		if (!opp)
>  			return false;
>  	} else {
> -		switch (target_opp_no) {
> -		case 3:
> -			nvalue_reciprocal = sr->opp3_nvalue;
> -			break;
> -		case 2:
> -			nvalue_reciprocal = sr->opp2_nvalue;
> -			break;
> -		case 1:
> -			nvalue_reciprocal = sr->opp1_nvalue;
> -			break;
> -		default:
> -			nvalue_reciprocal = sr->opp3_nvalue;
> -			break;
> -		}
> -
>  		opp = opp_find_by_opp_id(OPP_L3, target_opp_no);
>  		if (!opp)
>  			return false;
>  	}
>  
> +	if (target_opp_no > pdata->no_opp) {
> +		pr_notice("Wrong target opp\n");
> +		return false;
> +	}
> +
> +	if (!pdata->sr_nvalue) {
> +		pr_notice("N target values does not exist for SR%d\n",
> +								sr->srid);
> +		return false;
> +	}
> +
> +	nvalue_reciprocal = pdata->sr_nvalue[target_opp_no - 1];
> +
>  	if (nvalue_reciprocal == 0) {
>  		pr_notice("OPP%d doesn't support SmartReflex\n",
>  								target_opp_no);
> @@ -1033,49 +889,255 @@ static struct kobj_attribute sr_vdd2_autocomp = {
>  	.store = omap_sr_vdd2_autocomp_store,
>  };
>  
> +static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
> +{
> +	struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
> +	struct omap_device *odev = to_omap_device(pdev);
> +	int ret = 0;
> +
> +	if (WARN_ON(!sr_info))
> +		return -ENOMEM;
> +	sr_info->pdev = pdev;
> +	sr_info->srid = pdev->id + 1;
> +	sr_info->is_sr_reset = 1,
> +	sr_info->is_autocomp_active = 0;
> +	sr_info->clk_length = 0;
> +	sr_info->srbase_addr = odev->hwmods[0]->_rt_va;

Minor issue: srbase_addr shouln't be needed.  You could convert all
the sr_read/write_reg to use omap_hwmod_[read|write].

> +	if (odev->hwmods[0]->mpu_irqs)
> +		sr_info->irq = odev->hwmods[0]->mpu_irqs[0].irq;
> +	sr_set_clk_length(sr_info);
> +
> +	if (sr_info->srid == SR1) {
> +		sr_info->vdd_opp_clk = clk_get(NULL, "dpll1_ck");
> +		ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
> +		if (ret)
> +			pr_err("sysfs_create_file failed: %d\n", ret);
> +	} else {
> +		sr_info->vdd_opp_clk = clk_get(NULL, "l3_ick");
> +		ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
> +		if (ret)
> +			pr_err("sysfs_create_file failed: %d\n", ret);
> +	}
> +
> +	/* Call the VPConfig */
> +	sr_configure_vp(sr_info->srid);
> +	odev->hwmods[0]->dev_attr = sr_info;
> +	list_add(&sr_info->node, &sr_list);
> +	pr_info("SmartReflex driver initialized\n");
> +
> +	return ret;
> +}
> +
> +static int __devexit omap_smartreflex_remove(struct platform_device *pdev)
> +{
> +	struct omap_device *odev = to_omap_device(pdev);
> +	struct omap_sr *sr_info = odev->hwmods[0]->dev_attr;
> +
> +	/* Disable Autocompensation if enabled before removing the module */
> +	if (sr_info->is_autocomp_active == 1)
> +		sr_stop_vddautocomap(sr_info->srid);
> +	list_del(&sr_info->node);

should free sr_info too

> +	return 0;
> +}
>  
> +static struct platform_driver smartreflex_driver = {
> +	.probe          = omap_smartreflex_probe,
> +	.remove         = omap_smartreflex_remove,
> +	.driver		= {
> +		.name	= "smartreflex",
> +	},
> +};
>  
> -static int __init omap3_sr_init(void)
> +static int __init sr_init(void)
>  {
>  	int ret = 0;
>  	u8 RdReg;
>  
> +	/* TODO: Find an appropriate place for this */
>  	/* Enable SR on T2 */
>  	ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &RdReg,
>  			      R_DCDC_GLOBAL_CFG);
> -
>  	RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
>  	ret |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
>  				R_DCDC_GLOBAL_CFG);
> -	if (cpu_is_omap34xx()) {
> -		sr1.clk = clk_get(NULL, "sr1_fck");
> -		sr2.clk = clk_get(NULL, "sr2_fck");
> -	}
> -	sr1.vdd_opp_clk = clk_get(NULL, "dpll1_ck");
> -	sr2.vdd_opp_clk = clk_get(NULL, "l3_ick");
> -	sr_set_clk_length(&sr1);
> -	sr_set_clk_length(&sr2);
>  
> -	/* Call the VPConfig, VCConfig, set N Values. */
> -	sr_set_nvalues(&sr1);
> -	sr_configure_vp(SR1);
> +	ret = platform_driver_probe(&smartreflex_driver,
> +				omap_smartreflex_probe);
>  
> -	sr_set_nvalues(&sr2);
> -	sr_configure_vp(SR2);
> +	if (ret)
> +		pr_err("platform driver register failed for smartreflex");
> +	return 0;
> +}
>  
> -	pr_info("SmartReflex driver initialized\n");
> +void __exit sr_exit(void)
> +{
> +	platform_driver_unregister(&smartreflex_driver);
> +}
> +late_initcall(sr_init);
> +module_exit(sr_exit);
>  
> -	ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
> -	if (ret)
> -		pr_err("sysfs_create_file failed: %d\n", ret);
> +MODULE_DESCRIPTION("OMAP SMARTREFLEX DRIVER");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:" DRIVER_NAME);
> +MODULE_AUTHOR("Texas Instruments Inc");
>  
> -	ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
> -	if (ret)
> -		pr_err("sysfs_create_file failed: %d\n", ret);
> -	list_add(&sr1.node, &sr_list);
> -	list_add(&sr2.node, &sr_list);
> +/* Device registrations for smartreflex instances */
>  
> -	return 0;
> +#define MAX_HWMOD_NAME_LEN	16
> +
> +struct omap_device_pm_latency omap_sr_latency[] = {
> +	{
> +		.deactivate_func = omap_device_idle_hwmods,
> +		.activate_func	 = omap_device_enable_hwmods,
> +		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST
> +	},
> +};
> +
> +/* Read EFUSE values from control registers */
> +static void __init omap3_sr_read_efuse(struct omap_smartreflex_data *sr_data,
> +						int sr_id)
> +{
> +	if (sr_id == SR1) {
> +		/*
> +		 * TODO: When opp framework come into picture use appropriate
> +		 * API's to find out number of opp's.
> +		 */
> +		sr_data->no_opp = 5;

This already exists. See opp_get_opp_count(OPP_MPU)

> +		sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
> +					sr_data->no_opp , GFP_KERNEL);
> +		if (WARN_ON(!sr_data->sr_nvalue))
> +			return;
> +
> +		sr_data->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> +					OMAP343X_SR1_SENNENABLE_MASK) >>
> +					OMAP343X_SR1_SENNENABLE_SHIFT;
> +		sr_data->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> +					OMAP343X_SR1_SENPENABLE_MASK) >>
> +					OMAP343X_SR1_SENPENABLE_SHIFT;
> +		sr_data->sr_nvalue[4] = omap_ctrl_readl(
> +					OMAP343X_CONTROL_FUSE_OPP5_VDD1);
> +		sr_data->sr_nvalue[3] = omap_ctrl_readl(
> +					OMAP343X_CONTROL_FUSE_OPP4_VDD1);
> +		sr_data->sr_nvalue[2] = omap_ctrl_readl(
> +					OMAP343X_CONTROL_FUSE_OPP3_VDD1);
> +		sr_data->sr_nvalue[1] = omap_ctrl_readl(
> +					OMAP343X_CONTROL_FUSE_OPP2_VDD1);
> +		sr_data->sr_nvalue[0] = omap_ctrl_readl(
> +					OMAP343X_CONTROL_FUSE_OPP1_VDD1);
> +	} else if (sr_id == SR2) {
> +		/*
> +		 * TODO: When opp framework come into picture use appropriate
> +		 * API's to find out number of opp's.
> +		 */
> +		sr_data->no_opp = 3;

ditto:  opp_get_opp_count(OPP_L3)

> +		sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
> +					sr_data->no_opp , GFP_KERNEL);
> +		if (WARN_ON(!sr_data->sr_nvalue))
> +			return;
> +
> +		sr_data->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> +					OMAP343X_SR2_SENNENABLE_MASK) >>
> +					OMAP343X_SR2_SENNENABLE_SHIFT;
> +		sr_data->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> +					OMAP343X_SR2_SENPENABLE_MASK) >>
> +					OMAP343X_SR2_SENPENABLE_SHIFT;
> +		sr_data->sr_nvalue[2] = omap_ctrl_readl(
> +					OMAP343X_CONTROL_FUSE_OPP3_VDD2);
> +		sr_data->sr_nvalue[1] = omap_ctrl_readl(
> +					OMAP343X_CONTROL_FUSE_OPP2_VDD2);
> +		sr_data->sr_nvalue[0] = omap_ctrl_readl(
> +					OMAP343X_CONTROL_FUSE_OPP1_VDD2);
> +	}
>  }
>  
> -late_initcall(omap3_sr_init);
> +/* Hard coded nvalues for testing purposes, may cause device to hang! */
> +static void __init omap3_sr_set_testing_nvalues(
> +				struct omap_smartreflex_data *sr_data, int srid)
> +{
> +	if (srid == SR1) {
> +		/*
> +		 * TODO: When opp framework come into picture use appropriate
> +		 * API's to find out number of opp's.

> +		 */
> +		sr_data->no_opp = 5;
> +		sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
> +				sr_data->no_opp , GFP_KERNEL);
> +		if (WARN_ON(!sr_data->sr_nvalue))
> +			return;
> +
> +		sr_data->senp_mod = 0x03;	/* SenN-M5 enabled */
> +		sr_data->senn_mod = 0x03;
> +		/* calculate nvalues for each opp */
> +		sr_data->sr_nvalue[4] = 0x0;
> +		sr_data->sr_nvalue[3] = 0x0;
> +		sr_data->sr_nvalue[2] = 0x0;
> +		sr_data->sr_nvalue[1] = 0x0;
> +		sr_data->sr_nvalue[0] = 0x0;
> +	} else if (srid == SR2) {
> +		/*
> +		 * TODO: When opp framework come into picture use appropriate
> +		 * API's to find out number of opp's.
> +		 */
> +		sr_data->no_opp = 3;
> +		sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
> +					sr_data->no_opp , GFP_KERNEL);
> +		if (WARN_ON(!sr_data->sr_nvalue))
> +			return;
> +
> +		sr_data->senp_mod = 0x03;	/* SenN-M5 enabled */
> +		sr_data->senn_mod = 0x03;
> +		sr_data->sr_nvalue[2] = 0x0;
> +		sr_data->sr_nvalue[1] = 0x0;
> +		sr_data->sr_nvalue[0] = 0x0;
> +	}
> +}

Hmm, you set all the testing nvalues to zero.  Is there a reason you
didn't keep the previous ones?  I don't really remember where those
came from, so not sure if they are useful or not.  I'll let you
decide, but if you remove them, update the changelog accordingly so
there are no surprises.

Kevin

> +static void __init sr_set_nvalues(struct omap_smartreflex_data
> +*sr_data, int srid) { if (cpu_is_omap343x()) { if
> +(SR_TESTING_NVALUES) omap3_sr_set_testing_nvalues(sr_data, srid);
> +else omap3_sr_read_efuse(sr_data, srid);
> +	}
> +}
> +
> +static int __init omap_devinit_smartreflex(void)
> +{
> +	int i = 0;
> +	char *name = "smartreflex";
> +
> +	do {
> +		struct omap_smartreflex_data *sr_data;
> +		struct omap_device *od;
> +		struct omap_hwmod *oh;
> +		char oh_name[MAX_HWMOD_NAME_LEN];
> +
> +		snprintf(oh_name, MAX_HWMOD_NAME_LEN, "sr%d_hwmod", i + 1);
> +		oh = omap_hwmod_lookup(oh_name);
> +		if (!oh)
> +			break;
> +
> +		sr_data = kzalloc(sizeof(struct omap_smartreflex_data),
> +								GFP_KERNEL);
> +		if (WARN_ON(!sr_data))
> +			return -ENOMEM;
> +
> +		sr_data->init_enable = false;
> +		sr_data->device_enable = omap_device_enable;
> +		sr_data->device_shutdown = omap_device_shutdown;
> +		sr_data->device_idle = omap_device_idle;
> +		sr_set_nvalues(sr_data, i + 1);
> +
> +		od = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
> +				       omap_sr_latency,
> +				       ARRAY_SIZE(omap_sr_latency));
> +		WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
> +		     name, oh->name);
> +		i++;
> +	} while (1);
> +
> +	return 0;
> +}
> +arch_initcall(omap_devinit_smartreflex);
> diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
> index 2a0e823..f1e8676 100644
> --- a/arch/arm/mach-omap2/smartreflex.h
> +++ b/arch/arm/mach-omap2/smartreflex.h
> @@ -14,6 +14,8 @@
>   * published by the Free Software Foundation.
>   */
>  
> +#include <linux/platform_device.h>
> +
>  #define PHY_TO_OFF_PM_MASTER(p)		(p - 0x36)
>  #define PHY_TO_OFF_PM_RECIEVER(p)	(p - 0x5b)
>  #define PHY_TO_OFF_PM_INT(p)		(p - 0x2e)
> @@ -243,6 +245,31 @@ extern u32 current_vdd2_opp;
>   * do anything.
>   */
>  #ifdef CONFIG_OMAP_SMARTREFLEX
> +/*
> + * omap_smartreflex_data - Smartreflex platform data
> + *
> + * @senp_mod	: SENPENABLE value for the sr
> + * @senn_mod	: SENNENABLE value for sr
> + * @sr_nvalue	: array of n target values for sr
> + * @no_opp	: number of opp's for this SR
> + * @init_enable	: whether this sr module needs to enabled at boot up or not
> + * @device_enable	: fn pointer to be populated with omap_device
> + * 			enable API
> + * @device_shutdown	: fn pointer to be populated with omap_device
> + * 			shutdown API
> + * @device_idle		: fn pointer to be pouplated with omap_device idle API
> + */
> +struct omap_smartreflex_data {
> +	u32		senp_mod;
> +	u32		senn_mod;
> +	u32		*sr_nvalue;
> +	int		no_opp;
> +	bool		init_enable;
> +	int (*device_enable)(struct platform_device *pdev);
> +	int (*device_shutdown)(struct platform_device *pdev);
> +	int (*device_idle)(struct platform_device *pdev);
> +};
> +
>  void enable_smartreflex(int srid);
>  void disable_smartreflex(int srid);
>  int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel);
> -- 
> 1.7.0.rc1.33.g07cf0f

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

* Re: [PATCH 04/16] OMAP3: PM: Move smartreflex autocompensation enable disable hooks to PM debugfs.
  2010-02-24  9:29       ` [PATCH 04/16] OMAP3: PM: Move smartreflex autocompensation enable disable hooks to PM debugfs Thara Gopinath
  2010-02-24  9:29         ` [PATCH 05/16] OMAP3: PM: Export get_vdd1_opp and get_vdd2_opp from shared resource framework Thara Gopinath
@ 2010-03-02 18:28         ` Kevin Hilman
  1 sibling, 0 replies; 61+ messages in thread
From: Kevin Hilman @ 2010-03-02 18:28 UTC (permalink / raw)
  To: Thara Gopinath; +Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant

Thara Gopinath <thara@ti.com> writes:

> This patch moves the hooks to enable disable smartreflex
> autocompensation to pm debugfs from the /sys/power/.
>
> To enable autocompensation for smartreflex SR<n> do
>         echo 1 > <path>/pm_debug/sr<n>_autocomp
> To disable autocompensation for smartreflex SR<n> do
>         echo 0 > <path>/pm_debug/sr<n>_autocomp
>
> Signed-off-by: Thara Gopinath <thara@ti.com>

Looks good.

Kevin

> ---
>  arch/arm/mach-omap2/pm-debug.c    |    4 +-
>  arch/arm/mach-omap2/smartreflex.c |  114 ++++++++++--------------------------
>  arch/arm/mach-omap2/smartreflex.h |    2 +
>  3 files changed, 36 insertions(+), 84 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
> index ec76f3b..7931bad 100644
> --- a/arch/arm/mach-omap2/pm-debug.c
> +++ b/arch/arm/mach-omap2/pm-debug.c
> @@ -162,7 +162,7 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
>  
>  static void pm_dbg_regset_store(u32 *ptr);
>  
> -struct dentry *pm_dbg_dir;
> +struct dentry *pm_dbg_dir, *pm_dbg_main_dir;
>  
>  static int pm_dbg_init_done;
>  
> @@ -608,7 +608,7 @@ static int __init pm_dbg_init(void)
>  					   S_IRUGO | S_IWUGO, d,
>  					   &voltage_off_while_idle,
>  					   &pm_dbg_option_fops);
> -
> +	pm_dbg_main_dir = d;
>  	pm_dbg_init_done = 1;
>  
>  	return 0;
> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
> index 05c72b2..db2e9bf 100644
> --- a/arch/arm/mach-omap2/smartreflex.c
> +++ b/arch/arm/mach-omap2/smartreflex.c
> @@ -21,11 +21,11 @@
>  #include <linux/delay.h>
>  #include <linux/err.h>
>  #include <linux/clk.h>
> -#include <linux/sysfs.h>
>  #include <linux/kobject.h>
>  #include <linux/i2c/twl.h>
>  #include <linux/io.h>
>  #include <linux/list.h>
> +#include <linux/debugfs.h>
>  
>  #include <plat/omap34xx.h>
>  #include <plat/control.h>
> @@ -40,6 +40,7 @@
>  #include "prm-regbits-34xx.h"
>  
>  #define MAX_TRIES 100
> +#define SMARTREFLEX_NAME_LEN	16
>  
>  struct omap_sr {
>  	int			srid;
> @@ -797,103 +798,53 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
>  	return 0;
>  }
>  
> -/* Sysfs interface to select SR VDD1 auto compensation */
> -static ssize_t omap_sr_vdd1_autocomp_show(struct kobject *kobj,
> -					struct kobj_attribute *attr, char *buf)
> +/* PM Debug Fs enteries to enable disable smartreflex.*/
> +
> +static int omap_sr_autocomp_show(void *data, u64 *val)
>  {
> -	struct omap_sr *sr_info = _sr_lookup(SR1);
> +	struct omap_sr *sr_info = (struct omap_sr *) data;
>  
>  	if (!sr_info) {
> -		pr_warning("omap_sr struct corresponding to SR1 not found\n");
> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> +							sr_info->srid);
>  		return 0;
>  	}
> -	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
> -}
> -
> -static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj,
> -					struct kobj_attribute *attr,
> -					const char *buf, size_t n)
> -{
> -	unsigned short value;
> -
> -	if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
> -		pr_err("sr_vdd1_autocomp: Invalid value\n");
> -		return -EINVAL;
> -	}
> -
> -	if (value == 0) {
> -		sr_stop_vddautocomap(SR1);
> -	} else {
> -		u32 current_vdd1opp_no = get_vdd1_opp();
> -		if (!current_vdd1opp_no) {
> -			pr_err("sr_vdd1_autocomp: Current VDD1 opp unknown\n");
> -			return -EINVAL;
> -		}
> -		sr_start_vddautocomap(SR1, current_vdd1opp_no);
> -	}
> -	return n;
> +	*val = sr_info->is_autocomp_active;
> +	return 0;
>  }
>  
> -static struct kobj_attribute sr_vdd1_autocomp = {
> -	.attr = {
> -	.name = __stringify(sr_vdd1_autocomp),
> -	.mode = 0644,
> -	},
> -	.show = omap_sr_vdd1_autocomp_show,
> -	.store = omap_sr_vdd1_autocomp_store,
> -};
> -
> -/* Sysfs interface to select SR VDD2 auto compensation */
> -static ssize_t omap_sr_vdd2_autocomp_show(struct kobject *kobj,
> -					struct kobj_attribute *attr, char *buf)
> +static int omap_sr_autocomp_store(void *data, u64 val)
>  {
> -	struct omap_sr *sr_info = _sr_lookup(SR2);
> +	struct omap_sr *sr_info = (struct omap_sr *) data;
>  
>  	if (!sr_info) {
> -		pr_warning("omap_sr struct corresponding to SR2 not found\n");
> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> +							sr_info->srid);
>  		return 0;
>  	}
> -	return sprintf(buf, "%d\n", sr_info->is_autocomp_active);
> -}
> -
> -static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj,
> -					struct kobj_attribute *attr,
> -					const char *buf, size_t n)
> -{
> -	unsigned short value;
> -
> -	if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
> -		pr_err("sr_vdd2_autocomp: Invalid value\n");
> -		return -EINVAL;
> -	}
> -
> -	if (value == 0) {
> -		sr_stop_vddautocomap(SR2);
> +	if (val == 0) {
> +		sr_stop_vddautocomap(sr_info->srid);
>  	} else {
> -		u32 current_vdd2opp_no = get_vdd2_opp();
> -		if (!current_vdd2opp_no) {
> -			pr_err("sr_vdd2_autocomp: Current VDD2 opp unknown\n");
> -			return -EINVAL;
> -		}
> -		sr_start_vddautocomap(SR2, current_vdd2opp_no);
> +		u32 current_opp;
> +
> +		if (sr_info->srid == SR1)
> +			current_opp = get_vdd1_opp();
> +		else
> +			current_opp = get_vdd2_opp();
> +		sr_start_vddautocomap(sr_info->srid, current_opp);
>  	}
> -	return n;
> +	return 0;
>  }
>  
> -static struct kobj_attribute sr_vdd2_autocomp = {
> -	.attr = {
> -	.name = __stringify(sr_vdd2_autocomp),
> -	.mode = 0644,
> -	},
> -	.show = omap_sr_vdd2_autocomp_show,
> -	.store = omap_sr_vdd2_autocomp_store,
> -};
> +DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
> +		omap_sr_autocomp_store, "%llu\n");
>  
>  static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
>  {
>  	struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
>  	struct omap_device *odev = to_omap_device(pdev);
>  	int ret = 0;
> +	char name[SMARTREFLEX_NAME_LEN];
>  
>  	if (WARN_ON(!sr_info))
>  		return -ENOMEM;
> @@ -909,16 +860,15 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
>  
>  	if (sr_info->srid == SR1) {
>  		sr_info->vdd_opp_clk = clk_get(NULL, "dpll1_ck");
> -		ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
> -		if (ret)
> -			pr_err("sysfs_create_file failed: %d\n", ret);
>  	} else {
>  		sr_info->vdd_opp_clk = clk_get(NULL, "l3_ick");
> -		ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
> -		if (ret)
> -			pr_err("sysfs_create_file failed: %d\n", ret);
>  	}
>  
> +	/* Create the debug fs enteries */
> +	sprintf(name, "sr%d_autocomp", sr_info->srid);
> +	(void) debugfs_create_file(name, S_IRUGO | S_IWUGO, pm_dbg_main_dir,
> +				(void *)sr_info, &pm_sr_fops);
> +
>  	/* Call the VPConfig */
>  	sr_configure_vp(sr_info->srid);
>  	odev->hwmods[0]->dev_attr = sr_info;
> diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
> index f1e8676..20fc128 100644
> --- a/arch/arm/mach-omap2/smartreflex.h
> +++ b/arch/arm/mach-omap2/smartreflex.h
> @@ -16,6 +16,8 @@
>  
>  #include <linux/platform_device.h>
>  
> +extern struct dentry *pm_dbg_main_dir;
> +
>  #define PHY_TO_OFF_PM_MASTER(p)		(p - 0x36)
>  #define PHY_TO_OFF_PM_RECIEVER(p)	(p - 0x5b)
>  #define PHY_TO_OFF_PM_INT(p)		(p - 0x2e)
> -- 
> 1.7.0.rc1.33.g07cf0f

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

* Re: [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c
  2010-02-24  9:29           ` [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c Thara Gopinath
  2010-02-24  9:29             ` [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver Thara Gopinath
@ 2010-03-02 18:44             ` Kevin Hilman
  2010-03-05 15:00               ` Gopinath, Thara
  2010-03-02 23:37             ` Kevin Hilman
  2010-03-02 23:52             ` Kevin Hilman
  3 siblings, 1 reply; 61+ messages in thread
From: Kevin Hilman @ 2010-03-02 18:44 UTC (permalink / raw)
  To: Thara Gopinath; +Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant

Thara Gopinath <thara@ti.com> writes:

> OMAP3 smartreflex modules are capable of two different classes
> of implementaion -
> 	Class-2: Continuous Software Calibration
> 	Class-3: Continuous Hardware Calibration.
> OMAP3 along with T2/Gaia supports the Class 3 implementaion.
> With a different PMIC it can support Class 2 implementaion also.
>
> The idea behind this patch is that smartreflex.c should be able
> to support both the classes of Smartreflex and the class specific
> details for smartreflex should stay out of this file in a separate
> class file.
> This patch introduces smartreflex class specific hooks in
> smartreflex.c. This patch only takes care of smartreflex enable
> disable hooks which differ between Class 2 and Class 3. There
> are some register setting changes between both the classes which
> will be taken care of in a later patch.
> This will form the base for adding class specific
> drivers in later patches.
>
> Signed-off-by: Thara Gopinath <thara@ti.com>

Minor nit: the name change for omap_smartreflex_[enable|disable] is
unrelated to this change and should be a separate patch to go early in
the series.

Kevin

> ---
>  arch/arm/mach-omap2/pm34xx.c      |    8 +-
>  arch/arm/mach-omap2/smartreflex.c |  251 ++++++++++++++++++++----------------
>  arch/arm/mach-omap2/smartreflex.h |   48 ++++++--
>  3 files changed, 182 insertions(+), 125 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index cf9ca23..ece5195 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -430,9 +430,9 @@ void omap_sram_idle(void)
>  	 * Only needed if we are going to enter retention or off.
>  	 */
>  	if (mpu_next_state <= PWRDM_POWER_RET)
> -		disable_smartreflex(SR1);
> +		omap_smartreflex_disable(SR1);
>  	if (core_next_state <= PWRDM_POWER_RET)
> -		disable_smartreflex(SR2);
> +		omap_smartreflex_disable(SR2);
>  
>  	/* CORE */
>  	if (core_next_state < PWRDM_POWER_ON) {
> @@ -531,9 +531,9 @@ void omap_sram_idle(void)
>  	 * retention or off
>  	 */
>  	if (mpu_next_state <= PWRDM_POWER_RET)
> -		enable_smartreflex(SR1);
> +		omap_smartreflex_enable(SR1);
>  	if (core_next_state <= PWRDM_POWER_RET)
> -		enable_smartreflex(SR2);
> +		omap_smartreflex_enable(SR2);
>  
>  	/* PER */
>  	if (per_next_state < PWRDM_POWER_ON) {
> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
> index c00925d..ba9f899 100644
> --- a/arch/arm/mach-omap2/smartreflex.c
> +++ b/arch/arm/mach-omap2/smartreflex.c
> @@ -55,6 +55,7 @@ struct omap_sr {
>  
>  /* sr_list contains all the instances of smartreflex module */
>  static LIST_HEAD(sr_list);
> +static struct omap_smartreflex_class_data *sr_class;
>  
>  #define SR_REGADDR(offs)	(sr->srbase_addr + offset)
>  
> @@ -388,14 +389,86 @@ static int sr_reset_voltage(int srid)
>  	return 0;
>  }
>  
> -static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
> +static void sr_start_vddautocomap(int srid)
> +{
> +	struct omap_sr *sr = _sr_lookup(srid);
> +
> +	if (!sr) {
> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> +								srid);
> +		return;
> +	}
> +
> +	if (!sr_class || !(sr_class->enable)) {
> +		pr_warning("smartreflex class driver not registered\n");
> +		return;
> +	}
> +
> +	if (sr->is_sr_reset == 1) {
> +		sr_clk_enable(sr);
> +		sr_configure(sr);
> +	}
> +
> +	sr->is_autocomp_active = 1;
> +	if (!sr_class->enable(srid)) {
> +		sr->is_autocomp_active = 0;
> +		if (sr->is_sr_reset == 1)
> +			sr_clk_disable(sr);
> +	}
> +}
> +
> +static void sr_stop_vddautocomap(int srid)
> +{
> +	struct omap_sr *sr = _sr_lookup(srid);
> +
> +	if (!sr) {
> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> +								srid);
> +		return;
> +	}
> +	if (!sr_class || !(sr_class->disable)) {
> +		pr_warning("smartreflex class driver not registered\n");
> +		return;
> +	}
> +
> +	if (sr->is_autocomp_active == 1) {
> +		sr_class->disable(srid);
> +		sr_clk_disable(sr);
> +		sr->is_autocomp_active = 0;
> +		/* Reset the volatage for current OPP */
> +		sr_reset_voltage(srid);
> +	}
> +
> +}
> +
> +/* Public Functions */
> +
> +/**
> + * sr_enable : Enables the smartreflex module.
> + * @srid - The id of the sr module to be enabled.
> + * @target_opp_no - The OPP at which the Voltage domain associated with
> + * the smartreflex module is operating at. This is required only to program
> + * the correct Ntarget value.
> + *
> + * This API is to be called from the smartreflex class driver to
> + * enable a smartreflex module. Returns true on success.Returns false if the
> + * target opp id passed is wrong or if ntarget value is wrong.
> + */
> +int sr_enable(int srid, u32 target_opp_no)
>  {
>  	u32 nvalue_reciprocal, v;
> +	struct omap_sr *sr = _sr_lookup(srid);
>  	struct omap_opp *opp;
>  	struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>  	int uvdc;
>  	char vsel;
>  
> +	if (!sr) {
> +		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> +								srid);
> +		return false;
> +	}
> +
>  	if (sr->srid == SR1) {
>  		opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
>  		if (!opp)
> @@ -477,8 +550,16 @@ static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
>  	return true;
>  }
>  
> -static void sr_disable(struct omap_sr *sr)
> +/**
> + * sr_disable : Disables the smartreflex module.
> + * @srid - The id of the sr module to be disabled.
> + *
> + * This API is to be called from the smartreflex class driver to
> + * disable a smartreflex module.
> + */
> +void sr_disable(int srid)
>  {
> +	struct omap_sr *sr = _sr_lookup(srid);
>  	u32 i = 0;
>  
>  	sr->is_sr_reset = 1;
> @@ -518,9 +599,19 @@ static void sr_disable(struct omap_sr *sr)
>  	}
>  }
>  
> -
> -void sr_start_vddautocomap(int srid, u32 target_opp_no)
> +/**
> + * omap_smartreflex_enable : API to enable SR clocks and to call into the
> + * registered smartreflex class enable API.
> + * @srid - The id of the sr module to be enabled.
> + *
> + * This API is to be called from the kernel in order to enable
> + * a particular smartreflex module. This API will do the initial
> + * configurations to turn on the smartreflex module and in turn call
> + * into the registered smartreflex class enable API.
> + */
> +void omap_smartreflex_enable(int srid)
>  {
> +	u32 target_opp_no = 0;
>  	struct omap_sr *sr = _sr_lookup(srid);
>  
>  	if (!sr) {
> @@ -528,52 +619,8 @@ void sr_start_vddautocomap(int srid, u32 target_opp_no)
>  								srid);
>  		return;
>  	}
> -
> -	if (sr->is_sr_reset == 1) {
> -		sr_clk_enable(sr);
> -		sr_configure(sr);
> -	}
> -
> -	sr->is_autocomp_active = 1;
> -	if (!sr_enable(sr, target_opp_no)) {
> -		sr->is_autocomp_active = 0;
> -		if (sr->is_sr_reset == 1)
> -			sr_clk_disable(sr);
> -	}
> -}
> -EXPORT_SYMBOL(sr_start_vddautocomap);
> -
> -int sr_stop_vddautocomap(int srid)
> -{
> -	struct omap_sr *sr = _sr_lookup(srid);
> -
> -	if (!sr) {
> -		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> -								srid);
> -		return false;
> -	}
> -
> -	if (sr->is_autocomp_active == 1) {
> -		sr_disable(sr);
> -		sr_clk_disable(sr);
> -		sr->is_autocomp_active = 0;
> -		/* Reset the volatage for current OPP */
> -		sr_reset_voltage(srid);
> -		return true;
> -	} else
> -		return false;
> -
> -}
> -EXPORT_SYMBOL(sr_stop_vddautocomap);
> -
> -void enable_smartreflex(int srid)
> -{
> -	u32 target_opp_no = 0;
> -	struct omap_sr *sr = _sr_lookup(srid);
> -
> -	if (!sr) {
> -		pr_warning("omap_sr struct corresponding to SR%d not found\n",
> -								srid);
> +	if (!sr_class || !(sr_class->enable)) {
> +		pr_warning("smartreflex class driver not registered\n");
>  		return;
>  	}
>  
> @@ -581,26 +628,24 @@ void enable_smartreflex(int srid)
>  		if (sr->is_sr_reset == 1) {
>  			/* Enable SR clks */
>  			sr_clk_enable(sr);
> -
> -			if (srid == SR1)
> -				target_opp_no = get_vdd1_opp();
> -			else if (srid == SR2)
> -				target_opp_no = get_vdd2_opp();
> -
> -			if (!target_opp_no) {
> -				pr_info("Current OPP unknown \
> -						 Cannot configure SR\n");
> -			}
> -
>  			sr_configure(sr);
>  
> -			if (!sr_enable(sr, target_opp_no))
> +			if (!sr_class->enable(srid))
>  				sr_clk_disable(sr);
>  		}
>  	}
>  }
>  
> -void disable_smartreflex(int srid)
> +/**
> + * omap_smartreflex_disable : API to disable SR clocks and to call into the
> + * registered smartreflex class disable API.
> + * @srid - The id of the sr module to be disabled.
> + *
> + * This API is to be called from the kernel in order to disable
> + * a particular smartreflex module. This API will in turn call
> + * into the registered smartreflex class disable API.
> + */
> +void omap_smartreflex_disable(int srid)
>  {
>  	u32 i = 0;
>  	struct omap_sr *sr = _sr_lookup(srid);
> @@ -610,54 +655,43 @@ void disable_smartreflex(int srid)
>  								srid);
>  		return;
>  	}
> +	if (!sr_class || !(sr_class->disable)) {
> +		pr_warning("smartreflex class driver not registered\n");
> +		return;
> +	}
>  
>  	if (sr->is_autocomp_active == 1) {
>  		if (sr->is_sr_reset == 0) {
> -
> -			sr->is_sr_reset = 1;
> -			/* SRCONFIG - disable SR */
> -			sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
> -							~SRCONFIG_SRENABLE);
> -
> +			sr_class->disable(srid);
>  			/* Disable SR clk */
>  			sr_clk_disable(sr);
> -			if (sr->srid == SR1) {
> -				/* Wait for VP idle before disabling VP */
> -				while ((!prm_read_mod_reg(OMAP3430_GR_MOD,
> -						OMAP3_PRM_VP1_STATUS_OFFSET))
> -						&& i++ < MAX_TRIES)
> -					udelay(1);
> -
> -				if (i >= MAX_TRIES)
> -					pr_warning("VP1 not idle, still going \
> -						ahead with VP1 disable\n");
> -
> -				/* Disable VP1 */
> -				prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE,
> -						OMAP3430_GR_MOD,
> -						OMAP3_PRM_VP1_CONFIG_OFFSET);
> -			} else if (sr->srid == SR2) {
> -				/* Wait for VP idle before disabling VP */
> -				while ((!prm_read_mod_reg(OMAP3430_GR_MOD,
> -						OMAP3_PRM_VP2_STATUS_OFFSET))
> -						&& i++ < MAX_TRIES)
> -					udelay(1);
> -
> -				if (i >= MAX_TRIES)
> -					pr_warning("VP2 not idle, still going \
> -						 ahead with VP2 disable\n");
> -
> -				/* Disable VP2 */
> -				prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE,
> -						OMAP3430_GR_MOD,
> -						OMAP3_PRM_VP2_CONFIG_OFFSET);
> -			}
>  			/* Reset the volatage for current OPP */
>  			sr_reset_voltage(srid);
>  		}
>  	}
>  }
>  
> +/**
> + * omap_sr_register_class : API to register a smartreflex class parameters.
> + * @class_data - The structure containing various sr class specific data.
> + *
> + * This API is to be called by the smartreflex class driver to register itself
> + * with the smartreflex driver during init.
> + */
> +void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
> +{
> +	if (!class_data) {
> +		pr_warning("Smartreflex class data passed is NULL\n");
> +		return;
> +	}
> +
> +	if (sr_class) {
> +		pr_warning("Smartreflex class driver already registered\n");
> +		return;
> +	}
> +	sr_class = class_data;
> +}
> +
>  /* Voltage Scaling using SR VCBYPASS */
>  int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
>  					u8 target_vsel, u8 current_vsel)
> @@ -730,9 +764,9 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
>  
>  	if (sr_status) {
>  		if (vdd == VDD1_OPP)
> -			sr_start_vddautocomap(SR1, target_opp_no);
> +			sr_start_vddautocomap(SR1);
>  		else if (vdd == VDD2_OPP)
> -			sr_start_vddautocomap(SR2, target_opp_no);
> +			sr_start_vddautocomap(SR2);
>  	}
>  
>  	return 0;
> @@ -762,17 +796,10 @@ static int omap_sr_autocomp_store(void *data, u64 val)
>  							sr_info->srid);
>  		return 0;
>  	}
> -	if (val == 0) {
> +	if (val == 0)
>  		sr_stop_vddautocomap(sr_info->srid);
> -	} else {
> -		u32 current_opp;
> -
> -		if (sr_info->srid == SR1)
> -			current_opp = get_vdd1_opp();
> -		else
> -			current_opp = get_vdd2_opp();
> -		sr_start_vddautocomap(sr_info->srid, current_opp);
> -	}
> +	else
> +		sr_start_vddautocomap(sr_info->srid);
>  	return 0;
>  }
>  
> diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
> index 572cdca..a59a073 100644
> --- a/arch/arm/mach-omap2/smartreflex.h
> +++ b/arch/arm/mach-omap2/smartreflex.h
> @@ -243,12 +243,27 @@ extern u32 current_vdd2_opp;
>  #define SR_TESTING_NVALUES 	0
>  #endif
>  
> -/*
> - * Smartreflex module enable/disable interface.
> - * NOTE: if smartreflex is not enabled from sysfs, these functions will not
> - * do anything.
> - */
>  #ifdef CONFIG_OMAP_SMARTREFLEX
> +/**
> + * omap_smartreflex_class_data : Structure to be populated by
> + * Smartreflex class driver with corresponding class enable disable API's
> + *
> + * @enable - API to enable a particular class smaartreflex.
> + * @disable - API to disable a particular class smartreflex.
> + * @notify - API to notify the class driver about an event in SR. Not needed
> + *		for class3.
> + * @notify_flags - specify the events to be notified to the class driver
> + * @class_type - specify which smartreflex class. Can be used by the SR driver
> + * 		to tkae any class based decisions.
> + */
> +struct omap_smartreflex_class_data {
> +	int (*enable)(int sr_id);
> +	int (*disable)(int sr_id);
> +	int (*notify)(int sr_id, u32 status);
> +	u8 notify_flags;
> +	u8 class_type;
> +};
> +
>  /*
>   * omap_smartreflex_data - Smartreflex platform data
>   *
> @@ -274,11 +289,26 @@ struct omap_smartreflex_data {
>  	int (*device_idle)(struct platform_device *pdev);
>  };
>  
> -void enable_smartreflex(int srid);
> -void disable_smartreflex(int srid);
> +/*
> + * Smartreflex module enable/disable interface.
> + * NOTE: if smartreflex is not enabled from sysfs, these functions will not
> + * do anything.
> + */
> +void omap_smartreflex_enable(int srid);
> +void omap_smartreflex_disable(int srid);
> +
> +/**
> + * Smartreflex driver hooks to be called from Smartreflex class driver
> + */
> +int sr_enable(int srid, u32 target_opp_no);
> +void sr_disable(int srid);
> +
> +/**
> + * API to register the smartreflex class driver with the smartreflex driver
> + */
> +void omap_sr_register_class(struct omap_smartreflex_class_data *class_data);
> +
>  int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel);
> -void sr_start_vddautocomap(int srid, u32 target_opp_no);
> -int sr_stop_vddautocomap(int srid);
>  #else
>  static inline void enable_smartreflex(int srid) {}
>  static inline void disable_smartreflex(int srid) {}
> -- 
> 1.7.0.rc1.33.g07cf0f

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

* Re: [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver.
  2010-02-24  9:29             ` [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver Thara Gopinath
  2010-02-24  9:29               ` [PATCH 08/16] OMAP3: PM: Disabling Smartreflex across both frequency and voltage scaling during DVFS Thara Gopinath
@ 2010-03-02 19:36               ` Kevin Hilman
  2010-03-05 15:03                 ` Gopinath, Thara
  1 sibling, 1 reply; 61+ messages in thread
From: Kevin Hilman @ 2010-03-02 19:36 UTC (permalink / raw)
  To: Thara Gopinath; +Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant

Thara Gopinath <thara@ti.com> writes:

> This patch adds smartreflex class 3 driver. This driver hooks
> up with the generic smartreflex driver smartreflex.c to abstract
> out class specific implementations out of the generic driver.
>
> Signed-off-by: Thara Gopinath <thara@ti.com>

I like this abstraction, but I don't like that it still uses OPP IDs.

So, before doing this, we need to get rid of OPP IDs from the
smartreflex layer and keep OPP ID usage isolated to SRF.

It appears the only reason we need OPP IDs in SR is because the Nvalue
tables are indexed by OPP ID in sr_enable().  

One way to fix this is for this SR layer to keep it's own mapping of
voltage to nvalue.  So instead of taking OPP ID, sr_enable() should
take a voltage (or frequency) and use that to look up the nvalue.

a couple other minor comments below...

> ---
>  arch/arm/mach-omap2/Makefile             |    1 +
>  arch/arm/mach-omap2/smartreflex-class3.c |   49 ++++++++++++++++++++++++++++++
>  arch/arm/plat-omap/Kconfig               |   11 ++++++-
>  3 files changed, 60 insertions(+), 1 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
>
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index f6f901f..cd8ab86 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -52,6 +52,7 @@ obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o
>  obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o cpuidle34xx.o
>  obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
>  obj-$(CONFIG_OMAP_SMARTREFLEX)	+= smartreflex.o
> +obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)	+= smartreflex-class3.o
>  
>  AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
>  AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a
> diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
> new file mode 100644
> index 0000000..d2e98a5
> --- /dev/null
> +++ b/arch/arm/mach-omap2/smartreflex-class3.c
> @@ -0,0 +1,49 @@
> +/*
> + * Smart reflex Class 3 specific implementations
> + *
> + * Copyright (C) 2009 Texas Instruments, Inc.

2010

> + * Thara Gopinath <thara@ti.com>
> + *
> + * 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 "smartreflex.h"
> +
> +static int sr_class3_enable(int id)
> +{
> +	int target_opp_no = 0;

insert blank line

> +	if (id == SR1)
> +		target_opp_no = get_vdd1_opp();
> +	else if (id == SR2)
> +		target_opp_no = get_vdd2_opp();
> +	if (!target_opp_no) {
> +		pr_warning("Targetopp not known.Cannot enable SR%d\n", id);
> +		return false;
> +	}

and here

> +	return sr_enable(id, target_opp_no);
> +}
>
> +static int sr_class3_disable(int id)
> +{
> +	int target_opp_no = 0;

blank line

> +	if (id == SR1)
> +		target_opp_no = get_vdd1_opp();
> +	else if (id == SR2)
> +		target_opp_no = get_vdd2_opp();
> +	sr_disable(id);

blank line

> +	return true;
> +}
> +/* SR class3 structure */
> +struct omap_smartreflex_class_data class3_data = {
> +	.enable = sr_class3_enable,
> +	.disable = sr_class3_disable,
> +};
> +
> +static int __init sr_class3_init(void)
> +{
> +	omap_sr_register_class(&class3_data);
> +	return 0;
> +}
> +late_initcall(sr_class3_init);
> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
> index cef67f3..9d286e6 100644
> --- a/arch/arm/plat-omap/Kconfig
> +++ b/arch/arm/plat-omap/Kconfig
> @@ -54,7 +54,7 @@ config OMAP_DEBUG_LEDS
>  
>  config OMAP_SMARTREFLEX
>  	bool "SmartReflex support"
> -	depends on ARCH_OMAP3 && TWL4030_CORE && PM
> +	depends on ARCH_OMAP3 && PM
>  	help
>  	  Say Y if you want to enable SmartReflex.
>  
> @@ -69,6 +69,15 @@ config OMAP_SMARTREFLEX
>  	  compensation for VDD1 and VDD2, user must write 1 to
>  	  /sys/power/sr_vddX_autocomp, where X is 1 or 2.
>  
> +config OMAP_SMARTREFLEX_CLASS3
> +	bool "Class 3 mode of Smartreflex Implementation"
> +	depends on OMAP_SMARTREFLEX && TWL4030_CORE
> +	help
> +	  Say Y to enable Class 3 implementation of Smartreflex
> +
> +	  Class 3 implementation of Smartreflex employs continuous hardware
> +	  voltage caliberation.
> +
>  config OMAP_SMARTREFLEX_TESTING
>  	bool "Smartreflex testing support"
>  	depends on OMAP_SMARTREFLEX
> -- 
> 1.7.0.rc1.33.g07cf0f

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

* Re: [PATCH 09/16] OMAP3: PM: Creating separate files for handling OMAP3 voltage related operations.
  2010-02-24  9:29                 ` [PATCH 09/16] OMAP3: PM: Creating separate files for handling OMAP3 voltage related operations Thara Gopinath
  2010-02-24  9:29                   ` [PATCH 10/16] OMAP3: PM: Cleaning up of smartreflex header file Thara Gopinath
@ 2010-03-02 20:02                   ` Kevin Hilman
  2010-03-05 15:17                     ` Gopinath, Thara
  1 sibling, 1 reply; 61+ messages in thread
From: Kevin Hilman @ 2010-03-02 20:02 UTC (permalink / raw)
  To: Thara Gopinath; +Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant

Thara Gopinath <thara@ti.com> writes:

> This patch creates voltage.c and voltage.h files and
> moves all voltage processor and voltage controller specific code
> from smartreflex.c and other places in the OMAP3 codebase into
> these two files.
> This along with smartreflex class driver addition will make
> smartreflex.c a generic driver to support both Class 2 and
> Class 3 smartreflex implementaions.
>
> Signed-off-by: Thara Gopinath <thara@ti.com>

This is definitely in the right direction.  Thanks Thara.

Also, is this expected to be common for OMAP4?   If not, maybe
this should be named voltage3xxx.[ch]?

More comments below, primarily regarding how the various VP/VC
registers are defined and accessed.  I'd rather see them as offsets
into the PRCM rather than absolute virtual addresses.  More on that
below...

> ---
>  arch/arm/mach-omap2/Makefile             |    3 +-
>  arch/arm/mach-omap2/board-3430sdp.c      |    3 +-
>  arch/arm/mach-omap2/pm.h                 |    7 -
>  arch/arm/mach-omap2/pm34xx.c             |   87 +-----
>  arch/arm/mach-omap2/resource34xx.c       |   15 +-
>  arch/arm/mach-omap2/resource34xx.h       |    1 -
>  arch/arm/mach-omap2/smartreflex-class3.c |    4 +
>  arch/arm/mach-omap2/smartreflex.c        |  370 +--------------------
>  arch/arm/mach-omap2/smartreflex.h        |  139 --------
>  arch/arm/mach-omap2/voltage.c            |  550 ++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/voltage.h            |   74 ++++
>  11 files changed, 640 insertions(+), 613 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/voltage.c
>  create mode 100644 arch/arm/mach-omap2/voltage.h
>

[...]

> diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
> new file mode 100644
> index 0000000..c0c2c17
> --- /dev/null
> +++ b/arch/arm/mach-omap2/voltage.c
> @@ -0,0 +1,550 @@
> +/*
> + * OMAP3/OMAP4 Voltage Management Routines
> + *
> + * Copyright (C) 2007 Texas Instruments, Inc.
> + * Rajendra Nayak <rnayak@ti.com>
> + * Lesly A M <x0080970@ti.com>
> + *
> + * Copyright (C) 2008 Nokia Corporation
> + * Kalle Jokiniemi
> + *
> + * Copyright (C) 2010 Texas Instruments, Inc.
> + * Thara Gopinath <thara@ti.com>
> + *
> + * 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/pm.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +
> +#include <plat/omap-pm.h>
> +#include <plat/omap34xx.h>
> +#include <plat/opp.h>
> +#include <plat/opp_twl_tps.h>
> +
> +#include "prm-regbits-34xx.h"
> +#include "voltage.h"
> +
> +#define MAX_TRIES 100
> +
> +/**
> + * OMAP3 Voltage controller SR parameters. TODO: Pass this info as part of
> + * board data or PMIC data
> + */
> +#define R_SRI2C_SLAVE_ADDR              0x12
> +#define R_VDD1_SR_CONTROL               0x00
> +#define R_VDD2_SR_CONTROL		0x01
> +
> +
> +/* Voltage processor register offsets */
> +struct vp_reg_offs {
> +	void __iomem *vp_vpconfig_reg;
> +	void __iomem *vp_vstepmin_reg;
> +	void __iomem *vp_vstepmax_reg;
> +	void __iomem *vp_vlimitto_reg;
> +	void __iomem *vp_status_reg;
> +	void __iomem *vp_voltage_reg;
> +};
>
> +/*
> + * Voltage processor structure conttaining info about
> + * the various register offsets and the bit field values
> + * for a particular instance of voltage processor.
> + */
> +struct vp_reg_info {
> +	struct vp_reg_offs vp_offs;
> +	/* Bit fields for VPx_VPCONFIG */
> +	u32 vp_erroroffset;
> +	u32 vp_errorgain;
> +	/* Bit fields for VPx_VSTEPMIN */
> +	u32 vp_stepmin;
> +	u32 vp_smpswaittimemin;
> +	/* Bit fields for VPx_VSTEPMAX */
> +	u32 vp_stepmax;
> +	u32 vp_smpswaittimemax;
> +	/* Bit fields for VPx_VLIMITTO */
> +	u32 vp_vddmin;
> +	u32 vp_vddmax;
> +	u32 vp_timeout;
> +};
> +static struct vp_reg_info *vp_reg;
> +/*
> + * Number of scalable voltage domains that has an independent
> + * Voltage processor
> + */
> +static int no_scalable_vdd;
> +
> +/* OMAP3 VP register offsets and other definitions */
> +struct __init vp_reg_offs omap3_vp_offs[] = {
> +	/* VP1 */
> +	{
> +		.vp_vpconfig_reg = OMAP3430_PRM_VP1_CONFIG,
> +		.vp_vstepmin_reg = OMAP3430_PRM_VP1_VSTEPMIN,
> +		.vp_vstepmax_reg = OMAP3430_PRM_VP1_VSTEPMAX,
> +		.vp_vlimitto_reg = OMAP3430_PRM_VP1_VLIMITTO,
> +		.vp_status_reg = OMAP3430_PRM_VP1_STATUS,
> +		.vp_voltage_reg = OMAP3430_PRM_VP1_VOLTAGE,
> +	},
> +	/* VP2 */
> +	{	.vp_vpconfig_reg = OMAP3430_PRM_VP2_CONFIG,
> +		.vp_vstepmin_reg = OMAP3430_PRM_VP2_VSTEPMIN,
> +		.vp_vstepmax_reg = OMAP3430_PRM_VP2_VSTEPMAX,
> +		.vp_vlimitto_reg = OMAP3430_PRM_VP2_VLIMITTO,
> +		.vp_status_reg = OMAP3430_PRM_VP2_STATUS,
> +		.vp_voltage_reg = OMAP3430_PRM_VP2_VOLTAGE,
> +	},
> +};
> +


Rather than absolute physical addresses, these should all simply be u8
offset values from the GR_MOD base.  Changing the type to u8
and appending _OFFSET to the name should do the trick.

Also, I think you could remove the vp_ prefix from the name.

> +#define OMAP3_NO_SCALABLE_VDD ARRAY_SIZE(omap3_vp_offs)
> +static struct vp_reg_info omap3_vp_reg[OMAP3_NO_SCALABLE_VDD];
> +
> +
> +/* TODO: OMAP4 register offsets */
> +
> +/**
> + * Voltage controller register offsets
> + */
> +struct vc_reg_info {
> +	void __iomem *vc_cmdval0_reg;
> +	void __iomem *vc_cmdval1_reg;
> +	void __iomem *vc_bypass_val_reg;

u8 offsets from GR_MOD please.

vc_ prefix is redundant here also

> +} vc_reg;
> +/*
> + * Default voltage controller settings for OMAP3
> + */
> +static struct prm_setup_vc vc_config = {
> +	.clksetup = 0xff,
> +	.voltsetup_time1 = 0xfff,
> +	.voltsetup_time2 = 0xfff,
> +	.voltoffset = 0xff,
> +	.voltsetup2 = 0xff,
> +	.vdd0_on = 0x30,        /* 1.2v */
> +	.vdd0_onlp = 0x20,      /* 1.0v */
> +	.vdd0_ret = 0x1e,       /* 0.975v */
> +	.vdd0_off = 0x00,       /* 0.6v */
> +	.vdd1_on = 0x2c,        /* 1.15v */
> +	.vdd1_onlp = 0x20,      /* 1.0v */
> +	.vdd1_ret = 0x1e,       /* .975v */
> +	.vdd1_off = 0x00,       /* 0.6v */
> +};
> +
> +static inline u32 voltage_read_reg(void __iomem *offset)
> +{
> +	return __raw_readl(offset);
> +}

These should use prm_[read|write]_*

static inline u32 voltage_read_reg(u8 offset)
{
        return prm_read_mod_reg(OMAP3430_GR_MOD, offset);
}

> +
> +static inline void voltage_write_reg(void __iomem *offset, u32 value)
> +{
> +	__raw_writel(value, offset);
> +}
> +

Kevin

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

* Re: [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c
  2010-02-24  9:29           ` [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c Thara Gopinath
  2010-02-24  9:29             ` [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver Thara Gopinath
  2010-03-02 18:44             ` [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c Kevin Hilman
@ 2010-03-02 23:37             ` Kevin Hilman
  2010-03-02 23:52             ` Kevin Hilman
  3 siblings, 0 replies; 61+ messages in thread
From: Kevin Hilman @ 2010-03-02 23:37 UTC (permalink / raw)
  To: Thara Gopinath; +Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant

Thara Gopinath <thara@ti.com> writes:

> OMAP3 smartreflex modules are capable of two different classes
> of implementaion -
> 	Class-2: Continuous Software Calibration
> 	Class-3: Continuous Hardware Calibration.
> OMAP3 along with T2/Gaia supports the Class 3 implementaion.
> With a different PMIC it can support Class 2 implementaion also.
>
> The idea behind this patch is that smartreflex.c should be able
> to support both the classes of Smartreflex and the class specific
> details for smartreflex should stay out of this file in a separate
> class file.
> This patch introduces smartreflex class specific hooks in
> smartreflex.c. This patch only takes care of smartreflex enable
> disable hooks which differ between Class 2 and Class 3. There
> are some register setting changes between both the classes which
> will be taken care of in a later patch.
> This will form the base for adding class specific
> drivers in later patches.
>
> Signed-off-by: Thara Gopinath <thara@ti.com>
> ---
>  arch/arm/mach-omap2/pm34xx.c      |    8 +-
>  arch/arm/mach-omap2/smartreflex.c |  251 ++++++++++++++++++++----------------
>  arch/arm/mach-omap2/smartreflex.h |   48 ++++++--
>  3 files changed, 182 insertions(+), 125 deletions(-)
>
[...]

> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
> index c00925d..ba9f899 100644
> --- a/arch/arm/mach-omap2/smartreflex.c
> +++ b/arch/arm/mach-omap2/smartreflex.c
> @@ -55,6 +55,7 @@ struct omap_sr {
>  
>  /* sr_list contains all the instances of smartreflex module */
>  static LIST_HEAD(sr_list);
> +static struct omap_smartreflex_class_data *sr_class;

I think the class should be part of 'struct omap_sr'.  This should be
coded in a way to allow a different class type or each SR module (even
if that is never useful in practice.)

Kevin

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

* Re: [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c
  2010-02-24  9:29           ` [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c Thara Gopinath
                               ` (2 preceding siblings ...)
  2010-03-02 23:37             ` Kevin Hilman
@ 2010-03-02 23:52             ` Kevin Hilman
  2010-03-05 15:18               ` Gopinath, Thara
  3 siblings, 1 reply; 61+ messages in thread
From: Kevin Hilman @ 2010-03-02 23:52 UTC (permalink / raw)
  To: Thara Gopinath; +Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant

Thara Gopinath <thara@ti.com> writes:

> OMAP3 smartreflex modules are capable of two different classes
> of implementaion -
> 	Class-2: Continuous Software Calibration
> 	Class-3: Continuous Hardware Calibration.
> OMAP3 along with T2/Gaia supports the Class 3 implementaion.
> With a different PMIC it can support Class 2 implementaion also.
>
> The idea behind this patch is that smartreflex.c should be able
> to support both the classes of Smartreflex and the class specific
> details for smartreflex should stay out of this file in a separate
> class file.
> This patch introduces smartreflex class specific hooks in
> smartreflex.c. This patch only takes care of smartreflex enable
> disable hooks which differ between Class 2 and Class 3. There
> are some register setting changes between both the classes which
> will be taken care of in a later patch.
> This will form the base for adding class specific
> drivers in later patches.
>
> Signed-off-by: Thara Gopinath <thara@ti.com>
> ---
>  arch/arm/mach-omap2/pm34xx.c      |    8 +-
>  arch/arm/mach-omap2/smartreflex.c |  251 ++++++++++++++++++++----------------
>  arch/arm/mach-omap2/smartreflex.h |   48 ++++++--
>  3 files changed, 182 insertions(+), 125 deletions(-)
>

[...]

> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
> index c00925d..ba9f899 100644
> --- a/arch/arm/mach-omap2/smartreflex.c
> +++ b/arch/arm/mach-omap2/smartreflex.c
> @@ -55,6 +55,7 @@ struct omap_sr {
>  
>  /* sr_list contains all the instances of smartreflex module */
>  static LIST_HEAD(sr_list);
> +static struct omap_smartreflex_class_data *sr_class;
>  
>  #define SR_REGADDR(offs)	(sr->srbase_addr + offset)
>  
> @@ -388,14 +389,86 @@ static int sr_reset_voltage(int srid)
>  	return 0;
>  }
>  
> -static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
> +static void sr_start_vddautocomap(int srid)

Either in this patch or in an additional patch (previous to this one)
can you fix the name of these autocomp functions: *_vddautocomap ->
*_vddautocomp.  I don't think comap means anything.

Kevin

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

* Re: [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer
  2010-02-24  9:29     ` [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer Thara Gopinath
                         ` (2 preceding siblings ...)
  2010-03-02 18:28       ` Kevin Hilman
@ 2010-03-03  0:02       ` Kevin Hilman
  3 siblings, 0 replies; 61+ messages in thread
From: Kevin Hilman @ 2010-03-03  0:02 UTC (permalink / raw)
  To: Thara Gopinath; +Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant

Thara Gopinath <thara@ti.com> writes:

> This patch converts the exisitng smartreflex library into a
> platform driver with device , driver registrations using hardware mods.
> As part of this Ntarget values are passed as platform data.
>
> Signed-off-by: Thara Gopinath <thara@ti.com>

[...]

>  
> +static int __devinit omap_smartreflex_probe(struct platform_device *pdev)

This can be __init when using platform_driver_probe()...

[...]

>  
> +static struct platform_driver smartreflex_driver = {
> +	.probe          = omap_smartreflex_probe,

and shouldn't need to be listed here either, since it will be __init
and disappear after boot.


Kevin

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

* Re: [PATCH 11/16] OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3
  2010-02-24  9:29                     ` [PATCH 11/16] OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3 Thara Gopinath
  2010-02-24  9:29                       ` [PATCH 12/16] OMAP3: PM: Support for enabling smartreflex autocompensation by default Thara Gopinath
@ 2010-03-03  0:37                       ` Kevin Hilman
  2010-03-05 15:12                         ` Gopinath, Thara
  1 sibling, 1 reply; 61+ messages in thread
From: Kevin Hilman @ 2010-03-03  0:37 UTC (permalink / raw)
  To: Thara Gopinath; +Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant

Thara Gopinath <thara@ti.com> writes:

> There are two separate modules in SmartReflex-AVS :
> MinMaxAvg module and Error module. Class3 uses the Error module only.
> In Class2 you can choose between either module since it is software based.
> The registers are mapped to the modules as followed:
>
> MinMaxAvg module: AccumData, MinMaxAvgEnable, MinMaxAvgValid,
>         MinMaxAvgAccumValid, SenVal, SenMin, SenMax, SenAverage,
>         AverageWeight, MCUAccum, MCUValid, MCUBounds.
>
> Error module: SenNGain, SenPGain, SenPRN, SenNRN, AvgError,
>         SenError, VPBounds, ErrWeight, ErrMaxLimit, ErrMinLimit.
>
> Shared between both: SRClkLength, SREnable, SenEnable, SenNEnable,
>         SenPEnable, DelayCtrl, MCUDisableAck, ClkActivity.
>
> This patch introduces class specific configuration of registers in smartreflex.c
> This also allows for choosing between Error module and Minmaxavg module
> for Class 2 SR. This patch allows allows for registering for smartreflex
> interrupt handler and notification of interrupts in case requested by
> the smartreflex class driver.
>
> Signed-off-by: Thara Gopinath <thara@ti.com>
> ---
>  arch/arm/mach-omap2/smartreflex-class3.c |    1 +
>  arch/arm/mach-omap2/smartreflex.c        |  199 ++++++++++++++++++++++++------
>  arch/arm/mach-omap2/smartreflex.h        |   24 ++++-
>  3 files changed, 186 insertions(+), 38 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
> index 8e3b530..aae88b6 100644
> --- a/arch/arm/mach-omap2/smartreflex-class3.c
> +++ b/arch/arm/mach-omap2/smartreflex-class3.c
> @@ -43,6 +43,7 @@ static int sr_class3_disable(int id)
>  struct omap_smartreflex_class_data class3_data = {
>  	.enable = sr_class3_enable,
>  	.disable = sr_class3_disable,
> +	.class_type = SR_CLASS3,
>  };
>  
>  static int __init sr_class3_init(void)
> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
> index f7c1182..96dc76b 100644
> --- a/arch/arm/mach-omap2/smartreflex.c
> +++ b/arch/arm/mach-omap2/smartreflex.c
> @@ -38,6 +38,12 @@ struct omap_sr {
>  	int			is_sr_reset;
>  	int			is_autocomp_active;
>  	u32			clk_length;
> +	u32			err_weight;
> +	u32			err_minlimit;
> +	u32			err_maxlimit;
> +	u32			accum_data;
> +	u32			senn_avgweight;
> +	u32			senp_avgweight;
>  	void __iomem		*srbase_addr;
>  	unsigned int		irq;
>  	struct platform_device 	*pdev;
> @@ -106,6 +112,24 @@ static void sr_clk_disable(struct omap_sr *sr)
>  	sr->is_sr_reset = 1;
>  }
>  
> +static irqreturn_t sr_omap_isr(int irq, void *data)
> +{
> +	struct omap_sr *sr_info = (struct omap_sr *)data;
> +	u32 status;
> +
> +	/* Read the status bits */
> +	status = sr_read_reg(sr_info, ERRCONFIG);
> +
> +	/* Clear them by writing back */
> +	sr_write_reg(sr_info, ERRCONFIG, status);
> +
> +	/* Call the class driver notify function if registered*/
> +	if (sr_class->class_type == SR_CLASS2 && sr_class->notify)
> +		sr_class->notify(sr_info->srid, status);
> +
> +	return IRQ_HANDLED;
> +}
> +
>  static void sr_set_clk_length(struct omap_sr *sr)
>  {
>  	struct clk *sys_ck;
> @@ -137,50 +161,96 @@ static void sr_set_clk_length(struct omap_sr *sr)
>  	}
>  }
>  
> +static void sr_set_regfields(struct omap_sr *sr)
> +{
> +	/*
> +	 * For time being these values are defined in smartreflex.h
> +	 * and populated during init. May be they can be moved to board
> +	 * file or pmic specific data structure. In that case these structure
> +	 * fields will have to be populated using the pdata or pmic structure.
> +	 */
> +	if (cpu_is_omap343x()) {
> +		sr->err_weight = OMAP3430_SR_ERRWEIGHT;
> +		sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
> +		sr->accum_data = OMAP3430_SR_ACCUMDATA;
> +		if (sr->srid == SR1) {
> +			sr->err_minlimit = OMAP3430_SR1_ERRMINLIMIT;
> +			sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
> +			sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
> +		} else {
> +			sr->err_minlimit = OMAP3430_SR2_ERRMINLIMIT;
> +			sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
> +			sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
> +		}
> +	}
> +	/* TODO: 3630 and Omap4 specific bit field values */
> +}
> +
>  static void sr_configure(struct omap_sr *sr)
>  {
>  	u32 sr_config;
>  	u32 senp_en , senn_en;
>  	struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>  
> +	/* Common settings for SR Class3 and SR Class2 */
>  	if (sr->clk_length == 0)
>  		sr_set_clk_length(sr);
>  
>  	senp_en = pdata->senp_mod;
>  	senn_en = pdata->senn_mod;
> -	if (sr->srid == SR1) {
> -		sr_config = SR1_SRCONFIG_ACCUMDATA |
> -			(sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
> -			SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN |
> -			SRCONFIG_MINMAXAVG_EN |
> -			(senn_en << SRCONFIG_SENNENABLE_SHIFT) |
> -			(senp_en << SRCONFIG_SENPENABLE_SHIFT) |
> -			SRCONFIG_DELAYCTRL;
> -
> -		sr_write_reg(sr, SRCONFIG, sr_config);
> -		sr_write_reg(sr, AVGWEIGHT, SR1_AVGWEIGHT_SENPAVGWEIGHT |
> -					SR1_AVGWEIGHT_SENNAVGWEIGHT);
>  
> +	sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
> +		SRCONFIG_SENENABLE | (senn_en << SRCONFIG_SENNENABLE_SHIFT) |
> +		(senp_en << SRCONFIG_SENPENABLE_SHIFT) | SRCONFIG_DELAYCTRL;
> +	sr_write_reg(sr, SRCONFIG, sr_config);
> +
> +	if ((sr_class->class_type == SR_CLASS3) || (sr_class->class_type ==
> +		SR_CLASS2 && sr_class->mod_use == SR_USE_ERROR_MOD)) {
> +		/*
> +		 * SR settings if using the ERROR module inside Smartreflex.
> +		 * SR CLASS 3 by default uses only the ERROR module where as
> +		 * SR CLASS 2 can choose between ERROR module and MINMAXAVG
> +		 * module.
> +		 */
> +		u32 sr_errconfig;
> +
> +		sr_modify_reg(sr, SRCONFIG, SRCONFIG_ERRGEN_EN,
> +			SRCONFIG_ERRGEN_EN);
> +		sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
> +			(sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
> +			(sr->err_minlimit <<  ERRCONFIG_ERRMiNLIMIT_SHIFT);
>  		sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |
>  			SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
> -			(SR1_ERRWEIGHT | SR1_ERRMAXLIMIT | SR1_ERRMINLIMIT));
> -
> -	} else if (sr->srid == SR2) {
> -		sr_config = SR2_SRCONFIG_ACCUMDATA |
> -			(sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
> -			SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN |
> -			SRCONFIG_MINMAXAVG_EN |
> -			(senn_en << SRCONFIG_SENNENABLE_SHIFT) |
> -			(senp_en << SRCONFIG_SENPENABLE_SHIFT) |
> -			SRCONFIG_DELAYCTRL;
> -
> -		sr_write_reg(sr, SRCONFIG, sr_config);
> -		sr_write_reg(sr, AVGWEIGHT, SR2_AVGWEIGHT_SENPAVGWEIGHT |
> -					SR2_AVGWEIGHT_SENNAVGWEIGHT);
> -		sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |
> -			SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
> -			(SR2_ERRWEIGHT | SR2_ERRMAXLIMIT | SR2_ERRMINLIMIT));
> +			sr_errconfig);
> +		/* Enabling the interrupts if the ERROR module is used */
> +		sr_modify_reg(sr, ERRCONFIG,
> +			(ERRCONFIG_VPBOUNDINTEN),
> +			(ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST));
> +	} else if ((sr_class->class_type == SR_CLASS2) &&
> +			(sr_class->mod_use == SR_USE_ERROR_MOD)) {

This 'else if' will never happen as the condition is identical to one
of the conditions of the first if.

Based on the comment below, I'm assuming it you meant SR_USE_MINMAXAVG_MOD.

> +		/*
> +		 * SR settings if using the MINMAXAVG module inside
> +		 * Smartreflex. SR CLASS 3 does not use this module where as
> +		 * SR CLASS 2 can choose between ERROR module and MINMAXAVG
> +		 * module.
> +		 */
> +		u32 avgwt;
>  
> +		sr_modify_reg(sr, SRCONFIG, SRCONFIG_ACCUMDATA_MASK,
> +			sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
> +		avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
> +			(sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT);
> +		sr_write_reg(sr, AVGWEIGHT, avgwt);
> +		/*
> +		 * Enabling the interrupts if MINMAXAVG module is used.
> +		 * TODO: check if all the interrupts are mandatory
> +		 */
> +		sr_modify_reg(sr, ERRCONFIG,
> +			(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
> +			ERRCONFIG_MCUBOUNDINTEN),
> +			(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST |
> +			 ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST |
> +			 ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST));
>  	}
>  	sr->is_sr_reset = 0;
>  }
> @@ -280,12 +350,6 @@ int sr_enable(int srid, u32 target_opp_no)
>  	}
>  
>  	sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
> -
> -	/* Enable the interrupt */
> -	sr_modify_reg(sr, ERRCONFIG,
> -			(ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST),
> -			(ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST));
> -
>  	/* SRCONFIG - enable SR */
>  	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
>  	return true;
> @@ -384,6 +448,8 @@ void omap_smartreflex_disable(int srid)
>   */
>  void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
>  {
> +	struct omap_sr *sr_info;
> +
>  	if (!class_data) {
>  		pr_warning("Smartreflex class data passed is NULL\n");
>  		return;
> @@ -393,7 +459,44 @@ void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
>  		pr_warning("Smartreflex class driver already registered\n");
>  		return;
>  	}
> +
> +	if ((class_data->class_type != SR_CLASS2) &&
> +			(class_data->class_type != SR_CLASS3)) {
> +		pr_warning("SR Class type passed is invalid. So cannot \
> +				register the class structure\n");
> +		return;
> +	}
> +
> +	if ((class_data->class_type == SR_CLASS2) &&
> +			!((class_data->mod_use == SR_USE_MINMAXAVG_MOD) ||
> +			(class_data->mod_use == SR_USE_ERROR_MOD))) {
> +		pr_warning("SR Class 2 specified but whether to use error \
> +				module or minmaxavg module not specified\n");
> +		return;
> +	}
> +
>  	sr_class = class_data;
> +	/*
> +	 * Register the interrupt handler incase requested by the class driver
> +	 */
> +	list_for_each_entry(sr_info, &sr_list, node) {
> +		if (sr_class->class_type == SR_CLASS2 &&
> +				sr_class->notify_flags && sr_info->irq) {
> +			char name[SMARTREFLEX_NAME_LEN];
> +			int ret;
> +
> +			sprintf(name, "sr%d", sr_info->srid);
> +			ret = request_irq(sr_info->irq, sr_omap_isr,
> +					IRQF_DISABLED, name, (void *)sr_info);
> +			if (ret < 0) {
> +				pr_warning("ERROR in registering interrupt \
> +					handler for SR%d Smartreflex will \
> +					not function as desired\n",
> +					sr_info->srid);
> +				return;
> +			}
> +		}
> +	}
>  }
>  
>  /* PM Debug Fs enteries to enable disable smartreflex.*/
> @@ -448,6 +551,7 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
>  	if (odev->hwmods[0]->mpu_irqs)
>  		sr_info->irq = odev->hwmods[0]->mpu_irqs[0].irq;
>  	sr_set_clk_length(sr_info);
> +	sr_set_regfields(sr_info);
>  
>  	/* Create the debug fs enteries */
>  	sprintf(name, "sr%d_autocomp", sr_info->srid);
> @@ -456,8 +560,29 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
>  
>  	odev->hwmods[0]->dev_attr = sr_info;
>  	list_add(&sr_info->node, &sr_list);
> -	pr_info("SmartReflex driver initialized\n");
>  
> +	/*
> +	 * Register interrrupt handler if smartreflex class driver is already
> +	 * registered and has requested for interrupts. This will be attempted
> +	 * in the class driver register again if it does not happen here.
> +	 */

Why the duplicate attempts to request_irq()?  Seems like it's only needed
in the register_class hook above.

> +	if (sr_class) {
> +		if (sr_class->class_type == SR_CLASS2 &&
> +				sr_class->notify_flags && sr_info->irq) {
> +			sprintf(name, "sr%d", sr_info->srid);
> +			ret = request_irq(sr_info->irq, sr_omap_isr,
> +					IRQF_DISABLED, name, (void *)sr_info);
> +			if (ret < 0) {
> +				pr_warning("ERROR in registering interrupt \
> +					handler for SR%d. Smartreflex will \
> +					not function as desired\n",
> +					sr_info->srid);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	pr_info("SmartReflex driver initialized\n");
>  	return ret;
>  }
>  
> diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
> index 7a1f0c7..f8fc8a4 100644
> --- a/arch/arm/mach-omap2/smartreflex.h
> +++ b/arch/arm/mach-omap2/smartreflex.h
> @@ -124,6 +124,24 @@ extern struct dentry *pm_dbg_main_dir;
>  #endif
>  
>  #ifdef CONFIG_OMAP_SMARTREFLEX
> +/*
> + * The smart reflex driver supports both CLASS2 and CLASS3 SR.
> + * The smartreflex class driver should pass the class type.
> + * Should be used to populate the class_type field of the
> + * omap_smartreflex_class_data structure.
> + */
> +#define SR_CLASS2	0x1
> +#define SR_CLASS3	0x2
> +
> +/*
> + * CLASS2 SR can use either the MINMAXAVG module or the ERROR module
> + * of the Smartreflex. Should be used to populate the mod_use field
> + * of omap_smartreflex_class_data structure is class_type is chosen
> + * as SR_CLASS2.
> + */
> +#define SR_USE_MINMAXAVG_MOD	0x1
> +#define SR_USE_ERROR_MOD	0x2
> +
>  /**
>   * omap_smartreflex_class_data : Structure to be populated by
>   * Smartreflex class driver with corresponding class enable disable API's
> @@ -134,7 +152,10 @@ extern struct dentry *pm_dbg_main_dir;
>   *		for class3.
>   * @notify_flags - specify the events to be notified to the class driver
>   * @class_type - specify which smartreflex class. Can be used by the SR driver
> - * 		to tkae any class based decisions.
> + * 		to take any class based decisions.
> + * @mod_use - specify whether to use the error module or minmaxavg module for
> + *		smartreflex caliberations in case of class2 SR. In case of
                            ^^^^^^^^^^^^^
typo: calibration

> + *		class 3 SR only error module is used.
>   */
>  struct omap_smartreflex_class_data {
>  	int (*enable)(int sr_id);
> @@ -142,6 +163,7 @@ struct omap_smartreflex_class_data {
>  	int (*notify)(int sr_id, u32 status);
>  	u8 notify_flags;
>  	u8 class_type;
> +	u8 mod_use;

This name isn't terribly clear.  Maybe mode?  or calibration_mode?


Kevin

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

* Re: [PATCH 12/16] OMAP3: PM: Support for enabling smartreflex autocompensation by default.
  2010-02-24  9:29                       ` [PATCH 12/16] OMAP3: PM: Support for enabling smartreflex autocompensation by default Thara Gopinath
  2010-02-24  9:29                         ` [PATCH 13/16] OMAP3: PM: Correcting accessing of ERRCONFIG register in smartreflex.c Thara Gopinath
@ 2010-03-03  0:48                         ` Kevin Hilman
  2010-03-05 15:20                           ` Gopinath, Thara
  1 sibling, 1 reply; 61+ messages in thread
From: Kevin Hilman @ 2010-03-03  0:48 UTC (permalink / raw)
  To: Thara Gopinath; +Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant

Thara Gopinath <thara@ti.com> writes:

> This patch adds support to pdata enable smartreflex autocompenstion
> during init based on init_enable flag passed as pdata.
>
> This patch also adds enabling of autocompensation by
> default (setting init_enable flag to true) in case of ES3.1
> OMAP3430 chip. In the current implementation
> this step is kept in smartreflex.c itself.Later an API can be added
> so that the decision to enable autocompensation by default
> can be passed from the corresponding board files.
>
> Signed-off-by: Thara Gopinath <thara@ti.com>
> ---
>  arch/arm/mach-omap2/smartreflex.c |   32 ++++++++++++++++++++++++++++----
>  1 files changed, 28 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
> index 96dc76b..085dd05 100644
> --- a/arch/arm/mach-omap2/smartreflex.c
> +++ b/arch/arm/mach-omap2/smartreflex.c
> @@ -477,9 +477,15 @@ void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
>  
>  	sr_class = class_data;
>  	/*
> -	 * Register the interrupt handler incase requested by the class driver
> +	 * Check if any SR module needs to be enabled as part of init.
> +	 * In case the probe for the SR module is not yet called the enable
> +	 * will not be done here but will be done in the probe whenever
> +	 * it gets called. Also register the interrupt handler incase
> +	 * requested by the class driver.
>  	 */
>  	list_for_each_entry(sr_info, &sr_list, node) {
> +		struct omap_smartreflex_data *pdata =
> +				sr_info->pdev->dev.platform_data;
>  		if (sr_class->class_type == SR_CLASS2 &&
>  				sr_class->notify_flags && sr_info->irq) {
>  			char name[SMARTREFLEX_NAME_LEN];
> @@ -496,6 +502,8 @@ void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
>  				return;
>  			}
>  		}
> +		if (pdata->init_enable)
> +			sr_start_vddautocomap(sr_info->srid);

I think this flag is better named enable_on_init.  

>  	}
>  }
>  
> @@ -562,11 +570,15 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
>  	list_add(&sr_info->node, &sr_list);
>  
>  	/*
> -	 * Register interrrupt handler if smartreflex class driver is already
> -	 * registered and has requested for interrupts. This will be attempted
> +	 * Enable the smartreflex module if init_enable flag is set and
> +	 * if the class driver is registered. Also Register interrrupt handler
> +	 * if smartreflex class driver is already registered and has
> +	 * requested for interrupts. This will be attempted
>  	 * in the class driver register again if it does not happen here.
>  	 */
>  	if (sr_class) {
> +		struct omap_smartreflex_data *pdata = pdev->dev.platform_data;
> +
>  		if (sr_class->class_type == SR_CLASS2 &&
>  				sr_class->notify_flags && sr_info->irq) {
>  			sprintf(name, "sr%d", sr_info->srid);
> @@ -580,6 +592,8 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
>  				return ret;
>  			}
>  		}
> +		if (pdata->init_enable)
> +			sr_start_vddautocomap(sr_info->srid);
>  	}

As with the duplicate request_irq() in previous patch, I don't follow
why it's the start is needed twice.  

Is it to handle the case where no class driver is installed?

>  
>  	pr_info("SmartReflex driver initialized\n");
> @@ -782,7 +796,17 @@ static int __init omap_devinit_smartreflex(void)
>  		if (WARN_ON(!sr_data))
>  			return -ENOMEM;
>  
> -		sr_data->init_enable = false;
> +		/*
> +		 * Enable the SR module by default if it is a OMAP3430
> +		 * ES3.1 chip

You should add a comment about why: starting with ES3.1, efuse values can be trusted?

> +		 */
> +		if (cpu_is_omap343x()) {
> +			if (omap_rev() == OMAP3430_REV_ES3_1)
> +				sr_data->init_enable = true;
> +			else
> +				sr_data->init_enable = false;
> +		} else
> +			sr_data->init_enable = false;
>  		sr_data->device_enable = omap_device_enable;
>  		sr_data->device_shutdown = omap_device_shutdown;
>  		sr_data->device_idle = omap_device_idle;

Kevin

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

* Re: [PATCH 14/16] OMAP3: PM: Implement latest h/w recommendations for SR and VP registers and SR VP enable disable sequence.
  2010-02-24  9:29                           ` [PATCH 14/16] OMAP3: PM: Implement latest h/w recommendations for SR and VP registers and SR VP enable disable sequence Thara Gopinath
  2010-02-24  9:29                             ` [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling Thara Gopinath
@ 2010-03-03  0:54                             ` Kevin Hilman
  1 sibling, 0 replies; 61+ messages in thread
From: Kevin Hilman @ 2010-03-03  0:54 UTC (permalink / raw)
  To: Thara Gopinath; +Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant

Thara Gopinath <thara@ti.com> writes:

> This patch introduces OMAP3 specific values for Smartreflex and
> Voltage processor registers as per the latest TI recommendations.
> This patch also improves the smartreflex and voltage processor
> enable disable sequences as per the latest recommendations.
>
> These recommendations were first formed based on experimentations
> on Nokia Rover platform  and were implemented in the Rover code
> base first by Nishanth Menon and Paul Walmsley.

I think this was pointed out by others, but Rover should be replaced
with n900.

> Signed-off-by: Thara Gopinath <thara@ti.com>
> ---
>  arch/arm/mach-omap2/smartreflex.c |   65 ++++++++++++++++++++-----
>  arch/arm/mach-omap2/smartreflex.h |    6 +-
>  arch/arm/mach-omap2/voltage.c     |   95 ++++++++++++++++++++++++++++++------
>  arch/arm/mach-omap2/voltage.h     |   16 ++++---
>  4 files changed, 142 insertions(+), 40 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
> index 8a4c48b..ca2223d 100644
> --- a/arch/arm/mach-omap2/smartreflex.c
> +++ b/arch/arm/mach-omap2/smartreflex.c
> @@ -24,6 +24,7 @@
>  #include <linux/io.h>
>  #include <linux/list.h>
>  #include <linux/debugfs.h>
> +#include <linux/delay.h>
>  
>  #include <plat/control.h>
>  #include <plat/omap_hwmod.h>
> @@ -32,6 +33,7 @@
>  #include "smartreflex.h"
>  
>  #define SMARTREFLEX_NAME_LEN	16
> +#define SR_DISABLE_TIMEOUT	200
>  
>  struct omap_sr {
>  	int			srid;
> @@ -184,11 +186,9 @@ static void sr_set_regfields(struct omap_sr *sr)
>  		sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
>  		sr->accum_data = OMAP3430_SR_ACCUMDATA;
>  		if (sr->srid == SR1) {
> -			sr->err_minlimit = OMAP3430_SR1_ERRMINLIMIT;
>  			sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
>  			sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
>  		} else {
> -			sr->err_minlimit = OMAP3430_SR2_ERRMINLIMIT;
>  			sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
>  			sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
>  		}
> @@ -280,11 +280,6 @@ static void sr_start_vddautocomap(int srid)
>  		return;
>  	}
>  
> -	if (sr->is_sr_reset == 1) {
> -		sr_clk_enable(sr);
> -		sr_configure(sr);
> -	}
> -
>  	sr->is_autocomp_active = 1;
>  	if (!sr_class->enable(srid)) {
>  		sr->is_autocomp_active = 0;
> @@ -351,8 +346,20 @@ int sr_enable(int srid, u32 target_opp_no)
>  		return false;
>  	}
>  
> -	nvalue_reciprocal = pdata->sr_nvalue[target_opp_no - 1];
> +	/*
> +	 * For OMAP3430 errminlimit is dependent on opp. So choose
> +	 * it appropriately
> +	 */
> +	if (cpu_is_omap343x())
> +		sr->err_minlimit = (target_opp_no > 2) ?
> +			OMAP3430_SR_ERRMINLIMIT_HIGHOPP :
> +			OMAP3430_SR_ERRMINLIMIT_LOWOPP;
> +
> +	/* Enable the clocks and configure SR */
> +	sr_clk_enable(sr);
> +	sr_configure(sr);
>  
> +	nvalue_reciprocal = pdata->sr_nvalue[target_opp_no - 1];
>  	if (nvalue_reciprocal == 0) {
>  		pr_notice("OPP%d doesn't support SmartReflex\n",
>  								target_opp_no);
> @@ -375,10 +382,44 @@ int sr_enable(int srid, u32 target_opp_no)
>  void sr_disable(int srid)
>  {
>  	struct omap_sr *sr = _sr_lookup(srid);
> +	int timeout = 0;
> +
> +	/* Check if SR is already disabled. If yes do nothing */
> +	if (!(sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE))
> +		return;
> +
> +	/* Enable MCUDisableAcknowledge interrupt */
> +	sr_modify_reg(sr, ERRCONFIG,
> +			ERRCONFIG_MCUDISACKINTEN, ERRCONFIG_MCUDISACKINTEN);
>  
> -	sr->is_sr_reset = 1;
>  	/* SRCONFIG - disable SR */
> -	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, ~SRCONFIG_SRENABLE);
> +	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
> +
> +	/* Disable all other SR interrupts and clear the status */
> +	sr_modify_reg(sr, ERRCONFIG,
> +			(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
> +			ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN),
> +			(ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
> +			ERRCONFIG_MCUBOUNDINTST | ERRCONFIG_VPBOUNDINTST));
> +
> +	/* Wait for SR to be disabled.
> +	 * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us.
> +	 */
> +	while ((timeout < SR_DISABLE_TIMEOUT) &&
> +		(!(sr_read_reg(sr, ERRCONFIG) & ERRCONFIG_MCUDISACKINTST))) {
> +
> +		udelay(1);
> +		timeout++;
> +	}

Please use omap_test_timeout() from <plat/common.h>

> +	if (timeout == SR_DISABLE_TIMEOUT)
> +		pr_warning("SR%d disable timedout\n", srid);
> +
> +	/* Disable MCUDisableAcknowledge interrupt & clear pending interrupt
> +	 * Also enable VPBOUND interrrupt
> +	 */
> +	sr_modify_reg(sr, ERRCONFIG, ERRCONFIG_MCUDISACKINTEN,
> +			ERRCONFIG_MCUDISACKINTST);
>  }
>  
>  /**
> @@ -407,10 +448,6 @@ void omap_smartreflex_enable(int srid)
>  
>  	if (sr->is_autocomp_active == 1) {
>  		if (sr->is_sr_reset == 1) {
> -			/* Enable SR clks */
> -			sr_clk_enable(sr);
> -			sr_configure(sr);
> -
>  			if (!sr_class->enable(srid))
>  				sr_clk_disable(sr);
>  		}
> diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
> index fbb6bf4..ae8d5db 100644
> --- a/arch/arm/mach-omap2/smartreflex.h
> +++ b/arch/arm/mach-omap2/smartreflex.h
> @@ -110,10 +110,10 @@ extern struct dentry *pm_dbg_main_dir;
>  #define OMAP3430_SR2_SENPAVGWEIGHT	0x01
>  #define OMAP3430_SR2_SENNAVGWEIGHT	0x01
>  
> -#define OMAP3430_SR_ERRWEIGHT		0x07
> +#define OMAP3430_SR_ERRWEIGHT		0x04
>  #define OMAP3430_SR_ERRMAXLIMIT		0x02
> -#define OMAP3430_SR1_ERRMINLIMIT	0xFA
> -#define OMAP3430_SR2_ERRMINLIMIT	0xF9
> +#define OMAP3430_SR_ERRMINLIMIT_HIGHOPP	0xF9
> +#define OMAP3430_SR_ERRMINLIMIT_LOWOPP	0xF4
>  
>  /* TODO:3630/OMAP4 values if it has to come from this file */
>  
> diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
> index c0c2c17..49167c0 100644
> --- a/arch/arm/mach-omap2/voltage.c
> +++ b/arch/arm/mach-omap2/voltage.c
> @@ -19,6 +19,7 @@
>  #include <linux/pm.h>
>  #include <linux/delay.h>
>  #include <linux/io.h>
> +#include <linux/clk.h>
>  
>  #include <plat/omap-pm.h>
>  #include <plat/omap34xx.h>
> @@ -28,9 +29,9 @@
>  #include "prm-regbits-34xx.h"
>  #include "voltage.h"
>  
> -#define MAX_TRIES 100
> +#define VP_IDLE_TIMEOUT 200
>  
> -/**
> +/*
>   * OMAP3 Voltage controller SR parameters. TODO: Pass this info as part of
>   * board data or PMIC data
>   */
> @@ -281,13 +282,32 @@ static void __init vp_configure(int vp_id)
>  static void __init vp_reg_configure(int vp_id)
>  {
>  	if (cpu_is_omap34xx()) {
> +		struct clk *sys_ck;
> +		u32 sys_clk_speed, timeout_val;
> +
>  		vp_reg[vp_id].vp_offs = omap3_vp_offs[vp_id];
>  		if (vp_id == VP1) {
> +			/*
> +			 * OMAP3430 has error gain varying btw higher and
> +			 * lower opp's
> +			 */
> +			vp_reg[vp_id].vp_errorgain = (((get_vdd1_opp() > 2) ?
> +					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
> +					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
> +					OMAP3430_ERRORGAIN_SHIFT);
>  			vp_reg[vp_id].vp_vddmin = (OMAP3_VP1_VLIMITTO_VDDMIN <<
>  					OMAP3430_VDDMIN_SHIFT);
>  			vp_reg[vp_id].vp_vddmax = (OMAP3_VP1_VLIMITTO_VDDMAX <<
>  					OMAP3430_VDDMAX_SHIFT);
>  		} else if (vp_id == VP2) {
> +			/*
> +			 * OMAP3430 has error gain varying btw higher and
> +			 * lower opp's
> +			 */
> +			vp_reg[vp_id].vp_errorgain = (((get_vdd2_opp() > 2) ?
> +					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
> +					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
> +					OMAP3430_ERRORGAIN_SHIFT);
>  			vp_reg[vp_id].vp_vddmin = (OMAP3_VP2_VLIMITTO_VDDMIN <<
>  					OMAP3430_VDDMIN_SHIFT);
>  			vp_reg[vp_id].vp_vddmax = (OMAP3_VP2_VLIMITTO_VDDMAX <<
> @@ -299,8 +319,6 @@ static void __init vp_reg_configure(int vp_id)
>  		}
>  		vp_reg[vp_id].vp_erroroffset = (OMAP3_VP_CONFIG_ERROROFFSET <<
>  					OMAP3430_INITVOLTAGE_SHIFT);
> -		vp_reg[vp_id].vp_errorgain = (OMAP3_VP_CONFIG_ERRORGAIN <<
> -					OMAP3430_ERRORGAIN_SHIFT);
>  		vp_reg[vp_id].vp_smpswaittimemin =
>  					(OMAP3_VP_VSTEPMIN_SMPSWAITTIMEMIN <<
>  					OMAP3430_SMPSWAITTIMEMIN_SHIFT);
> @@ -311,7 +329,18 @@ static void __init vp_reg_configure(int vp_id)
>  					OMAP3430_VSTEPMIN_SHIFT);
>  		vp_reg[vp_id].vp_stepmax = (OMAP3_VP_VSTEPMAX_VSTEPMAX <<
>  					OMAP3430_VSTEPMAX_SHIFT);
> -		vp_reg[vp_id].vp_timeout = (OMAP3_VP_VLIMITTO_TIMEOUT <<
> +		/*
> +		 * Use sys clk speed to convet the VP timeout in us to no of
                                        ^^^^^^
typo: convert
also, please change 'no of...' to 'number of...'

> +		 * clock cycles
> +		 */
> +		sys_ck = clk_get(NULL, "sys_ck");

need to check for error here

> +		sys_clk_speed = clk_get_rate(sys_ck);
> +		clk_put(sys_ck);
> +		/* Divide to avoid overflow */
> +		sys_clk_speed /= 1000;
> +		timeout_val = (sys_clk_speed * OMAP3_VP_VLIMITTO_TIMEOUT_US) /
> +					1000;
> +		vp_reg[vp_id].vp_timeout = (timeout_val <<
>  					OMAP3430_TIMEOUT_SHIFT);
>  	}
>  	/* TODO Extend this for OMAP4 ?? Or need a separate file  */
> @@ -338,7 +367,12 @@ static int vc_bypass_scale_voltage(u32 vdd, u8 target_vsel, u8 current_vsel)
>  		vc_cmdval0 |= (target_vsel << VC_CMD_ON_SHIFT);
>  		voltage_write_reg(vc_reg.vc_cmdval0_reg, vc_cmdval0);
>  		reg_addr = R_VDD1_SR_CONTROL;
> -
> +		/* OMAP3430 has errorgain varying btw higher and lower opp's */
> +		if (cpu_is_omap34xx())
> +			vp_reg[vdd].vp_errorgain = (((get_vdd1_opp() > 2) ?
> +					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
> +					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
> +					OMAP3430_ERRORGAIN_SHIFT);
>  	} else if (vdd == VDD2_OPP) {
>  		u32 vc_cmdval1;
>  
> @@ -347,12 +381,29 @@ static int vc_bypass_scale_voltage(u32 vdd, u8 target_vsel, u8 current_vsel)
>  		vc_cmdval1 |= (target_vsel << VC_CMD_ON_SHIFT);
>  		voltage_write_reg(vc_reg.vc_cmdval1_reg, vc_cmdval1);
>  		reg_addr = R_VDD2_SR_CONTROL;
> +		/* OMAP3430 has errorgain varying btw higher and lower opp's */
> +		if (cpu_is_omap34xx())
> +			vp_reg[vdd].vp_errorgain = (((get_vdd2_opp() > 2) ?
> +					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
> +					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
> +					OMAP3430_ERRORGAIN_SHIFT);
>  	} else {
>  		pr_warning("Wrong VDD passed in vc_bypass_scale_voltage %d\n",
>  				vdd);
>  		return false;
>  	}
>  
> +	/* OMAP3430 has errorgain varying btw higher and lower opp's */
> +	if (cpu_is_omap34xx()) {
> +		u32 errorgain =
> +			voltage_read_reg(vp_reg[vdd - 1].vp_offs.
> +				vp_vpconfig_reg);
> +		errorgain &= ~VP_ERRORGAIN_MASK;
> +		errorgain |= vp_reg[vdd].vp_errorgain;
> +
> +		voltage_write_reg(vp_reg[vdd - 1].vp_offs.vp_vpconfig_reg,
> +				errorgain);
> +	}
>  	vc_bypass_value = (target_vsel << VC_DATA_SHIFT) |
>  			(reg_addr << VC_REGADDR_SHIFT) |
>  			(R_SRI2C_SLAVE_ADDR << VC_SLAVEADDR_SHIFT);
> @@ -419,6 +470,10 @@ void omap_voltageprocessor_enable(int vp_id)
>  {
>  	u32 vpconfig;
>  
> +	/* If VP is already enabled, do nothing. Return */
> +	if (voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg) &
> +				VP_CONFIG_VPENABLE)
> +		return;
>  	/*
>  	 * This latching is required only if VC bypass method is used for
>  	 * voltage scaling during dvfs.
> @@ -439,21 +494,29 @@ void omap_voltageprocessor_enable(int vp_id)
>   */
>  void omap_voltageprocessor_disable(int vp_id)
>  {
> -	int i = 0;
>  	u32 vpconfig;
> +	int timeout = 0;
>  
> -	/* Wait for VP idle before disabling VP */
> -	while ((!voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_status_reg)) &&
> -				i++ < MAX_TRIES)
> -		udelay(1);
> -
> -	if (i >= MAX_TRIES)
> -		pr_warning("VP1 not idle, still going ahead with \
> -						VP1 disable\n");
> -	/* Disable VP1 */
> +	/* If VP is already disabled, do nothing. Return */
> +	if (!(voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg) &
> +				VP_CONFIG_VPENABLE))
> +		return;
> +	/* Disable VP */
>  	vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
>  	vpconfig &= ~VP_CONFIG_VPENABLE;
>  	voltage_write_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg, vpconfig);
> +
> +	/*
> +	 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
> +	 */
> +	while ((timeout++ < VP_IDLE_TIMEOUT) &&
> +			(!(voltage_read_reg(vp_reg[vp_id - 1].vp_offs
> +			.vp_status_reg))))
> +		udelay(1);

another use for omap_test_timeout()

> +	if (timeout >= VP_IDLE_TIMEOUT)
> +		pr_warning("VP%d idle timedout\n", vp_id);
> +	return;
>  }
>  
>  /**
> diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
> index 64c506c..c3203c9 100644
> --- a/arch/arm/mach-omap2/voltage.h
> +++ b/arch/arm/mach-omap2/voltage.h
> @@ -22,6 +22,7 @@ extern int get_vdd2_opp(void);
>  #define VP_CONFIG_INITVDD	OMAP3430_INITVDD
>  #define VP_FORCEUPDATE		OMAP3430_FORCEUPDATE
>  #define VP_CONFIG_VPENABLE	OMAP3430_VPENABLE
> +#define VP_ERRORGAIN_MASK	OMAP3430_ERRORGAIN_MASK
>  #define VP_INITVOLTAGE_MASK	OMAP3430_INITVOLTAGE_MASK
>  #define VP_INITVOLTAGE_SHIFT	OMAP3430_INITVOLTAGE_SHIFT
>  
> @@ -52,16 +53,17 @@ extern int get_vdd2_opp(void);
>   * board file or PMIC data structure
>   */
>  #define OMAP3_VP_CONFIG_ERROROFFSET		0x00
> -#define OMAP3_VP_CONFIG_ERRORGAIN		0x20
> -#define	OMAP3_VP_VSTEPMIN_SMPSWAITTIMEMIN	0x01F4
> +#define OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP	0x0C
> +#define OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP	0x18
> +#define	OMAP3_VP_VSTEPMIN_SMPSWAITTIMEMIN	0x3C
>  #define OMAP3_VP_VSTEPMIN_VSTEPMIN		0x1
> -#define OMAP3_VP_VSTEPMAX_SMPSWAITTIMEMAX	0x01F4
> +#define OMAP3_VP_VSTEPMAX_SMPSWAITTIMEMAX	0x3C
>  #define OMAP3_VP_VSTEPMAX_VSTEPMAX		0x04
> -#define OMAP3_VP1_VLIMITTO_VDDMIN		0x0
> -#define OMAP3_VP1_VLIMITTO_VDDMAX		0x3C
> +#define OMAP3_VP1_VLIMITTO_VDDMIN		0x14
> +#define OMAP3_VP1_VLIMITTO_VDDMAX		0x42
>  #define OMAP3_VP2_VLIMITTO_VDDMAX		0x2C
> -#define OMAP3_VP2_VLIMITTO_VDDMIN		0x0
> -#define OMAP3_VP_VLIMITTO_TIMEOUT		0xFFFF
> +#define OMAP3_VP2_VLIMITTO_VDDMIN		0x18
> +#define OMAP3_VP_VLIMITTO_TIMEOUT_US		0x200
>  
>  #define VOLTAGE_MOD	OMAP3430_GR_MOD
>  /* TODO OMAP4 VP register values if the same file is used for OMAP4*/
> -- 
> 1.7.0.rc1.33.g07cf0f

Kevin

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

* Re: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling
  2010-02-24  9:29                             ` [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling Thara Gopinath
  2010-02-24  9:29                               ` [PATCH 16/16] OMAP3: PM: Enabling Smartreflex Class 3 driver by default in pm defconfig Thara Gopinath
@ 2010-03-03  0:58                               ` Kevin Hilman
  2010-03-05 15:22                                 ` Gopinath, Thara
  1 sibling, 1 reply; 61+ messages in thread
From: Kevin Hilman @ 2010-03-03  0:58 UTC (permalink / raw)
  To: Thara Gopinath; +Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant

Thara Gopinath <thara@ti.com> writes:

> This patch introduces VP force update method of voltage scaling
> and enables it by default. The older method of vc bypass is now
> configuratble through a menu config option. VP force update is the
> hardware recommended method of voltage scaling.
>
> Signed-off-by: Thara Gopinath <thara@ti.com>

This should be a runtime option intead of a compile-time option.
Default should be HW recommended method, but board code should be able
to override.

Only did a quick glance at this, an some minor coding style issues below...

> ---
>  arch/arm/mach-omap2/voltage.c |  149 +++++++++++++++++++++++++++++++++++++++--
>  arch/arm/mach-omap2/voltage.h |    1 +
>  arch/arm/plat-omap/Kconfig    |   19 +++++
>  3 files changed, 162 insertions(+), 7 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
> index 49167c0..4f325af 100644
> --- a/arch/arm/mach-omap2/voltage.c
> +++ b/arch/arm/mach-omap2/voltage.c
> @@ -29,7 +29,8 @@
>  #include "prm-regbits-34xx.h"
>  #include "voltage.h"
>  
> -#define VP_IDLE_TIMEOUT 200
> +#define VP_IDLE_TIMEOUT 	200
> +#define VP_TRANXDONE_TIMEOUT	300
>  
>  /*
>   * OMAP3 Voltage controller SR parameters. TODO: Pass this info as part of
> @@ -70,6 +71,7 @@ struct vp_reg_info {
>  	u32 vp_vddmin;
>  	u32 vp_vddmax;
>  	u32 vp_timeout;
> +	u32 vp_tranxdone_status;
>  };
>  static struct vp_reg_info *vp_reg;
>  /*
> @@ -299,6 +301,8 @@ static void __init vp_reg_configure(int vp_id)
>  					OMAP3430_VDDMIN_SHIFT);
>  			vp_reg[vp_id].vp_vddmax = (OMAP3_VP1_VLIMITTO_VDDMAX <<
>  					OMAP3430_VDDMAX_SHIFT);
> +			vp_reg[vp_id].vp_tranxdone_status =
> +					OMAP3430_VP1_TRANXDONE_ST;
>  		} else if (vp_id == VP2) {
>  			/*
>  			 * OMAP3430 has error gain varying btw higher and
> @@ -312,6 +316,8 @@ static void __init vp_reg_configure(int vp_id)
>  					OMAP3430_VDDMIN_SHIFT);
>  			vp_reg[vp_id].vp_vddmax = (OMAP3_VP2_VLIMITTO_VDDMAX <<
>  					OMAP3430_VDDMAX_SHIFT);
> +			vp_reg[vp_id].vp_tranxdone_status =
> +					OMAP3430_VP2_TRANXDONE_ST;
>  		} else {
>  			pr_warning("Voltage processor%d does not exisit\
>  					in OMAP3 \n", vp_id);
> @@ -346,6 +352,131 @@ static void __init vp_reg_configure(int vp_id)
>  	/* TODO Extend this for OMAP4 ?? Or need a separate file  */
>  }
>  
> +#ifdef CONFIG_OMAP_VOLT_VPFORCEUPDATE
> +/* VP force update method of voltage scaling */
> +static int vp_forceupdate_scale_voltage(u32 vdd, u8 target_vsel,
> +				u8 current_vsel)
> +{
> +	u32 smps_steps = 0, smps_delay = 0;
> +	u32 vpconfig;
> +	int timeout = 0;
> +	int vp_id = vdd - 1;
> +
> +	if (!((vdd == VDD1_OPP) || (vdd == VDD2_OPP))) {
> +		pr_warning("Wrong vdd id passed to vp forceupdate\n");
> +		return false;
> +	}
> +
> +	smps_steps = abs(target_vsel - current_vsel);
> +
> +	/* OMAP3430 has errorgain varying btw higher and lower opp's */
> +	if (cpu_is_omap34xx()) {
> +		if (vdd == VDD1_OPP) {
> +			u32 vc_cmdval0;
> +
> +			vc_cmdval0 = voltage_read_reg(vc_reg.vc_cmdval0_reg);
> +			vc_cmdval0 &= ~VC_CMD_ON_MASK;
> +			vc_cmdval0 |= (target_vsel << VC_CMD_ON_SHIFT);
> +			voltage_write_reg(vc_reg.vc_cmdval0_reg, vc_cmdval0);
> +			vp_reg[vp_id].vp_errorgain = (((get_vdd1_opp() > 2) ?
> +					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
> +					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
> +					OMAP3430_ERRORGAIN_SHIFT);
> +		} else if (vdd == VDD2_OPP) {
> +			u32 vc_cmdval1;
> +
> +			vc_cmdval1 = voltage_read_reg(vc_reg.vc_cmdval1_reg);
> +			vc_cmdval1 &= ~VC_CMD_ON_MASK;
> +			vc_cmdval1 |= (target_vsel << VC_CMD_ON_SHIFT);
> +			voltage_write_reg(vc_reg.vc_cmdval1_reg, vc_cmdval1);
> +			vp_reg[vp_id].vp_errorgain = (((get_vdd2_opp() > 2) ?
> +					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
> +					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
> +					OMAP3430_ERRORGAIN_SHIFT);
> +		}
> +	}
> +
> +	/* Clear all pending TransactionDone interrupt/status. Typical latency
> +	 * is <3us
> +	 */
> +	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
> +		voltage_write_reg(PRM_IRQSTATUS_REG,
> +				vp_reg[vp_id].vp_tranxdone_status);
> +		if (!(voltage_read_reg(PRM_IRQSTATUS_REG) &
> +				vp_reg[vp_id].vp_tranxdone_status))
> +				break;
> +		udelay(1);
> +	}
> +
> +	if (timeout >= VP_TRANXDONE_TIMEOUT) {
> +		pr_warning("VP%d TRANXDONE timeout exceeded. Voltage change \
> +				aborted", vdd);
> +		return false;
> +	}
> +
> +	/* Configure for VP-Force Update */
> +	vpconfig = voltage_read_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg);
> +	vpconfig &= ~(VP_CONFIG_INITVDD | VP_FORCEUPDATE |
> +			VP_INITVOLTAGE_MASK | VP_ERRORGAIN_MASK);
> +	vpconfig |= ((target_vsel << VP_INITVOLTAGE_SHIFT) |
> +			vp_reg[vp_id].vp_errorgain);
> +	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
> +
> +	/* Trigger initVDD value copy to voltage processor */
> +	vpconfig |= VP_CONFIG_INITVDD;
> +	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
> +
> +	/* Force update of voltage */
> +	vpconfig |= VP_FORCEUPDATE;
> +	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
> +
> +	timeout = 0;
> +	/* Wait for TransactionDone. Typical latency is <200us.
> +	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
> +	 */

multi-line comment style

> +	while ((timeout++ < VP_TRANXDONE_TIMEOUT) &&
> +			(!(voltage_read_reg(PRM_IRQSTATUS_REG) &
> +			vp_reg[vp_id].vp_tranxdone_status)))
> +		udelay(1);
> +
> +	if (timeout >= VP_TRANXDONE_TIMEOUT)
> +		pr_warning("VP%d TRANXDONE timeout exceeded. TRANXDONE never \
> +			got set after the voltage update.Serious error!!!!\n",
> +			vdd);
> +
> +	/* Wait for voltage to settle with SW wait-loop */
> +	smps_delay = ((smps_steps * 125) / 40) + 2;
> +	udelay(smps_delay);
> +
> +	/* Disable TransactionDone interrupt , clear all status, clear
> +	 * control registers
> +	 */

muti-line comment

> +	timeout = 0;
> +	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
> +		voltage_write_reg(PRM_IRQSTATUS_REG,
> +				vp_reg[vp_id].vp_tranxdone_status);
> +		if (!(voltage_read_reg(PRM_IRQSTATUS_REG) &
> +				vp_reg[vp_id].vp_tranxdone_status))
> +				break;
> +		udelay(1);
> +	}
> +	if (timeout >= VP_TRANXDONE_TIMEOUT)
> +		pr_warning("VP%d TRANXDONE timeout exceeded while trying to \
> +			clear the TRANXDONE status\n", vdd);
> +
> +	vpconfig = voltage_read_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg);
> +	/* Clear initVDD copy trigger bit */
> +	vpconfig &= ~VP_CONFIG_INITVDD;
> +	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
> +	/* Clear force bit */
> +	vpconfig &= ~VP_FORCEUPDATE;
> +	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
> +
> +	return true;
> +}
> +#endif
> +
> +#ifdef CONFIG_OMAP_VOLT_VCBYPASS
>  /**
>   * vc_bypass_scale_voltage - VC bypass method of voltage scaling
>   */
> @@ -437,7 +568,7 @@ static int vc_bypass_scale_voltage(u32 vdd, u8 target_vsel, u8 current_vsel)
>  	udelay(smps_delay);
>  	return true;
>  }
> -
> +#endif
>  
>  static void __init init_voltageprocessors(void)
>  {
> @@ -474,13 +605,16 @@ void omap_voltageprocessor_enable(int vp_id)
>  	if (voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg) &
>  				VP_CONFIG_VPENABLE)
>  		return;
> +
> +#ifdef CONFIG_OMAP_VOLT_VCBYPASS
>  	/*
>  	 * This latching is required only if VC bypass method is used for
>  	 * voltage scaling during dvfs.
>  	 */
>  	vp_latch_vsel(vp_id - 1);
> -	vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
> +#endif
>  	/* Enable VP */
> +	vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
>  	voltage_write_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg,
>  				vpconfig | VP_CONFIG_VPENABLE);
>  }
> @@ -529,11 +663,12 @@ void omap_voltageprocessor_disable(int vp_id)
>   * for a particular voltage domain during dvfs or any other situation.
>   */
>  int omap_voltage_scale(int vdd, u8 target_vsel, u8 current_vsel)
> -{	/*
> -	 * TODO add VP force update method of voltage scaling
> -	 * and choose btw the two
> -	 */
> +{
> +#ifdef CONFIG_OMAP_VOLT_VCBYPASS
>  	return vc_bypass_scale_voltage(vdd, target_vsel, current_vsel);
> +#elif CONFIG_OMAP_VOLT_VPFORCEUPDATE
> +	return vp_forceupdate_scale_voltage(vdd, target_vsel, current_vsel);
> +#endif
>  }
>  
>  /**
> diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
> index c3203c9..615bde6 100644
> --- a/arch/arm/mach-omap2/voltage.h
> +++ b/arch/arm/mach-omap2/voltage.h
> @@ -17,6 +17,7 @@
>  extern int get_vdd1_opp(void);
>  extern int get_vdd2_opp(void);
>  
> +#define PRM_IRQSTATUS_REG	OMAP3430_PRM_IRQSTATUS_MPU
>  /* Generic VP definitions. Need to be redefined for OMAP4 */
>  #define VP_CONFIG_TIMEOUTEN	OMAP3430_TIMEOUTEN
>  #define VP_CONFIG_INITVDD	OMAP3430_INITVDD
> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
> index 9d286e6..1a611a9 100644
> --- a/arch/arm/plat-omap/Kconfig
> +++ b/arch/arm/plat-omap/Kconfig
> @@ -92,6 +92,25 @@ config OMAP_SMARTREFLEX_TESTING
>  
>  	  WARNING: Enabling this option may cause your device to hang!
>  
> +choice
> +	prompt "Choose Voltage Scale method"
> +	depends on ARCH_OMAP3 && PM
> +	default OMAP_VOLT_VPFORCEUPDATE
> +
> +config OMAP_VOLT_VPFORCEUPDATE
> +	bool "Voltage scaling via VP force update method"
> +	help
> +	 Say Y if you want to enable VP force update method
> +	 of voltage scaling. This is the h/w recomended way
> +	 of voltage scaling in OMAP3.
> +
> +config OMAP_VOLT_VCBYPASS
> +	bool "Voltage Scale via Voltage controller in bypass"
> +	help
> +	 Say Y if you want to enable VC Bypass method of voltage scaling.
> +	 Not the default recommended method.
> +endchoice
> +
>  config OMAP_RESET_CLOCKS
>  	bool "Reset unused clocks during boot"
>  	depends on ARCH_OMAP
> -- 
> 1.7.0.rc1.33.g07cf0f

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

* RE: [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer
  2010-03-02 18:28       ` Kevin Hilman
@ 2010-03-05 14:26         ` Gopinath, Thara
  2010-03-12  9:48         ` Gopinath, Thara
  1 sibling, 0 replies; 61+ messages in thread
From: Gopinath, Thara @ 2010-03-05 14:26 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand



>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>Sent: Tuesday, March 02, 2010 11:58 PM
>>To: Gopinath, Thara
>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
>>Vishwanath; Sawant, Anand
>>Subject: Re: [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods
>>and omap-device layer
>>
>>Thara Gopinath <thara@ti.com> writes:
>>
>>> This patch converts the exisitng smartreflex library into a
>>> platform driver with device , driver registrations using hardware mods.
>>> As part of this Ntarget values are passed as platform data.
>>>
>>> Signed-off-by: Thara Gopinath <thara@ti.com>
>>
>>Nice work Thara.  This is good.  Some minor comments below, but some
>>general comments first.
>>
>>As discussed, eventually (longer term) we'll want to move the driver
>>parts of this to a regulator driver.  To ease that transition, I think
>>it would be nice to start now by separating the driver portions of
>>this file from the device portions.
>>
>>You've already done a good job of keeping them separate in this file
>>(most of the device stuff is at the end) but I think having a separate
>>file is probably even better.  Maybe move driver stuff to sr_driver.c
>>and leave device stuff in smartreflex.c?  I don't care much about the
>>names at this point.

This is precisely why I kept the device part separate. But now I will make a separate file.
>>
>>> ---
>>>  arch/arm/mach-omap2/smartreflex.c |  470 +++++++++++++++++++++----------------
>>>  arch/arm/mach-omap2/smartreflex.h |   27 ++
>>>  2 files changed, 293 insertions(+), 204 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
>>> index 4a9c2e2..05c72b2 100644
>>> --- a/arch/arm/mach-omap2/smartreflex.c
>>> +++ b/arch/arm/mach-omap2/smartreflex.c
>>> @@ -14,7 +14,6 @@
>>>   * published by the Free Software Foundation.
>>>   */
>>>
>>> -
>>>  #include <linux/kernel.h>
>>>  #include <linux/init.h>
>>>  #include <linux/interrupt.h>
>>> @@ -33,6 +32,8 @@
>>>  #include <plat/clock.h>
>>>  #include <plat/opp.h>
>>>  #include <plat/opp_twl_tps.h>
>>> +#include <plat/omap_hwmod.h>
>>> +#include <plat/omap_device.h>
>>>
>>>  #include "prm.h"
>>>  #include "smartreflex.h"
>>> @@ -41,17 +42,14 @@
>>>  #define MAX_TRIES 100
>>>
>>>  struct omap_sr {
>>> -   int             srid;
>>> -   int             is_sr_reset;
>>> -   int             is_autocomp_active;
>>> -   struct clk      *clk;
>>> -   struct clk      *vdd_opp_clk;
>>> -   u32             clk_length;
>>> -   u32             req_opp_no;
>>> -   u32             opp1_nvalue, opp2_nvalue, opp3_nvalue, opp4_nvalue;
>>> -   u32             opp5_nvalue;
>>> -   u32             senp_mod, senn_mod;
>>> -   void __iomem    *srbase_addr;
>>> +   int                     srid;
>>> +   int                     is_sr_reset;
>>> +   int                     is_autocomp_active;
>>> +   struct clk              *vdd_opp_clk;
>>> +   u32                     clk_length;
>>> +   void __iomem            *srbase_addr;
>>> +   unsigned int            irq;
>>> +   struct platform_device  *pdev;
>>>     struct list_head        node;
>>>  };
>>>
>>> @@ -98,71 +96,22 @@ static struct omap_sr *_sr_lookup(int srid)
>>>
>>>  static int sr_clk_enable(struct omap_sr *sr)
>>>  {
>>> -   if (clk_enable(sr->clk) != 0) {
>>> -           pr_err("Could not enable %s\n", sr->clk->name);
>>> -           return -1;
>>> -   }
>>> +   struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>>>
>>> -   /* set fclk- active , iclk- idle */
>>> -   sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
>>> -                 SR_CLKACTIVITY_IOFF_FON);
>>> +   if (pdata->device_enable)
>>> +           pdata->device_enable(sr->pdev);
>>>     return 0;
>>>  }
>>>
>>>  static void sr_clk_disable(struct omap_sr *sr)
>>>  {
>>> -   /* set fclk, iclk- idle */
>>> -   sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
>>> -                 SR_CLKACTIVITY_IOFF_FOFF);
>>> -
>>> -   clk_disable(sr->clk);
>>> -   sr->is_sr_reset = 1;
>>> -}
>>> +   struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>>>
>>> -static struct omap_sr sr1 = {
>>> -   .srid                   = SR1,
>>> -   .is_sr_reset            = 1,
>>> -   .is_autocomp_active     = 0,
>>> -   .clk_length             = 0,
>>> -   .srbase_addr            = OMAP2_L4_IO_ADDRESS(OMAP34XX_SR1_BASE),
>>> -};
>>> -
>>> -static struct omap_sr sr2 = {
>>> -   .srid                   = SR2,
>>> -   .is_sr_reset            = 1,
>>> -   .is_autocomp_active     = 0,
>>> -   .clk_length             = 0,
>>> -   .srbase_addr            = OMAP2_L4_IO_ADDRESS(OMAP34XX_SR2_BASE),
>>> -};
>>> +   if (pdata->device_idle)
>>> +           pdata->device_idle(sr->pdev);
>>>
>>> -static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen)
>>> -{
>>> -   u32 gn, rn, mul;
>>> -
>>> -   for (gn = 0; gn < GAIN_MAXLIMIT; gn++) {
>>> -           mul = 1 << (gn + 8);
>>> -           rn = mul / sensor;
>>> -           if (rn < R_MAXLIMIT) {
>>> -                   *sengain = gn;
>>> -                   *rnsen = rn;
>>> -           }
>>> -   }
>>> -}
>>> -
>>> -static u32 cal_test_nvalue(u32 sennval, u32 senpval)
>>> -{
>>> -   u32 senpgain, senngain;
>>> -   u32 rnsenp, rnsenn;
>>> -
>>> -   /* Calculating the gain and reciprocal of the SenN and SenP values */
>>> -   cal_reciprocal(senpval, &senpgain, &rnsenp);
>>> -   cal_reciprocal(sennval, &senngain, &rnsenn);
>>> -
>>> -   return (senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |
>>> -           (senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |
>>> -           (rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |
>>> -           (rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT);
>>> +   sr->is_sr_reset = 1;
>>>  }
>>>
>>>  static u8 get_vdd1_opp(void)
>>> @@ -255,76 +204,6 @@ static void sr_set_clk_length(struct omap_sr *sr)
>>>     }
>>>  }
>>>
>>> -static void sr_set_efuse_nvalues(struct omap_sr *sr)
>>> -{
>>> -   if (sr->srid == SR1) {
>>> -           sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
>>> -                                   OMAP343X_SR1_SENNENABLE_MASK) >>
>>> -                                   OMAP343X_SR1_SENNENABLE_SHIFT;
>>> -           sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
>>> -                                   OMAP343X_SR1_SENPENABLE_MASK) >>
>>> -                                   OMAP343X_SR1_SENPENABLE_SHIFT;
>>> -
>>> -           sr->opp5_nvalue = omap_ctrl_readl(
>>> -                                   OMAP343X_CONTROL_FUSE_OPP5_VDD1);
>>> -           sr->opp4_nvalue = omap_ctrl_readl(
>>> -                                   OMAP343X_CONTROL_FUSE_OPP4_VDD1);
>>> -           sr->opp3_nvalue = omap_ctrl_readl(
>>> -                                   OMAP343X_CONTROL_FUSE_OPP3_VDD1);
>>> -           sr->opp2_nvalue = omap_ctrl_readl(
>>> -                                   OMAP343X_CONTROL_FUSE_OPP2_VDD1);
>>> -           sr->opp1_nvalue = omap_ctrl_readl(
>>> -                                   OMAP343X_CONTROL_FUSE_OPP1_VDD1);
>>> -   } else if (sr->srid == SR2) {
>>> -           sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
>>> -                                   OMAP343X_SR2_SENNENABLE_MASK) >>
>>> -                                   OMAP343X_SR2_SENNENABLE_SHIFT;
>>> -
>>> -           sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
>>> -                                   OMAP343X_SR2_SENPENABLE_MASK) >>
>>> -                                   OMAP343X_SR2_SENPENABLE_SHIFT;
>>> -
>>> -           sr->opp3_nvalue = omap_ctrl_readl(
>>> -                                   OMAP343X_CONTROL_FUSE_OPP3_VDD2);
>>> -           sr->opp2_nvalue = omap_ctrl_readl(
>>> -                                   OMAP343X_CONTROL_FUSE_OPP2_VDD2);
>>> -           sr->opp1_nvalue = omap_ctrl_readl(
>>> -                                   OMAP343X_CONTROL_FUSE_OPP1_VDD2);
>>> -   }
>>> -}
>>> -
>>> -/* Hard coded nvalues for testing purposes, may cause device to hang! */
>>> -static void sr_set_testing_nvalues(struct omap_sr *sr)
>>> -{
>>> -   if (sr->srid == SR1) {
>>> -           sr->senp_mod = 0x03;    /* SenN-M5 enabled */
>>> -           sr->senn_mod = 0x03;
>>> -
>>> -           /* calculate nvalues for each opp */
>>> -           sr->opp5_nvalue = cal_test_nvalue(0xacd + 0x330, 0x848 + 0x330);
>>> -           sr->opp4_nvalue = cal_test_nvalue(0x964 + 0x2a0, 0x727 + 0x2a0);
>>> -           sr->opp3_nvalue = cal_test_nvalue(0x85b + 0x200, 0x655 + 0x200);
>>> -           sr->opp2_nvalue = cal_test_nvalue(0x506 + 0x1a0, 0x3be + 0x1a0);
>>> -           sr->opp1_nvalue = cal_test_nvalue(0x373 + 0x100, 0x28c + 0x100);
>>> -   } else if (sr->srid == SR2) {
>>> -           sr->senp_mod = 0x03;
>>> -           sr->senn_mod = 0x03;
>>> -
>>> -           sr->opp3_nvalue = cal_test_nvalue(0x76f + 0x200, 0x579 + 0x200);
>>> -           sr->opp2_nvalue = cal_test_nvalue(0x4f5 + 0x1c0, 0x390 + 0x1c0);
>>> -           sr->opp1_nvalue = cal_test_nvalue(0x359, 0x25d);
>>> -   }
>>> -
>>> -}
>>> -
>>> -static void sr_set_nvalues(struct omap_sr *sr)
>>> -{
>>> -   if (SR_TESTING_NVALUES)
>>> -           sr_set_testing_nvalues(sr);
>>> -   else
>>> -           sr_set_efuse_nvalues(sr);
>>> -}
>>> -
>>>  static void sr_configure_vp(int srid)
>>>  {
>>>     u32 vpconfig;
>>> @@ -438,12 +317,13 @@ static void sr_configure(struct omap_sr *sr)
>>>  {
>>>     u32 sr_config;
>>>     u32 senp_en , senn_en;
>>> +   struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>>>
>>>     if (sr->clk_length == 0)
>>>             sr_set_clk_length(sr);
>>>
>>> -   senp_en = sr->senp_mod;
>>> -   senn_en = sr->senn_mod;
>>> +   senp_en = pdata->senp_mod;
>>> +   senn_en = pdata->senn_mod;
>>>     if (sr->srid == SR1) {
>>>             sr_config = SR1_SRCONFIG_ACCUMDATA |
>>>                     (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
>>> @@ -571,57 +451,33 @@ static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
>>>  {
>>>     u32 nvalue_reciprocal, v;
>>>     struct omap_opp *opp;
>>> +   struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>>>     int uvdc;
>>>     char vsel;
>>>
>>> -   sr->req_opp_no = target_opp_no;
>>> -
>>>     if (sr->srid == SR1) {
>>> -           switch (target_opp_no) {
>>> -           case 5:
>>> -                   nvalue_reciprocal = sr->opp5_nvalue;
>>> -                   break;
>>> -           case 4:
>>> -                   nvalue_reciprocal = sr->opp4_nvalue;
>>> -                   break;
>>> -           case 3:
>>> -                   nvalue_reciprocal = sr->opp3_nvalue;
>>> -                   break;
>>> -           case 2:
>>> -                   nvalue_reciprocal = sr->opp2_nvalue;
>>> -                   break;
>>> -           case 1:
>>> -                   nvalue_reciprocal = sr->opp1_nvalue;
>>> -                   break;
>>> -           default:
>>> -                   nvalue_reciprocal = sr->opp3_nvalue;
>>> -                   break;
>>> -           }
>>> -
>>>             opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
>>>             if (!opp)
>>>                     return false;
>>>     } else {
>>> -           switch (target_opp_no) {
>>> -           case 3:
>>> -                   nvalue_reciprocal = sr->opp3_nvalue;
>>> -                   break;
>>> -           case 2:
>>> -                   nvalue_reciprocal = sr->opp2_nvalue;
>>> -                   break;
>>> -           case 1:
>>> -                   nvalue_reciprocal = sr->opp1_nvalue;
>>> -                   break;
>>> -           default:
>>> -                   nvalue_reciprocal = sr->opp3_nvalue;
>>> -                   break;
>>> -           }
>>> -
>>>             opp = opp_find_by_opp_id(OPP_L3, target_opp_no);
>>>             if (!opp)
>>>                     return false;
>>>     }
>>>
>>> +   if (target_opp_no > pdata->no_opp) {
>>> +           pr_notice("Wrong target opp\n");
>>> +           return false;
>>> +   }
>>> +
>>> +   if (!pdata->sr_nvalue) {
>>> +           pr_notice("N target values does not exist for SR%d\n",
>>> +                                                           sr->srid);
>>> +           return false;
>>> +   }
>>> +
>>> +   nvalue_reciprocal = pdata->sr_nvalue[target_opp_no - 1];
>>> +
>>>     if (nvalue_reciprocal == 0) {
>>>             pr_notice("OPP%d doesn't support SmartReflex\n",
>>>                                                             target_opp_no);
>>> @@ -1033,49 +889,255 @@ static struct kobj_attribute sr_vdd2_autocomp = {
>>>     .store = omap_sr_vdd2_autocomp_store,
>>>  };
>>>
>>> +static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
>>> +{
>>> +   struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
>>> +   struct omap_device *odev = to_omap_device(pdev);
>>> +   int ret = 0;
>>> +
>>> +   if (WARN_ON(!sr_info))
>>> +           return -ENOMEM;
>>> +   sr_info->pdev = pdev;
>>> +   sr_info->srid = pdev->id + 1;
>>> +   sr_info->is_sr_reset = 1,
>>> +   sr_info->is_autocomp_active = 0;
>>> +   sr_info->clk_length = 0;
>>> +   sr_info->srbase_addr = odev->hwmods[0]->_rt_va;
>>
>>Minor issue: srbase_addr shouln't be needed.  You could convert all
>>the sr_read/write_reg to use omap_hwmod_[read|write].

I have not tried this approach till now. I will try it and let you know if there are any hiccups.

>>
>>> +   if (odev->hwmods[0]->mpu_irqs)
>>> +           sr_info->irq = odev->hwmods[0]->mpu_irqs[0].irq;
>>> +   sr_set_clk_length(sr_info);
>>> +
>>> +   if (sr_info->srid == SR1) {
>>> +           sr_info->vdd_opp_clk = clk_get(NULL, "dpll1_ck");
>>> +           ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
>>> +           if (ret)
>>> +                   pr_err("sysfs_create_file failed: %d\n", ret);
>>> +   } else {
>>> +           sr_info->vdd_opp_clk = clk_get(NULL, "l3_ick");
>>> +           ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
>>> +           if (ret)
>>> +                   pr_err("sysfs_create_file failed: %d\n", ret);
>>> +   }
>>> +
>>> +   /* Call the VPConfig */
>>> +   sr_configure_vp(sr_info->srid);
>>> +   odev->hwmods[0]->dev_attr = sr_info;
>>> +   list_add(&sr_info->node, &sr_list);
>>> +   pr_info("SmartReflex driver initialized\n");
>>> +
>>> +   return ret;
>>> +}
>>> +
>>> +static int __devexit omap_smartreflex_remove(struct platform_device *pdev)
>>> +{
>>> +   struct omap_device *odev = to_omap_device(pdev);
>>> +   struct omap_sr *sr_info = odev->hwmods[0]->dev_attr;
>>> +
>>> +   /* Disable Autocompensation if enabled before removing the module */
>>> +   if (sr_info->is_autocomp_active == 1)
>>> +           sr_stop_vddautocomap(sr_info->srid);
>>> +   list_del(&sr_info->node);
>>
>>should free sr_info too
>>
>>> +   return 0;
>>> +}
>>>
>>> +static struct platform_driver smartreflex_driver = {
>>> +   .probe          = omap_smartreflex_probe,
>>> +   .remove         = omap_smartreflex_remove,
>>> +   .driver         = {
>>> +           .name   = "smartreflex",
>>> +   },
>>> +};
>>>
>>> -static int __init omap3_sr_init(void)
>>> +static int __init sr_init(void)
>>>  {
>>>     int ret = 0;
>>>     u8 RdReg;
>>>
>>> +   /* TODO: Find an appropriate place for this */
>>>     /* Enable SR on T2 */
>>>     ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &RdReg,
>>>                           R_DCDC_GLOBAL_CFG);
>>> -
>>>     RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
>>>     ret |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
>>>                             R_DCDC_GLOBAL_CFG);
>>> -   if (cpu_is_omap34xx()) {
>>> -           sr1.clk = clk_get(NULL, "sr1_fck");
>>> -           sr2.clk = clk_get(NULL, "sr2_fck");
>>> -   }
>>> -   sr1.vdd_opp_clk = clk_get(NULL, "dpll1_ck");
>>> -   sr2.vdd_opp_clk = clk_get(NULL, "l3_ick");
>>> -   sr_set_clk_length(&sr1);
>>> -   sr_set_clk_length(&sr2);
>>>
>>> -   /* Call the VPConfig, VCConfig, set N Values. */
>>> -   sr_set_nvalues(&sr1);
>>> -   sr_configure_vp(SR1);
>>> +   ret = platform_driver_probe(&smartreflex_driver,
>>> +                           omap_smartreflex_probe);
>>>
>>> -   sr_set_nvalues(&sr2);
>>> -   sr_configure_vp(SR2);
>>> +   if (ret)
>>> +           pr_err("platform driver register failed for smartreflex");
>>> +   return 0;
>>> +}
>>>
>>> -   pr_info("SmartReflex driver initialized\n");
>>> +void __exit sr_exit(void)
>>> +{
>>> +   platform_driver_unregister(&smartreflex_driver);
>>> +}
>>> +late_initcall(sr_init);
>>> +module_exit(sr_exit);
>>>
>>> -   ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
>>> -   if (ret)
>>> -           pr_err("sysfs_create_file failed: %d\n", ret);
>>> +MODULE_DESCRIPTION("OMAP SMARTREFLEX DRIVER");
>>> +MODULE_LICENSE("GPL");
>>> +MODULE_ALIAS("platform:" DRIVER_NAME);
>>> +MODULE_AUTHOR("Texas Instruments Inc");
>>>
>>> -   ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
>>> -   if (ret)
>>> -           pr_err("sysfs_create_file failed: %d\n", ret);
>>> -   list_add(&sr1.node, &sr_list);
>>> -   list_add(&sr2.node, &sr_list);
>>> +/* Device registrations for smartreflex instances */
>>>
>>> -   return 0;
>>> +#define MAX_HWMOD_NAME_LEN 16
>>> +
>>> +struct omap_device_pm_latency omap_sr_latency[] = {
>>> +   {
>>> +           .deactivate_func = omap_device_idle_hwmods,
>>> +           .activate_func   = omap_device_enable_hwmods,
>>> +           .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST
>>> +   },
>>> +};
>>> +
>>> +/* Read EFUSE values from control registers */
>>> +static void __init omap3_sr_read_efuse(struct omap_smartreflex_data *sr_data,
>>> +                                           int sr_id)
>>> +{
>>> +   if (sr_id == SR1) {
>>> +           /*
>>> +            * TODO: When opp framework come into picture use appropriate
>>> +            * API's to find out number of opp's.
>>> +            */
>>> +           sr_data->no_opp = 5;
>>
>>This already exists. See opp_get_opp_count(OPP_MPU)
>>
>>> +           sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
>>> +                                   sr_data->no_opp , GFP_KERNEL);
>>> +           if (WARN_ON(!sr_data->sr_nvalue))
>>> +                   return;
>>> +
>>> +           sr_data->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
>>> +                                   OMAP343X_SR1_SENNENABLE_MASK) >>
>>> +                                   OMAP343X_SR1_SENNENABLE_SHIFT;
>>> +           sr_data->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
>>> +                                   OMAP343X_SR1_SENPENABLE_MASK) >>
>>> +                                   OMAP343X_SR1_SENPENABLE_SHIFT;
>>> +           sr_data->sr_nvalue[4] = omap_ctrl_readl(
>>> +                                   OMAP343X_CONTROL_FUSE_OPP5_VDD1);
>>> +           sr_data->sr_nvalue[3] = omap_ctrl_readl(
>>> +                                   OMAP343X_CONTROL_FUSE_OPP4_VDD1);
>>> +           sr_data->sr_nvalue[2] = omap_ctrl_readl(
>>> +                                   OMAP343X_CONTROL_FUSE_OPP3_VDD1);
>>> +           sr_data->sr_nvalue[1] = omap_ctrl_readl(
>>> +                                   OMAP343X_CONTROL_FUSE_OPP2_VDD1);
>>> +           sr_data->sr_nvalue[0] = omap_ctrl_readl(
>>> +                                   OMAP343X_CONTROL_FUSE_OPP1_VDD1);
>>> +   } else if (sr_id == SR2) {
>>> +           /*
>>> +            * TODO: When opp framework come into picture use appropriate
>>> +            * API's to find out number of opp's.
>>> +            */
>>> +           sr_data->no_opp = 3;
>>
>>ditto:  opp_get_opp_count(OPP_L3)
>>
>>> +           sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
>>> +                                   sr_data->no_opp , GFP_KERNEL);
>>> +           if (WARN_ON(!sr_data->sr_nvalue))
>>> +                   return;
>>> +
>>> +           sr_data->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
>>> +                                   OMAP343X_SR2_SENNENABLE_MASK) >>
>>> +                                   OMAP343X_SR2_SENNENABLE_SHIFT;
>>> +           sr_data->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
>>> +                                   OMAP343X_SR2_SENPENABLE_MASK) >>
>>> +                                   OMAP343X_SR2_SENPENABLE_SHIFT;
>>> +           sr_data->sr_nvalue[2] = omap_ctrl_readl(
>>> +                                   OMAP343X_CONTROL_FUSE_OPP3_VDD2);
>>> +           sr_data->sr_nvalue[1] = omap_ctrl_readl(
>>> +                                   OMAP343X_CONTROL_FUSE_OPP2_VDD2);
>>> +           sr_data->sr_nvalue[0] = omap_ctrl_readl(
>>> +                                   OMAP343X_CONTROL_FUSE_OPP1_VDD2);
>>> +   }
>>>  }
>>>
>>> -late_initcall(omap3_sr_init);
>>> +/* Hard coded nvalues for testing purposes, may cause device to hang! */
>>> +static void __init omap3_sr_set_testing_nvalues(
>>> +                           struct omap_smartreflex_data *sr_data, int srid)
>>> +{
>>> +   if (srid == SR1) {
>>> +           /*
>>> +            * TODO: When opp framework come into picture use appropriate
>>> +            * API's to find out number of opp's.
>>
>>> +            */
>>> +           sr_data->no_opp = 5;
>>> +           sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
>>> +                           sr_data->no_opp , GFP_KERNEL);
>>> +           if (WARN_ON(!sr_data->sr_nvalue))
>>> +                   return;
>>> +
>>> +           sr_data->senp_mod = 0x03;       /* SenN-M5 enabled */
>>> +           sr_data->senn_mod = 0x03;
>>> +           /* calculate nvalues for each opp */
>>> +           sr_data->sr_nvalue[4] = 0x0;
>>> +           sr_data->sr_nvalue[3] = 0x0;
>>> +           sr_data->sr_nvalue[2] = 0x0;
>>> +           sr_data->sr_nvalue[1] = 0x0;
>>> +           sr_data->sr_nvalue[0] = 0x0;
>>> +   } else if (srid == SR2) {
>>> +           /*
>>> +            * TODO: When opp framework come into picture use appropriate
>>> +            * API's to find out number of opp's.
>>> +            */
>>> +           sr_data->no_opp = 3;
>>> +           sr_data->sr_nvalue = kzalloc(sizeof(sr_data->sr_nvalue) *
>>> +                                   sr_data->no_opp , GFP_KERNEL);
>>> +           if (WARN_ON(!sr_data->sr_nvalue))
>>> +                   return;
>>> +
>>> +           sr_data->senp_mod = 0x03;       /* SenN-M5 enabled */
>>> +           sr_data->senn_mod = 0x03;
>>> +           sr_data->sr_nvalue[2] = 0x0;
>>> +           sr_data->sr_nvalue[1] = 0x0;
>>> +           sr_data->sr_nvalue[0] = 0x0;
>>> +   }
>>> +}
>>
>>Hmm, you set all the testing nvalues to zero.  Is there a reason you
>>didn't keep the previous ones?  I don't really remember where those
>>came from, so not sure if they are useful or not.  I'll let you
>>decide, but if you remove them, update the changelog accordingly so
>>there are no surprises.

Oops my bad.. Earlier we ere calculating the test N values. I had to remove the calculation part due to TI propriety reasons. I intended to put the calculated values here but forgot. I will correct this in V2.

Regards
Thara
>>
>>Kevin
>>
>>> +static void __init sr_set_nvalues(struct omap_smartreflex_data
>>> +*sr_data, int srid) { if (cpu_is_omap343x()) { if
>>> +(SR_TESTING_NVALUES) omap3_sr_set_testing_nvalues(sr_data, srid);
>>> +else omap3_sr_read_efuse(sr_data, srid);
>>> +   }
>>> +}
>>> +
>>> +static int __init omap_devinit_smartreflex(void)
>>> +{
>>> +   int i = 0;
>>> +   char *name = "smartreflex";
>>> +
>>> +   do {
>>> +           struct omap_smartreflex_data *sr_data;
>>> +           struct omap_device *od;
>>> +           struct omap_hwmod *oh;
>>> +           char oh_name[MAX_HWMOD_NAME_LEN];
>>> +
>>> +           snprintf(oh_name, MAX_HWMOD_NAME_LEN, "sr%d_hwmod", i + 1);
>>> +           oh = omap_hwmod_lookup(oh_name);
>>> +           if (!oh)
>>> +                   break;
>>> +
>>> +           sr_data = kzalloc(sizeof(struct omap_smartreflex_data),
>>> +                                                           GFP_KERNEL);
>>> +           if (WARN_ON(!sr_data))
>>> +                   return -ENOMEM;
>>> +
>>> +           sr_data->init_enable = false;
>>> +           sr_data->device_enable = omap_device_enable;
>>> +           sr_data->device_shutdown = omap_device_shutdown;
>>> +           sr_data->device_idle = omap_device_idle;
>>> +           sr_set_nvalues(sr_data, i + 1);
>>> +
>>> +           od = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
>>> +                                  omap_sr_latency,
>>> +                                  ARRAY_SIZE(omap_sr_latency));
>>> +           WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
>>> +                name, oh->name);
>>> +           i++;
>>> +   } while (1);
>>> +
>>> +   return 0;
>>> +}
>>> +arch_initcall(omap_devinit_smartreflex);
>>> diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
>>> index 2a0e823..f1e8676 100644
>>> --- a/arch/arm/mach-omap2/smartreflex.h
>>> +++ b/arch/arm/mach-omap2/smartreflex.h
>>> @@ -14,6 +14,8 @@
>>>   * published by the Free Software Foundation.
>>>   */
>>>
>>> +#include <linux/platform_device.h>
>>> +
>>>  #define PHY_TO_OFF_PM_MASTER(p)            (p - 0x36)
>>>  #define PHY_TO_OFF_PM_RECIEVER(p)  (p - 0x5b)
>>>  #define PHY_TO_OFF_PM_INT(p)               (p - 0x2e)
>>> @@ -243,6 +245,31 @@ extern u32 current_vdd2_opp;
>>>   * do anything.
>>>   */
>>>  #ifdef CONFIG_OMAP_SMARTREFLEX
>>> +/*
>>> + * omap_smartreflex_data - Smartreflex platform data
>>> + *
>>> + * @senp_mod       : SENPENABLE value for the sr
>>> + * @senn_mod       : SENNENABLE value for sr
>>> + * @sr_nvalue      : array of n target values for sr
>>> + * @no_opp : number of opp's for this SR
>>> + * @init_enable    : whether this sr module needs to enabled at boot up or not
>>> + * @device_enable  : fn pointer to be populated with omap_device
>>> + *                         enable API
>>> + * @device_shutdown        : fn pointer to be populated with omap_device
>>> + *                         shutdown API
>>> + * @device_idle            : fn pointer to be pouplated with omap_device idle API
>>> + */
>>> +struct omap_smartreflex_data {
>>> +   u32             senp_mod;
>>> +   u32             senn_mod;
>>> +   u32             *sr_nvalue;
>>> +   int             no_opp;
>>> +   bool            init_enable;
>>> +   int (*device_enable)(struct platform_device *pdev);
>>> +   int (*device_shutdown)(struct platform_device *pdev);
>>> +   int (*device_idle)(struct platform_device *pdev);
>>> +};
>>> +
>>>  void enable_smartreflex(int srid);
>>>  void disable_smartreflex(int srid);
>>>  int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel);
>>> --
>>> 1.7.0.rc1.33.g07cf0f

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

* RE: [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c
  2010-03-02 18:44             ` [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c Kevin Hilman
@ 2010-03-05 15:00               ` Gopinath, Thara
  2010-03-05 18:29                 ` Kevin Hilman
  0 siblings, 1 reply; 61+ messages in thread
From: Gopinath, Thara @ 2010-03-05 15:00 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand



>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>Sent: Wednesday, March 03, 2010 12:14 AM
>>To: Gopinath, Thara
>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
>>Vishwanath; Sawant, Anand
>>Subject: Re: [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c
>>
>>Thara Gopinath <thara@ti.com> writes:
>>
>>> OMAP3 smartreflex modules are capable of two different classes
>>> of implementaion -
>>>     Class-2: Continuous Software Calibration
>>>     Class-3: Continuous Hardware Calibration.
>>> OMAP3 along with T2/Gaia supports the Class 3 implementaion.
>>> With a different PMIC it can support Class 2 implementaion also.
>>>
>>> The idea behind this patch is that smartreflex.c should be able
>>> to support both the classes of Smartreflex and the class specific
>>> details for smartreflex should stay out of this file in a separate
>>> class file.
>>> This patch introduces smartreflex class specific hooks in
>>> smartreflex.c. This patch only takes care of smartreflex enable
>>> disable hooks which differ between Class 2 and Class 3. There
>>> are some register setting changes between both the classes which
>>> will be taken care of in a later patch.
>>> This will form the base for adding class specific
>>> drivers in later patches.
>>>
>>> Signed-off-by: Thara Gopinath <thara@ti.com>
>>
>>Minor nit: the name change for omap_smartreflex_[enable|disable] is
>>unrelated to this change and should be a separate patch to go early in
>>the series.

Hi Kevin,

I agree the name change need not be part of this patch. But is it necessary for it to be separated out. I am asking this because when I send out the review comments fixed patch set I can send them out as V2 . But if I split this change into a separate patch the patch set will contain 17 patches instead of 16 patches and will have to be submitted as a new patch set not as V2. Do let me know your thoughts on this.

Regards
Thara

>>
>>Kevin
>>
>>> ---
>>>  arch/arm/mach-omap2/pm34xx.c      |    8 +-
>>>  arch/arm/mach-omap2/smartreflex.c |  251 ++++++++++++++++++++----------------
>>>  arch/arm/mach-omap2/smartreflex.h |   48 ++++++--
>>>  3 files changed, 182 insertions(+), 125 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
>>> index cf9ca23..ece5195 100644
>>> --- a/arch/arm/mach-omap2/pm34xx.c
>>> +++ b/arch/arm/mach-omap2/pm34xx.c
>>> @@ -430,9 +430,9 @@ void omap_sram_idle(void)
>>>      * Only needed if we are going to enter retention or off.
>>>      */
>>>     if (mpu_next_state <= PWRDM_POWER_RET)
>>> -           disable_smartreflex(SR1);
>>> +           omap_smartreflex_disable(SR1);
>>>     if (core_next_state <= PWRDM_POWER_RET)
>>> -           disable_smartreflex(SR2);
>>> +           omap_smartreflex_disable(SR2);
>>>
>>>     /* CORE */
>>>     if (core_next_state < PWRDM_POWER_ON) {
>>> @@ -531,9 +531,9 @@ void omap_sram_idle(void)
>>>      * retention or off
>>>      */
>>>     if (mpu_next_state <= PWRDM_POWER_RET)
>>> -           enable_smartreflex(SR1);
>>> +           omap_smartreflex_enable(SR1);
>>>     if (core_next_state <= PWRDM_POWER_RET)
>>> -           enable_smartreflex(SR2);
>>> +           omap_smartreflex_enable(SR2);
>>>
>>>     /* PER */
>>>     if (per_next_state < PWRDM_POWER_ON) {
>>> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
>>> index c00925d..ba9f899 100644
>>> --- a/arch/arm/mach-omap2/smartreflex.c
>>> +++ b/arch/arm/mach-omap2/smartreflex.c
>>> @@ -55,6 +55,7 @@ struct omap_sr {
>>>
>>>  /* sr_list contains all the instances of smartreflex module */
>>>  static LIST_HEAD(sr_list);
>>> +static struct omap_smartreflex_class_data *sr_class;
>>>
>>>  #define SR_REGADDR(offs)   (sr->srbase_addr + offset)
>>>
>>> @@ -388,14 +389,86 @@ static int sr_reset_voltage(int srid)
>>>     return 0;
>>>  }
>>>
>>> -static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
>>> +static void sr_start_vddautocomap(int srid)
>>> +{
>>> +   struct omap_sr *sr = _sr_lookup(srid);
>>> +
>>> +   if (!sr) {
>>> +           pr_warning("omap_sr struct corresponding to SR%d not found\n",
>>> +                                                           srid);
>>> +           return;
>>> +   }
>>> +
>>> +   if (!sr_class || !(sr_class->enable)) {
>>> +           pr_warning("smartreflex class driver not registered\n");
>>> +           return;
>>> +   }
>>> +
>>> +   if (sr->is_sr_reset == 1) {
>>> +           sr_clk_enable(sr);
>>> +           sr_configure(sr);
>>> +   }
>>> +
>>> +   sr->is_autocomp_active = 1;
>>> +   if (!sr_class->enable(srid)) {
>>> +           sr->is_autocomp_active = 0;
>>> +           if (sr->is_sr_reset == 1)
>>> +                   sr_clk_disable(sr);
>>> +   }
>>> +}
>>> +
>>> +static void sr_stop_vddautocomap(int srid)
>>> +{
>>> +   struct omap_sr *sr = _sr_lookup(srid);
>>> +
>>> +   if (!sr) {
>>> +           pr_warning("omap_sr struct corresponding to SR%d not found\n",
>>> +                                                           srid);
>>> +           return;
>>> +   }
>>> +   if (!sr_class || !(sr_class->disable)) {
>>> +           pr_warning("smartreflex class driver not registered\n");
>>> +           return;
>>> +   }
>>> +
>>> +   if (sr->is_autocomp_active == 1) {
>>> +           sr_class->disable(srid);
>>> +           sr_clk_disable(sr);
>>> +           sr->is_autocomp_active = 0;
>>> +           /* Reset the volatage for current OPP */
>>> +           sr_reset_voltage(srid);
>>> +   }
>>> +
>>> +}
>>> +
>>> +/* Public Functions */
>>> +
>>> +/**
>>> + * sr_enable : Enables the smartreflex module.
>>> + * @srid - The id of the sr module to be enabled.
>>> + * @target_opp_no - The OPP at which the Voltage domain associated with
>>> + * the smartreflex module is operating at. This is required only to program
>>> + * the correct Ntarget value.
>>> + *
>>> + * This API is to be called from the smartreflex class driver to
>>> + * enable a smartreflex module. Returns true on success.Returns false if the
>>> + * target opp id passed is wrong or if ntarget value is wrong.
>>> + */
>>> +int sr_enable(int srid, u32 target_opp_no)
>>>  {
>>>     u32 nvalue_reciprocal, v;
>>> +   struct omap_sr *sr = _sr_lookup(srid);
>>>     struct omap_opp *opp;
>>>     struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>>>     int uvdc;
>>>     char vsel;
>>>
>>> +   if (!sr) {
>>> +           pr_warning("omap_sr struct corresponding to SR%d not found\n",
>>> +                                                           srid);
>>> +           return false;
>>> +   }
>>> +
>>>     if (sr->srid == SR1) {
>>>             opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
>>>             if (!opp)
>>> @@ -477,8 +550,16 @@ static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
>>>     return true;
>>>  }
>>>
>>> -static void sr_disable(struct omap_sr *sr)
>>> +/**
>>> + * sr_disable : Disables the smartreflex module.
>>> + * @srid - The id of the sr module to be disabled.
>>> + *
>>> + * This API is to be called from the smartreflex class driver to
>>> + * disable a smartreflex module.
>>> + */
>>> +void sr_disable(int srid)
>>>  {
>>> +   struct omap_sr *sr = _sr_lookup(srid);
>>>     u32 i = 0;
>>>
>>>     sr->is_sr_reset = 1;
>>> @@ -518,9 +599,19 @@ static void sr_disable(struct omap_sr *sr)
>>>     }
>>>  }
>>>
>>> -
>>> -void sr_start_vddautocomap(int srid, u32 target_opp_no)
>>> +/**
>>> + * omap_smartreflex_enable : API to enable SR clocks and to call into the
>>> + * registered smartreflex class enable API.
>>> + * @srid - The id of the sr module to be enabled.
>>> + *
>>> + * This API is to be called from the kernel in order to enable
>>> + * a particular smartreflex module. This API will do the initial
>>> + * configurations to turn on the smartreflex module and in turn call
>>> + * into the registered smartreflex class enable API.
>>> + */
>>> +void omap_smartreflex_enable(int srid)
>>>  {
>>> +   u32 target_opp_no = 0;
>>>     struct omap_sr *sr = _sr_lookup(srid);
>>>
>>>     if (!sr) {
>>> @@ -528,52 +619,8 @@ void sr_start_vddautocomap(int srid, u32 target_opp_no)
>>>                                                             srid);
>>>             return;
>>>     }
>>> -
>>> -   if (sr->is_sr_reset == 1) {
>>> -           sr_clk_enable(sr);
>>> -           sr_configure(sr);
>>> -   }
>>> -
>>> -   sr->is_autocomp_active = 1;
>>> -   if (!sr_enable(sr, target_opp_no)) {
>>> -           sr->is_autocomp_active = 0;
>>> -           if (sr->is_sr_reset == 1)
>>> -                   sr_clk_disable(sr);
>>> -   }
>>> -}
>>> -EXPORT_SYMBOL(sr_start_vddautocomap);
>>> -
>>> -int sr_stop_vddautocomap(int srid)
>>> -{
>>> -   struct omap_sr *sr = _sr_lookup(srid);
>>> -
>>> -   if (!sr) {
>>> -           pr_warning("omap_sr struct corresponding to SR%d not found\n",
>>> -                                                           srid);
>>> -           return false;
>>> -   }
>>> -
>>> -   if (sr->is_autocomp_active == 1) {
>>> -           sr_disable(sr);
>>> -           sr_clk_disable(sr);
>>> -           sr->is_autocomp_active = 0;
>>> -           /* Reset the volatage for current OPP */
>>> -           sr_reset_voltage(srid);
>>> -           return true;
>>> -   } else
>>> -           return false;
>>> -
>>> -}
>>> -EXPORT_SYMBOL(sr_stop_vddautocomap);
>>> -
>>> -void enable_smartreflex(int srid)
>>> -{
>>> -   u32 target_opp_no = 0;
>>> -   struct omap_sr *sr = _sr_lookup(srid);
>>> -
>>> -   if (!sr) {
>>> -           pr_warning("omap_sr struct corresponding to SR%d not found\n",
>>> -                                                           srid);
>>> +   if (!sr_class || !(sr_class->enable)) {
>>> +           pr_warning("smartreflex class driver not registered\n");
>>>             return;
>>>     }
>>>
>>> @@ -581,26 +628,24 @@ void enable_smartreflex(int srid)
>>>             if (sr->is_sr_reset == 1) {
>>>                     /* Enable SR clks */
>>>                     sr_clk_enable(sr);
>>> -
>>> -                   if (srid == SR1)
>>> -                           target_opp_no = get_vdd1_opp();
>>> -                   else if (srid == SR2)
>>> -                           target_opp_no = get_vdd2_opp();
>>> -
>>> -                   if (!target_opp_no) {
>>> -                           pr_info("Current OPP unknown \
>>> -                                            Cannot configure SR\n");
>>> -                   }
>>> -
>>>                     sr_configure(sr);
>>>
>>> -                   if (!sr_enable(sr, target_opp_no))
>>> +                   if (!sr_class->enable(srid))
>>>                             sr_clk_disable(sr);
>>>             }
>>>     }
>>>  }
>>>
>>> -void disable_smartreflex(int srid)
>>> +/**
>>> + * omap_smartreflex_disable : API to disable SR clocks and to call into the
>>> + * registered smartreflex class disable API.
>>> + * @srid - The id of the sr module to be disabled.
>>> + *
>>> + * This API is to be called from the kernel in order to disable
>>> + * a particular smartreflex module. This API will in turn call
>>> + * into the registered smartreflex class disable API.
>>> + */
>>> +void omap_smartreflex_disable(int srid)
>>>  {
>>>     u32 i = 0;
>>>     struct omap_sr *sr = _sr_lookup(srid);
>>> @@ -610,54 +655,43 @@ void disable_smartreflex(int srid)
>>>                                                             srid);
>>>             return;
>>>     }
>>> +   if (!sr_class || !(sr_class->disable)) {
>>> +           pr_warning("smartreflex class driver not registered\n");
>>> +           return;
>>> +   }
>>>
>>>     if (sr->is_autocomp_active == 1) {
>>>             if (sr->is_sr_reset == 0) {
>>> -
>>> -                   sr->is_sr_reset = 1;
>>> -                   /* SRCONFIG - disable SR */
>>> -                   sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
>>> -                                                   ~SRCONFIG_SRENABLE);
>>> -
>>> +                   sr_class->disable(srid);
>>>                     /* Disable SR clk */
>>>                     sr_clk_disable(sr);
>>> -                   if (sr->srid == SR1) {
>>> -                           /* Wait for VP idle before disabling VP */
>>> -                           while ((!prm_read_mod_reg(OMAP3430_GR_MOD,
>>> -                                           OMAP3_PRM_VP1_STATUS_OFFSET))
>>> -                                           && i++ < MAX_TRIES)
>>> -                                   udelay(1);
>>> -
>>> -                           if (i >= MAX_TRIES)
>>> -                                   pr_warning("VP1 not idle, still going \
>>> -                                           ahead with VP1 disable\n");
>>> -
>>> -                           /* Disable VP1 */
>>> -                           prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE,
>>> -                                           OMAP3430_GR_MOD,
>>> -                                           OMAP3_PRM_VP1_CONFIG_OFFSET);
>>> -                   } else if (sr->srid == SR2) {
>>> -                           /* Wait for VP idle before disabling VP */
>>> -                           while ((!prm_read_mod_reg(OMAP3430_GR_MOD,
>>> -                                           OMAP3_PRM_VP2_STATUS_OFFSET))
>>> -                                           && i++ < MAX_TRIES)
>>> -                                   udelay(1);
>>> -
>>> -                           if (i >= MAX_TRIES)
>>> -                                   pr_warning("VP2 not idle, still going \
>>> -                                            ahead with VP2 disable\n");
>>> -
>>> -                           /* Disable VP2 */
>>> -                           prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE,
>>> -                                           OMAP3430_GR_MOD,
>>> -                                           OMAP3_PRM_VP2_CONFIG_OFFSET);
>>> -                   }
>>>                     /* Reset the volatage for current OPP */
>>>                     sr_reset_voltage(srid);
>>>             }
>>>     }
>>>  }
>>>
>>> +/**
>>> + * omap_sr_register_class : API to register a smartreflex class parameters.
>>> + * @class_data - The structure containing various sr class specific data.
>>> + *
>>> + * This API is to be called by the smartreflex class driver to register itself
>>> + * with the smartreflex driver during init.
>>> + */
>>> +void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
>>> +{
>>> +   if (!class_data) {
>>> +           pr_warning("Smartreflex class data passed is NULL\n");
>>> +           return;
>>> +   }
>>> +
>>> +   if (sr_class) {
>>> +           pr_warning("Smartreflex class driver already registered\n");
>>> +           return;
>>> +   }
>>> +   sr_class = class_data;
>>> +}
>>> +
>>>  /* Voltage Scaling using SR VCBYPASS */
>>>  int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
>>>                                     u8 target_vsel, u8 current_vsel)
>>> @@ -730,9 +764,9 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
>>>
>>>     if (sr_status) {
>>>             if (vdd == VDD1_OPP)
>>> -                   sr_start_vddautocomap(SR1, target_opp_no);
>>> +                   sr_start_vddautocomap(SR1);
>>>             else if (vdd == VDD2_OPP)
>>> -                   sr_start_vddautocomap(SR2, target_opp_no);
>>> +                   sr_start_vddautocomap(SR2);
>>>     }
>>>
>>>     return 0;
>>> @@ -762,17 +796,10 @@ static int omap_sr_autocomp_store(void *data, u64 val)
>>>                                                     sr_info->srid);
>>>             return 0;
>>>     }
>>> -   if (val == 0) {
>>> +   if (val == 0)
>>>             sr_stop_vddautocomap(sr_info->srid);
>>> -   } else {
>>> -           u32 current_opp;
>>> -
>>> -           if (sr_info->srid == SR1)
>>> -                   current_opp = get_vdd1_opp();
>>> -           else
>>> -                   current_opp = get_vdd2_opp();
>>> -           sr_start_vddautocomap(sr_info->srid, current_opp);
>>> -   }
>>> +   else
>>> +           sr_start_vddautocomap(sr_info->srid);
>>>     return 0;
>>>  }
>>>
>>> diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
>>> index 572cdca..a59a073 100644
>>> --- a/arch/arm/mach-omap2/smartreflex.h
>>> +++ b/arch/arm/mach-omap2/smartreflex.h
>>> @@ -243,12 +243,27 @@ extern u32 current_vdd2_opp;
>>>  #define SR_TESTING_NVALUES         0
>>>  #endif
>>>
>>> -/*
>>> - * Smartreflex module enable/disable interface.
>>> - * NOTE: if smartreflex is not enabled from sysfs, these functions will not
>>> - * do anything.
>>> - */
>>>  #ifdef CONFIG_OMAP_SMARTREFLEX
>>> +/**
>>> + * omap_smartreflex_class_data : Structure to be populated by
>>> + * Smartreflex class driver with corresponding class enable disable API's
>>> + *
>>> + * @enable - API to enable a particular class smaartreflex.
>>> + * @disable - API to disable a particular class smartreflex.
>>> + * @notify - API to notify the class driver about an event in SR. Not needed
>>> + *         for class3.
>>> + * @notify_flags - specify the events to be notified to the class driver
>>> + * @class_type - specify which smartreflex class. Can be used by the SR driver
>>> + *                 to tkae any class based decisions.
>>> + */
>>> +struct omap_smartreflex_class_data {
>>> +   int (*enable)(int sr_id);
>>> +   int (*disable)(int sr_id);
>>> +   int (*notify)(int sr_id, u32 status);
>>> +   u8 notify_flags;
>>> +   u8 class_type;
>>> +};
>>> +
>>>  /*
>>>   * omap_smartreflex_data - Smartreflex platform data
>>>   *
>>> @@ -274,11 +289,26 @@ struct omap_smartreflex_data {
>>>     int (*device_idle)(struct platform_device *pdev);
>>>  };
>>>
>>> -void enable_smartreflex(int srid);
>>> -void disable_smartreflex(int srid);
>>> +/*
>>> + * Smartreflex module enable/disable interface.
>>> + * NOTE: if smartreflex is not enabled from sysfs, these functions will not
>>> + * do anything.
>>> + */
>>> +void omap_smartreflex_enable(int srid);
>>> +void omap_smartreflex_disable(int srid);
>>> +
>>> +/**
>>> + * Smartreflex driver hooks to be called from Smartreflex class driver
>>> + */
>>> +int sr_enable(int srid, u32 target_opp_no);
>>> +void sr_disable(int srid);
>>> +
>>> +/**
>>> + * API to register the smartreflex class driver with the smartreflex driver
>>> + */
>>> +void omap_sr_register_class(struct omap_smartreflex_class_data *class_data);
>>> +
>>>  int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel);
>>> -void sr_start_vddautocomap(int srid, u32 target_opp_no);
>>> -int sr_stop_vddautocomap(int srid);
>>>  #else
>>>  static inline void enable_smartreflex(int srid) {}
>>>  static inline void disable_smartreflex(int srid) {}
>>> --
>>> 1.7.0.rc1.33.g07cf0f

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

* RE: [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver.
  2010-03-02 19:36               ` [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver Kevin Hilman
@ 2010-03-05 15:03                 ` Gopinath, Thara
  2010-03-05 19:12                   ` Kevin Hilman
  0 siblings, 1 reply; 61+ messages in thread
From: Gopinath, Thara @ 2010-03-05 15:03 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand



>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>Sent: Wednesday, March 03, 2010 1:07 AM
>>To: Gopinath, Thara
>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
>>Vishwanath; Sawant, Anand
>>Subject: Re: [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver.
>>
>>Thara Gopinath <thara@ti.com> writes:
>>
>>> This patch adds smartreflex class 3 driver. This driver hooks
>>> up with the generic smartreflex driver smartreflex.c to abstract
>>> out class specific implementations out of the generic driver.
>>>
>>> Signed-off-by: Thara Gopinath <thara@ti.com>
>>
>>I like this abstraction, but I don't like that it still uses OPP IDs.
>>
>>So, before doing this, we need to get rid of OPP IDs from the
>>smartreflex layer and keep OPP ID usage isolated to SRF.
>>
>>It appears the only reason we need OPP IDs in SR is because the Nvalue
>>tables are indexed by OPP ID in sr_enable().

Actually this is not true. If you see my patch14 sr err_minlimit and vp errorgain are opp dependent. In fact for 3630 for VDD1 there are 4 supported OPP's and 4 different values for err_minlimit and errorgain - one for each opp. So we might still need the opp id.
>>
>>One way to fix this is for this SR layer to keep it's own mapping of
>>voltage to nvalue.  So instead of taking OPP ID, sr_enable() should
>>take a voltage (or frequency) and use that to look up the nvalue.
>>
>>a couple other minor comments below...

Thank you for these comments and I will fix them in V2

Regards
Thara
>>
>>> ---
>>>  arch/arm/mach-omap2/Makefile             |    1 +
>>>  arch/arm/mach-omap2/smartreflex-class3.c |   49 ++++++++++++++++++++++++++++++
>>>  arch/arm/plat-omap/Kconfig               |   11 ++++++-
>>>  3 files changed, 60 insertions(+), 1 deletions(-)
>>>  create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
>>>
>>> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
>>> index f6f901f..cd8ab86 100644
>>> --- a/arch/arm/mach-omap2/Makefile
>>> +++ b/arch/arm/mach-omap2/Makefile
>>> @@ -52,6 +52,7 @@ obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o
>>>  obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o cpuidle34xx.o
>>>  obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
>>>  obj-$(CONFIG_OMAP_SMARTREFLEX)	+= smartreflex.o
>>> +obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)	+= smartreflex-class3.o
>>>
>>>  AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
>>>  AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a
>>> diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
>>> new file mode 100644
>>> index 0000000..d2e98a5
>>> --- /dev/null
>>> +++ b/arch/arm/mach-omap2/smartreflex-class3.c
>>> @@ -0,0 +1,49 @@
>>> +/*
>>> + * Smart reflex Class 3 specific implementations
>>> + *
>>> + * Copyright (C) 2009 Texas Instruments, Inc.
>>
>>2010
>>
>>> + * Thara Gopinath <thara@ti.com>
>>> + *
>>> + * 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 "smartreflex.h"
>>> +
>>> +static int sr_class3_enable(int id)
>>> +{
>>> +	int target_opp_no = 0;
>>
>>insert blank line
>>
>>> +	if (id == SR1)
>>> +		target_opp_no = get_vdd1_opp();
>>> +	else if (id == SR2)
>>> +		target_opp_no = get_vdd2_opp();
>>> +	if (!target_opp_no) {
>>> +		pr_warning("Targetopp not known.Cannot enable SR%d\n", id);
>>> +		return false;
>>> +	}
>>
>>and here
>>
>>> +	return sr_enable(id, target_opp_no);
>>> +}
>>>
>>> +static int sr_class3_disable(int id)
>>> +{
>>> +	int target_opp_no = 0;
>>
>>blank line
>>
>>> +	if (id == SR1)
>>> +		target_opp_no = get_vdd1_opp();
>>> +	else if (id == SR2)
>>> +		target_opp_no = get_vdd2_opp();
>>> +	sr_disable(id);
>>
>>blank line
>>
>>> +	return true;
>>> +}
>>> +/* SR class3 structure */
>>> +struct omap_smartreflex_class_data class3_data = {
>>> +	.enable = sr_class3_enable,
>>> +	.disable = sr_class3_disable,
>>> +};
>>> +
>>> +static int __init sr_class3_init(void)
>>> +{
>>> +	omap_sr_register_class(&class3_data);
>>> +	return 0;
>>> +}
>>> +late_initcall(sr_class3_init);
>>> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
>>> index cef67f3..9d286e6 100644
>>> --- a/arch/arm/plat-omap/Kconfig
>>> +++ b/arch/arm/plat-omap/Kconfig
>>> @@ -54,7 +54,7 @@ config OMAP_DEBUG_LEDS
>>>
>>>  config OMAP_SMARTREFLEX
>>>  	bool "SmartReflex support"
>>> -	depends on ARCH_OMAP3 && TWL4030_CORE && PM
>>> +	depends on ARCH_OMAP3 && PM
>>>  	help
>>>  	  Say Y if you want to enable SmartReflex.
>>>
>>> @@ -69,6 +69,15 @@ config OMAP_SMARTREFLEX
>>>  	  compensation for VDD1 and VDD2, user must write 1 to
>>>  	  /sys/power/sr_vddX_autocomp, where X is 1 or 2.
>>>
>>> +config OMAP_SMARTREFLEX_CLASS3
>>> +	bool "Class 3 mode of Smartreflex Implementation"
>>> +	depends on OMAP_SMARTREFLEX && TWL4030_CORE
>>> +	help
>>> +	  Say Y to enable Class 3 implementation of Smartreflex
>>> +
>>> +	  Class 3 implementation of Smartreflex employs continuous hardware
>>> +	  voltage caliberation.
>>> +
>>>  config OMAP_SMARTREFLEX_TESTING
>>>  	bool "Smartreflex testing support"
>>>  	depends on OMAP_SMARTREFLEX
>>> --
>>> 1.7.0.rc1.33.g07cf0f

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

* RE: [PATCH 11/16] OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3
  2010-03-03  0:37                       ` [PATCH 11/16] OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3 Kevin Hilman
@ 2010-03-05 15:12                         ` Gopinath, Thara
  2010-03-05 19:20                           ` Kevin Hilman
  0 siblings, 1 reply; 61+ messages in thread
From: Gopinath, Thara @ 2010-03-05 15:12 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand



>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>Sent: Wednesday, March 03, 2010 6:08 AM
>>To: Gopinath, Thara
>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
>>Vishwanath; Sawant, Anand
>>Subject: Re: [PATCH 11/16] OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3
>>
>>Thara Gopinath <thara@ti.com> writes:
>>
>>> There are two separate modules in SmartReflex-AVS :
>>> MinMaxAvg module and Error module. Class3 uses the Error module only.
>>> In Class2 you can choose between either module since it is software based.
>>> The registers are mapped to the modules as followed:
>>>
>>> MinMaxAvg module: AccumData, MinMaxAvgEnable, MinMaxAvgValid,
>>>         MinMaxAvgAccumValid, SenVal, SenMin, SenMax, SenAverage,
>>>         AverageWeight, MCUAccum, MCUValid, MCUBounds.
>>>
>>> Error module: SenNGain, SenPGain, SenPRN, SenNRN, AvgError,
>>>         SenError, VPBounds, ErrWeight, ErrMaxLimit, ErrMinLimit.
>>>
>>> Shared between both: SRClkLength, SREnable, SenEnable, SenNEnable,
>>>         SenPEnable, DelayCtrl, MCUDisableAck, ClkActivity.
>>>
>>> This patch introduces class specific configuration of registers in smartreflex.c
>>> This also allows for choosing between Error module and Minmaxavg module
>>> for Class 2 SR. This patch allows allows for registering for smartreflex
>>> interrupt handler and notification of interrupts in case requested by
>>> the smartreflex class driver.
>>>
>>> Signed-off-by: Thara Gopinath <thara@ti.com>
>>> ---
>>>  arch/arm/mach-omap2/smartreflex-class3.c |    1 +
>>>  arch/arm/mach-omap2/smartreflex.c        |  199 ++++++++++++++++++++++++------
>>>  arch/arm/mach-omap2/smartreflex.h        |   24 ++++-
>>>  3 files changed, 186 insertions(+), 38 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
>>> index 8e3b530..aae88b6 100644
>>> --- a/arch/arm/mach-omap2/smartreflex-class3.c
>>> +++ b/arch/arm/mach-omap2/smartreflex-class3.c
>>> @@ -43,6 +43,7 @@ static int sr_class3_disable(int id)
>>>  struct omap_smartreflex_class_data class3_data = {
>>>     .enable = sr_class3_enable,
>>>     .disable = sr_class3_disable,
>>> +   .class_type = SR_CLASS3,
>>>  };
>>>
>>>  static int __init sr_class3_init(void)
>>> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
>>> index f7c1182..96dc76b 100644
>>> --- a/arch/arm/mach-omap2/smartreflex.c
>>> +++ b/arch/arm/mach-omap2/smartreflex.c
>>> @@ -38,6 +38,12 @@ struct omap_sr {
>>>     int                     is_sr_reset;
>>>     int                     is_autocomp_active;
>>>     u32                     clk_length;
>>> +   u32                     err_weight;
>>> +   u32                     err_minlimit;
>>> +   u32                     err_maxlimit;
>>> +   u32                     accum_data;
>>> +   u32                     senn_avgweight;
>>> +   u32                     senp_avgweight;
>>>     void __iomem            *srbase_addr;
>>>     unsigned int            irq;
>>>     struct platform_device  *pdev;
>>> @@ -106,6 +112,24 @@ static void sr_clk_disable(struct omap_sr *sr)
>>>     sr->is_sr_reset = 1;
>>>  }
>>>
>>> +static irqreturn_t sr_omap_isr(int irq, void *data)
>>> +{
>>> +   struct omap_sr *sr_info = (struct omap_sr *)data;
>>> +   u32 status;
>>> +
>>> +   /* Read the status bits */
>>> +   status = sr_read_reg(sr_info, ERRCONFIG);
>>> +
>>> +   /* Clear them by writing back */
>>> +   sr_write_reg(sr_info, ERRCONFIG, status);
>>> +
>>> +   /* Call the class driver notify function if registered*/
>>> +   if (sr_class->class_type == SR_CLASS2 && sr_class->notify)
>>> +           sr_class->notify(sr_info->srid, status);
>>> +
>>> +   return IRQ_HANDLED;
>>> +}
>>> +
>>>  static void sr_set_clk_length(struct omap_sr *sr)
>>>  {
>>>     struct clk *sys_ck;
>>> @@ -137,50 +161,96 @@ static void sr_set_clk_length(struct omap_sr *sr)
>>>     }
>>>  }
>>>
>>> +static void sr_set_regfields(struct omap_sr *sr)
>>> +{
>>> +   /*
>>> +    * For time being these values are defined in smartreflex.h
>>> +    * and populated during init. May be they can be moved to board
>>> +    * file or pmic specific data structure. In that case these structure
>>> +    * fields will have to be populated using the pdata or pmic structure.
>>> +    */
>>> +   if (cpu_is_omap343x()) {
>>> +           sr->err_weight = OMAP3430_SR_ERRWEIGHT;
>>> +           sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
>>> +           sr->accum_data = OMAP3430_SR_ACCUMDATA;
>>> +           if (sr->srid == SR1) {
>>> +                   sr->err_minlimit = OMAP3430_SR1_ERRMINLIMIT;
>>> +                   sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
>>> +                   sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
>>> +           } else {
>>> +                   sr->err_minlimit = OMAP3430_SR2_ERRMINLIMIT;
>>> +                   sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
>>> +                   sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
>>> +           }
>>> +   }
>>> +   /* TODO: 3630 and Omap4 specific bit field values */
>>> +}
>>> +
>>>  static void sr_configure(struct omap_sr *sr)
>>>  {
>>>     u32 sr_config;
>>>     u32 senp_en , senn_en;
>>>     struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>>>
>>> +   /* Common settings for SR Class3 and SR Class2 */
>>>     if (sr->clk_length == 0)
>>>             sr_set_clk_length(sr);
>>>
>>>     senp_en = pdata->senp_mod;
>>>     senn_en = pdata->senn_mod;
>>> -   if (sr->srid == SR1) {
>>> -           sr_config = SR1_SRCONFIG_ACCUMDATA |
>>> -                   (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
>>> -                   SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN |
>>> -                   SRCONFIG_MINMAXAVG_EN |
>>> -                   (senn_en << SRCONFIG_SENNENABLE_SHIFT) |
>>> -                   (senp_en << SRCONFIG_SENPENABLE_SHIFT) |
>>> -                   SRCONFIG_DELAYCTRL;
>>> -
>>> -           sr_write_reg(sr, SRCONFIG, sr_config);
>>> -           sr_write_reg(sr, AVGWEIGHT, SR1_AVGWEIGHT_SENPAVGWEIGHT |
>>> -                                   SR1_AVGWEIGHT_SENNAVGWEIGHT);
>>>
>>> +   sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
>>> +           SRCONFIG_SENENABLE | (senn_en << SRCONFIG_SENNENABLE_SHIFT) |
>>> +           (senp_en << SRCONFIG_SENPENABLE_SHIFT) | SRCONFIG_DELAYCTRL;
>>> +   sr_write_reg(sr, SRCONFIG, sr_config);
>>> +
>>> +   if ((sr_class->class_type == SR_CLASS3) || (sr_class->class_type ==
>>> +           SR_CLASS2 && sr_class->mod_use == SR_USE_ERROR_MOD)) {
>>> +           /*
>>> +            * SR settings if using the ERROR module inside Smartreflex.
>>> +            * SR CLASS 3 by default uses only the ERROR module where as
>>> +            * SR CLASS 2 can choose between ERROR module and MINMAXAVG
>>> +            * module.
>>> +            */
>>> +           u32 sr_errconfig;
>>> +
>>> +           sr_modify_reg(sr, SRCONFIG, SRCONFIG_ERRGEN_EN,
>>> +                   SRCONFIG_ERRGEN_EN);
>>> +           sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
>>> +                   (sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
>>> +                   (sr->err_minlimit <<  ERRCONFIG_ERRMiNLIMIT_SHIFT);
>>>             sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |
>>>                     SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
>>> -                   (SR1_ERRWEIGHT | SR1_ERRMAXLIMIT | SR1_ERRMINLIMIT));
>>> -
>>> -   } else if (sr->srid == SR2) {
>>> -           sr_config = SR2_SRCONFIG_ACCUMDATA |
>>> -                   (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
>>> -                   SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN |
>>> -                   SRCONFIG_MINMAXAVG_EN |
>>> -                   (senn_en << SRCONFIG_SENNENABLE_SHIFT) |
>>> -                   (senp_en << SRCONFIG_SENPENABLE_SHIFT) |
>>> -                   SRCONFIG_DELAYCTRL;
>>> -
>>> -           sr_write_reg(sr, SRCONFIG, sr_config);
>>> -           sr_write_reg(sr, AVGWEIGHT, SR2_AVGWEIGHT_SENPAVGWEIGHT |
>>> -                                   SR2_AVGWEIGHT_SENNAVGWEIGHT);
>>> -           sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |
>>> -                   SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
>>> -                   (SR2_ERRWEIGHT | SR2_ERRMAXLIMIT | SR2_ERRMINLIMIT));
>>> +                   sr_errconfig);
>>> +           /* Enabling the interrupts if the ERROR module is used */
>>> +           sr_modify_reg(sr, ERRCONFIG,
>>> +                   (ERRCONFIG_VPBOUNDINTEN),
>>> +                   (ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST));
>>> +   } else if ((sr_class->class_type == SR_CLASS2) &&
>>> +                   (sr_class->mod_use == SR_USE_ERROR_MOD)) {
>>
>>This 'else if' will never happen as the condition is identical to one
>>of the conditions of the first if.
>>
>>Based on the comment below, I'm assuming it you meant SR_USE_MINMAXAVG_MOD.

Yes .. Thanks for catching this.

>>
>>> +           /*
>>> +            * SR settings if using the MINMAXAVG module inside
>>> +            * Smartreflex. SR CLASS 3 does not use this module where as
>>> +            * SR CLASS 2 can choose between ERROR module and MINMAXAVG
>>> +            * module.
>>> +            */
>>> +           u32 avgwt;
>>>
>>> +           sr_modify_reg(sr, SRCONFIG, SRCONFIG_ACCUMDATA_MASK,
>>> +                   sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
>>> +           avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
>>> +                   (sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT);
>>> +           sr_write_reg(sr, AVGWEIGHT, avgwt);
>>> +           /*
>>> +            * Enabling the interrupts if MINMAXAVG module is used.
>>> +            * TODO: check if all the interrupts are mandatory
>>> +            */
>>> +           sr_modify_reg(sr, ERRCONFIG,
>>> +                   (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
>>> +                   ERRCONFIG_MCUBOUNDINTEN),
>>> +                   (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST |
>>> +                    ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST |
>>> +                    ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST));
>>>     }
>>>     sr->is_sr_reset = 0;
>>>  }
>>> @@ -280,12 +350,6 @@ int sr_enable(int srid, u32 target_opp_no)
>>>     }
>>>
>>>     sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
>>> -
>>> -   /* Enable the interrupt */
>>> -   sr_modify_reg(sr, ERRCONFIG,
>>> -                   (ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST),
>>> -                   (ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST));
>>> -
>>>     /* SRCONFIG - enable SR */
>>>     sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
>>>     return true;
>>> @@ -384,6 +448,8 @@ void omap_smartreflex_disable(int srid)
>>>   */
>>>  void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
>>>  {
>>> +   struct omap_sr *sr_info;
>>> +
>>>     if (!class_data) {
>>>             pr_warning("Smartreflex class data passed is NULL\n");
>>>             return;
>>> @@ -393,7 +459,44 @@ void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
>>>             pr_warning("Smartreflex class driver already registered\n");
>>>             return;
>>>     }
>>> +
>>> +   if ((class_data->class_type != SR_CLASS2) &&
>>> +                   (class_data->class_type != SR_CLASS3)) {
>>> +           pr_warning("SR Class type passed is invalid. So cannot \
>>> +                           register the class structure\n");
>>> +           return;
>>> +   }
>>> +
>>> +   if ((class_data->class_type == SR_CLASS2) &&
>>> +                   !((class_data->mod_use == SR_USE_MINMAXAVG_MOD) ||
>>> +                   (class_data->mod_use == SR_USE_ERROR_MOD))) {
>>> +           pr_warning("SR Class 2 specified but whether to use error \
>>> +                           module or minmaxavg module not specified\n");
>>> +           return;
>>> +   }
>>> +
>>>     sr_class = class_data;
>>> +   /*
>>> +    * Register the interrupt handler incase requested by the class driver
>>> +    */
>>> +   list_for_each_entry(sr_info, &sr_list, node) {
>>> +           if (sr_class->class_type == SR_CLASS2 &&
>>> +                           sr_class->notify_flags && sr_info->irq) {
>>> +                   char name[SMARTREFLEX_NAME_LEN];
>>> +                   int ret;
>>> +
>>> +                   sprintf(name, "sr%d", sr_info->srid);
>>> +                   ret = request_irq(sr_info->irq, sr_omap_isr,
>>> +                                   IRQF_DISABLED, name, (void *)sr_info);
>>> +                   if (ret < 0) {
>>> +                           pr_warning("ERROR in registering interrupt \
>>> +                                   handler for SR%d Smartreflex will \
>>> +                                   not function as desired\n",
>>> +                                   sr_info->srid);
>>> +                           return;
>>> +                   }
>>> +           }
>>> +   }
>>>  }
>>>
>>>  /* PM Debug Fs enteries to enable disable smartreflex.*/
>>> @@ -448,6 +551,7 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
>>>     if (odev->hwmods[0]->mpu_irqs)
>>>             sr_info->irq = odev->hwmods[0]->mpu_irqs[0].irq;
>>>     sr_set_clk_length(sr_info);
>>> +   sr_set_regfields(sr_info);
>>>
>>>     /* Create the debug fs enteries */
>>>     sprintf(name, "sr%d_autocomp", sr_info->srid);
>>> @@ -456,8 +560,29 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
>>>
>>>     odev->hwmods[0]->dev_attr = sr_info;
>>>     list_add(&sr_info->node, &sr_list);
>>> -   pr_info("SmartReflex driver initialized\n");
>>>
>>> +   /*
>>> +    * Register interrrupt handler if smartreflex class driver is already
>>> +    * registered and has requested for interrupts. This will be attempted
>>> +    * in the class driver register again if it does not happen here.
>>> +    */
>>
>>Why the duplicate attempts to request_irq()?  Seems like it's only needed
>>in the register_class hook above.

Duplicate attempt is so that it does not matter whether the class driver gets registered before the smartreflex driver gets registered. So if smartreflex driver gets registered first the request_irq will happen only when class driver gets registered. On the other hand if class driver gets registered first then the request_irq will happen from here. The thing to notice is that there is only a duplicate attempt. Actual double registrations does not happen.

Regards
Thara
>>
>>> +   if (sr_class) {
>>> +           if (sr_class->class_type == SR_CLASS2 &&
>>> +                           sr_class->notify_flags && sr_info->irq) {
>>> +                   sprintf(name, "sr%d", sr_info->srid);
>>> +                   ret = request_irq(sr_info->irq, sr_omap_isr,
>>> +                                   IRQF_DISABLED, name, (void *)sr_info);
>>> +                   if (ret < 0) {
>>> +                           pr_warning("ERROR in registering interrupt \
>>> +                                   handler for SR%d. Smartreflex will \
>>> +                                   not function as desired\n",
>>> +                                   sr_info->srid);
>>> +                           return ret;
>>> +                   }
>>> +           }
>>> +   }
>>> +
>>> +   pr_info("SmartReflex driver initialized\n");
>>>     return ret;
>>>  }
>>>
>>> diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
>>> index 7a1f0c7..f8fc8a4 100644
>>> --- a/arch/arm/mach-omap2/smartreflex.h
>>> +++ b/arch/arm/mach-omap2/smartreflex.h
>>> @@ -124,6 +124,24 @@ extern struct dentry *pm_dbg_main_dir;
>>>  #endif
>>>
>>>  #ifdef CONFIG_OMAP_SMARTREFLEX
>>> +/*
>>> + * The smart reflex driver supports both CLASS2 and CLASS3 SR.
>>> + * The smartreflex class driver should pass the class type.
>>> + * Should be used to populate the class_type field of the
>>> + * omap_smartreflex_class_data structure.
>>> + */
>>> +#define SR_CLASS2  0x1
>>> +#define SR_CLASS3  0x2
>>> +
>>> +/*
>>> + * CLASS2 SR can use either the MINMAXAVG module or the ERROR module
>>> + * of the Smartreflex. Should be used to populate the mod_use field
>>> + * of omap_smartreflex_class_data structure is class_type is chosen
>>> + * as SR_CLASS2.
>>> + */
>>> +#define SR_USE_MINMAXAVG_MOD       0x1
>>> +#define SR_USE_ERROR_MOD   0x2
>>> +
>>>  /**
>>>   * omap_smartreflex_class_data : Structure to be populated by
>>>   * Smartreflex class driver with corresponding class enable disable API's
>>> @@ -134,7 +152,10 @@ extern struct dentry *pm_dbg_main_dir;
>>>   *         for class3.
>>>   * @notify_flags - specify the events to be notified to the class driver
>>>   * @class_type - specify which smartreflex class. Can be used by the SR driver
>>> - *                 to tkae any class based decisions.
>>> + *                 to take any class based decisions.
>>> + * @mod_use - specify whether to use the error module or minmaxavg module for
>>> + *         smartreflex caliberations in case of class2 SR. In case of
>>                            ^^^^^^^^^^^^^
>>typo: calibration
>>
>>> + *         class 3 SR only error module is used.
>>>   */
>>>  struct omap_smartreflex_class_data {
>>>     int (*enable)(int sr_id);
>>> @@ -142,6 +163,7 @@ struct omap_smartreflex_class_data {
>>>     int (*notify)(int sr_id, u32 status);
>>>     u8 notify_flags;
>>>     u8 class_type;
>>> +   u8 mod_use;
>>
>>This name isn't terribly clear.  Maybe mode?  or calibration_mode?
>>
>>
>>Kevin

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

* RE: [PATCH 09/16] OMAP3: PM: Creating separate files for handling OMAP3 voltage related operations.
  2010-03-02 20:02                   ` [PATCH 09/16] OMAP3: PM: Creating separate files for handling OMAP3 voltage related operations Kevin Hilman
@ 2010-03-05 15:17                     ` Gopinath, Thara
  0 siblings, 0 replies; 61+ messages in thread
From: Gopinath, Thara @ 2010-03-05 15:17 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand



>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>Sent: Wednesday, March 03, 2010 1:33 AM
>>To: Gopinath, Thara
>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
>>Vishwanath; Sawant, Anand
>>Subject: Re: [PATCH 09/16] OMAP3: PM: Creating separate files for handling OMAP3 voltage related
>>operations.
>>
>>Thara Gopinath <thara@ti.com> writes:
>>
>>> This patch creates voltage.c and voltage.h files and
>>> moves all voltage processor and voltage controller specific code
>>> from smartreflex.c and other places in the OMAP3 codebase into
>>> these two files.
>>> This along with smartreflex class driver addition will make
>>> smartreflex.c a generic driver to support both Class 2 and
>>> Class 3 smartreflex implementaions.
>>>
>>> Signed-off-by: Thara Gopinath <thara@ti.com>
>>
>>This is definitely in the right direction.  Thanks Thara.
>>
>>Also, is this expected to be common for OMAP4?   If not, maybe
>>this should be named voltage3xxx.[ch]?

Hi Kevin,

Looks like we could re-use the same file. I will anyways double check this with the experts in TI and let you know.
>>
>>More comments below, primarily regarding how the various VP/VC
>>registers are defined and accessed.  I'd rather see them as offsets
>>into the PRCM rather than absolute virtual addresses.  More on that
>>below...
>>
>>> ---
>>>  arch/arm/mach-omap2/Makefile             |    3 +-
>>>  arch/arm/mach-omap2/board-3430sdp.c      |    3 +-
>>>  arch/arm/mach-omap2/pm.h                 |    7 -
>>>  arch/arm/mach-omap2/pm34xx.c             |   87 +-----
>>>  arch/arm/mach-omap2/resource34xx.c       |   15 +-
>>>  arch/arm/mach-omap2/resource34xx.h       |    1 -
>>>  arch/arm/mach-omap2/smartreflex-class3.c |    4 +
>>>  arch/arm/mach-omap2/smartreflex.c        |  370 +--------------------
>>>  arch/arm/mach-omap2/smartreflex.h        |  139 --------
>>>  arch/arm/mach-omap2/voltage.c            |  550 ++++++++++++++++++++++++++++++
>>>  arch/arm/mach-omap2/voltage.h            |   74 ++++
>>>  11 files changed, 640 insertions(+), 613 deletions(-)
>>>  create mode 100644 arch/arm/mach-omap2/voltage.c
>>>  create mode 100644 arch/arm/mach-omap2/voltage.h
>>>
>>
>>[...]
>>
>>> diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
>>> new file mode 100644
>>> index 0000000..c0c2c17
>>> --- /dev/null
>>> +++ b/arch/arm/mach-omap2/voltage.c
>>> @@ -0,0 +1,550 @@
>>> +/*
>>> + * OMAP3/OMAP4 Voltage Management Routines
>>> + *
>>> + * Copyright (C) 2007 Texas Instruments, Inc.
>>> + * Rajendra Nayak <rnayak@ti.com>
>>> + * Lesly A M <x0080970@ti.com>
>>> + *
>>> + * Copyright (C) 2008 Nokia Corporation
>>> + * Kalle Jokiniemi
>>> + *
>>> + * Copyright (C) 2010 Texas Instruments, Inc.
>>> + * Thara Gopinath <thara@ti.com>
>>> + *
>>> + * 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/pm.h>
>>> +#include <linux/delay.h>
>>> +#include <linux/io.h>
>>> +
>>> +#include <plat/omap-pm.h>
>>> +#include <plat/omap34xx.h>
>>> +#include <plat/opp.h>
>>> +#include <plat/opp_twl_tps.h>
>>> +
>>> +#include "prm-regbits-34xx.h"
>>> +#include "voltage.h"
>>> +
>>> +#define MAX_TRIES 100
>>> +
>>> +/**
>>> + * OMAP3 Voltage controller SR parameters. TODO: Pass this info as part of
>>> + * board data or PMIC data
>>> + */
>>> +#define R_SRI2C_SLAVE_ADDR              0x12
>>> +#define R_VDD1_SR_CONTROL               0x00
>>> +#define R_VDD2_SR_CONTROL		0x01
>>> +
>>> +
>>> +/* Voltage processor register offsets */
>>> +struct vp_reg_offs {
>>> +	void __iomem *vp_vpconfig_reg;
>>> +	void __iomem *vp_vstepmin_reg;
>>> +	void __iomem *vp_vstepmax_reg;
>>> +	void __iomem *vp_vlimitto_reg;
>>> +	void __iomem *vp_status_reg;
>>> +	void __iomem *vp_voltage_reg;
>>> +};
>>>
>>> +/*
>>> + * Voltage processor structure conttaining info about
>>> + * the various register offsets and the bit field values
>>> + * for a particular instance of voltage processor.
>>> + */
>>> +struct vp_reg_info {
>>> +	struct vp_reg_offs vp_offs;
>>> +	/* Bit fields for VPx_VPCONFIG */
>>> +	u32 vp_erroroffset;
>>> +	u32 vp_errorgain;
>>> +	/* Bit fields for VPx_VSTEPMIN */
>>> +	u32 vp_stepmin;
>>> +	u32 vp_smpswaittimemin;
>>> +	/* Bit fields for VPx_VSTEPMAX */
>>> +	u32 vp_stepmax;
>>> +	u32 vp_smpswaittimemax;
>>> +	/* Bit fields for VPx_VLIMITTO */
>>> +	u32 vp_vddmin;
>>> +	u32 vp_vddmax;
>>> +	u32 vp_timeout;
>>> +};
>>> +static struct vp_reg_info *vp_reg;
>>> +/*
>>> + * Number of scalable voltage domains that has an independent
>>> + * Voltage processor
>>> + */
>>> +static int no_scalable_vdd;
>>> +
>>> +/* OMAP3 VP register offsets and other definitions */
>>> +struct __init vp_reg_offs omap3_vp_offs[] = {
>>> +	/* VP1 */
>>> +	{
>>> +		.vp_vpconfig_reg = OMAP3430_PRM_VP1_CONFIG,
>>> +		.vp_vstepmin_reg = OMAP3430_PRM_VP1_VSTEPMIN,
>>> +		.vp_vstepmax_reg = OMAP3430_PRM_VP1_VSTEPMAX,
>>> +		.vp_vlimitto_reg = OMAP3430_PRM_VP1_VLIMITTO,
>>> +		.vp_status_reg = OMAP3430_PRM_VP1_STATUS,
>>> +		.vp_voltage_reg = OMAP3430_PRM_VP1_VOLTAGE,
>>> +	},
>>> +	/* VP2 */
>>> +	{	.vp_vpconfig_reg = OMAP3430_PRM_VP2_CONFIG,
>>> +		.vp_vstepmin_reg = OMAP3430_PRM_VP2_VSTEPMIN,
>>> +		.vp_vstepmax_reg = OMAP3430_PRM_VP2_VSTEPMAX,
>>> +		.vp_vlimitto_reg = OMAP3430_PRM_VP2_VLIMITTO,
>>> +		.vp_status_reg = OMAP3430_PRM_VP2_STATUS,
>>> +		.vp_voltage_reg = OMAP3430_PRM_VP2_VOLTAGE,
>>> +	},
>>> +};
>>> +
>>
>>
>>Rather than absolute physical addresses, these should all simply be u8
>>offset values from the GR_MOD base.  Changing the type to u8
>>and appending _OFFSET to the name should do the trick.
>>
>>Also, I think you could remove the vp_ prefix from the name.

I also initially thought of keeping u8 offsets and using prm_read_mod_reg and prm_write_mod_reg. But apparently in OMAP4 we are thinking of doing away with the u8 offsets and define only the absolute register value. Plus GR_MOD will be different for OMAP3 and OMAP4. Also not all registers may belong to GR_MOD(esp in OMAP4). To avoid all these complications I thought let me use absolute addresses in voltage.c

Regards
Thara
>>
>>> +#define OMAP3_NO_SCALABLE_VDD ARRAY_SIZE(omap3_vp_offs)
>>> +static struct vp_reg_info omap3_vp_reg[OMAP3_NO_SCALABLE_VDD];
>>> +
>>> +
>>> +/* TODO: OMAP4 register offsets */
>>> +
>>> +/**
>>> + * Voltage controller register offsets
>>> + */
>>> +struct vc_reg_info {
>>> +	void __iomem *vc_cmdval0_reg;
>>> +	void __iomem *vc_cmdval1_reg;
>>> +	void __iomem *vc_bypass_val_reg;
>>
>>u8 offsets from GR_MOD please.
>>
>>vc_ prefix is redundant here also
>>
>>> +} vc_reg;
>>> +/*
>>> + * Default voltage controller settings for OMAP3
>>> + */
>>> +static struct prm_setup_vc vc_config = {
>>> +	.clksetup = 0xff,
>>> +	.voltsetup_time1 = 0xfff,
>>> +	.voltsetup_time2 = 0xfff,
>>> +	.voltoffset = 0xff,
>>> +	.voltsetup2 = 0xff,
>>> +	.vdd0_on = 0x30,        /* 1.2v */
>>> +	.vdd0_onlp = 0x20,      /* 1.0v */
>>> +	.vdd0_ret = 0x1e,       /* 0.975v */
>>> +	.vdd0_off = 0x00,       /* 0.6v */
>>> +	.vdd1_on = 0x2c,        /* 1.15v */
>>> +	.vdd1_onlp = 0x20,      /* 1.0v */
>>> +	.vdd1_ret = 0x1e,       /* .975v */
>>> +	.vdd1_off = 0x00,       /* 0.6v */
>>> +};
>>> +
>>> +static inline u32 voltage_read_reg(void __iomem *offset)
>>> +{
>>> +	return __raw_readl(offset);
>>> +}
>>
>>These should use prm_[read|write]_*
>>
>>static inline u32 voltage_read_reg(u8 offset)
>>{
>>        return prm_read_mod_reg(OMAP3430_GR_MOD, offset);
>>}
>>
>>> +
>>> +static inline void voltage_write_reg(void __iomem *offset, u32 value)
>>> +{
>>> +	__raw_writel(value, offset);
>>> +}
>>> +
>>
>>Kevin

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

* RE: [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c
  2010-03-02 23:52             ` Kevin Hilman
@ 2010-03-05 15:18               ` Gopinath, Thara
  2010-03-05 18:30                 ` Kevin Hilman
  0 siblings, 1 reply; 61+ messages in thread
From: Gopinath, Thara @ 2010-03-05 15:18 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand



>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>Sent: Wednesday, March 03, 2010 5:23 AM
>>To: Gopinath, Thara
>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
>>Vishwanath; Sawant, Anand
>>Subject: Re: [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c
>>
>>Thara Gopinath <thara@ti.com> writes:
>>
>>> OMAP3 smartreflex modules are capable of two different classes
>>> of implementaion -
>>> 	Class-2: Continuous Software Calibration
>>> 	Class-3: Continuous Hardware Calibration.
>>> OMAP3 along with T2/Gaia supports the Class 3 implementaion.
>>> With a different PMIC it can support Class 2 implementaion also.
>>>
>>> The idea behind this patch is that smartreflex.c should be able
>>> to support both the classes of Smartreflex and the class specific
>>> details for smartreflex should stay out of this file in a separate
>>> class file.
>>> This patch introduces smartreflex class specific hooks in
>>> smartreflex.c. This patch only takes care of smartreflex enable
>>> disable hooks which differ between Class 2 and Class 3. There
>>> are some register setting changes between both the classes which
>>> will be taken care of in a later patch.
>>> This will form the base for adding class specific
>>> drivers in later patches.
>>>
>>> Signed-off-by: Thara Gopinath <thara@ti.com>
>>> ---
>>>  arch/arm/mach-omap2/pm34xx.c      |    8 +-
>>>  arch/arm/mach-omap2/smartreflex.c |  251 ++++++++++++++++++++----------------
>>>  arch/arm/mach-omap2/smartreflex.h |   48 ++++++--
>>>  3 files changed, 182 insertions(+), 125 deletions(-)
>>>
>>
>>[...]
>>
>>> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
>>> index c00925d..ba9f899 100644
>>> --- a/arch/arm/mach-omap2/smartreflex.c
>>> +++ b/arch/arm/mach-omap2/smartreflex.c
>>> @@ -55,6 +55,7 @@ struct omap_sr {
>>>
>>>  /* sr_list contains all the instances of smartreflex module */
>>>  static LIST_HEAD(sr_list);
>>> +static struct omap_smartreflex_class_data *sr_class;
>>>
>>>  #define SR_REGADDR(offs)	(sr->srbase_addr + offset)
>>>
>>> @@ -388,14 +389,86 @@ static int sr_reset_voltage(int srid)
>>>  	return 0;
>>>  }
>>>
>>> -static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
>>> +static void sr_start_vddautocomap(int srid)
>>
>>Either in this patch or in an additional patch (previous to this one)
>>can you fix the name of these autocomp functions: *_vddautocomap ->
>>*_vddautocomp.  I don't think comap means anything.

I can fix this. I would prefer this change to be a part of one of the existing patches in the patch set so that I do not increase the patch count and it will be easier for me to sen a V2.

Regards
Thara
>>
>>Kevin

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

* RE: [PATCH 12/16] OMAP3: PM: Support for enabling smartreflex autocompensation by default.
  2010-03-03  0:48                         ` [PATCH 12/16] OMAP3: PM: Support for enabling smartreflex autocompensation by default Kevin Hilman
@ 2010-03-05 15:20                           ` Gopinath, Thara
  0 siblings, 0 replies; 61+ messages in thread
From: Gopinath, Thara @ 2010-03-05 15:20 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand



>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>Sent: Wednesday, March 03, 2010 6:19 AM
>>To: Gopinath, Thara
>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
>>Vishwanath; Sawant, Anand
>>Subject: Re: [PATCH 12/16] OMAP3: PM: Support for enabling smartreflex autocompensation by default.
>>
>>Thara Gopinath <thara@ti.com> writes:
>>
>>> This patch adds support to pdata enable smartreflex autocompenstion
>>> during init based on init_enable flag passed as pdata.
>>>
>>> This patch also adds enabling of autocompensation by
>>> default (setting init_enable flag to true) in case of ES3.1
>>> OMAP3430 chip. In the current implementation
>>> this step is kept in smartreflex.c itself.Later an API can be added
>>> so that the decision to enable autocompensation by default
>>> can be passed from the corresponding board files.
>>>
>>> Signed-off-by: Thara Gopinath <thara@ti.com>
>>> ---
>>>  arch/arm/mach-omap2/smartreflex.c |   32 ++++++++++++++++++++++++++++----
>>>  1 files changed, 28 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
>>> index 96dc76b..085dd05 100644
>>> --- a/arch/arm/mach-omap2/smartreflex.c
>>> +++ b/arch/arm/mach-omap2/smartreflex.c
>>> @@ -477,9 +477,15 @@ void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
>>>
>>>  	sr_class = class_data;
>>>  	/*
>>> -	 * Register the interrupt handler incase requested by the class driver
>>> +	 * Check if any SR module needs to be enabled as part of init.
>>> +	 * In case the probe for the SR module is not yet called the enable
>>> +	 * will not be done here but will be done in the probe whenever
>>> +	 * it gets called. Also register the interrupt handler incase
>>> +	 * requested by the class driver.
>>>  	 */
>>>  	list_for_each_entry(sr_info, &sr_list, node) {
>>> +		struct omap_smartreflex_data *pdata =
>>> +				sr_info->pdev->dev.platform_data;
>>>  		if (sr_class->class_type == SR_CLASS2 &&
>>>  				sr_class->notify_flags && sr_info->irq) {
>>>  			char name[SMARTREFLEX_NAME_LEN];
>>> @@ -496,6 +502,8 @@ void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
>>>  				return;
>>>  			}
>>>  		}
>>> +		if (pdata->init_enable)
>>> +			sr_start_vddautocomap(sr_info->srid);
>>
>>I think this flag is better named enable_on_init.
>>
>>>  	}
>>>  }
>>>
>>> @@ -562,11 +570,15 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
>>>  	list_add(&sr_info->node, &sr_list);
>>>
>>>  	/*
>>> -	 * Register interrrupt handler if smartreflex class driver is already
>>> -	 * registered and has requested for interrupts. This will be attempted
>>> +	 * Enable the smartreflex module if init_enable flag is set and
>>> +	 * if the class driver is registered. Also Register interrrupt handler
>>> +	 * if smartreflex class driver is already registered and has
>>> +	 * requested for interrupts. This will be attempted
>>>  	 * in the class driver register again if it does not happen here.
>>>  	 */
>>>  	if (sr_class) {
>>> +		struct omap_smartreflex_data *pdata = pdev->dev.platform_data;
>>> +
>>>  		if (sr_class->class_type == SR_CLASS2 &&
>>>  				sr_class->notify_flags && sr_info->irq) {
>>>  			sprintf(name, "sr%d", sr_info->srid);
>>> @@ -580,6 +592,8 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
>>>  				return ret;
>>>  			}
>>>  		}
>>> +		if (pdata->init_enable)
>>> +			sr_start_vddautocomap(sr_info->srid);
>>>  	}
>>
>>As with the duplicate request_irq() in previous patch, I don't follow
>>why it's the start is needed twice.
>>
>>Is it to handle the case where no class driver is installed?

Same reason as I explained for request_irq.. so as to avoid dependency that class driver can be registered only after smartreflex driver initialization is done

Regards
Thara
>>
>>>
>>>  	pr_info("SmartReflex driver initialized\n");
>>> @@ -782,7 +796,17 @@ static int __init omap_devinit_smartreflex(void)
>>>  		if (WARN_ON(!sr_data))
>>>  			return -ENOMEM;
>>>
>>> -		sr_data->init_enable = false;
>>> +		/*
>>> +		 * Enable the SR module by default if it is a OMAP3430
>>> +		 * ES3.1 chip
>>
>>You should add a comment about why: starting with ES3.1, efuse values can be trusted?
>>
>>> +		 */
>>> +		if (cpu_is_omap343x()) {
>>> +			if (omap_rev() == OMAP3430_REV_ES3_1)
>>> +				sr_data->init_enable = true;
>>> +			else
>>> +				sr_data->init_enable = false;
>>> +		} else
>>> +			sr_data->init_enable = false;
>>>  		sr_data->device_enable = omap_device_enable;
>>>  		sr_data->device_shutdown = omap_device_shutdown;
>>>  		sr_data->device_idle = omap_device_idle;
>>
>>Kevin

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

* RE: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling
  2010-03-03  0:58                               ` [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling Kevin Hilman
@ 2010-03-05 15:22                                 ` Gopinath, Thara
  2010-03-05 15:26                                   ` Felipe Contreras
  0 siblings, 1 reply; 61+ messages in thread
From: Gopinath, Thara @ 2010-03-05 15:22 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand



>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>Sent: Wednesday, March 03, 2010 6:29 AM
>>To: Gopinath, Thara
>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
>>Vishwanath; Sawant, Anand
>>Subject: Re: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling
>>
>>Thara Gopinath <thara@ti.com> writes:
>>
>>> This patch introduces VP force update method of voltage scaling
>>> and enables it by default. The older method of vc bypass is now
>>> configuratble through a menu config option. VP force update is the
>>> hardware recommended method of voltage scaling.
>>>
>>> Signed-off-by: Thara Gopinath <thara@ti.com>
>>
>>This should be a runtime option intead of a compile-time option.
>>Default should be HW recommended method, but board code should be able
>>to override.
>>
>>Only did a quick glance at this, an some minor coding style issues below...

Will do this as V2

Regards
Thara
>>
>>> ---
>>>  arch/arm/mach-omap2/voltage.c |  149 +++++++++++++++++++++++++++++++++++++++--
>>>  arch/arm/mach-omap2/voltage.h |    1 +
>>>  arch/arm/plat-omap/Kconfig    |   19 +++++
>>>  3 files changed, 162 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
>>> index 49167c0..4f325af 100644
>>> --- a/arch/arm/mach-omap2/voltage.c
>>> +++ b/arch/arm/mach-omap2/voltage.c
>>> @@ -29,7 +29,8 @@
>>>  #include "prm-regbits-34xx.h"
>>>  #include "voltage.h"
>>>
>>> -#define VP_IDLE_TIMEOUT 200
>>> +#define VP_IDLE_TIMEOUT 	200
>>> +#define VP_TRANXDONE_TIMEOUT	300
>>>
>>>  /*
>>>   * OMAP3 Voltage controller SR parameters. TODO: Pass this info as part of
>>> @@ -70,6 +71,7 @@ struct vp_reg_info {
>>>  	u32 vp_vddmin;
>>>  	u32 vp_vddmax;
>>>  	u32 vp_timeout;
>>> +	u32 vp_tranxdone_status;
>>>  };
>>>  static struct vp_reg_info *vp_reg;
>>>  /*
>>> @@ -299,6 +301,8 @@ static void __init vp_reg_configure(int vp_id)
>>>  					OMAP3430_VDDMIN_SHIFT);
>>>  			vp_reg[vp_id].vp_vddmax = (OMAP3_VP1_VLIMITTO_VDDMAX <<
>>>  					OMAP3430_VDDMAX_SHIFT);
>>> +			vp_reg[vp_id].vp_tranxdone_status =
>>> +					OMAP3430_VP1_TRANXDONE_ST;
>>>  		} else if (vp_id == VP2) {
>>>  			/*
>>>  			 * OMAP3430 has error gain varying btw higher and
>>> @@ -312,6 +316,8 @@ static void __init vp_reg_configure(int vp_id)
>>>  					OMAP3430_VDDMIN_SHIFT);
>>>  			vp_reg[vp_id].vp_vddmax = (OMAP3_VP2_VLIMITTO_VDDMAX <<
>>>  					OMAP3430_VDDMAX_SHIFT);
>>> +			vp_reg[vp_id].vp_tranxdone_status =
>>> +					OMAP3430_VP2_TRANXDONE_ST;
>>>  		} else {
>>>  			pr_warning("Voltage processor%d does not exisit\
>>>  					in OMAP3 \n", vp_id);
>>> @@ -346,6 +352,131 @@ static void __init vp_reg_configure(int vp_id)
>>>  	/* TODO Extend this for OMAP4 ?? Or need a separate file  */
>>>  }
>>>
>>> +#ifdef CONFIG_OMAP_VOLT_VPFORCEUPDATE
>>> +/* VP force update method of voltage scaling */
>>> +static int vp_forceupdate_scale_voltage(u32 vdd, u8 target_vsel,
>>> +				u8 current_vsel)
>>> +{
>>> +	u32 smps_steps = 0, smps_delay = 0;
>>> +	u32 vpconfig;
>>> +	int timeout = 0;
>>> +	int vp_id = vdd - 1;
>>> +
>>> +	if (!((vdd == VDD1_OPP) || (vdd == VDD2_OPP))) {
>>> +		pr_warning("Wrong vdd id passed to vp forceupdate\n");
>>> +		return false;
>>> +	}
>>> +
>>> +	smps_steps = abs(target_vsel - current_vsel);
>>> +
>>> +	/* OMAP3430 has errorgain varying btw higher and lower opp's */
>>> +	if (cpu_is_omap34xx()) {
>>> +		if (vdd == VDD1_OPP) {
>>> +			u32 vc_cmdval0;
>>> +
>>> +			vc_cmdval0 = voltage_read_reg(vc_reg.vc_cmdval0_reg);
>>> +			vc_cmdval0 &= ~VC_CMD_ON_MASK;
>>> +			vc_cmdval0 |= (target_vsel << VC_CMD_ON_SHIFT);
>>> +			voltage_write_reg(vc_reg.vc_cmdval0_reg, vc_cmdval0);
>>> +			vp_reg[vp_id].vp_errorgain = (((get_vdd1_opp() > 2) ?
>>> +					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
>>> +					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
>>> +					OMAP3430_ERRORGAIN_SHIFT);
>>> +		} else if (vdd == VDD2_OPP) {
>>> +			u32 vc_cmdval1;
>>> +
>>> +			vc_cmdval1 = voltage_read_reg(vc_reg.vc_cmdval1_reg);
>>> +			vc_cmdval1 &= ~VC_CMD_ON_MASK;
>>> +			vc_cmdval1 |= (target_vsel << VC_CMD_ON_SHIFT);
>>> +			voltage_write_reg(vc_reg.vc_cmdval1_reg, vc_cmdval1);
>>> +			vp_reg[vp_id].vp_errorgain = (((get_vdd2_opp() > 2) ?
>>> +					(OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
>>> +					(OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
>>> +					OMAP3430_ERRORGAIN_SHIFT);
>>> +		}
>>> +	}
>>> +
>>> +	/* Clear all pending TransactionDone interrupt/status. Typical latency
>>> +	 * is <3us
>>> +	 */
>>> +	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
>>> +		voltage_write_reg(PRM_IRQSTATUS_REG,
>>> +				vp_reg[vp_id].vp_tranxdone_status);
>>> +		if (!(voltage_read_reg(PRM_IRQSTATUS_REG) &
>>> +				vp_reg[vp_id].vp_tranxdone_status))
>>> +				break;
>>> +		udelay(1);
>>> +	}
>>> +
>>> +	if (timeout >= VP_TRANXDONE_TIMEOUT) {
>>> +		pr_warning("VP%d TRANXDONE timeout exceeded. Voltage change \
>>> +				aborted", vdd);
>>> +		return false;
>>> +	}
>>> +
>>> +	/* Configure for VP-Force Update */
>>> +	vpconfig = voltage_read_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg);
>>> +	vpconfig &= ~(VP_CONFIG_INITVDD | VP_FORCEUPDATE |
>>> +			VP_INITVOLTAGE_MASK | VP_ERRORGAIN_MASK);
>>> +	vpconfig |= ((target_vsel << VP_INITVOLTAGE_SHIFT) |
>>> +			vp_reg[vp_id].vp_errorgain);
>>> +	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>> +
>>> +	/* Trigger initVDD value copy to voltage processor */
>>> +	vpconfig |= VP_CONFIG_INITVDD;
>>> +	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>> +
>>> +	/* Force update of voltage */
>>> +	vpconfig |= VP_FORCEUPDATE;
>>> +	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>> +
>>> +	timeout = 0;
>>> +	/* Wait for TransactionDone. Typical latency is <200us.
>>> +	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
>>> +	 */
>>
>>multi-line comment style
>>
>>> +	while ((timeout++ < VP_TRANXDONE_TIMEOUT) &&
>>> +			(!(voltage_read_reg(PRM_IRQSTATUS_REG) &
>>> +			vp_reg[vp_id].vp_tranxdone_status)))
>>> +		udelay(1);
>>> +
>>> +	if (timeout >= VP_TRANXDONE_TIMEOUT)
>>> +		pr_warning("VP%d TRANXDONE timeout exceeded. TRANXDONE never \
>>> +			got set after the voltage update.Serious error!!!!\n",
>>> +			vdd);
>>> +
>>> +	/* Wait for voltage to settle with SW wait-loop */
>>> +	smps_delay = ((smps_steps * 125) / 40) + 2;
>>> +	udelay(smps_delay);
>>> +
>>> +	/* Disable TransactionDone interrupt , clear all status, clear
>>> +	 * control registers
>>> +	 */
>>
>>muti-line comment
>>
>>> +	timeout = 0;
>>> +	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
>>> +		voltage_write_reg(PRM_IRQSTATUS_REG,
>>> +				vp_reg[vp_id].vp_tranxdone_status);
>>> +		if (!(voltage_read_reg(PRM_IRQSTATUS_REG) &
>>> +				vp_reg[vp_id].vp_tranxdone_status))
>>> +				break;
>>> +		udelay(1);
>>> +	}
>>> +	if (timeout >= VP_TRANXDONE_TIMEOUT)
>>> +		pr_warning("VP%d TRANXDONE timeout exceeded while trying to \
>>> +			clear the TRANXDONE status\n", vdd);
>>> +
>>> +	vpconfig = voltage_read_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg);
>>> +	/* Clear initVDD copy trigger bit */
>>> +	vpconfig &= ~VP_CONFIG_INITVDD;
>>> +	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>> +	/* Clear force bit */
>>> +	vpconfig &= ~VP_FORCEUPDATE;
>>> +	voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>> +
>>> +	return true;
>>> +}
>>> +#endif
>>> +
>>> +#ifdef CONFIG_OMAP_VOLT_VCBYPASS
>>>  /**
>>>   * vc_bypass_scale_voltage - VC bypass method of voltage scaling
>>>   */
>>> @@ -437,7 +568,7 @@ static int vc_bypass_scale_voltage(u32 vdd, u8 target_vsel, u8 current_vsel)
>>>  	udelay(smps_delay);
>>>  	return true;
>>>  }
>>> -
>>> +#endif
>>>
>>>  static void __init init_voltageprocessors(void)
>>>  {
>>> @@ -474,13 +605,16 @@ void omap_voltageprocessor_enable(int vp_id)
>>>  	if (voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg) &
>>>  				VP_CONFIG_VPENABLE)
>>>  		return;
>>> +
>>> +#ifdef CONFIG_OMAP_VOLT_VCBYPASS
>>>  	/*
>>>  	 * This latching is required only if VC bypass method is used for
>>>  	 * voltage scaling during dvfs.
>>>  	 */
>>>  	vp_latch_vsel(vp_id - 1);
>>> -	vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
>>> +#endif
>>>  	/* Enable VP */
>>> +	vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
>>>  	voltage_write_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg,
>>>  				vpconfig | VP_CONFIG_VPENABLE);
>>>  }
>>> @@ -529,11 +663,12 @@ void omap_voltageprocessor_disable(int vp_id)
>>>   * for a particular voltage domain during dvfs or any other situation.
>>>   */
>>>  int omap_voltage_scale(int vdd, u8 target_vsel, u8 current_vsel)
>>> -{	/*
>>> -	 * TODO add VP force update method of voltage scaling
>>> -	 * and choose btw the two
>>> -	 */
>>> +{
>>> +#ifdef CONFIG_OMAP_VOLT_VCBYPASS
>>>  	return vc_bypass_scale_voltage(vdd, target_vsel, current_vsel);
>>> +#elif CONFIG_OMAP_VOLT_VPFORCEUPDATE
>>> +	return vp_forceupdate_scale_voltage(vdd, target_vsel, current_vsel);
>>> +#endif
>>>  }
>>>
>>>  /**
>>> diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
>>> index c3203c9..615bde6 100644
>>> --- a/arch/arm/mach-omap2/voltage.h
>>> +++ b/arch/arm/mach-omap2/voltage.h
>>> @@ -17,6 +17,7 @@
>>>  extern int get_vdd1_opp(void);
>>>  extern int get_vdd2_opp(void);
>>>
>>> +#define PRM_IRQSTATUS_REG	OMAP3430_PRM_IRQSTATUS_MPU
>>>  /* Generic VP definitions. Need to be redefined for OMAP4 */
>>>  #define VP_CONFIG_TIMEOUTEN	OMAP3430_TIMEOUTEN
>>>  #define VP_CONFIG_INITVDD	OMAP3430_INITVDD
>>> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
>>> index 9d286e6..1a611a9 100644
>>> --- a/arch/arm/plat-omap/Kconfig
>>> +++ b/arch/arm/plat-omap/Kconfig
>>> @@ -92,6 +92,25 @@ config OMAP_SMARTREFLEX_TESTING
>>>
>>>  	  WARNING: Enabling this option may cause your device to hang!
>>>
>>> +choice
>>> +	prompt "Choose Voltage Scale method"
>>> +	depends on ARCH_OMAP3 && PM
>>> +	default OMAP_VOLT_VPFORCEUPDATE
>>> +
>>> +config OMAP_VOLT_VPFORCEUPDATE
>>> +	bool "Voltage scaling via VP force update method"
>>> +	help
>>> +	 Say Y if you want to enable VP force update method
>>> +	 of voltage scaling. This is the h/w recomended way
>>> +	 of voltage scaling in OMAP3.
>>> +
>>> +config OMAP_VOLT_VCBYPASS
>>> +	bool "Voltage Scale via Voltage controller in bypass"
>>> +	help
>>> +	 Say Y if you want to enable VC Bypass method of voltage scaling.
>>> +	 Not the default recommended method.
>>> +endchoice
>>> +
>>>  config OMAP_RESET_CLOCKS
>>>  	bool "Reset unused clocks during boot"
>>>  	depends on ARCH_OMAP
>>> --
>>> 1.7.0.rc1.33.g07cf0f

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

* Re: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling
  2010-03-05 15:22                                 ` Gopinath, Thara
@ 2010-03-05 15:26                                   ` Felipe Contreras
  2010-03-05 15:30                                     ` Gopinath, Thara
  0 siblings, 1 reply; 61+ messages in thread
From: Felipe Contreras @ 2010-03-05 15:26 UTC (permalink / raw)
  To: Gopinath, Thara
  Cc: Kevin Hilman, linux-omap, paul, Menon, Nishanth, Cousson, Benoit,
	Sripathy, Vishwanath, Sawant, Anand

Hi Thara,

On Fri, Mar 5, 2010 at 5:22 PM, Gopinath, Thara <thara@ti.com> wrote:
> Will do this as V2

Can you please remove the chunks of text you are not replying to in your mails?

All the following text is just a waste of bandwidth, and time for
people that actually scroll down trying to find further comments. This
is a practice not only you, but other people have started to follow in
this mailing list and it's annoying me a bit.

Cheers.

>>>
>>>> ---
>>>>  arch/arm/mach-omap2/voltage.c |  149 +++++++++++++++++++++++++++++++++++++++--
>>>>  arch/arm/mach-omap2/voltage.h |    1 +
>>>>  arch/arm/plat-omap/Kconfig    |   19 +++++
>>>>  3 files changed, 162 insertions(+), 7 deletions(-)
>>>>
>>>> diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
>>>> index 49167c0..4f325af 100644
>>>> --- a/arch/arm/mach-omap2/voltage.c
>>>> +++ b/arch/arm/mach-omap2/voltage.c
>>>> @@ -29,7 +29,8 @@
>>>>  #include "prm-regbits-34xx.h"
>>>>  #include "voltage.h"
>>>>
>>>> -#define VP_IDLE_TIMEOUT 200
>>>> +#define VP_IDLE_TIMEOUT    200
>>>> +#define VP_TRANXDONE_TIMEOUT       300
>>>>
>>>>  /*
>>>>   * OMAP3 Voltage controller SR parameters. TODO: Pass this info as part of
>>>> @@ -70,6 +71,7 @@ struct vp_reg_info {
>>>>     u32 vp_vddmin;
>>>>     u32 vp_vddmax;
>>>>     u32 vp_timeout;
>>>> +   u32 vp_tranxdone_status;
>>>>  };
>>>>  static struct vp_reg_info *vp_reg;
>>>>  /*
>>>> @@ -299,6 +301,8 @@ static void __init vp_reg_configure(int vp_id)
>>>>                                     OMAP3430_VDDMIN_SHIFT);
>>>>                     vp_reg[vp_id].vp_vddmax = (OMAP3_VP1_VLIMITTO_VDDMAX <<
>>>>                                     OMAP3430_VDDMAX_SHIFT);
>>>> +                   vp_reg[vp_id].vp_tranxdone_status =
>>>> +                                   OMAP3430_VP1_TRANXDONE_ST;
>>>>             } else if (vp_id == VP2) {
>>>>                     /*
>>>>                      * OMAP3430 has error gain varying btw higher and
>>>> @@ -312,6 +316,8 @@ static void __init vp_reg_configure(int vp_id)
>>>>                                     OMAP3430_VDDMIN_SHIFT);
>>>>                     vp_reg[vp_id].vp_vddmax = (OMAP3_VP2_VLIMITTO_VDDMAX <<
>>>>                                     OMAP3430_VDDMAX_SHIFT);
>>>> +                   vp_reg[vp_id].vp_tranxdone_status =
>>>> +                                   OMAP3430_VP2_TRANXDONE_ST;
>>>>             } else {
>>>>                     pr_warning("Voltage processor%d does not exisit\
>>>>                                     in OMAP3 \n", vp_id);
>>>> @@ -346,6 +352,131 @@ static void __init vp_reg_configure(int vp_id)
>>>>     /* TODO Extend this for OMAP4 ?? Or need a separate file  */
>>>>  }
>>>>
>>>> +#ifdef CONFIG_OMAP_VOLT_VPFORCEUPDATE
>>>> +/* VP force update method of voltage scaling */
>>>> +static int vp_forceupdate_scale_voltage(u32 vdd, u8 target_vsel,
>>>> +                           u8 current_vsel)
>>>> +{
>>>> +   u32 smps_steps = 0, smps_delay = 0;
>>>> +   u32 vpconfig;
>>>> +   int timeout = 0;
>>>> +   int vp_id = vdd - 1;
>>>> +
>>>> +   if (!((vdd == VDD1_OPP) || (vdd == VDD2_OPP))) {
>>>> +           pr_warning("Wrong vdd id passed to vp forceupdate\n");
>>>> +           return false;
>>>> +   }
>>>> +
>>>> +   smps_steps = abs(target_vsel - current_vsel);
>>>> +
>>>> +   /* OMAP3430 has errorgain varying btw higher and lower opp's */
>>>> +   if (cpu_is_omap34xx()) {
>>>> +           if (vdd == VDD1_OPP) {
>>>> +                   u32 vc_cmdval0;
>>>> +
>>>> +                   vc_cmdval0 = voltage_read_reg(vc_reg.vc_cmdval0_reg);
>>>> +                   vc_cmdval0 &= ~VC_CMD_ON_MASK;
>>>> +                   vc_cmdval0 |= (target_vsel << VC_CMD_ON_SHIFT);
>>>> +                   voltage_write_reg(vc_reg.vc_cmdval0_reg, vc_cmdval0);
>>>> +                   vp_reg[vp_id].vp_errorgain = (((get_vdd1_opp() > 2) ?
>>>> +                                   (OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
>>>> +                                   (OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
>>>> +                                   OMAP3430_ERRORGAIN_SHIFT);
>>>> +           } else if (vdd == VDD2_OPP) {
>>>> +                   u32 vc_cmdval1;
>>>> +
>>>> +                   vc_cmdval1 = voltage_read_reg(vc_reg.vc_cmdval1_reg);
>>>> +                   vc_cmdval1 &= ~VC_CMD_ON_MASK;
>>>> +                   vc_cmdval1 |= (target_vsel << VC_CMD_ON_SHIFT);
>>>> +                   voltage_write_reg(vc_reg.vc_cmdval1_reg, vc_cmdval1);
>>>> +                   vp_reg[vp_id].vp_errorgain = (((get_vdd2_opp() > 2) ?
>>>> +                                   (OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
>>>> +                                   (OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
>>>> +                                   OMAP3430_ERRORGAIN_SHIFT);
>>>> +           }
>>>> +   }
>>>> +
>>>> +   /* Clear all pending TransactionDone interrupt/status. Typical latency
>>>> +    * is <3us
>>>> +    */
>>>> +   while (timeout++ < VP_TRANXDONE_TIMEOUT) {
>>>> +           voltage_write_reg(PRM_IRQSTATUS_REG,
>>>> +                           vp_reg[vp_id].vp_tranxdone_status);
>>>> +           if (!(voltage_read_reg(PRM_IRQSTATUS_REG) &
>>>> +                           vp_reg[vp_id].vp_tranxdone_status))
>>>> +                           break;
>>>> +           udelay(1);
>>>> +   }
>>>> +
>>>> +   if (timeout >= VP_TRANXDONE_TIMEOUT) {
>>>> +           pr_warning("VP%d TRANXDONE timeout exceeded. Voltage change \
>>>> +                           aborted", vdd);
>>>> +           return false;
>>>> +   }
>>>> +
>>>> +   /* Configure for VP-Force Update */
>>>> +   vpconfig = voltage_read_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg);
>>>> +   vpconfig &= ~(VP_CONFIG_INITVDD | VP_FORCEUPDATE |
>>>> +                   VP_INITVOLTAGE_MASK | VP_ERRORGAIN_MASK);
>>>> +   vpconfig |= ((target_vsel << VP_INITVOLTAGE_SHIFT) |
>>>> +                   vp_reg[vp_id].vp_errorgain);
>>>> +   voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>>> +
>>>> +   /* Trigger initVDD value copy to voltage processor */
>>>> +   vpconfig |= VP_CONFIG_INITVDD;
>>>> +   voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>>> +
>>>> +   /* Force update of voltage */
>>>> +   vpconfig |= VP_FORCEUPDATE;
>>>> +   voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>>> +
>>>> +   timeout = 0;
>>>> +   /* Wait for TransactionDone. Typical latency is <200us.
>>>> +    * Depends on SMPSWAITTIMEMIN/MAX and voltage change
>>>> +    */
>>>
>>>multi-line comment style
>>>
>>>> +   while ((timeout++ < VP_TRANXDONE_TIMEOUT) &&
>>>> +                   (!(voltage_read_reg(PRM_IRQSTATUS_REG) &
>>>> +                   vp_reg[vp_id].vp_tranxdone_status)))
>>>> +           udelay(1);
>>>> +
>>>> +   if (timeout >= VP_TRANXDONE_TIMEOUT)
>>>> +           pr_warning("VP%d TRANXDONE timeout exceeded. TRANXDONE never \
>>>> +                   got set after the voltage update.Serious error!!!!\n",
>>>> +                   vdd);
>>>> +
>>>> +   /* Wait for voltage to settle with SW wait-loop */
>>>> +   smps_delay = ((smps_steps * 125) / 40) + 2;
>>>> +   udelay(smps_delay);
>>>> +
>>>> +   /* Disable TransactionDone interrupt , clear all status, clear
>>>> +    * control registers
>>>> +    */
>>>
>>>muti-line comment
>>>
>>>> +   timeout = 0;
>>>> +   while (timeout++ < VP_TRANXDONE_TIMEOUT) {
>>>> +           voltage_write_reg(PRM_IRQSTATUS_REG,
>>>> +                           vp_reg[vp_id].vp_tranxdone_status);
>>>> +           if (!(voltage_read_reg(PRM_IRQSTATUS_REG) &
>>>> +                           vp_reg[vp_id].vp_tranxdone_status))
>>>> +                           break;
>>>> +           udelay(1);
>>>> +   }
>>>> +   if (timeout >= VP_TRANXDONE_TIMEOUT)
>>>> +           pr_warning("VP%d TRANXDONE timeout exceeded while trying to \
>>>> +                   clear the TRANXDONE status\n", vdd);
>>>> +
>>>> +   vpconfig = voltage_read_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg);
>>>> +   /* Clear initVDD copy trigger bit */
>>>> +   vpconfig &= ~VP_CONFIG_INITVDD;
>>>> +   voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>>> +   /* Clear force bit */
>>>> +   vpconfig &= ~VP_FORCEUPDATE;
>>>> +   voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>>> +
>>>> +   return true;
>>>> +}
>>>> +#endif
>>>> +
>>>> +#ifdef CONFIG_OMAP_VOLT_VCBYPASS
>>>>  /**
>>>>   * vc_bypass_scale_voltage - VC bypass method of voltage scaling
>>>>   */
>>>> @@ -437,7 +568,7 @@ static int vc_bypass_scale_voltage(u32 vdd, u8 target_vsel, u8 current_vsel)
>>>>     udelay(smps_delay);
>>>>     return true;
>>>>  }
>>>> -
>>>> +#endif
>>>>
>>>>  static void __init init_voltageprocessors(void)
>>>>  {
>>>> @@ -474,13 +605,16 @@ void omap_voltageprocessor_enable(int vp_id)
>>>>     if (voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg) &
>>>>                             VP_CONFIG_VPENABLE)
>>>>             return;
>>>> +
>>>> +#ifdef CONFIG_OMAP_VOLT_VCBYPASS
>>>>     /*
>>>>      * This latching is required only if VC bypass method is used for
>>>>      * voltage scaling during dvfs.
>>>>      */
>>>>     vp_latch_vsel(vp_id - 1);
>>>> -   vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
>>>> +#endif
>>>>     /* Enable VP */
>>>> +   vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
>>>>     voltage_write_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg,
>>>>                             vpconfig | VP_CONFIG_VPENABLE);
>>>>  }
>>>> @@ -529,11 +663,12 @@ void omap_voltageprocessor_disable(int vp_id)
>>>>   * for a particular voltage domain during dvfs or any other situation.
>>>>   */
>>>>  int omap_voltage_scale(int vdd, u8 target_vsel, u8 current_vsel)
>>>> -{  /*
>>>> -    * TODO add VP force update method of voltage scaling
>>>> -    * and choose btw the two
>>>> -    */
>>>> +{
>>>> +#ifdef CONFIG_OMAP_VOLT_VCBYPASS
>>>>     return vc_bypass_scale_voltage(vdd, target_vsel, current_vsel);
>>>> +#elif CONFIG_OMAP_VOLT_VPFORCEUPDATE
>>>> +   return vp_forceupdate_scale_voltage(vdd, target_vsel, current_vsel);
>>>> +#endif
>>>>  }
>>>>
>>>>  /**
>>>> diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
>>>> index c3203c9..615bde6 100644
>>>> --- a/arch/arm/mach-omap2/voltage.h
>>>> +++ b/arch/arm/mach-omap2/voltage.h
>>>> @@ -17,6 +17,7 @@
>>>>  extern int get_vdd1_opp(void);
>>>>  extern int get_vdd2_opp(void);
>>>>
>>>> +#define PRM_IRQSTATUS_REG  OMAP3430_PRM_IRQSTATUS_MPU
>>>>  /* Generic VP definitions. Need to be redefined for OMAP4 */
>>>>  #define VP_CONFIG_TIMEOUTEN        OMAP3430_TIMEOUTEN
>>>>  #define VP_CONFIG_INITVDD  OMAP3430_INITVDD
>>>> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
>>>> index 9d286e6..1a611a9 100644
>>>> --- a/arch/arm/plat-omap/Kconfig
>>>> +++ b/arch/arm/plat-omap/Kconfig
>>>> @@ -92,6 +92,25 @@ config OMAP_SMARTREFLEX_TESTING
>>>>
>>>>       WARNING: Enabling this option may cause your device to hang!
>>>>
>>>> +choice
>>>> +   prompt "Choose Voltage Scale method"
>>>> +   depends on ARCH_OMAP3 && PM
>>>> +   default OMAP_VOLT_VPFORCEUPDATE
>>>> +
>>>> +config OMAP_VOLT_VPFORCEUPDATE
>>>> +   bool "Voltage scaling via VP force update method"
>>>> +   help
>>>> +    Say Y if you want to enable VP force update method
>>>> +    of voltage scaling. This is the h/w recomended way
>>>> +    of voltage scaling in OMAP3.
>>>> +
>>>> +config OMAP_VOLT_VCBYPASS
>>>> +   bool "Voltage Scale via Voltage controller in bypass"
>>>> +   help
>>>> +    Say Y if you want to enable VC Bypass method of voltage scaling.
>>>> +    Not the default recommended method.
>>>> +endchoice
>>>> +
>>>>  config OMAP_RESET_CLOCKS
>>>>     bool "Reset unused clocks during boot"
>>>>     depends on ARCH_OMAP
>>>> --
>>>> 1.7.0.rc1.33.g07cf0f
> --
> 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
>



-- 
Felipe Contreras
--
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] 61+ messages in thread

* RE: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling
  2010-03-05 15:26                                   ` Felipe Contreras
@ 2010-03-05 15:30                                     ` Gopinath, Thara
  2010-03-05 16:22                                       ` Felipe Contreras
  0 siblings, 1 reply; 61+ messages in thread
From: Gopinath, Thara @ 2010-03-05 15:30 UTC (permalink / raw)
  To: Felipe Contreras
  Cc: Kevin Hilman, linux-omap, paul, Menon, Nishanth, Cousson, Benoit,
	Sripathy, Vishwanath, Sawant, Anand



>>-----Original Message-----
>>From: Felipe Contreras [mailto:felipe.contreras@gmail.com]
>>Sent: Friday, March 05, 2010 8:57 PM
>>To: Gopinath, Thara
>>Cc: Kevin Hilman; linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit;
>>Sripathy, Vishwanath; Sawant, Anand
>>Subject: Re: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling
>>
>>Hi Thara,
>>
>>On Fri, Mar 5, 2010 at 5:22 PM, Gopinath, Thara <thara@ti.com> wrote:
>>> Will do this as V2
>>
>>Can you please remove the chunks of text you are not replying to in your mails?
>>
>>All the following text is just a waste of bandwidth, and time for
>>people that actually scroll down trying to find further comments. This
>>is a practice not only you, but other people have started to follow in
>>this mailing list and it's annoying me a bit.
>>
>>Cheers.

Hello Filipe

I have been putting "Regards Thara" at the end of my comments precisely so that people do not have to scroll down and waste their bandwidth. I have seen this as an accepted practice in the mailing list through observing mails from other experts.

Regards
Thara
>>
>>>>>
>>>>>> ---
>>>>>>  arch/arm/mach-omap2/voltage.c |  149 +++++++++++++++++++++++++++++++++++++++--
>>>>>>  arch/arm/mach-omap2/voltage.h |    1 +
>>>>>>  arch/arm/plat-omap/Kconfig    |   19 +++++
>>>>>>  3 files changed, 162 insertions(+), 7 deletions(-)
>>>>>>
>>>>>> diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
>>>>>> index 49167c0..4f325af 100644
>>>>>> --- a/arch/arm/mach-omap2/voltage.c
>>>>>> +++ b/arch/arm/mach-omap2/voltage.c
>>>>>> @@ -29,7 +29,8 @@
>>>>>>  #include "prm-regbits-34xx.h"
>>>>>>  #include "voltage.h"
>>>>>>
>>>>>> -#define VP_IDLE_TIMEOUT 200
>>>>>> +#define VP_IDLE_TIMEOUT    200
>>>>>> +#define VP_TRANXDONE_TIMEOUT       300
>>>>>>
>>>>>>  /*
>>>>>>   * OMAP3 Voltage controller SR parameters. TODO: Pass this info as part of
>>>>>> @@ -70,6 +71,7 @@ struct vp_reg_info {
>>>>>>     u32 vp_vddmin;
>>>>>>     u32 vp_vddmax;
>>>>>>     u32 vp_timeout;
>>>>>> +   u32 vp_tranxdone_status;
>>>>>>  };
>>>>>>  static struct vp_reg_info *vp_reg;
>>>>>>  /*
>>>>>> @@ -299,6 +301,8 @@ static void __init vp_reg_configure(int vp_id)
>>>>>>                                     OMAP3430_VDDMIN_SHIFT);
>>>>>>                     vp_reg[vp_id].vp_vddmax = (OMAP3_VP1_VLIMITTO_VDDMAX <<
>>>>>>                                     OMAP3430_VDDMAX_SHIFT);
>>>>>> +                   vp_reg[vp_id].vp_tranxdone_status =
>>>>>> +                                   OMAP3430_VP1_TRANXDONE_ST;
>>>>>>             } else if (vp_id == VP2) {
>>>>>>                     /*
>>>>>>                      * OMAP3430 has error gain varying btw higher and
>>>>>> @@ -312,6 +316,8 @@ static void __init vp_reg_configure(int vp_id)
>>>>>>                                     OMAP3430_VDDMIN_SHIFT);
>>>>>>                     vp_reg[vp_id].vp_vddmax = (OMAP3_VP2_VLIMITTO_VDDMAX <<
>>>>>>                                     OMAP3430_VDDMAX_SHIFT);
>>>>>> +                   vp_reg[vp_id].vp_tranxdone_status =
>>>>>> +                                   OMAP3430_VP2_TRANXDONE_ST;
>>>>>>             } else {
>>>>>>                     pr_warning("Voltage processor%d does not exisit\
>>>>>>                                     in OMAP3 \n", vp_id);
>>>>>> @@ -346,6 +352,131 @@ static void __init vp_reg_configure(int vp_id)
>>>>>>     /* TODO Extend this for OMAP4 ?? Or need a separate file  */
>>>>>>  }
>>>>>>
>>>>>> +#ifdef CONFIG_OMAP_VOLT_VPFORCEUPDATE
>>>>>> +/* VP force update method of voltage scaling */
>>>>>> +static int vp_forceupdate_scale_voltage(u32 vdd, u8 target_vsel,
>>>>>> +                           u8 current_vsel)
>>>>>> +{
>>>>>> +   u32 smps_steps = 0, smps_delay = 0;
>>>>>> +   u32 vpconfig;
>>>>>> +   int timeout = 0;
>>>>>> +   int vp_id = vdd - 1;
>>>>>> +
>>>>>> +   if (!((vdd == VDD1_OPP) || (vdd == VDD2_OPP))) {
>>>>>> +           pr_warning("Wrong vdd id passed to vp forceupdate\n");
>>>>>> +           return false;
>>>>>> +   }
>>>>>> +
>>>>>> +   smps_steps = abs(target_vsel - current_vsel);
>>>>>> +
>>>>>> +   /* OMAP3430 has errorgain varying btw higher and lower opp's */
>>>>>> +   if (cpu_is_omap34xx()) {
>>>>>> +           if (vdd == VDD1_OPP) {
>>>>>> +                   u32 vc_cmdval0;
>>>>>> +
>>>>>> +                   vc_cmdval0 = voltage_read_reg(vc_reg.vc_cmdval0_reg);
>>>>>> +                   vc_cmdval0 &= ~VC_CMD_ON_MASK;
>>>>>> +                   vc_cmdval0 |= (target_vsel << VC_CMD_ON_SHIFT);
>>>>>> +                   voltage_write_reg(vc_reg.vc_cmdval0_reg, vc_cmdval0);
>>>>>> +                   vp_reg[vp_id].vp_errorgain = (((get_vdd1_opp() > 2) ?
>>>>>> +                                   (OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
>>>>>> +                                   (OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
>>>>>> +                                   OMAP3430_ERRORGAIN_SHIFT);
>>>>>> +           } else if (vdd == VDD2_OPP) {
>>>>>> +                   u32 vc_cmdval1;
>>>>>> +
>>>>>> +                   vc_cmdval1 = voltage_read_reg(vc_reg.vc_cmdval1_reg);
>>>>>> +                   vc_cmdval1 &= ~VC_CMD_ON_MASK;
>>>>>> +                   vc_cmdval1 |= (target_vsel << VC_CMD_ON_SHIFT);
>>>>>> +                   voltage_write_reg(vc_reg.vc_cmdval1_reg, vc_cmdval1);
>>>>>> +                   vp_reg[vp_id].vp_errorgain = (((get_vdd2_opp() > 2) ?
>>>>>> +                                   (OMAP3_VP_CONFIG_ERRORGAIN_HIGHOPP) :
>>>>>> +                                   (OMAP3_VP_CONFIG_ERRORGAIN_LOWOPP)) <<
>>>>>> +                                   OMAP3430_ERRORGAIN_SHIFT);
>>>>>> +           }
>>>>>> +   }
>>>>>> +
>>>>>> +   /* Clear all pending TransactionDone interrupt/status. Typical latency
>>>>>> +    * is <3us
>>>>>> +    */
>>>>>> +   while (timeout++ < VP_TRANXDONE_TIMEOUT) {
>>>>>> +           voltage_write_reg(PRM_IRQSTATUS_REG,
>>>>>> +                           vp_reg[vp_id].vp_tranxdone_status);
>>>>>> +           if (!(voltage_read_reg(PRM_IRQSTATUS_REG) &
>>>>>> +                           vp_reg[vp_id].vp_tranxdone_status))
>>>>>> +                           break;
>>>>>> +           udelay(1);
>>>>>> +   }
>>>>>> +
>>>>>> +   if (timeout >= VP_TRANXDONE_TIMEOUT) {
>>>>>> +           pr_warning("VP%d TRANXDONE timeout exceeded. Voltage change \
>>>>>> +                           aborted", vdd);
>>>>>> +           return false;
>>>>>> +   }
>>>>>> +
>>>>>> +   /* Configure for VP-Force Update */
>>>>>> +   vpconfig = voltage_read_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg);
>>>>>> +   vpconfig &= ~(VP_CONFIG_INITVDD | VP_FORCEUPDATE |
>>>>>> +                   VP_INITVOLTAGE_MASK | VP_ERRORGAIN_MASK);
>>>>>> +   vpconfig |= ((target_vsel << VP_INITVOLTAGE_SHIFT) |
>>>>>> +                   vp_reg[vp_id].vp_errorgain);
>>>>>> +   voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>>>>> +
>>>>>> +   /* Trigger initVDD value copy to voltage processor */
>>>>>> +   vpconfig |= VP_CONFIG_INITVDD;
>>>>>> +   voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>>>>> +
>>>>>> +   /* Force update of voltage */
>>>>>> +   vpconfig |= VP_FORCEUPDATE;
>>>>>> +   voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>>>>> +
>>>>>> +   timeout = 0;
>>>>>> +   /* Wait for TransactionDone. Typical latency is <200us.
>>>>>> +    * Depends on SMPSWAITTIMEMIN/MAX and voltage change
>>>>>> +    */
>>>>>
>>>>>multi-line comment style
>>>>>
>>>>>> +   while ((timeout++ < VP_TRANXDONE_TIMEOUT) &&
>>>>>> +                   (!(voltage_read_reg(PRM_IRQSTATUS_REG) &
>>>>>> +                   vp_reg[vp_id].vp_tranxdone_status)))
>>>>>> +           udelay(1);
>>>>>> +
>>>>>> +   if (timeout >= VP_TRANXDONE_TIMEOUT)
>>>>>> +           pr_warning("VP%d TRANXDONE timeout exceeded. TRANXDONE never \
>>>>>> +                   got set after the voltage update.Serious error!!!!\n",
>>>>>> +                   vdd);
>>>>>> +
>>>>>> +   /* Wait for voltage to settle with SW wait-loop */
>>>>>> +   smps_delay = ((smps_steps * 125) / 40) + 2;
>>>>>> +   udelay(smps_delay);
>>>>>> +
>>>>>> +   /* Disable TransactionDone interrupt , clear all status, clear
>>>>>> +    * control registers
>>>>>> +    */
>>>>>
>>>>>muti-line comment
>>>>>
>>>>>> +   timeout = 0;
>>>>>> +   while (timeout++ < VP_TRANXDONE_TIMEOUT) {
>>>>>> +           voltage_write_reg(PRM_IRQSTATUS_REG,
>>>>>> +                           vp_reg[vp_id].vp_tranxdone_status);
>>>>>> +           if (!(voltage_read_reg(PRM_IRQSTATUS_REG) &
>>>>>> +                           vp_reg[vp_id].vp_tranxdone_status))
>>>>>> +                           break;
>>>>>> +           udelay(1);
>>>>>> +   }
>>>>>> +   if (timeout >= VP_TRANXDONE_TIMEOUT)
>>>>>> +           pr_warning("VP%d TRANXDONE timeout exceeded while trying to \
>>>>>> +                   clear the TRANXDONE status\n", vdd);
>>>>>> +
>>>>>> +   vpconfig = voltage_read_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg);
>>>>>> +   /* Clear initVDD copy trigger bit */
>>>>>> +   vpconfig &= ~VP_CONFIG_INITVDD;
>>>>>> +   voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>>>>> +   /* Clear force bit */
>>>>>> +   vpconfig &= ~VP_FORCEUPDATE;
>>>>>> +   voltage_write_reg(vp_reg[vp_id].vp_offs.vp_vpconfig_reg, vpconfig);
>>>>>> +
>>>>>> +   return true;
>>>>>> +}
>>>>>> +#endif
>>>>>> +
>>>>>> +#ifdef CONFIG_OMAP_VOLT_VCBYPASS
>>>>>>  /**
>>>>>>   * vc_bypass_scale_voltage - VC bypass method of voltage scaling
>>>>>>   */
>>>>>> @@ -437,7 +568,7 @@ static int vc_bypass_scale_voltage(u32 vdd, u8 target_vsel, u8 current_vsel)
>>>>>>     udelay(smps_delay);
>>>>>>     return true;
>>>>>>  }
>>>>>> -
>>>>>> +#endif
>>>>>>
>>>>>>  static void __init init_voltageprocessors(void)
>>>>>>  {
>>>>>> @@ -474,13 +605,16 @@ void omap_voltageprocessor_enable(int vp_id)
>>>>>>     if (voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg) &
>>>>>>                             VP_CONFIG_VPENABLE)
>>>>>>             return;
>>>>>> +
>>>>>> +#ifdef CONFIG_OMAP_VOLT_VCBYPASS
>>>>>>     /*
>>>>>>      * This latching is required only if VC bypass method is used for
>>>>>>      * voltage scaling during dvfs.
>>>>>>      */
>>>>>>     vp_latch_vsel(vp_id - 1);
>>>>>> -   vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
>>>>>> +#endif
>>>>>>     /* Enable VP */
>>>>>> +   vpconfig = voltage_read_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg);
>>>>>>     voltage_write_reg(vp_reg[vp_id - 1].vp_offs.vp_vpconfig_reg,
>>>>>>                             vpconfig | VP_CONFIG_VPENABLE);
>>>>>>  }
>>>>>> @@ -529,11 +663,12 @@ void omap_voltageprocessor_disable(int vp_id)
>>>>>>   * for a particular voltage domain during dvfs or any other situation.
>>>>>>   */
>>>>>>  int omap_voltage_scale(int vdd, u8 target_vsel, u8 current_vsel)
>>>>>> -{  /*
>>>>>> -    * TODO add VP force update method of voltage scaling
>>>>>> -    * and choose btw the two
>>>>>> -    */
>>>>>> +{
>>>>>> +#ifdef CONFIG_OMAP_VOLT_VCBYPASS
>>>>>>     return vc_bypass_scale_voltage(vdd, target_vsel, current_vsel);
>>>>>> +#elif CONFIG_OMAP_VOLT_VPFORCEUPDATE
>>>>>> +   return vp_forceupdate_scale_voltage(vdd, target_vsel, current_vsel);
>>>>>> +#endif
>>>>>>  }
>>>>>>
>>>>>>  /**
>>>>>> diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
>>>>>> index c3203c9..615bde6 100644
>>>>>> --- a/arch/arm/mach-omap2/voltage.h
>>>>>> +++ b/arch/arm/mach-omap2/voltage.h
>>>>>> @@ -17,6 +17,7 @@
>>>>>>  extern int get_vdd1_opp(void);
>>>>>>  extern int get_vdd2_opp(void);
>>>>>>
>>>>>> +#define PRM_IRQSTATUS_REG  OMAP3430_PRM_IRQSTATUS_MPU
>>>>>>  /* Generic VP definitions. Need to be redefined for OMAP4 */
>>>>>>  #define VP_CONFIG_TIMEOUTEN        OMAP3430_TIMEOUTEN
>>>>>>  #define VP_CONFIG_INITVDD  OMAP3430_INITVDD
>>>>>> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
>>>>>> index 9d286e6..1a611a9 100644
>>>>>> --- a/arch/arm/plat-omap/Kconfig
>>>>>> +++ b/arch/arm/plat-omap/Kconfig
>>>>>> @@ -92,6 +92,25 @@ config OMAP_SMARTREFLEX_TESTING
>>>>>>
>>>>>>       WARNING: Enabling this option may cause your device to hang!
>>>>>>
>>>>>> +choice
>>>>>> +   prompt "Choose Voltage Scale method"
>>>>>> +   depends on ARCH_OMAP3 && PM
>>>>>> +   default OMAP_VOLT_VPFORCEUPDATE
>>>>>> +
>>>>>> +config OMAP_VOLT_VPFORCEUPDATE
>>>>>> +   bool "Voltage scaling via VP force update method"
>>>>>> +   help
>>>>>> +    Say Y if you want to enable VP force update method
>>>>>> +    of voltage scaling. This is the h/w recomended way
>>>>>> +    of voltage scaling in OMAP3.
>>>>>> +
>>>>>> +config OMAP_VOLT_VCBYPASS
>>>>>> +   bool "Voltage Scale via Voltage controller in bypass"
>>>>>> +   help
>>>>>> +    Say Y if you want to enable VC Bypass method of voltage scaling.
>>>>>> +    Not the default recommended method.
>>>>>> +endchoice
>>>>>> +
>>>>>>  config OMAP_RESET_CLOCKS
>>>>>>     bool "Reset unused clocks during boot"
>>>>>>     depends on ARCH_OMAP
>>>>>> --
>>>>>> 1.7.0.rc1.33.g07cf0f
>>> --
>>> 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
>>>
>>
>>
>>
>>--
>>Felipe Contreras

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

* Re: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling
  2010-03-05 15:30                                     ` Gopinath, Thara
@ 2010-03-05 16:22                                       ` Felipe Contreras
  2010-03-05 18:17                                         ` Snipping irrelevant text from a discussion (was: "RE: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling") Aguirre, Sergio
  0 siblings, 1 reply; 61+ messages in thread
From: Felipe Contreras @ 2010-03-05 16:22 UTC (permalink / raw)
  To: Gopinath, Thara
  Cc: Kevin Hilman, linux-omap, paul, Menon, Nishanth, Cousson, Benoit,
	Sripathy, Vishwanath, Sawant, Anand

On Fri, Mar 5, 2010 at 5:30 PM, Gopinath, Thara <thara@ti.com> wrote:
> I have been putting "Regards Thara" at the end of my comments precisely so
> that people do not have to scroll down and waste their bandwidth. I have seen
> this as an accepted practice in the mailing list through observing mails from
> other experts.

This is what messages from "other experts" look like:

Peter Zijlstra
http://article.gmane.org/gmane.linux.kernel/958012

Alan Cox
http://article.gmane.org/gmane.linux.kernel/958009

Andrew Morton
http://article.gmane.org/gmane.linux.kernel/957749

Thomas Gleixner
http://article.gmane.org/gmane.linux.kernel/957657

Linus Torvalds
http://article.gmane.org/gmane.linux.kernel/529672

And this is what yours look like (nothing like them):
http://article.gmane.org/gmane.linux.ports.arm.omap/32334

The fact that other people do it (mostly from TI), doesn't mean that
it's an *accepted* practice, but I guess it's much easier for me to
just filter these messages. Although I'm pretty sure other people find
them annoying, I'll push for that in some later time.

Cheers.

-- 
Felipe Contreras

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

* Snipping irrelevant text from a discussion (was: "RE: [PATCH 15/16] OMAP3: PM: VP force update method of voltage  scaling")
  2010-03-05 16:22                                       ` Felipe Contreras
@ 2010-03-05 18:17                                         ` Aguirre, Sergio
  2010-03-05 21:18                                           ` Felipe Contreras
  0 siblings, 1 reply; 61+ messages in thread
From: Aguirre, Sergio @ 2010-03-05 18:17 UTC (permalink / raw)
  To: Felipe Contreras, Gopinath, Thara
  Cc: Kevin Hilman, linux-omap, paul, Menon, Nishanth, Cousson, Benoit,
	Sripathy, Vishwanath, Sawant, Anand



From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
owner@vger.kernel.org] On Behalf Of Felipe Contreras
Sent: Friday, March 05, 2010 10:23 AM
> On Fri, Mar 5, 2010 at 5:30 PM, Gopinath, Thara <thara@ti.com> wrote:
> > I have been putting "Regards Thara" at the end of my comments precisely
> so
> > that people do not have to scroll down and waste their bandwidth. I have
> seen
> > this as an accepted practice in the mailing list through observing mails
> from
> > other experts.
> 
> This is what messages from "other experts" look like:
> 
> Peter Zijlstra
> http://article.gmane.org/gmane.linux.kernel/958012
> 
> Alan Cox
> http://article.gmane.org/gmane.linux.kernel/958009
> 
> Andrew Morton
> http://article.gmane.org/gmane.linux.kernel/957749
> 
> Thomas Gleixner
> http://article.gmane.org/gmane.linux.kernel/957657
> 
> Linus Torvalds
> http://article.gmane.org/gmane.linux.kernel/529672
> 
> And this is what yours look like (nothing like them):
> http://article.gmane.org/gmane.linux.ports.arm.omap/32334
> 
> The fact that other people do it (mostly from TI), doesn't mean that
> it's an *accepted* practice, but I guess it's much easier for me to
> just filter these messages. Although I'm pretty sure other people find
> them annoying, I'll push for that in some later time.

Hey!

You guys take a "chill pill", ok? :) Let's not start shouting at people and point fingers.

My 2 cents is that, usually, when discussion starts about a topic, or a
specific parts of code, you should remove irrelevant text, and substitute
by a "<snip>" line, just to give reference that some irrelevant text used to
be there... so if you're interested, just jump to the mailing list archive, and look it out for yourself.

Also, this is completely off topic, and has nothing to do with the original patch subject. Therefore a proper subject rename must happen.

If you want to take this topic further, please figure it out between you two
And, if necessary, the list maintainer, allright?

Regards,
Sergio

> 
> Cheers.
> 
> --
> Felipe Contreras
> --
> 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] 61+ messages in thread

* Re: [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c
  2010-03-05 15:00               ` Gopinath, Thara
@ 2010-03-05 18:29                 ` Kevin Hilman
  0 siblings, 0 replies; 61+ messages in thread
From: Kevin Hilman @ 2010-03-05 18:29 UTC (permalink / raw)
  To: Gopinath, Thara
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand

"Gopinath, Thara" <thara@ti.com> writes:


>>>-----Original Message-----
>>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>Sent: Wednesday, March 03, 2010 12:14 AM
>>>To: Gopinath, Thara
>>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
>>>Vishwanath; Sawant, Anand
>>>Subject: Re: [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c
>>>
>>>Thara Gopinath <thara@ti.com> writes:
>>>
>>>> OMAP3 smartreflex modules are capable of two different classes
>>>> of implementaion -
>>>>     Class-2: Continuous Software Calibration
>>>>     Class-3: Continuous Hardware Calibration.
>>>> OMAP3 along with T2/Gaia supports the Class 3 implementaion.
>>>> With a different PMIC it can support Class 2 implementaion also.
>>>>
>>>> The idea behind this patch is that smartreflex.c should be able
>>>> to support both the classes of Smartreflex and the class specific
>>>> details for smartreflex should stay out of this file in a separate
>>>> class file.
>>>> This patch introduces smartreflex class specific hooks in
>>>> smartreflex.c. This patch only takes care of smartreflex enable
>>>> disable hooks which differ between Class 2 and Class 3. There
>>>> are some register setting changes between both the classes which
>>>> will be taken care of in a later patch.
>>>> This will form the base for adding class specific
>>>> drivers in later patches.
>>>>
>>>> Signed-off-by: Thara Gopinath <thara@ti.com>
>>>
>>>Minor nit: the name change for omap_smartreflex_[enable|disable] is
>>>unrelated to this change and should be a separate patch to go early in
>>>the series.
>
> Hi Kevin,
>
> I agree the name change need not be part of this patch. But is it necessary for it to be separated out. I am asking this because when I send out the review comments fixed patch set I can send them out as V2 . But if I split this change into a separate patch the patch set will contain 17 patches instead of 16 patches and will have to be submitted as a new patch set not as V2. Do let me know your thoughts on this.

Yes, I think it should be split out.

It's common for a V2 series to contain more or less patches than the
original.  In the 'PATCH 0/x' just summarize those differences.

Most maintainers (including myself) prefer that when updates are
(re)sent, the whole series is (re)sent as well, even if there were
changes in only some of the patches.  It is easier to track with
automated tools (like patchwork) when all the patches are together in
a series.

Thanks,

Kevin


>
>>>
>>>Kevin
>>>
>>>> ---
>>>>  arch/arm/mach-omap2/pm34xx.c      |    8 +-
>>>>  arch/arm/mach-omap2/smartreflex.c |  251 ++++++++++++++++++++----------------
>>>>  arch/arm/mach-omap2/smartreflex.h |   48 ++++++--
>>>>  3 files changed, 182 insertions(+), 125 deletions(-)
>>>>
>>>> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
>>>> index cf9ca23..ece5195 100644
>>>> --- a/arch/arm/mach-omap2/pm34xx.c
>>>> +++ b/arch/arm/mach-omap2/pm34xx.c
>>>> @@ -430,9 +430,9 @@ void omap_sram_idle(void)
>>>>      * Only needed if we are going to enter retention or off.
>>>>      */
>>>>     if (mpu_next_state <= PWRDM_POWER_RET)
>>>> -           disable_smartreflex(SR1);
>>>> +           omap_smartreflex_disable(SR1);
>>>>     if (core_next_state <= PWRDM_POWER_RET)
>>>> -           disable_smartreflex(SR2);
>>>> +           omap_smartreflex_disable(SR2);
>>>>
>>>>     /* CORE */
>>>>     if (core_next_state < PWRDM_POWER_ON) {
>>>> @@ -531,9 +531,9 @@ void omap_sram_idle(void)
>>>>      * retention or off
>>>>      */
>>>>     if (mpu_next_state <= PWRDM_POWER_RET)
>>>> -           enable_smartreflex(SR1);
>>>> +           omap_smartreflex_enable(SR1);
>>>>     if (core_next_state <= PWRDM_POWER_RET)
>>>> -           enable_smartreflex(SR2);
>>>> +           omap_smartreflex_enable(SR2);
>>>>
>>>>     /* PER */
>>>>     if (per_next_state < PWRDM_POWER_ON) {
>>>> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
>>>> index c00925d..ba9f899 100644
>>>> --- a/arch/arm/mach-omap2/smartreflex.c
>>>> +++ b/arch/arm/mach-omap2/smartreflex.c
>>>> @@ -55,6 +55,7 @@ struct omap_sr {
>>>>
>>>>  /* sr_list contains all the instances of smartreflex module */
>>>>  static LIST_HEAD(sr_list);
>>>> +static struct omap_smartreflex_class_data *sr_class;
>>>>
>>>>  #define SR_REGADDR(offs)   (sr->srbase_addr + offset)
>>>>
>>>> @@ -388,14 +389,86 @@ static int sr_reset_voltage(int srid)
>>>>     return 0;
>>>>  }
>>>>
>>>> -static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
>>>> +static void sr_start_vddautocomap(int srid)
>>>> +{
>>>> +   struct omap_sr *sr = _sr_lookup(srid);
>>>> +
>>>> +   if (!sr) {
>>>> +           pr_warning("omap_sr struct corresponding to SR%d not found\n",
>>>> +                                                           srid);
>>>> +           return;
>>>> +   }
>>>> +
>>>> +   if (!sr_class || !(sr_class->enable)) {
>>>> +           pr_warning("smartreflex class driver not registered\n");
>>>> +           return;
>>>> +   }
>>>> +
>>>> +   if (sr->is_sr_reset == 1) {
>>>> +           sr_clk_enable(sr);
>>>> +           sr_configure(sr);
>>>> +   }
>>>> +
>>>> +   sr->is_autocomp_active = 1;
>>>> +   if (!sr_class->enable(srid)) {
>>>> +           sr->is_autocomp_active = 0;
>>>> +           if (sr->is_sr_reset == 1)
>>>> +                   sr_clk_disable(sr);
>>>> +   }
>>>> +}
>>>> +
>>>> +static void sr_stop_vddautocomap(int srid)
>>>> +{
>>>> +   struct omap_sr *sr = _sr_lookup(srid);
>>>> +
>>>> +   if (!sr) {
>>>> +           pr_warning("omap_sr struct corresponding to SR%d not found\n",
>>>> +                                                           srid);
>>>> +           return;
>>>> +   }
>>>> +   if (!sr_class || !(sr_class->disable)) {
>>>> +           pr_warning("smartreflex class driver not registered\n");
>>>> +           return;
>>>> +   }
>>>> +
>>>> +   if (sr->is_autocomp_active == 1) {
>>>> +           sr_class->disable(srid);
>>>> +           sr_clk_disable(sr);
>>>> +           sr->is_autocomp_active = 0;
>>>> +           /* Reset the volatage for current OPP */
>>>> +           sr_reset_voltage(srid);
>>>> +   }
>>>> +
>>>> +}
>>>> +
>>>> +/* Public Functions */
>>>> +
>>>> +/**
>>>> + * sr_enable : Enables the smartreflex module.
>>>> + * @srid - The id of the sr module to be enabled.
>>>> + * @target_opp_no - The OPP at which the Voltage domain associated with
>>>> + * the smartreflex module is operating at. This is required only to program
>>>> + * the correct Ntarget value.
>>>> + *
>>>> + * This API is to be called from the smartreflex class driver to
>>>> + * enable a smartreflex module. Returns true on success.Returns false if the
>>>> + * target opp id passed is wrong or if ntarget value is wrong.
>>>> + */
>>>> +int sr_enable(int srid, u32 target_opp_no)
>>>>  {
>>>>     u32 nvalue_reciprocal, v;
>>>> +   struct omap_sr *sr = _sr_lookup(srid);
>>>>     struct omap_opp *opp;
>>>>     struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data;
>>>>     int uvdc;
>>>>     char vsel;
>>>>
>>>> +   if (!sr) {
>>>> +           pr_warning("omap_sr struct corresponding to SR%d not found\n",
>>>> +                                                           srid);
>>>> +           return false;
>>>> +   }
>>>> +
>>>>     if (sr->srid == SR1) {
>>>>             opp = opp_find_by_opp_id(OPP_MPU, target_opp_no);
>>>>             if (!opp)
>>>> @@ -477,8 +550,16 @@ static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
>>>>     return true;
>>>>  }
>>>>
>>>> -static void sr_disable(struct omap_sr *sr)
>>>> +/**
>>>> + * sr_disable : Disables the smartreflex module.
>>>> + * @srid - The id of the sr module to be disabled.
>>>> + *
>>>> + * This API is to be called from the smartreflex class driver to
>>>> + * disable a smartreflex module.
>>>> + */
>>>> +void sr_disable(int srid)
>>>>  {
>>>> +   struct omap_sr *sr = _sr_lookup(srid);
>>>>     u32 i = 0;
>>>>
>>>>     sr->is_sr_reset = 1;
>>>> @@ -518,9 +599,19 @@ static void sr_disable(struct omap_sr *sr)
>>>>     }
>>>>  }
>>>>
>>>> -
>>>> -void sr_start_vddautocomap(int srid, u32 target_opp_no)
>>>> +/**
>>>> + * omap_smartreflex_enable : API to enable SR clocks and to call into the
>>>> + * registered smartreflex class enable API.
>>>> + * @srid - The id of the sr module to be enabled.
>>>> + *
>>>> + * This API is to be called from the kernel in order to enable
>>>> + * a particular smartreflex module. This API will do the initial
>>>> + * configurations to turn on the smartreflex module and in turn call
>>>> + * into the registered smartreflex class enable API.
>>>> + */
>>>> +void omap_smartreflex_enable(int srid)
>>>>  {
>>>> +   u32 target_opp_no = 0;
>>>>     struct omap_sr *sr = _sr_lookup(srid);
>>>>
>>>>     if (!sr) {
>>>> @@ -528,52 +619,8 @@ void sr_start_vddautocomap(int srid, u32 target_opp_no)
>>>>                                                             srid);
>>>>             return;
>>>>     }
>>>> -
>>>> -   if (sr->is_sr_reset == 1) {
>>>> -           sr_clk_enable(sr);
>>>> -           sr_configure(sr);
>>>> -   }
>>>> -
>>>> -   sr->is_autocomp_active = 1;
>>>> -   if (!sr_enable(sr, target_opp_no)) {
>>>> -           sr->is_autocomp_active = 0;
>>>> -           if (sr->is_sr_reset == 1)
>>>> -                   sr_clk_disable(sr);
>>>> -   }
>>>> -}
>>>> -EXPORT_SYMBOL(sr_start_vddautocomap);
>>>> -
>>>> -int sr_stop_vddautocomap(int srid)
>>>> -{
>>>> -   struct omap_sr *sr = _sr_lookup(srid);
>>>> -
>>>> -   if (!sr) {
>>>> -           pr_warning("omap_sr struct corresponding to SR%d not found\n",
>>>> -                                                           srid);
>>>> -           return false;
>>>> -   }
>>>> -
>>>> -   if (sr->is_autocomp_active == 1) {
>>>> -           sr_disable(sr);
>>>> -           sr_clk_disable(sr);
>>>> -           sr->is_autocomp_active = 0;
>>>> -           /* Reset the volatage for current OPP */
>>>> -           sr_reset_voltage(srid);
>>>> -           return true;
>>>> -   } else
>>>> -           return false;
>>>> -
>>>> -}
>>>> -EXPORT_SYMBOL(sr_stop_vddautocomap);
>>>> -
>>>> -void enable_smartreflex(int srid)
>>>> -{
>>>> -   u32 target_opp_no = 0;
>>>> -   struct omap_sr *sr = _sr_lookup(srid);
>>>> -
>>>> -   if (!sr) {
>>>> -           pr_warning("omap_sr struct corresponding to SR%d not found\n",
>>>> -                                                           srid);
>>>> +   if (!sr_class || !(sr_class->enable)) {
>>>> +           pr_warning("smartreflex class driver not registered\n");
>>>>             return;
>>>>     }
>>>>
>>>> @@ -581,26 +628,24 @@ void enable_smartreflex(int srid)
>>>>             if (sr->is_sr_reset == 1) {
>>>>                     /* Enable SR clks */
>>>>                     sr_clk_enable(sr);
>>>> -
>>>> -                   if (srid == SR1)
>>>> -                           target_opp_no = get_vdd1_opp();
>>>> -                   else if (srid == SR2)
>>>> -                           target_opp_no = get_vdd2_opp();
>>>> -
>>>> -                   if (!target_opp_no) {
>>>> -                           pr_info("Current OPP unknown \
>>>> -                                            Cannot configure SR\n");
>>>> -                   }
>>>> -
>>>>                     sr_configure(sr);
>>>>
>>>> -                   if (!sr_enable(sr, target_opp_no))
>>>> +                   if (!sr_class->enable(srid))
>>>>                             sr_clk_disable(sr);
>>>>             }
>>>>     }
>>>>  }
>>>>
>>>> -void disable_smartreflex(int srid)
>>>> +/**
>>>> + * omap_smartreflex_disable : API to disable SR clocks and to call into the
>>>> + * registered smartreflex class disable API.
>>>> + * @srid - The id of the sr module to be disabled.
>>>> + *
>>>> + * This API is to be called from the kernel in order to disable
>>>> + * a particular smartreflex module. This API will in turn call
>>>> + * into the registered smartreflex class disable API.
>>>> + */
>>>> +void omap_smartreflex_disable(int srid)
>>>>  {
>>>>     u32 i = 0;
>>>>     struct omap_sr *sr = _sr_lookup(srid);
>>>> @@ -610,54 +655,43 @@ void disable_smartreflex(int srid)
>>>>                                                             srid);
>>>>             return;
>>>>     }
>>>> +   if (!sr_class || !(sr_class->disable)) {
>>>> +           pr_warning("smartreflex class driver not registered\n");
>>>> +           return;
>>>> +   }
>>>>
>>>>     if (sr->is_autocomp_active == 1) {
>>>>             if (sr->is_sr_reset == 0) {
>>>> -
>>>> -                   sr->is_sr_reset = 1;
>>>> -                   /* SRCONFIG - disable SR */
>>>> -                   sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
>>>> -                                                   ~SRCONFIG_SRENABLE);
>>>> -
>>>> +                   sr_class->disable(srid);
>>>>                     /* Disable SR clk */
>>>>                     sr_clk_disable(sr);
>>>> -                   if (sr->srid == SR1) {
>>>> -                           /* Wait for VP idle before disabling VP */
>>>> -                           while ((!prm_read_mod_reg(OMAP3430_GR_MOD,
>>>> -                                           OMAP3_PRM_VP1_STATUS_OFFSET))
>>>> -                                           && i++ < MAX_TRIES)
>>>> -                                   udelay(1);
>>>> -
>>>> -                           if (i >= MAX_TRIES)
>>>> -                                   pr_warning("VP1 not idle, still going \
>>>> -                                           ahead with VP1 disable\n");
>>>> -
>>>> -                           /* Disable VP1 */
>>>> -                           prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE,
>>>> -                                           OMAP3430_GR_MOD,
>>>> -                                           OMAP3_PRM_VP1_CONFIG_OFFSET);
>>>> -                   } else if (sr->srid == SR2) {
>>>> -                           /* Wait for VP idle before disabling VP */
>>>> -                           while ((!prm_read_mod_reg(OMAP3430_GR_MOD,
>>>> -                                           OMAP3_PRM_VP2_STATUS_OFFSET))
>>>> -                                           && i++ < MAX_TRIES)
>>>> -                                   udelay(1);
>>>> -
>>>> -                           if (i >= MAX_TRIES)
>>>> -                                   pr_warning("VP2 not idle, still going \
>>>> -                                            ahead with VP2 disable\n");
>>>> -
>>>> -                           /* Disable VP2 */
>>>> -                           prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE,
>>>> -                                           OMAP3430_GR_MOD,
>>>> -                                           OMAP3_PRM_VP2_CONFIG_OFFSET);
>>>> -                   }
>>>>                     /* Reset the volatage for current OPP */
>>>>                     sr_reset_voltage(srid);
>>>>             }
>>>>     }
>>>>  }
>>>>
>>>> +/**
>>>> + * omap_sr_register_class : API to register a smartreflex class parameters.
>>>> + * @class_data - The structure containing various sr class specific data.
>>>> + *
>>>> + * This API is to be called by the smartreflex class driver to register itself
>>>> + * with the smartreflex driver during init.
>>>> + */
>>>> +void omap_sr_register_class(struct omap_smartreflex_class_data *class_data)
>>>> +{
>>>> +   if (!class_data) {
>>>> +           pr_warning("Smartreflex class data passed is NULL\n");
>>>> +           return;
>>>> +   }
>>>> +
>>>> +   if (sr_class) {
>>>> +           pr_warning("Smartreflex class driver already registered\n");
>>>> +           return;
>>>> +   }
>>>> +   sr_class = class_data;
>>>> +}
>>>> +
>>>>  /* Voltage Scaling using SR VCBYPASS */
>>>>  int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
>>>>                                     u8 target_vsel, u8 current_vsel)
>>>> @@ -730,9 +764,9 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
>>>>
>>>>     if (sr_status) {
>>>>             if (vdd == VDD1_OPP)
>>>> -                   sr_start_vddautocomap(SR1, target_opp_no);
>>>> +                   sr_start_vddautocomap(SR1);
>>>>             else if (vdd == VDD2_OPP)
>>>> -                   sr_start_vddautocomap(SR2, target_opp_no);
>>>> +                   sr_start_vddautocomap(SR2);
>>>>     }
>>>>
>>>>     return 0;
>>>> @@ -762,17 +796,10 @@ static int omap_sr_autocomp_store(void *data, u64 val)
>>>>                                                     sr_info->srid);
>>>>             return 0;
>>>>     }
>>>> -   if (val == 0) {
>>>> +   if (val == 0)
>>>>             sr_stop_vddautocomap(sr_info->srid);
>>>> -   } else {
>>>> -           u32 current_opp;
>>>> -
>>>> -           if (sr_info->srid == SR1)
>>>> -                   current_opp = get_vdd1_opp();
>>>> -           else
>>>> -                   current_opp = get_vdd2_opp();
>>>> -           sr_start_vddautocomap(sr_info->srid, current_opp);
>>>> -   }
>>>> +   else
>>>> +           sr_start_vddautocomap(sr_info->srid);
>>>>     return 0;
>>>>  }
>>>>
>>>> diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
>>>> index 572cdca..a59a073 100644
>>>> --- a/arch/arm/mach-omap2/smartreflex.h
>>>> +++ b/arch/arm/mach-omap2/smartreflex.h
>>>> @@ -243,12 +243,27 @@ extern u32 current_vdd2_opp;
>>>>  #define SR_TESTING_NVALUES         0
>>>>  #endif
>>>>
>>>> -/*
>>>> - * Smartreflex module enable/disable interface.
>>>> - * NOTE: if smartreflex is not enabled from sysfs, these functions will not
>>>> - * do anything.
>>>> - */
>>>>  #ifdef CONFIG_OMAP_SMARTREFLEX
>>>> +/**
>>>> + * omap_smartreflex_class_data : Structure to be populated by
>>>> + * Smartreflex class driver with corresponding class enable disable API's
>>>> + *
>>>> + * @enable - API to enable a particular class smaartreflex.
>>>> + * @disable - API to disable a particular class smartreflex.
>>>> + * @notify - API to notify the class driver about an event in SR. Not needed
>>>> + *         for class3.
>>>> + * @notify_flags - specify the events to be notified to the class driver
>>>> + * @class_type - specify which smartreflex class. Can be used by the SR driver
>>>> + *                 to tkae any class based decisions.
>>>> + */
>>>> +struct omap_smartreflex_class_data {
>>>> +   int (*enable)(int sr_id);
>>>> +   int (*disable)(int sr_id);
>>>> +   int (*notify)(int sr_id, u32 status);
>>>> +   u8 notify_flags;
>>>> +   u8 class_type;
>>>> +};
>>>> +
>>>>  /*
>>>>   * omap_smartreflex_data - Smartreflex platform data
>>>>   *
>>>> @@ -274,11 +289,26 @@ struct omap_smartreflex_data {
>>>>     int (*device_idle)(struct platform_device *pdev);
>>>>  };
>>>>
>>>> -void enable_smartreflex(int srid);
>>>> -void disable_smartreflex(int srid);
>>>> +/*
>>>> + * Smartreflex module enable/disable interface.
>>>> + * NOTE: if smartreflex is not enabled from sysfs, these functions will not
>>>> + * do anything.
>>>> + */
>>>> +void omap_smartreflex_enable(int srid);
>>>> +void omap_smartreflex_disable(int srid);
>>>> +
>>>> +/**
>>>> + * Smartreflex driver hooks to be called from Smartreflex class driver
>>>> + */
>>>> +int sr_enable(int srid, u32 target_opp_no);
>>>> +void sr_disable(int srid);
>>>> +
>>>> +/**
>>>> + * API to register the smartreflex class driver with the smartreflex driver
>>>> + */
>>>> +void omap_sr_register_class(struct omap_smartreflex_class_data *class_data);
>>>> +
>>>>  int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel);
>>>> -void sr_start_vddautocomap(int srid, u32 target_opp_no);
>>>> -int sr_stop_vddautocomap(int srid);
>>>>  #else
>>>>  static inline void enable_smartreflex(int srid) {}
>>>>  static inline void disable_smartreflex(int srid) {}
>>>> --
>>>> 1.7.0.rc1.33.g07cf0f

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

* Re: [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c
  2010-03-05 15:18               ` Gopinath, Thara
@ 2010-03-05 18:30                 ` Kevin Hilman
  0 siblings, 0 replies; 61+ messages in thread
From: Kevin Hilman @ 2010-03-05 18:30 UTC (permalink / raw)
  To: Gopinath, Thara
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand

"Gopinath, Thara" <thara@ti.com> writes:

>>>-----Original Message-----
>>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>Sent: Wednesday, March 03, 2010 5:23 AM
>>>To: Gopinath, Thara
>>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
>>>Vishwanath; Sawant, Anand
>>>Subject: Re: [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c
>>>
>>>Thara Gopinath <thara@ti.com> writes:
>>>
>>>> OMAP3 smartreflex modules are capable of two different classes
>>>> of implementaion -
>>>> 	Class-2: Continuous Software Calibration
>>>> 	Class-3: Continuous Hardware Calibration.
>>>> OMAP3 along with T2/Gaia supports the Class 3 implementaion.
>>>> With a different PMIC it can support Class 2 implementaion also.
>>>>
>>>> The idea behind this patch is that smartreflex.c should be able
>>>> to support both the classes of Smartreflex and the class specific
>>>> details for smartreflex should stay out of this file in a separate
>>>> class file.
>>>> This patch introduces smartreflex class specific hooks in
>>>> smartreflex.c. This patch only takes care of smartreflex enable
>>>> disable hooks which differ between Class 2 and Class 3. There
>>>> are some register setting changes between both the classes which
>>>> will be taken care of in a later patch.
>>>> This will form the base for adding class specific
>>>> drivers in later patches.
>>>>
>>>> Signed-off-by: Thara Gopinath <thara@ti.com>
>>>> ---
>>>>  arch/arm/mach-omap2/pm34xx.c      |    8 +-
>>>>  arch/arm/mach-omap2/smartreflex.c |  251 ++++++++++++++++++++----------------
>>>>  arch/arm/mach-omap2/smartreflex.h |   48 ++++++--
>>>>  3 files changed, 182 insertions(+), 125 deletions(-)
>>>>
>>>
>>>[...]
>>>
>>>> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
>>>> index c00925d..ba9f899 100644
>>>> --- a/arch/arm/mach-omap2/smartreflex.c
>>>> +++ b/arch/arm/mach-omap2/smartreflex.c
>>>> @@ -55,6 +55,7 @@ struct omap_sr {
>>>>
>>>>  /* sr_list contains all the instances of smartreflex module */
>>>>  static LIST_HEAD(sr_list);
>>>> +static struct omap_smartreflex_class_data *sr_class;
>>>>
>>>>  #define SR_REGADDR(offs)	(sr->srbase_addr + offset)
>>>>
>>>> @@ -388,14 +389,86 @@ static int sr_reset_voltage(int srid)
>>>>  	return 0;
>>>>  }
>>>>
>>>> -static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
>>>> +static void sr_start_vddautocomap(int srid)
>>>
>>>Either in this patch or in an additional patch (previous to this one)
>>>can you fix the name of these autocomp functions: *_vddautocomap ->
>>>*_vddautocomp.  I don't think comap means anything.
>
> I can fix this. I would prefer this change to be a part of one of the existing patches in the patch set so that I do not increase the patch count and it will be easier for me to sen a V2.

See previous reply.  Please feel free to add/remove patches when
sending a V2 series.

Kevin

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

* Re: [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver.
  2010-03-05 15:03                 ` Gopinath, Thara
@ 2010-03-05 19:12                   ` Kevin Hilman
  0 siblings, 0 replies; 61+ messages in thread
From: Kevin Hilman @ 2010-03-05 19:12 UTC (permalink / raw)
  To: Gopinath, Thara
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand

"Gopinath, Thara" <thara@ti.com> writes:

>>>-----Original Message-----
>>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>Sent: Wednesday, March 03, 2010 1:07 AM
>>>To: Gopinath, Thara
>>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
>>>Vishwanath; Sawant, Anand
>>>Subject: Re: [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver.
>>>
>>>Thara Gopinath <thara@ti.com> writes:
>>>
>>>> This patch adds smartreflex class 3 driver. This driver hooks
>>>> up with the generic smartreflex driver smartreflex.c to abstract
>>>> out class specific implementations out of the generic driver.
>>>>
>>>> Signed-off-by: Thara Gopinath <thara@ti.com>
>>>
>>>I like this abstraction, but I don't like that it still uses OPP IDs.
>>>
>>>So, before doing this, we need to get rid of OPP IDs from the
>>>smartreflex layer and keep OPP ID usage isolated to SRF.
>>>
>>>It appears the only reason we need OPP IDs in SR is because the Nvalue
>>>tables are indexed by OPP ID in sr_enable().
>
> Actually this is not true. If you see my patch14 sr err_minlimit and
> vp errorgain are opp dependent. In fact for 3630 for VDD1 there are
> 4 supported OPP's and 4 different values for err_minlimit and
> errorgain - one for each opp. So we might still need the opp id.

Yes, they are related to OPP IDs, but my primary objection is passing
around OPP IDs.  Passing around OPP IDs *musb* be removed from the new
SR layer.  OPP IDs are deprecated, and create multiple portability
problems.

As I proposed initially, this mapping needs to stay inside
smartreflex.  A mapping of voltage to OPP ID (which will give you the
nvalue, err_minlimit and errorgain) should work fine.

Kevin

>>>
>>>One way to fix this is for this SR layer to keep it's own mapping of
>>>voltage to nvalue.  So instead of taking OPP ID, sr_enable() should
>>>take a voltage (or frequency) and use that to look up the nvalue.
>>>
>
>>>a couple other minor comments below...
>
> Thank you for these comments and I will fix them in V2
>
> Regards
> Thara
>>>
>>>> ---
>>>>  arch/arm/mach-omap2/Makefile             |    1 +
>>>>  arch/arm/mach-omap2/smartreflex-class3.c |   49 ++++++++++++++++++++++++++++++
>>>>  arch/arm/plat-omap/Kconfig               |   11 ++++++-
>>>>  3 files changed, 60 insertions(+), 1 deletions(-)
>>>>  create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
>>>>
>>>> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
>>>> index f6f901f..cd8ab86 100644
>>>> --- a/arch/arm/mach-omap2/Makefile
>>>> +++ b/arch/arm/mach-omap2/Makefile
>>>> @@ -52,6 +52,7 @@ obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o
>>>>  obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o cpuidle34xx.o
>>>>  obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
>>>>  obj-$(CONFIG_OMAP_SMARTREFLEX)	+= smartreflex.o
>>>> +obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)	+= smartreflex-class3.o
>>>>
>>>>  AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
>>>>  AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a
>>>> diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
>>>> new file mode 100644
>>>> index 0000000..d2e98a5
>>>> --- /dev/null
>>>> +++ b/arch/arm/mach-omap2/smartreflex-class3.c
>>>> @@ -0,0 +1,49 @@
>>>> +/*
>>>> + * Smart reflex Class 3 specific implementations
>>>> + *
>>>> + * Copyright (C) 2009 Texas Instruments, Inc.
>>>
>>>2010
>>>
>>>> + * Thara Gopinath <thara@ti.com>
>>>> + *
>>>> + * 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 "smartreflex.h"
>>>> +
>>>> +static int sr_class3_enable(int id)
>>>> +{
>>>> +	int target_opp_no = 0;
>>>
>>>insert blank line
>>>
>>>> +	if (id == SR1)
>>>> +		target_opp_no = get_vdd1_opp();
>>>> +	else if (id == SR2)
>>>> +		target_opp_no = get_vdd2_opp();
>>>> +	if (!target_opp_no) {
>>>> +		pr_warning("Targetopp not known.Cannot enable SR%d\n", id);
>>>> +		return false;
>>>> +	}
>>>
>>>and here
>>>
>>>> +	return sr_enable(id, target_opp_no);
>>>> +}
>>>>
>>>> +static int sr_class3_disable(int id)
>>>> +{
>>>> +	int target_opp_no = 0;
>>>
>>>blank line
>>>
>>>> +	if (id == SR1)
>>>> +		target_opp_no = get_vdd1_opp();
>>>> +	else if (id == SR2)
>>>> +		target_opp_no = get_vdd2_opp();
>>>> +	sr_disable(id);
>>>
>>>blank line
>>>
>>>> +	return true;
>>>> +}
>>>> +/* SR class3 structure */
>>>> +struct omap_smartreflex_class_data class3_data = {
>>>> +	.enable = sr_class3_enable,
>>>> +	.disable = sr_class3_disable,
>>>> +};
>>>> +
>>>> +static int __init sr_class3_init(void)
>>>> +{
>>>> +	omap_sr_register_class(&class3_data);
>>>> +	return 0;
>>>> +}
>>>> +late_initcall(sr_class3_init);
>>>> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
>>>> index cef67f3..9d286e6 100644
>>>> --- a/arch/arm/plat-omap/Kconfig
>>>> +++ b/arch/arm/plat-omap/Kconfig
>>>> @@ -54,7 +54,7 @@ config OMAP_DEBUG_LEDS
>>>>
>>>>  config OMAP_SMARTREFLEX
>>>>  	bool "SmartReflex support"
>>>> -	depends on ARCH_OMAP3 && TWL4030_CORE && PM
>>>> +	depends on ARCH_OMAP3 && PM
>>>>  	help
>>>>  	  Say Y if you want to enable SmartReflex.
>>>>
>>>> @@ -69,6 +69,15 @@ config OMAP_SMARTREFLEX
>>>>  	  compensation for VDD1 and VDD2, user must write 1 to
>>>>  	  /sys/power/sr_vddX_autocomp, where X is 1 or 2.
>>>>
>>>> +config OMAP_SMARTREFLEX_CLASS3
>>>> +	bool "Class 3 mode of Smartreflex Implementation"
>>>> +	depends on OMAP_SMARTREFLEX && TWL4030_CORE
>>>> +	help
>>>> +	  Say Y to enable Class 3 implementation of Smartreflex
>>>> +
>>>> +	  Class 3 implementation of Smartreflex employs continuous hardware
>>>> +	  voltage caliberation.
>>>> +
>>>>  config OMAP_SMARTREFLEX_TESTING
>>>>  	bool "Smartreflex testing support"
>>>>  	depends on OMAP_SMARTREFLEX
>>>> --
>>>> 1.7.0.rc1.33.g07cf0f

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

* Re: [PATCH 11/16] OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3
  2010-03-05 15:12                         ` Gopinath, Thara
@ 2010-03-05 19:20                           ` Kevin Hilman
  0 siblings, 0 replies; 61+ messages in thread
From: Kevin Hilman @ 2010-03-05 19:20 UTC (permalink / raw)
  To: Gopinath, Thara
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand

"Gopinath, Thara" <thara@ti.com> writes:

[...]

>>>>  /* PM Debug Fs enteries to enable disable smartreflex.*/
>>>> @@ -448,6 +551,7 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
>>>>     if (odev->hwmods[0]->mpu_irqs)
>>>>             sr_info->irq = odev->hwmods[0]->mpu_irqs[0].irq;
>>>>     sr_set_clk_length(sr_info);
>>>> +   sr_set_regfields(sr_info);
>>>>
>>>>     /* Create the debug fs enteries */
>>>>     sprintf(name, "sr%d_autocomp", sr_info->srid);
>>>> @@ -456,8 +560,29 @@ static int __devinit omap_smartreflex_probe(struct platform_device *pdev)
>>>>
>>>>     odev->hwmods[0]->dev_attr = sr_info;
>>>>     list_add(&sr_info->node, &sr_list);
>>>> -   pr_info("SmartReflex driver initialized\n");
>>>>
>>>> +   /*
>>>> +    * Register interrrupt handler if smartreflex class driver is already
>>>> +    * registered and has requested for interrupts. This will be attempted
>>>> +    * in the class driver register again if it does not happen here.
>>>> +    */
>>>
>>>Why the duplicate attempts to request_irq()?  Seems like it's only needed
>>>in the register_class hook above.
>
> Duplicate attempt is so that it does not matter whether the class driver gets registered before the smartreflex driver gets registered. So if smartreflex driver gets registered first the request_irq will happen only when class driver gets registered. On the other hand if class driver gets registered first then the request_irq will happen from here. The thing to notice is that there is only a duplicate attempt. Actual double registrations does not happen.

OK, thanks for the clarification.

Then, the two blocks of code that reqest_irq + init_enable should be
combined into a subroutine (with comment) called from both places.
This will help avoid the confusion I had and increase readability.

Kevin


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

* Re: Snipping irrelevant text from a discussion (was: "RE: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling")
  2010-03-05 18:17                                         ` Snipping irrelevant text from a discussion (was: "RE: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling") Aguirre, Sergio
@ 2010-03-05 21:18                                           ` Felipe Contreras
  2010-03-09  1:42                                             ` Tony Lindgren
  0 siblings, 1 reply; 61+ messages in thread
From: Felipe Contreras @ 2010-03-05 21:18 UTC (permalink / raw)
  To: Aguirre, Sergio
  Cc: Gopinath, Thara, Kevin Hilman, linux-omap, paul, Menon, Nishanth,
	Cousson, Benoit, Sripathy, Vishwanath, Sawant, Anand

Hey Sergio,

On Fri, Mar 5, 2010 at 8:17 PM, Aguirre, Sergio <saaguirre@ti.com> wrote:
> Hey!
>
> You guys take a "chill pill", ok? :) Let's not start shouting at people and point fingers.

I'm not really angry, and I'm not blaming Thara either. I just tried
to do some constructive criticism that was apparently not accepted,
and I decided not to push it any further.

> My 2 cents is that, usually, when discussion starts about a topic, or a
> specific parts of code, you should remove irrelevant text, and substitute
> by a "<snip>" line, just to give reference that some irrelevant text used to
> be there... so if you're interested, just jump to the mailing list archive, and look it out for yourself.

Indeed, specially when dealing with a heated argument, it's sometimes
important to specify where you have snipped text. Although I think
most of the time that's not needed, a "snip" comment is preferable to
dozes or hundreds of extra lines.

> Also, this is completely off topic, and has nothing to do with the original patch subject. Therefore a proper subject rename must happen.

Right.

> If you want to take this topic further, please figure it out between you two
> And, if necessary, the list maintainer, allright?

Yeah, that's something for Tony to decide, but I didn't think it was a
good idea to push for it right now.

Cheers.

-- 
Felipe Contreras

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

* Re: [PATCH 01/16] OMAP3: PM: Adding hwmod data for Smartreflex
  2010-02-24  9:29 ` [PATCH 01/16] OMAP3: PM: Adding hwmod data for Smartreflex Thara Gopinath
  2010-02-24  9:29   ` [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances Thara Gopinath
  2010-02-24 16:52   ` [PATCH 01/16] OMAP3: PM: Adding hwmod data for Smartreflex Mike Turquette
@ 2010-03-06  0:45   ` Kevin Hilman
  2 siblings, 0 replies; 61+ messages in thread
From: Kevin Hilman @ 2010-03-06  0:45 UTC (permalink / raw)
  To: Thara Gopinath; +Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant

Thara Gopinath <thara@ti.com> writes:

> This patch adds the hwmod strucutres and other hwmod data for
> OMAP3 Smartreflex IP's.
>
> Signed-off-by: Thara Gopinath <thara@ti.com>

Thara,

When resending, please rebase on top of current PM branch and current
pm-wip-opp.  The hwmod data in mainline has been reorganized a bit and
will require a slight rework of this patch.

Thanks,

Kevin

> ---
>  arch/arm/mach-omap2/omap_hwmod_34xx.h |   92 +++++++++++++++++++++++++++++++++
>  1 files changed, 92 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/omap_hwmod_34xx.h b/arch/arm/mach-omap2/omap_hwmod_34xx.h
> index 2e629dc..dccb4a4 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_34xx.h
> +++ b/arch/arm/mach-omap2/omap_hwmod_34xx.h
> @@ -25,6 +25,8 @@ static struct omap_hwmod omap34xx_mpu_hwmod;
>  static struct omap_hwmod omap34xx_l3_hwmod;
>  static struct omap_hwmod omap34xx_l4_core_hwmod;
>  static struct omap_hwmod omap34xx_l4_per_hwmod;
> +static struct omap_hwmod omap34xx_sr1_hwmod;
> +static struct omap_hwmod omap34xx_sr2_hwmod;
>  
>  /* L3 -> L4_CORE interface */
>  static struct omap_hwmod_ocp_if omap34xx_l3__l4_core = {
> @@ -77,9 +79,49 @@ static struct omap_hwmod_ocp_if omap34xx_l4_core__l4_wkup = {
>  	.user	= OCP_USER_MPU | OCP_USER_SDMA,
>  };
>  
> +/* L4 CORE -> SR1 interface */
> +static struct omap_hwmod_addr_space omap34xx_sr1_addr_space[] = {
> +	{
> +		.pa_start	= OMAP34XX_SR1_BASE,
> +		.pa_end		= OMAP34XX_SR1_BASE + SZ_1K - 1,
> +		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
> +	},
> +};
> +
> +static struct omap_hwmod_ocp_if omap3_l4_core__sr1 = {
> +	.master		= &omap34xx_l4_core_hwmod,
> +	.slave		= &omap34xx_sr1_hwmod,
> +	.clkdev_dev_id	= NULL,
> +	.clkdev_con_id  = NULL,
> +	.addr		= omap34xx_sr1_addr_space,
> +	.addr_cnt	= ARRAY_SIZE(omap34xx_sr1_addr_space),
> +	.user		= OCP_USER_MPU,
> +};
> +
> +/* L4 CORE -> SR1 interface */
> +static struct omap_hwmod_addr_space omap34xx_sr2_addr_space[] = {
> +	{
> +		.pa_start	= OMAP34XX_SR2_BASE,
> +		.pa_end		= OMAP34XX_SR2_BASE + SZ_1K - 1,
> +		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
> +	},
> +};
> +
> +static struct omap_hwmod_ocp_if omap3_l4_core__sr2 = {
> +	.master		= &omap34xx_l4_core_hwmod,
> +	.slave		= &omap34xx_sr2_hwmod,
> +	.clkdev_dev_id	= NULL,
> +	.clkdev_con_id  = NULL,
> +	.addr		= omap34xx_sr2_addr_space,
> +	.addr_cnt	= ARRAY_SIZE(omap34xx_sr2_addr_space),
> +	.user		= OCP_USER_MPU,
> +};
> +
>  /* Slave interfaces on the L4_CORE interconnect */
>  static struct omap_hwmod_ocp_if *omap34xx_l4_core_slaves[] = {
>  	&omap34xx_l3__l4_core,
> +	&omap3_l4_core__sr1,
> +	&omap3_l4_core__sr2,
>  };
>  
>  /* Master interfaces on the L4_CORE interconnect */
> @@ -150,12 +192,62 @@ static struct omap_hwmod omap34xx_mpu_hwmod = {
>  	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
>  };
>  
> +/* SR common */
> +static struct omap_hwmod_sysc_fields sr_sysc_fields = {
> +	.clkact_shift	= 20,
> +};
> +
> +static struct omap_hwmod_sysconfig sr_if_ctrl = {
> +	.sysc_offs	= 0x24,
> +	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_NO_CACHE),
> +	.clockact	= CLOCKACT_TEST_ICLK,
> +	.sysc_fields	= &sr_sysc_fields,
> +};
> +
> +/* SR1 */
> +static struct omap_hwmod_ocp_if *omap34xx_sr1_slaves[] = {
> +	&omap3_l4_core__sr1,
> +};
> +
> +static struct omap_hwmod omap34xx_sr1_hwmod = {
> +	.name		= "sr1_hwmod",
> +	.mpu_irqs	= NULL,
> +	.sdma_chs	= NULL,
> +	.clkdev_dev_id	= NULL,
> +	.clkdev_con_id	= "sr1_fck",
> +	.slaves		= omap34xx_sr1_slaves,
> +	.slaves_cnt	= ARRAY_SIZE(omap34xx_sr1_slaves),
> +	.sysconfig	= &sr_if_ctrl,
> +	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
> +	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
> +};
> +
> +/* SR2 */
> +static struct omap_hwmod_ocp_if *omap34xx_sr2_slaves[] = {
> +	&omap3_l4_core__sr2,
> +};
> +
> +static struct omap_hwmod omap34xx_sr2_hwmod = {
> +	.name		= "sr2_hwmod",
> +	.mpu_irqs	= NULL,
> +	.sdma_chs	= NULL,
> +	.clkdev_dev_id	= NULL,
> +	.clkdev_con_id	= "sr2_fck",
> +	.slaves		= omap34xx_sr2_slaves,
> +	.slaves_cnt	= ARRAY_SIZE(omap34xx_sr2_slaves),
> +	.sysconfig	= &sr_if_ctrl,
> +	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
> +	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
> +};
> +
>  static __initdata struct omap_hwmod *omap34xx_hwmods[] = {
>  	&omap34xx_l3_hwmod,
>  	&omap34xx_l4_core_hwmod,
>  	&omap34xx_l4_per_hwmod,
>  	&omap34xx_l4_wkup_hwmod,
>  	&omap34xx_mpu_hwmod,
> +	&omap34xx_sr1_hwmod,
> +	&omap34xx_sr2_hwmod,
>  	NULL,
>  };
>  
> -- 
> 1.7.0.rc1.33.g07cf0f

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

* Re: [PATCH 00/16] OMAP3: PM: Smartreflex and voltage revamp.
  2010-02-24  9:29 [PATCH 00/16] OMAP3: PM: Smartreflex and voltage revamp Thara Gopinath
  2010-02-24  9:29 ` [PATCH 01/16] OMAP3: PM: Adding hwmod data for Smartreflex Thara Gopinath
@ 2010-03-06  0:58 ` Kevin Hilman
  1 sibling, 0 replies; 61+ messages in thread
From: Kevin Hilman @ 2010-03-06  0:58 UTC (permalink / raw)
  To: Thara Gopinath
  Cc: linux-omap, paul, nm, b-cousson, vishwanath.bs, sawant,
	Thara Gopinath (none)

Thara Gopinath <thara@ti.com> writes:

> From: Thara Gopinath <thara@omaplbp.(none)>
>
> This main motivations behind this patch series are the following
> 1. Making smartreflex a platform driver with omap-device layer.
> 2. Separating voltage specific code from smartreflex.c and other
>    locations and consolidating them into voltage.c and voltage.h.
> 3. Smartreflex module can have Class 3 or Class 2 implementations
>    depending on the PMIC in use. Making smartreflex.c capable
>    of handling both the class implementaions and separating out
>    class specific code into a separate class driver.
> 4. Implementating  latest TI recommended register settings for
>   Smartreflex and Voltage processor module as well as recommended
>   sequences for enabling and disabling of Smartreflex and Voltage
>   processor modules.
> 5. Implementing VP force update method of voltage scaling which is
>    again TI hardware recommended.
>
> What this patch series does not address are
> 1. Separating PMIC specific portions from smartreflex and voltage code.
> 2. OMAP3630 and OMP4 smartreflex support.
>
> This patch series is based on Kevin's PM tree origin/pm-wip-opp branch
> and is dependent on the following patches not yet applied onto this branch.

Hi Thara,

One other request for V2.

Could you separate out any patches to SRF (resourc34xx) into their own
patches please?  This will facilitate upstream merging when SR is
finalized because while SR will be (hopefully) going upstream soon,
SRF will not.

A quick look shows patches 5, 8, 9 as having changes to
resource*.[ch].  Please separate those out as separate patches.

Once again, thanks for your efforts on this much needed SR rework,

Kevin

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

* Re: Snipping irrelevant text from a discussion (was: "RE: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling")
  2010-03-05 21:18                                           ` Felipe Contreras
@ 2010-03-09  1:42                                             ` Tony Lindgren
  2010-03-09  6:51                                               ` Felipe Balbi
  0 siblings, 1 reply; 61+ messages in thread
From: Tony Lindgren @ 2010-03-09  1:42 UTC (permalink / raw)
  To: Felipe Contreras
  Cc: Aguirre, Sergio, Gopinath, Thara, Kevin Hilman, linux-omap, paul,
	Menon, Nishanth, Cousson, Benoit, Sripathy, Vishwanath, Sawant,
	Anand

* Felipe Contreras <felipe.contreras@gmail.com> [100305 13:15]:
> Hey Sergio,
> 
> On Fri, Mar 5, 2010 at 8:17 PM, Aguirre, Sergio <saaguirre@ti.com> wrote:
> > Hey!
> >
> > You guys take a "chill pill", ok? :) Let's not start shouting at people and point fingers.
> 
> I'm not really angry, and I'm not blaming Thara either. I just tried
> to do some constructive criticism that was apparently not accepted,
> and I decided not to push it any further.

I (and many others I've spoken with) totally agree with your
comments. We should follow the usual mailing list standards, and
keep the messages readable. Until somebody comes up with a better
method for coordinating development online, that's all we have :)

After a quick search for "mailing list netiquette" I cam up with
the following links:

http://linux.sgms-centre.com/misc/netiquette.php
http://en.opensuse.org/OpenSUSE_mailing_list_netiquette

We can add that to some of the wiki pages so people can start
following the "proper" standards. Anybody got better links?
 
> > My 2 cents is that, usually, when discussion starts about a topic, or a
> > specific parts of code, you should remove irrelevant text, and substitute
> > by a "<snip>" line, just to give reference that some irrelevant text used to
> > be there... so if you're interested, just jump to the mailing list archive, and look it out for yourself.
> 
> Indeed, specially when dealing with a heated argument, it's sometimes
> important to specify where you have snipped text. Although I think
> most of the time that's not needed, a "snip" comment is preferable to
> dozes or hundreds of extra lines.
> 
> > Also, this is completely off topic, and has nothing to do with the original patch subject. Therefore a proper subject rename must happen.
> 
> Right.
> 
> > If you want to take this topic further, please figure it out between you two
> > And, if necessary, the list maintainer, allright?
> 
> Yeah, that's something for Tony to decide, but I didn't think it was a
> good idea to push for it right now.

Yeah.. Letting people know about the mailing list standards is
pretty regular topic on almost all mailing lists. Once we have
the wikipage links figured out, let's just start pointing people
to those.

Regards,

Tony

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

* Re: Snipping irrelevant text from a discussion (was: "RE: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling")
  2010-03-09  1:42                                             ` Tony Lindgren
@ 2010-03-09  6:51                                               ` Felipe Balbi
  2010-03-09 15:21                                                 ` Aguirre, Sergio
  0 siblings, 1 reply; 61+ messages in thread
From: Felipe Balbi @ 2010-03-09  6:51 UTC (permalink / raw)
  To: ext Tony Lindgren
  Cc: Felipe Contreras, Aguirre, Sergio, Gopinath, Thara, Kevin Hilman,
	linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand

On Tue, Mar 09, 2010 at 02:42:36AM +0100, ext Tony Lindgren wrote:
>After a quick search for "mailing list netiquette" I cam up with
>the following links:
>
>http://linux.sgms-centre.com/misc/netiquette.php
>http://en.opensuse.org/OpenSUSE_mailing_list_netiquette
>
>We can add that to some of the wiki pages so people can start
>following the "proper" standards. Anybody got better links?

How about this ?

http://en.wikipedia.org/wiki/Top_posting#Interleaved_style

it explains all the posting styles but we want the interleaved style or 
inline reply without top-posting.

-- 
balbi

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

* RE: Snipping irrelevant text from a discussion (was: "RE: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling")
  2010-03-09  6:51                                               ` Felipe Balbi
@ 2010-03-09 15:21                                                 ` Aguirre, Sergio
  2010-03-09 18:21                                                   ` Tony Lindgren
  0 siblings, 1 reply; 61+ messages in thread
From: Aguirre, Sergio @ 2010-03-09 15:21 UTC (permalink / raw)
  To: felipe.balbi, ext Tony Lindgren
  Cc: Felipe Contreras, Gopinath, Thara, Kevin Hilman, linux-omap,
	paul, Menon, Nishanth, Cousson, Benoit, Sripathy, Vishwanath,
	Sawant, Anand

Hi,

From: Felipe Balbi [mailto:felipe.balbi@nokia.com]
Sent: Tuesday, March 09, 2010 12:52 AM
> On Tue, Mar 09, 2010 at 02:42:36AM +0100, ext Tony Lindgren wrote:
> >After a quick search for "mailing list netiquette" I cam up with
> >the following links:
> >
> >http://linux.sgms-centre.com/misc/netiquette.php
> >http://en.opensuse.org/OpenSUSE_mailing_list_netiquette
> >
> >We can add that to some of the wiki pages so people can start
> >following the "proper" standards. Anybody got better links?
> 
> How about this ?
> 
> http://en.wikipedia.org/wiki/Top_posting#Interleaved_style
> 
> it explains all the posting styles but we want the interleaved style or
> inline reply without top-posting.

I think that many things can be inherited from LKML FAQ about
"Mailing list questions":

http://www.kernel.org/pub/linux/docs/lkml/#ss3

But it might be a good idea to have a linux-omap specific wiki with a FAQ
section aswell, with the above answers adapted to it (some of the lkml
answers might not directly apply).

Anyways, just a thought.

Regards,
Sergio

> 
> --
> balbi

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

* Re: Snipping irrelevant text from a discussion (was: "RE: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling")
  2010-03-09 15:21                                                 ` Aguirre, Sergio
@ 2010-03-09 18:21                                                   ` Tony Lindgren
  0 siblings, 0 replies; 61+ messages in thread
From: Tony Lindgren @ 2010-03-09 18:21 UTC (permalink / raw)
  To: Aguirre, Sergio
  Cc: felipe.balbi, Felipe Contreras, Gopinath, Thara, Kevin Hilman,
	linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand

* Aguirre, Sergio <saaguirre@ti.com> [100309 07:18]:
> Hi,
> 
> From: Felipe Balbi [mailto:felipe.balbi@nokia.com]
> Sent: Tuesday, March 09, 2010 12:52 AM
> > On Tue, Mar 09, 2010 at 02:42:36AM +0100, ext Tony Lindgren wrote:
> > >After a quick search for "mailing list netiquette" I cam up with
> > >the following links:
> > >
> > >http://linux.sgms-centre.com/misc/netiquette.php
> > >http://en.opensuse.org/OpenSUSE_mailing_list_netiquette
> > >
> > >We can add that to some of the wiki pages so people can start
> > >following the "proper" standards. Anybody got better links?
> > 
> > How about this ?
> > 
> > http://en.wikipedia.org/wiki/Top_posting#Interleaved_style
> > 
> > it explains all the posting styles but we want the interleaved style or
> > inline reply without top-posting.

Yeah that's a good one.
 
> I think that many things can be inherited from LKML FAQ about
> "Mailing list questions":
> 
> http://www.kernel.org/pub/linux/docs/lkml/#ss3

This too.
 
> But it might be a good idea to have a linux-omap specific wiki with a FAQ
> section aswell, with the above answers adapted to it (some of the lkml
> answers might not directly apply).

OK, I've added a generic page for netiquette to elinux.org with
the relevant links above:

http://www.elinux.org/Netiquette

Also linked to that page from the main omap page there:

http://www.elinux.org/OMAP

Regards,

Tony

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

* RE: [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer
  2010-03-02 18:28       ` Kevin Hilman
  2010-03-05 14:26         ` Gopinath, Thara
@ 2010-03-12  9:48         ` Gopinath, Thara
  2010-03-13  0:36           ` Kevin Hilman
  1 sibling, 1 reply; 61+ messages in thread
From: Gopinath, Thara @ 2010-03-12  9:48 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand



>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>Sent: Tuesday, March 02, 2010 11:58 PM
>>To: Gopinath, Thara
>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
>>Vishwanath; Sawant, Anand
>>Subject: Re: [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods
>>and omap-device layer
>>
>>Thara Gopinath <thara@ti.com> writes:
>>
>>> This patch converts the exisitng smartreflex library into a
>>> platform driver with device , driver registrations using hardware mods.
>>> As part of this Ntarget values are passed as platform data.
>>>
>>> Signed-off-by: Thara Gopinath <thara@ti.com>
>>
>>Nice work Thara.  This is good.  Some minor comments below, but some
>>general comments first.
>>
>>As discussed, eventually (longer term) we'll want to move the driver
>>parts of this to a regulator driver.  To ease that transition, I think
>>it would be nice to start now by separating the driver portions of
>>this file from the device portions.
>>
>>You've already done a good job of keeping them separate in this file
>>(most of the device stuff is at the end) but I think having a separate
>>file is probably even better.  Maybe move driver stuff to sr_driver.c
>>and leave device stuff in smartreflex.c?  I don't care much about the
>>names at this point.
Hi Kevin,

Quick question.. If we are going to separate out smartreflex device portions from this file , can't we keep them in devices.c instead of going for a separate file?

Regards
Thara


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

* Re: [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer
  2010-03-12  9:48         ` Gopinath, Thara
@ 2010-03-13  0:36           ` Kevin Hilman
  2010-03-15 19:00             ` Tony Lindgren
  0 siblings, 1 reply; 61+ messages in thread
From: Kevin Hilman @ 2010-03-13  0:36 UTC (permalink / raw)
  To: Gopinath, Thara
  Cc: linux-omap, paul, Menon, Nishanth, Cousson, Benoit, Sripathy,
	Vishwanath, Sawant, Anand

"Gopinath, Thara" <thara@ti.com> writes:

>>>-----Original Message-----
>>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
>>>Sent: Tuesday, March 02, 2010 11:58 PM
>>>To: Gopinath, Thara
>>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
>>>Vishwanath; Sawant, Anand
>>>Subject: Re: [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods
>>>and omap-device layer
>>>
>>>Thara Gopinath <thara@ti.com> writes:
>>>
>>>> This patch converts the exisitng smartreflex library into a
>>>> platform driver with device , driver registrations using hardware mods.
>>>> As part of this Ntarget values are passed as platform data.
>>>>
>>>> Signed-off-by: Thara Gopinath <thara@ti.com>
>>>
>>>Nice work Thara.  This is good.  Some minor comments below, but some
>>>general comments first.
>>>
>>>As discussed, eventually (longer term) we'll want to move the driver
>>>parts of this to a regulator driver.  To ease that transition, I think
>>>it would be nice to start now by separating the driver portions of
>>>this file from the device portions.
>>>
>>>You've already done a good job of keeping them separate in this file
>>>(most of the device stuff is at the end) but I think having a separate
>>>file is probably even better.  Maybe move driver stuff to sr_driver.c
>>>and leave device stuff in smartreflex.c?  I don't care much about the
>>>names at this point.
>
> Quick question.. If we are going to separate out smartreflex device
> portions from this file , can't we keep them in devices.c instead of
> going for a separate file?

Ultimately, that's Tony's call, but I would prefer to see a separate
specific file for SR device init.

Kevin




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

* Re: [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer
  2010-03-13  0:36           ` Kevin Hilman
@ 2010-03-15 19:00             ` Tony Lindgren
  0 siblings, 0 replies; 61+ messages in thread
From: Tony Lindgren @ 2010-03-15 19:00 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Gopinath, Thara, linux-omap, paul, Menon, Nishanth, Cousson,
	Benoit, Sripathy, Vishwanath, Sawant, Anand

* Kevin Hilman <khilman@deeprootsystems.com> [100312 16:38]:
> "Gopinath, Thara" <thara@ti.com> writes:
> 
> >>>-----Original Message-----
> >>>From: Kevin Hilman [mailto:khilman@deeprootsystems.com]
> >>>Sent: Tuesday, March 02, 2010 11:58 PM
> >>>To: Gopinath, Thara
> >>>Cc: linux-omap@vger.kernel.org; paul@pwsan.com; Menon, Nishanth; Cousson, Benoit; Sripathy,
> >>>Vishwanath; Sawant, Anand
> >>>Subject: Re: [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods
> >>>and omap-device layer
> >>>
> >>>Thara Gopinath <thara@ti.com> writes:
> >>>
> >>>> This patch converts the exisitng smartreflex library into a
> >>>> platform driver with device , driver registrations using hardware mods.
> >>>> As part of this Ntarget values are passed as platform data.
> >>>>
> >>>> Signed-off-by: Thara Gopinath <thara@ti.com>
> >>>
> >>>Nice work Thara.  This is good.  Some minor comments below, but some
> >>>general comments first.
> >>>
> >>>As discussed, eventually (longer term) we'll want to move the driver
> >>>parts of this to a regulator driver.  To ease that transition, I think
> >>>it would be nice to start now by separating the driver portions of
> >>>this file from the device portions.
> >>>
> >>>You've already done a good job of keeping them separate in this file
> >>>(most of the device stuff is at the end) but I think having a separate
> >>>file is probably even better.  Maybe move driver stuff to sr_driver.c
> >>>and leave device stuff in smartreflex.c?  I don't care much about the
> >>>names at this point.
> >
> > Quick question.. If we are going to separate out smartreflex device
> > portions from this file , can't we keep them in devices.c instead of
> > going for a separate file?
> 
> Ultimately, that's Tony's call, but I would prefer to see a separate
> specific file for SR device init.

Yeah me too considering the amount of code. I also agree that most of
the smartreflex code should be done under drivers/ to allow loading it
as a module.

Regards,

Tony

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

end of thread, other threads:[~2010-03-15 18:59 UTC | newest]

Thread overview: 61+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-24  9:29 [PATCH 00/16] OMAP3: PM: Smartreflex and voltage revamp Thara Gopinath
2010-02-24  9:29 ` [PATCH 01/16] OMAP3: PM: Adding hwmod data for Smartreflex Thara Gopinath
2010-02-24  9:29   ` [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances Thara Gopinath
2010-02-24  9:29     ` [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer Thara Gopinath
2010-02-24  9:29       ` [PATCH 04/16] OMAP3: PM: Move smartreflex autocompensation enable disable hooks to PM debugfs Thara Gopinath
2010-02-24  9:29         ` [PATCH 05/16] OMAP3: PM: Export get_vdd1_opp and get_vdd2_opp from shared resource framework Thara Gopinath
2010-02-24  9:29           ` [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c Thara Gopinath
2010-02-24  9:29             ` [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver Thara Gopinath
2010-02-24  9:29               ` [PATCH 08/16] OMAP3: PM: Disabling Smartreflex across both frequency and voltage scaling during DVFS Thara Gopinath
2010-02-24  9:29                 ` [PATCH 09/16] OMAP3: PM: Creating separate files for handling OMAP3 voltage related operations Thara Gopinath
2010-02-24  9:29                   ` [PATCH 10/16] OMAP3: PM: Cleaning up of smartreflex header file Thara Gopinath
2010-02-24  9:29                     ` [PATCH 11/16] OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3 Thara Gopinath
2010-02-24  9:29                       ` [PATCH 12/16] OMAP3: PM: Support for enabling smartreflex autocompensation by default Thara Gopinath
2010-02-24  9:29                         ` [PATCH 13/16] OMAP3: PM: Correcting accessing of ERRCONFIG register in smartreflex.c Thara Gopinath
2010-02-24  9:29                           ` [PATCH 14/16] OMAP3: PM: Implement latest h/w recommendations for SR and VP registers and SR VP enable disable sequence Thara Gopinath
2010-02-24  9:29                             ` [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling Thara Gopinath
2010-02-24  9:29                               ` [PATCH 16/16] OMAP3: PM: Enabling Smartreflex Class 3 driver by default in pm defconfig Thara Gopinath
2010-03-03  0:58                               ` [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling Kevin Hilman
2010-03-05 15:22                                 ` Gopinath, Thara
2010-03-05 15:26                                   ` Felipe Contreras
2010-03-05 15:30                                     ` Gopinath, Thara
2010-03-05 16:22                                       ` Felipe Contreras
2010-03-05 18:17                                         ` Snipping irrelevant text from a discussion (was: "RE: [PATCH 15/16] OMAP3: PM: VP force update method of voltage scaling") Aguirre, Sergio
2010-03-05 21:18                                           ` Felipe Contreras
2010-03-09  1:42                                             ` Tony Lindgren
2010-03-09  6:51                                               ` Felipe Balbi
2010-03-09 15:21                                                 ` Aguirre, Sergio
2010-03-09 18:21                                                   ` Tony Lindgren
2010-03-03  0:54                             ` [PATCH 14/16] OMAP3: PM: Implement latest h/w recommendations for SR and VP registers and SR VP enable disable sequence Kevin Hilman
2010-03-03  0:48                         ` [PATCH 12/16] OMAP3: PM: Support for enabling smartreflex autocompensation by default Kevin Hilman
2010-03-05 15:20                           ` Gopinath, Thara
2010-03-03  0:37                       ` [PATCH 11/16] OMAP3: PM: Configurations for Smartreflex Class 2 and Smartreflex Class 3 Kevin Hilman
2010-03-05 15:12                         ` Gopinath, Thara
2010-03-05 19:20                           ` Kevin Hilman
2010-03-02 20:02                   ` [PATCH 09/16] OMAP3: PM: Creating separate files for handling OMAP3 voltage related operations Kevin Hilman
2010-03-05 15:17                     ` Gopinath, Thara
2010-03-02 19:36               ` [PATCH 07/16] OMAP3: PM: Adding smartreflex class 3 driver Kevin Hilman
2010-03-05 15:03                 ` Gopinath, Thara
2010-03-05 19:12                   ` Kevin Hilman
2010-03-02 18:44             ` [PATCH 06/16] OMAP3: PM: Smartreflex class related changes for smartreflex.c Kevin Hilman
2010-03-05 15:00               ` Gopinath, Thara
2010-03-05 18:29                 ` Kevin Hilman
2010-03-02 23:37             ` Kevin Hilman
2010-03-02 23:52             ` Kevin Hilman
2010-03-05 15:18               ` Gopinath, Thara
2010-03-05 18:30                 ` Kevin Hilman
2010-03-02 18:28         ` [PATCH 04/16] OMAP3: PM: Move smartreflex autocompensation enable disable hooks to PM debugfs Kevin Hilman
2010-02-25  2:39       ` [PATCH 03/16] OMAP3: PM: Convert smartreflex driver into a platform driver using hwmods and omap-device layer ambresh
2010-03-02 18:28       ` Kevin Hilman
2010-03-05 14:26         ` Gopinath, Thara
2010-03-12  9:48         ` Gopinath, Thara
2010-03-13  0:36           ` Kevin Hilman
2010-03-15 19:00             ` Tony Lindgren
2010-03-03  0:02       ` Kevin Hilman
2010-02-25  1:42     ` [PATCH 02/16] OMAP3: PM: Create list to keep track of various smartreflex instances ambresh
2010-03-02 17:40       ` Kevin Hilman
2010-02-26 23:21     ` Mike Turquette
2010-03-02 17:39       ` Kevin Hilman
2010-02-24 16:52   ` [PATCH 01/16] OMAP3: PM: Adding hwmod data for Smartreflex Mike Turquette
2010-03-06  0:45   ` Kevin Hilman
2010-03-06  0:58 ` [PATCH 00/16] OMAP3: PM: Smartreflex and voltage revamp 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.