Skip to contentSkip to conversation

OMAP: Adding Smartreflex and Voltage driver support

PATCH New Thara Gopinath 5 participants 22 messages Dec 20, 2010 – Jan 2, 2011

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

v6 cover OMAP: Adding Smartreflex and Voltage driver support

This patch series introduces smartreflex and voltage driver support for OMAP3430 and OMAP3630. SmartReflex modules do adaptive voltage control for real-time voltage adjustments.

Originally all the functionalities introduced in this patch were present in arch/arm/mach-omap2/smartreflex.c file in Kevin's pm tree. This patch series does a major rewrite of this file and introduces a separate voltage driver. Major contributors to the original driver are

Eduardo Valentin (1):
OMAP3: PM: SmartReflex: Fix scheduled while atomic problem

Kalle Jokiniemi (1):
OMAP3: PM: SmartReflex driver integration

Kevin Hilman (2):
temp: SR: IO_ADDRESS conversion
OMAP: SR: OPP interfaces removed from OMAP PM layer

Nishanth Menon (1):
omap3: pm: sr: replace get_opp with freq_to_opp

Paul Walmsley (2):
OMAP SR: use opp_find_opp_by_opp_id()
OMAP SR: use OPP API for OPP ID, remove direct access

Phil Carmody (2):
OMAP3: PM: Don't do unnecessary searches in omap_sr_vdd*_autocomp_store
OMAP3: PM: Early exit on invalid parameters

Rajendra Nayak (9):
OMAP3: SR: Fix init voltage on OPP change
OMAP3: SR: Update VDD1/2 voltages at boot
OMAP3: SR: Use sysclk for SR CLKLENGTH calc
OMAP3: SR: Reset voltage level on SR disable
OMAP3: SR: Replace printk's with pr_* calls
OMAP3: SR: Remove redundant defines
OMAP3: SR: Fix SR driver to check for omap-pm return values
OMAP3: PM: Put optimal SMPS stabilization delay
OMAP3: SR: Wait for VP idle before a VP disable

Roger Quadros (4):
OMAP3: PM: Fix Smartreflex when used with PM_NOOP layer
OMAP3: PM: Make Smartreflex driver independent of SRF
OMAP3: PM: Do not Enable SmartReflex if OPP tables not defined
OMAP3: PM: Smartreflex: Fix VDD2 OPP determining logic

Romit Dasgupta (1):
omap: pm: SR: use enum for OPP types

Teerth Reddy (1):
OMAP3: SR: Replace SR_PASS/FAIL,SR_TRUE/FALSE

Tero Kristo (1):
Smartreflex: Avoid unnecessary spam

This patch series is against pm-core branch of Kevin Hilman's OMAP PM tree with the following additional patch applied.

	https://patchwork.kernel.org/patch/421351/

The entire series with the dependencies are available at
http://dev.omapzoom.org/?p=thara/omap-dvfs.git;a=summary
head: kevin-pm-sr

This patch series has been tested on OMAP3430 SDP with omap2plus_defconfig with the following menuconfig options enabled.
System type -> TI OMAP Implementations -> Smartreflex Support System type -> TI OMAP Implementations ->
Class 3 mode of Smartreflex Implementation

Major Changes in v6
-Rebased to pm-core branch of Kevin Hilman's OMAP PM tree.

Major Changes in v5
- Rebased to k.org 2.6.37-rc3
- Rebased to Nishant Menon's latest opp patches
- Voltage pmic info structure extended to include a vast set of PMIC dependent parameters.
- Smartreflex software n-target values support removed from the kernel. Instead n-target values are exposed as debugfs entries which can be written into by the user if needed.
- Introduced a new file arch/arm/mach-omap2/omap_twl.c for specifying OMAP and TWL related info for the voltage layer.
- Remove default enabling of smartreflex autocompensation during boot on OMAP3430 ES3.1 chips. Instead an API is provided that can be called from board files in case autocompensation needs to be enabled during boot up itself.
- Other review comments on v4

Thara Gopinath (10):
OMAP3: PM: Adding voltage driver support.
OMAP: Introduce voltage domain information in the hwmod structures
OMAP3: PM: Adding smartreflex driver support.
OMAP3: PM: Adding smartreflex device file.
OMAP3: PM: Adding smartreflex hwmod data
OMAP3: PM: Adding smartreflex class3 driver
OMAP3: PM: Adding T2 enabling of smartreflex support
OMAP3: PM: Register TWL4030 pmic info with the voltage driver.
OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers
OMAP3: PM: Program correct init voltages for VDD1 and VDD2

 arch/arm/mach-omap2/Makefile                  |    7 +-
 arch/arm/mach-omap2/control.h                 |   17 +
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c    |  176 ++++
 arch/arm/mach-omap2/omap_twl.c                |  111 +++
 arch/arm/mach-omap2/pm.c                      |   90 ++
 arch/arm/mach-omap2/pm.h                      |   23 +
 arch/arm/mach-omap2/smartreflex-class3.c      |   59 ++
 arch/arm/mach-omap2/smartreflex.c             | 1025 ++++++++++++++++++++
 arch/arm/mach-omap2/sr_device.c               |  131 +++
 arch/arm/mach-omap2/voltage.c                 | 1292 +++++++++++++++++++++++++
 arch/arm/plat-omap/Kconfig                    |   31 +
 arch/arm/plat-omap/include/plat/omap_hwmod.h  |    5 +
 arch/arm/plat-omap/include/plat/smartreflex.h |  245 +++++
 arch/arm/plat-omap/include/plat/voltage.h     |  134 +++
 drivers/mfd/twl-core.c                        |   13 +
 include/linux/i2c/twl.h                       |   11 +
 16 files changed, 3369 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/omap_twl.c
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
 create mode 100644 arch/arm/mach-omap2/smartreflex.c
 create mode 100644 arch/arm/mach-omap2/sr_device.c
 create mode 100644 arch/arm/mach-omap2/voltage.c
 create mode 100644 arch/arm/plat-omap/include/plat/smartreflex.h
 create mode 100644 arch/arm/plat-omap/include/plat/voltage.h
#1 lore raw

PATCH v6 1/10 OMAP3: PM: Adding voltage driver support.

This patch adds voltage driver support for OMAP3. The driver allows configuring the voltage controller and voltage processors during init and exports APIs to enable/disable voltage processors, scale voltage and reset voltage. The driver maintains the global voltage table on a per VDD basis which contains the various voltages supported by the VDD along with per voltage dependent data like smartreflex efuse offset, errminlimit and voltage processor errorgain. The driver also allows the voltage parameters dependent on the PMIC to be passed from the PMIC file through an API. The driver allows scaling of VDD voltages either through "vc bypass method" or through "vp forceupdate method" the choice being configurable through the board file.

This patch contains code originally in linux omap pm branch smartreflex driver. Major contributors to this driver are Lesly A M, Rajendra Nayak, Kalle Jokiniemi, Paul Walmsley, Nishant Menon, Kevin Hilman. The separation of PMIC parameters into a separate structure which can be populated from the PMIC file is based on the work of Lun Chang from Motorola in an internal tree.

---
This patch has 14 checkpatch.pl above 80-chars warnings for the definitions of omap34xx_vddmpu_volt_data, omap36xx_vddmpu_volt_data, omap34xx_vddcore_volt_data and omap36xx_vddcore_volt_data structures. IMHO splitting of the entries in these structures affects readability and looks very ugly. Hence they are left as is.

 arch/arm/mach-omap2/Makefile              |    3 +-
 arch/arm/mach-omap2/control.h             |   17 +
 arch/arm/mach-omap2/pm.c                  |    8 +
 arch/arm/mach-omap2/voltage.c             | 1226 +++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/voltage.h |  134 ++++
 5 files changed, 1387 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/voltage.c
 create mode 100644 arch/arm/plat-omap/include/plat/voltage.h
arch/arm/mach-omap2/Makefile +2 -1
index 7c79683..5034797 100644
@@ -57,7 +57,8 @@ endif
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
 obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o pm_bus.o
-obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o cpuidle34xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o voltage.o \
+					   cpuidle34xx.o pm_bus.o
 obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o pm_bus.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 
arch/arm/mach-omap2/control.h +17 -0
index 5289461..9fe32dc 100644
@@ -148,6 +148,15 @@
 #define OMAP343X_CONTROL_TEST_KEY_11	(OMAP2_CONTROL_GENERAL + 0x00f4)
 #define OMAP343X_CONTROL_TEST_KEY_12	(OMAP2_CONTROL_GENERAL + 0x00f8)
 #define OMAP343X_CONTROL_TEST_KEY_13	(OMAP2_CONTROL_GENERAL + 0x00fc)
+#define OMAP343X_CONTROL_FUSE_OPP1_VDD1 (OMAP2_CONTROL_GENERAL + 0x0110)
+#define OMAP343X_CONTROL_FUSE_OPP2_VDD1 (OMAP2_CONTROL_GENERAL + 0x0114)
+#define OMAP343X_CONTROL_FUSE_OPP3_VDD1 (OMAP2_CONTROL_GENERAL + 0x0118)
+#define OMAP343X_CONTROL_FUSE_OPP4_VDD1 (OMAP2_CONTROL_GENERAL + 0x011c)
+#define OMAP343X_CONTROL_FUSE_OPP5_VDD1 (OMAP2_CONTROL_GENERAL + 0x0120)
+#define OMAP343X_CONTROL_FUSE_OPP1_VDD2 (OMAP2_CONTROL_GENERAL + 0x0124)
+#define OMAP343X_CONTROL_FUSE_OPP2_VDD2 (OMAP2_CONTROL_GENERAL + 0x0128)
+#define OMAP343X_CONTROL_FUSE_OPP3_VDD2 (OMAP2_CONTROL_GENERAL + 0x012c)
+#define OMAP343X_CONTROL_FUSE_SR        (OMAP2_CONTROL_GENERAL + 0x0130)
 #define OMAP343X_CONTROL_IVA2_BOOTADDR	(OMAP2_CONTROL_GENERAL + 0x0190)
 #define OMAP343X_CONTROL_IVA2_BOOTMOD	(OMAP2_CONTROL_GENERAL + 0x0194)
 #define OMAP343X_CONTROL_DEBOBS(i)	(OMAP2_CONTROL_GENERAL + 0x01B0 \
@@ -164,6 +173,14 @@
 #define OMAP343X_CONTROL_SRAMLDO5	(OMAP2_CONTROL_GENERAL + 0x02C0)
 #define OMAP343X_CONTROL_CSI		(OMAP2_CONTROL_GENERAL + 0x02C4)
 
+/* OMAP3630 only CONTROL_GENERAL register offsets */
+#define OMAP3630_CONTROL_FUSE_OPP1G_VDD1        (OMAP2_CONTROL_GENERAL + 0x0110)
+#define OMAP3630_CONTROL_FUSE_OPP50_VDD1        (OMAP2_CONTROL_GENERAL + 0x0114)
+#define OMAP3630_CONTROL_FUSE_OPP100_VDD1       (OMAP2_CONTROL_GENERAL + 0x0118)
+#define OMAP3630_CONTROL_FUSE_OPP120_VDD1       (OMAP2_CONTROL_GENERAL + 0x0120)
+#define OMAP3630_CONTROL_FUSE_OPP50_VDD2        (OMAP2_CONTROL_GENERAL + 0x0128)
+#define OMAP3630_CONTROL_FUSE_OPP100_VDD2       (OMAP2_CONTROL_GENERAL + 0x012C)
+
 /* AM35XX only CONTROL_GENERAL register offsets */
 #define AM35XX_CONTROL_MSUSPENDMUX_6    (OMAP2_CONTROL_GENERAL + 0x0038)
 #define AM35XX_CONTROL_DEVCONF2         (OMAP2_CONTROL_GENERAL + 0x0310)
arch/arm/mach-omap2/pm.c +8 -0
index 227a211..22adfb2 100644
@@ -17,6 +17,7 @@
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 #include <plat/common.h>
+#include <plat/voltage.h>
 
 #include "powerdomain.h"
 #include "clockdomain.h"
@@ -145,3 +146,10 @@ static int __init omap2_common_pm_init(void)
 }
 postcore_initcall(omap2_common_pm_init);
 
+static int __init omap2_common_pm_late_init(void)
+{
+	omap_voltage_late_init();
+
+	return 0;
+}
+late_initcall(omap2_common_pm_late_init);
arch/arm/mach-omap2/voltage.c new file +1226 -0

1,226 lines not on this page · raw message

arch/arm/plat-omap/include/plat/voltage.h new file +134 -0

134 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#2 lore raw

PATCH v6 1/10 OMAP3: PM: Adding voltage driver support.

Quoted 44 lines · Thara Gopinath

This patch adds voltage driver support for OMAP3. The driver allows configuring the voltage controller and voltage processors during init and exports APIs to enable/disable voltage processors, scale voltage and reset voltage. The driver maintains the global voltage table on a per VDD basis which contains the various voltages supported by the VDD along with per voltage dependent data like smartreflex efuse offset, errminlimit and voltage processor errorgain. The driver also allows the voltage parameters dependent on the PMIC to be passed from the PMIC file through an API. The driver allows scaling of VDD voltages either through "vc bypass method" or through "vp forceupdate method" the choice being configurable through the board file.

This patch contains code originally in linux omap pm branch smartreflex driver. Major contributors to this driver are Lesly A M, Rajendra Nayak, Kalle Jokiniemi, Paul Walmsley, Nishant Menon, Kevin Hilman. The separation of PMIC parameters into a separate structure which can be populated from the PMIC file is based on the work of Lun Chang from Motorola in an internal tree.

---
This patch has 14 checkpatch.pl above 80-chars warnings for the definitions of omap34xx_vddmpu_volt_data, omap36xx_vddmpu_volt_data, omap34xx_vddcore_volt_data and omap36xx_vddcore_volt_data structures. IMHO splitting of the entries in these structures affects readability and looks very ugly. Hence they are left as is.

 arch/arm/mach-omap2/Makefile              |    3 +-
 arch/arm/mach-omap2/control.h             |   17 +
 arch/arm/mach-omap2/pm.c                  |    8 +
 arch/arm/mach-omap2/voltage.c             | 1226 +++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/voltage.h |  134 ++++
 5 files changed, 1387 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/voltage.c
 create mode 100644 arch/arm/plat-omap/include/plat/voltage.h
arch/arm/mach-omap2/Makefile +0 -0
index 7c79683..5034797 100644

arch/arm/mach-omap2/Makefile endif · line 61

Quoted 6 lines
arch/arm/mach-omap2/Makefile +2 -1
@@ -57,7 +57,8 @@ endif
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
 obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o pm_bus.o
-obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o cpuidle34xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o voltage.o \
+					   cpuidle34xx.o pm_bus.o

This will not link when building OMAP2 only (common for n8x0 testing due to kernel size limitation.) In this config, voltage.o is not compiled, but its functions are still called from the common pm.c.

Will fold the following diff into this patch.

Kevin

arch/arm/mach-omap2/Makefile +1 -1
index 91c9b60..4ab82f6 100644
@@ -59,7 +59,7 @@ endif
 # Power Management
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
-obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o pm_bus.o voltage.o
 obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o voltage.o \
 					   cpuidle34xx.o pm_bus.o
 obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o voltage.o pm_bus.o
#3 lore raw

PATCH v6 1/10 OMAP3: PM: Adding voltage driver support.

In reply to Thara Gopinath

Thara,

Here are some comments on the voltage layer; many of them are cosmetic in nature.

Quoted 196 lines

-----Original Message-----
From: Thara Gopinath [mailto:thara at ti.com]
Sent: Monday, December 20, 2010 10:29 PM
To: linux-omap at vger.kernel.org; linux-arm- kernel at lists.infradead.org
Cc: khilman at deeprootsystems.com; paul at pwsan.com; b- cousson at ti.com; vishwanath.bs at ti.com; sawant at ti.com; nm at ti.com; Thara Gopinath
Subject: [PATCH v6 01/10] OMAP3: PM: Adding voltage driver support.

This patch adds voltage driver support for OMAP3. The driver allows configuring the voltage controller and voltage processors during init and exports APIs to enable/disable voltage processors, scale voltage and reset voltage. The driver maintains the global voltage table on a per VDD basis which contains the various voltages supported by the
VDD along with per voltage dependent data like smartreflex efuse offset, errminlimit and voltage processor errorgain. The driver also allows the voltage parameters dependent on the
PMIC to be passed from the PMIC file through an API. The driver allows scaling of VDD voltages either through "vc bypass method" or through "vp forceupdate method" the choice being configurable through the board file.

This patch contains code originally in linux omap pm branch smartreflex driver. Major contributors to this driver are Lesly A M, Rajendra Nayak, Kalle Jokiniemi, Paul Walmsley, Nishant Menon, Kevin Hilman. The separation of PMIC parameters
into a separate structure which can be populated from the PMIC file is based on the work of Lun Chang from Motorola
in an internal tree.

---
This patch has 14 checkpatch.pl above 80-chars warnings for the definitions of omap34xx_vddmpu_volt_data, omap36xx_vddmpu_volt_data, omap34xx_vddcore_volt_data and omap36xx_vddcore_volt_data structures.
IMHO splitting of the entries in these structures affects readability and looks very ugly. Hence they are left as is.

 arch/arm/mach-omap2/Makefile              |    3 +-
 arch/arm/mach-omap2/control.h             |   17 +
 arch/arm/mach-omap2/pm.c                  |    8 +
 arch/arm/mach-omap2/voltage.c             | 1226
+++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/voltage.h |  134 ++++
 5 files changed, 1387 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/voltage.c
 create mode 100644 arch/arm/plat-

omap/include/plat/voltage.h

arch/arm/mach- renamed from arch/arm/mach-omap2/Makefile +0 -0

omap2/Makefile
index 7c79683..5034797 100644

arch/arm/mach-omap2/Makefile +0 -1
@@ -57,7 +57,8 @@ endif
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
 obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o pm_bus.o
-obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o

cpuidle34xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o
voltage.o \

arch/arm/mach-omap2/Makefile +1 -0
+					   cpuidle34xx.o pm_bus.o
 obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o pm_bus.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
arch/arm/mach- renamed from arch/arm/mach-omap2/control.h +0 -0

omap2/control.h
index 5289461..9fe32dc 100644

arch/arm/mach-omap2/control.h +1 -0
@@ -148,6 +148,15 @@
 #define OMAP343X_CONTROL_TEST_KEY_11
 	(OMAP2_CONTROL_GENERAL + 0x00f4)
 #define OMAP343X_CONTROL_TEST_KEY_12
 	(OMAP2_CONTROL_GENERAL + 0x00f8)
 #define OMAP343X_CONTROL_TEST_KEY_13
 	(OMAP2_CONTROL_GENERAL + 0x00fc)
+#define OMAP343X_CONTROL_FUSE_OPP1_VDD1

(OMAP2_CONTROL_GENERAL + 0x0110)
+#define OMAP343X_CONTROL_FUSE_OPP2_VDD1
(OMAP2_CONTROL_GENERAL + 0x0114)
+#define OMAP343X_CONTROL_FUSE_OPP3_VDD1
(OMAP2_CONTROL_GENERAL + 0x0118)
+#define OMAP343X_CONTROL_FUSE_OPP4_VDD1
(OMAP2_CONTROL_GENERAL + 0x011c)
+#define OMAP343X_CONTROL_FUSE_OPP5_VDD1
(OMAP2_CONTROL_GENERAL + 0x0120)
+#define OMAP343X_CONTROL_FUSE_OPP1_VDD2
(OMAP2_CONTROL_GENERAL + 0x0124)
+#define OMAP343X_CONTROL_FUSE_OPP2_VDD2
(OMAP2_CONTROL_GENERAL + 0x0128)
+#define OMAP343X_CONTROL_FUSE_OPP3_VDD2
(OMAP2_CONTROL_GENERAL + 0x012c)
+#define OMAP343X_CONTROL_FUSE_SR
(OMAP2_CONTROL_GENERAL + 0x0130)

 #define OMAP343X_CONTROL_IVA2_BOOTADDR
	(OMAP2_CONTROL_GENERAL + 0x0190)
 #define OMAP343X_CONTROL_IVA2_BOOTMOD
	(OMAP2_CONTROL_GENERAL + 0x0194)

#define OMAP343X_CONTROL_DEBOBS(i) (OMAP2_CONTROL_GENERAL +
0x01B0 \

arch/arm/mach-omap2/control.h +3 -0
@@ -164,6 +173,14 @@
 #define OMAP343X_CONTROL_SRAMLDO5	(OMAP2_CONTROL_GENERAL +
 0x02C0)
 #define OMAP343X_CONTROL_CSI		(OMAP2_CONTROL_GENERAL +
 0x02C4)
 
+/* OMAP3630 only CONTROL_GENERAL register offsets */
+#define OMAP3630_CONTROL_FUSE_OPP1G_VDD1
 (OMAP2_CONTROL_GENERAL + 0x0110)
+#define OMAP3630_CONTROL_FUSE_OPP50_VDD1

(OMAP2_CONTROL_GENERAL + 0x0114)
+#define OMAP3630_CONTROL_FUSE_OPP100_VDD1 (OMAP2_CONTROL_GENERAL + 0x0118)
+#define OMAP3630_CONTROL_FUSE_OPP120_VDD1 (OMAP2_CONTROL_GENERAL + 0x0120)
+#define OMAP3630_CONTROL_FUSE_OPP50_VDD2 (OMAP2_CONTROL_GENERAL + 0x0128)
+#define OMAP3630_CONTROL_FUSE_OPP100_VDD2 (OMAP2_CONTROL_GENERAL + 0x012C)
+
/* AM35XX only CONTROL_GENERAL register offsets */ #define AM35XX_CONTROL_MSUSPENDMUX_6
(OMAP2_CONTROL_GENERAL + 0x0038)
#define AM35XX_CONTROL_DEVCONF2
(OMAP2_CONTROL_GENERAL + 0x0310)

arch/arm/mach- renamed from arch/arm/mach-omap2/pm.c +0 -0

omap2/pm.c
index 227a211..22adfb2 100644

arch/arm/mach-omap2/pm.c +8 -0
@@ -17,6 +17,7 @@
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 #include <plat/common.h>
+#include <plat/voltage.h>
 
 #include "powerdomain.h"
 #include "clockdomain.h"
@@ -145,3 +146,10 @@ static int __init
 omap2_common_pm_init(void)
 }
 postcore_initcall(omap2_common_pm_init);
 
+static int __init omap2_common_pm_late_init(void)
+{
+	omap_voltage_late_init();
+
+	return 0;
+}
+late_initcall(omap2_common_pm_late_init);
arch/arm/mach- renamed from arch/arm/mach-omap2/voltage.c +0 -0

omap2/voltage.c
new file mode 100644
index 0000000..875667f

arch/arm/mach-omap2/voltage.c new file +16 -0
@@ -0,0 +1,1226 @@
+/*
+ * OMAP3/OMAP4 Voltage Management Routines
+ *
+ * Author: Thara Gopinath	<[email protected]>
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Rajendra Nayak <[email protected]>
+ * Lesly A M <[email protected]>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <[email protected]>
+ *
+ * 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.
+ */

arch/arm/mach-omap2/voltage.c new file +7 -0
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>

arch/arm/mach-omap2/voltage.c line 36

Quoted 10 lines
arch/arm/mach-omap2/voltage.c new file +10 -0
+
+#include <plat/common.h>
+#include <plat/voltage.h>
+
+#include "prm-regbits-34xx.h"
+#include "control.h"
+
+#define VP_IDLE_TIMEOUT		200
+#define VP_TRANXDONE_TIMEOUT	300
+#define VOLTAGE_DIR_SIZE	16

Add comments for the above #defines.

arch/arm/mach-omap2/voltage.c

Quoted 2 lines
arch/arm/mach-omap2/voltage.c new file +2 -0
+
+/* Voltage processor register offsets */

Add comments for the data members.

arch/arm/mach-omap2/voltage.c line 48

Quoted 10 lines
arch/arm/mach-omap2/voltage.c new file +10 -0
+struct vp_reg_offs {
+	u8 vpconfig;
+	u8 vstepmin;
+	u8 vstepmax;
+	u8 vlimitto;
+	u8 vstatus;
+	u8 voltage;
+};
+
+/* Voltage Processor bit field values, shifts and masks */

Add comments for the data members.

Quoted 26 lines
arch/arm/mach-omap2/voltage.c new file +26 -0
+struct vp_reg_val {
+	/* PRM module */
+	u16 prm_mod;
+	/* VPx_VPCONFIG */
+	u32 vpconfig_erroroffset;
+	u16 vpconfig_errorgain;
+	u32 vpconfig_errorgain_mask;
+	u8 vpconfig_errorgain_shift;
+	u32 vpconfig_initvoltage_mask;
+	u8 vpconfig_initvoltage_shift;
+	u32 vpconfig_timeouten;
+	u32 vpconfig_initvdd;
+	u32 vpconfig_forceupdate;
+	u32 vpconfig_vpenable;
+	/* VPx_VSTEPMIN */
+	u8 vstepmin_stepmin;
+	u16 vstepmin_smpswaittimemin;
+	u8 vstepmin_stepmin_shift;
+	u8 vstepmin_smpswaittimemin_shift;
+	/* VPx_VSTEPMAX */
+	u8 vstepmax_stepmax;
+	u16 vstepmax_smpswaittimemax;
+	u8 vstepmax_stepmax_shift;
+	u8 vstepmax_smpswaittimemax_shift;
+	/* VPx_VLIMITTO */
+	u8 vlimitto_vddmin;

arch/arm/mach-omap2/voltage.c line 84

Quoted 10 lines
arch/arm/mach-omap2/voltage.c new file +10 -0
+	u8 vlimitto_vddmax;
+	u16 vlimitto_timeout;
+	u8 vlimitto_vddmin_shift;
+	u8 vlimitto_vddmax_shift;
+	u8 vlimitto_timeout_shift;
+	/* PRM_IRQSTATUS*/
+	u32 tranxdone_status;
+};
+
+/* Voltage controller registers and offsets */

Add comments for the data members.

Quoted 51 lines
arch/arm/mach-omap2/voltage.c new file +35 -0
+struct vc_reg_info {
+	/* PRM module */
+	u16 prm_mod;
+	/* VC register offsets */
+	u8 smps_sa_reg;
+	u8 smps_volra_reg;
+	u8 bypass_val_reg;
+	u8 cmdval_reg;
+	u8 voltsetup_reg;
+	/*VC_SMPS_SA*/
+	u8 smps_sa_shift;
+	u32 smps_sa_mask;
+	/* VC_SMPS_VOL_RA */
+	u8 smps_volra_shift;
+	u32 smps_volra_mask;
+	/* VC_BYPASS_VAL */
+	u8 data_shift;
+	u8 slaveaddr_shift;
+	u8 regaddr_shift;
+	u32 valid;
+	/* VC_CMD_VAL */
+	u8 cmd_on_shift;
+	u8 cmd_onlp_shift;
+	u8 cmd_ret_shift;
+	u8 cmd_off_shift;
+	u32 cmd_on_mask;
+	/* PRM_VOLTSETUP */
+	u8 voltsetup_shift;
+	u32 voltsetup_mask;
+};
+
+/**
+ * omap_vdd_info - Per Voltage Domain info
+ *
+ * @volt_data		: voltage table having the distinct

voltages supported
+ * by the domain and other associated per
voltage data.
+ * @pmic_info : pmic specific parameters which
should be populted by
+ * the pmic drivers.
+ * @vp_offs : structure containing the offsets
for various
+ * vp registers
+ * @vp_reg : the register values, shifts, masks for
various
+ * vp registers
+ * @vc_reg : structure containing various various vc
registers,
+ * shifts, masks etc.
+ * @voltdm : pointer to the voltage domain structure

Quoted 8 lines

+ * @debug_dir : debug directory for this voltage
domain.
+ * @curr_volt : current voltage for this vdd.
+ * @ocp_mod : The prm module for accessing the
prm irqstatus reg.
+ * @prm_irqst_reg : prm irqstatus register.
+ * @vp_enabled : flag to keep track of whether vp
is enabled or not

Add comments for read_reg & write_reg.

Quoted 2 lines

+ * @volt_scale : API to scale the voltage of the
vdd.

Add more explanation about the structure - like its significance, how it is populated and used etc.

arch/arm/mach-omap2/voltage.c line 143

Quoted 8 lines

+ */

arch/arm/mach-omap2/voltage.c new file +7 -0
+struct omap_vdd_info {
+	struct omap_volt_data *volt_data;
+	struct omap_volt_pmic_info *pmic_info;
+	struct vp_reg_offs vp_offs;
+	struct vp_reg_val vp_reg;
+	struct vc_reg_info vc_reg;
+	struct voltagedomain voltdm;

Make voltdm the first member of the structure as it's a key identifier.

arch/arm/mach-omap2/voltage.c line 155

Quoted 12 lines
arch/arm/mach-omap2/voltage.c new file +12 -0
+	struct dentry *debug_dir;
+	u32 curr_volt;
+	u16 ocp_mod;
+	u8 prm_irqst_reg;
+	bool vp_enabled;
+	u32 (*read_reg) (u16 mod, u8 offset);
+	void (*write_reg) (u32 val, u16 mod, u8 offset);
+	int (*volt_scale) (struct omap_vdd_info *vdd,
+		unsigned long target_volt);
+};
+
+static struct omap_vdd_info *vdd_info;

Add comment. It's an important pointer.

arch/arm/mach-omap2/voltage.c line 161

Quoted 6 lines
arch/arm/mach-omap2/voltage.c new file +6 -0
+/*
+ * Number of scalable voltage domains.
+ */
+static int nr_scalable_vdd;
+
+/* OMAP3 VDD sturctures */

Add comment to mention that partial initialization is done here & the rest is done in omap3_vdd_data_configure() function.

arch/arm/mach-omap2/voltage.c line 171

Quoted 10 lines
arch/arm/mach-omap2/voltage.c new file +10 -0
+static struct omap_vdd_info omap3_vdd_info[] = {
+	{
+		.vp_offs = {
+			.vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET,
+			.vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET,
+			.vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET,
+			.vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET,
+			.vstatus = OMAP3_PRM_VP1_STATUS_OFFSET,
+			.voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET,
+		},

Recommend to use DEFINE_VP_REG_OFFS macro similar to VOLT_DATA_DEFINE to make it more readable.

arch/arm/mach-omap2/voltage.c line 174

Quoted 3 lines
arch/arm/mach-omap2/voltage.c new file +3 -0
+		.voltdm = {
+			.name = "mpu",
+		},

Make this initialization the first initialization.

Quoted 32 lines
arch/arm/mach-omap2/voltage.c new file +20 -0
+	},
+	{
+		.vp_offs = {
+			.vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET,
+			.vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET,
+			.vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET,
+			.vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET,
+			.vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
+			.voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
+		},
+		.voltdm = {
+			.name = "core",
+		},
+	},
+};
+
+#define OMAP3_NR_SCALABLE_VDD ARRAY_SIZE(omap3_vdd_info)
+
+/*
+ * Structures containing OMAP3430/OMAP3630 voltage

supported and various
+ * voltage dependent data for each VDD.
+ */
+#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit,
_errgain) \

arch/arm/mach-omap2/voltage.c new file +2 -0
+{									\
+	.volt_nominal	= _v_nom,
	\
arch/arm/mach-omap2/voltage.c new file +1 -0
+	.sr_efuse_offs	= _efuse_offs,
	\
arch/arm/mach-omap2/voltage.c new file +1 -0
+	.sr_errminlimit	= _errminlimit,
	\

arch/arm/mach-omap2/voltage.c line 205

Quoted 4 lines
arch/arm/mach-omap2/voltage.c new file +4 -0
+	.vp_errgain	= _errgain					\
+}
+
+/* VDD1 */

Add a comment stressing the need to keep VOLT_DATA_DEFINE(0, 0, 0, 0) as always the last member. Otherwise, the loop in omap_voltage_get_voltdata() will not function properly.

Quoted 46 lines

+static struct omap_volt_data omap34xx_vddmpu_volt_data[] = {

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV,

OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c),

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV,

OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c),

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV,

OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18),

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV,

OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18),

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV,

OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18),

arch/arm/mach-omap2/voltage.c new file +4 -0
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+static struct omap_volt_data omap36xx_vddmpu_volt_data[] =

{

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV,

OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c),

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV,

OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16),

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV,

OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23),

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV,

OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27),

arch/arm/mach-omap2/voltage.c new file +5 -0
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* VDD2 */
+static struct omap_volt_data omap34xx_vddcore_volt_data[] =

{

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV,

OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c),

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV,

OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c),

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV,

OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18),

arch/arm/mach-omap2/voltage.c new file +4 -0
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+static struct omap_volt_data omap36xx_vddcore_volt_data[] =

{

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV,

OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c),

arch/arm/mach-omap2/voltage.c new file +1 -0
+	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV,

OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16),

arch/arm/mach-omap2/voltage.c line 237

Quoted 4 lines
arch/arm/mach-omap2/voltage.c new file +4 -0
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+static struct dentry *voltage_dir;

Add comment.

arch/arm/mach-omap2/voltage.c

Quoted 2 lines
arch/arm/mach-omap2/voltage.c new file +2 -0
+
+/* Init function pointers */

Add comment mentioning how they are populated.

Quoted 3 lines
arch/arm/mach-omap2/voltage.c new file +2 -0
+static void (*vc_init) (struct omap_vdd_info *vdd);
+static int (*vdd_data_configure) (struct omap_vdd_info

*vdd);

Recommend to define a similar init function pointer for vp initialization. At present, it will be initialized with the generic vp_init(). But it will allow easy migration in case vp initialization is different for future OMAPs.

Also, highlight the difference between init (actually writes to module registers) and data_configure (populates data structures; no writing to registers) for clarity.

arch/arm/mach-omap2/voltage.c line 252

Quoted 12 lines
arch/arm/mach-omap2/voltage.c new file +7 -0
+
+static u32 omap3_voltage_read_reg(u16 mod, u8 offset)
+{
+	return omap2_prm_read_mod_reg(mod, offset);
+}
+
+static void omap3_voltage_write_reg(u32 val, u16 mod, u8

offset)

arch/arm/mach-omap2/voltage.c new file +4 -0
+{
+	omap2_prm_write_mod_reg(val, mod, offset);
+}
+

Add comment for vp_latch_vsel.

Quoted 37 lines
arch/arm/mach-omap2/voltage.c new file +10 -0
+static void vp_latch_vsel(struct omap_vdd_info *vdd)
+{
+	u32 vpconfig;
+	u16 mod;
+	unsigned long uvdc;
+	char vsel;
+
+	uvdc = omap_voltage_get_nom_volt(&vdd->voltdm);
+	if (!uvdc) {
+		pr_warning("%s: unable to find current voltage

for vdd_%s\n",

arch/arm/mach-omap2/voltage.c new file +6 -0
+			__func__, vdd->voltdm.name);
+		return;
+	}
+
+	if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
+		pr_warning("%s: PMIC function to convert voltage

in uV to"

arch/arm/mach-omap2/voltage.c new file +12 -0
+			" vsel not registered\n", __func__);
+		return;
+	}
+
+	mod = vdd->vp_reg.prm_mod;
+
+	vsel = vdd->pmic_info->uv_to_vsel(uvdc);
+
+	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
+	vpconfig &= ~(vdd->vp_reg.vpconfig_initvoltage_mask |
+			vdd->vp_reg.vpconfig_initvdd);
+	vpconfig |= vsel << vdd-
Quoted 1 line

vp_reg.vpconfig_initvoltage_shift;

arch/arm/mach-omap2/voltage.c new file +5 -0
+
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+
+	/* Trigger initVDD value copy to voltage processor */
+	vdd->write_reg((vpconfig | vdd-
Quoted 1 line

vp_reg.vpconfig_initvdd), mod,

arch/arm/mach-omap2/voltage.c

Quoted 2 lines
arch/arm/mach-omap2/voltage.c new file +2 -0
+			vdd->vp_offs.vpconfig);
+

Check if any delay is needed between triggering initVDD copy & clearing initVDD copy. Check if the two need to be atomic.

arch/arm/mach-omap2/voltage.c line 293

Quoted 6 lines
arch/arm/mach-omap2/voltage.c new file +6 -0
+	/* Clear initVDD copy trigger bit */
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+}
+
+/* Generic voltage init functions */
+static void __init vp_init(struct omap_vdd_info *vdd)

Recommend to change the return type to int to allow for better error handling & diagnostic messages.

Quoted 30 lines
arch/arm/mach-omap2/voltage.c new file +6 -0
+{
+	u32 vp_val;
+	u16 mod;
+
+	if (!vdd->read_reg || !vdd->write_reg) {
+		pr_err("%s: No read/write API for accessing

vdd_%s regs\n",

arch/arm/mach-omap2/voltage.c new file +23 -0
+			__func__, vdd->voltdm.name);
+		return;
+	}
+
+	mod = vdd->vp_reg.prm_mod;
+
+	vp_val = vdd->vp_reg.vpconfig_erroroffset |
+		(vdd->vp_reg.vpconfig_errorgain <<
+		vdd->vp_reg.vpconfig_errorgain_shift) |
+		vdd->vp_reg.vpconfig_timeouten;
+	vdd->write_reg(vp_val, mod, vdd->vp_offs.vpconfig);
+
+	vp_val = ((vdd->vp_reg.vstepmin_smpswaittimemin <<
+		vdd->vp_reg.vstepmin_smpswaittimemin_shift) |
+		(vdd->vp_reg.vstepmin_stepmin <<
+		vdd->vp_reg.vstepmin_stepmin_shift));
+	vdd->write_reg(vp_val, mod, vdd->vp_offs.vstepmin);
+
+	vp_val = ((vdd->vp_reg.vstepmax_smpswaittimemax <<
+		vdd->vp_reg.vstepmax_smpswaittimemax_shift) |
+		(vdd->vp_reg.vstepmax_stepmax <<
+		vdd->vp_reg.vstepmax_stepmax_shift));
+	vdd->write_reg(vp_val, mod, vdd->vp_offs.vstepmax);

arch/arm/mach-omap2/voltage.c line 332

Quoted 10 lines
arch/arm/mach-omap2/voltage.c new file +10 -0
+
+	vp_val = ((vdd->vp_reg.vlimitto_vddmax <<
+		vdd->vp_reg.vlimitto_vddmax_shift) |
+		(vdd->vp_reg.vlimitto_vddmin <<
+		vdd->vp_reg.vlimitto_vddmin_shift) |
+		(vdd->vp_reg.vlimitto_timeout <<
+		vdd->vp_reg.vlimitto_timeout_shift));
+	vdd->write_reg(vp_val, mod, vdd->vp_offs.vlimitto);
+}
+

Add comment for vdd_debugfs_init.

Quoted 21 lines

+static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)

arch/arm/mach-omap2/voltage.c new file +6 -0
+{
+	char *name;
+
+	name = kzalloc(VOLTAGE_DIR_SIZE, GFP_KERNEL);
+	if (!name) {
+		pr_warning("%s: Unable to allocate memory for

debugfs"

arch/arm/mach-omap2/voltage.c new file +8 -0
+			" directory name for vdd_%s",
+			__func__, vdd->voltdm.name);
+		return;
+	}
+	strcpy(name, "vdd_");
+	strcat(name, vdd->voltdm.name);
+
+	vdd->debug_dir = debugfs_create_dir(name,

voltage_dir);

arch/arm/mach-omap2/voltage.c new file +2 -0
+	if (IS_ERR(vdd->debug_dir)) {
+		pr_warning("%s: Unable to create debugfs

directory for"

arch/arm/mach-omap2/voltage.c line 355

Quoted 6 lines
arch/arm/mach-omap2/voltage.c new file +6 -0
+			" vdd_%s\n", __func__, vdd->voltdm.name);
+		vdd->debug_dir = NULL;
+	}
+}
+
+/* Voltage scale and accessory APIs */

Add comment for _pre_volt_scale.

Quoted 40 lines
arch/arm/mach-omap2/voltage.c new file +2 -0
+static int _pre_volt_scale(struct omap_vdd_info *vdd,
+		unsigned long target_volt, u8 *target_vsel, u8

*current_vsel)

arch/arm/mach-omap2/voltage.c new file +6 -0
+{
+	struct omap_volt_data *volt_data;
+	u32 vc_cmdval, vp_errgain_val;
+	u16 vp_mod, vc_mod;
+
+	/* Check if suffiecient pmic info is available for

this vdd */

arch/arm/mach-omap2/voltage.c new file +2 -0
+	if (!vdd->pmic_info) {
+		pr_err("%s: Insufficient pmic info to scale the

vdd_%s\n",

arch/arm/mach-omap2/voltage.c new file +6 -0
+			__func__, vdd->voltdm.name);
+		return -EINVAL;
+	}
+
+	if (!vdd->pmic_info->uv_to_vsel) {
+		pr_err("%s: PMIC function to convert voltage in

uV to"

arch/arm/mach-omap2/voltage.c new file +1 -0
+			"vsel not registered. Hence unable to

scale voltage"

arch/arm/mach-omap2/voltage.c new file +1 -0
+			"for vdd_%s\n", __func__, vdd-
Quoted 1 line

voltdm.name);

arch/arm/mach-omap2/voltage.c new file +5 -0
+		return -ENODATA;
+	}
+
+	if (!vdd->read_reg || !vdd->write_reg) {
+		pr_err("%s: No read/write API for accessing

vdd_%s regs\n",

arch/arm/mach-omap2/voltage.c new file +9 -0
+			__func__, vdd->voltdm.name);
+		return -EINVAL;
+	}
+
+	vp_mod = vdd->vp_reg.prm_mod;
+	vc_mod = vdd->vc_reg.prm_mod;
+
+	/* Get volt_data corresponding to target_volt */
+	volt_data = omap_voltage_get_voltdata(&vdd->voltdm,

target_volt);

arch/arm/mach-omap2/voltage.c line 389

Quoted 2 lines
arch/arm/mach-omap2/voltage.c new file +2 -0
+	if (IS_ERR(volt_data))
+		volt_data = NULL;

If there is an error on volt_data; return an error code. No need to continue with the rest of the processing.

Quoted 27 lines
arch/arm/mach-omap2/voltage.c new file +2 -0
+
+	*target_vsel = vdd->pmic_info-
Quoted 1 line

uv_to_vsel(target_volt);

arch/arm/mach-omap2/voltage.c new file +1 -0
+	*current_vsel = vdd->read_reg(vp_mod, vdd-
Quoted 1 line

vp_offs.voltage);

arch/arm/mach-omap2/voltage.c new file +3 -0
+
+	/* Setting the ON voltage to the new target voltage */
+	vc_cmdval = vdd->read_reg(vc_mod, vdd-
Quoted 1 line

vc_reg.cmdval_reg);

arch/arm/mach-omap2/voltage.c new file +2 -0
+	vc_cmdval &= ~vdd->vc_reg.cmd_on_mask;
+	vc_cmdval |= (*target_vsel << vdd-
Quoted 1 line

vc_reg.cmd_on_shift);

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->write_reg(vc_cmdval, vc_mod, vdd-
Quoted 1 line

vc_reg.cmdval_reg);

arch/arm/mach-omap2/voltage.c new file +6 -0
+
+	/* Setting vp errorgain based on the voltage */
+	if (volt_data) {
+		vp_errgain_val = vdd->read_reg(vp_mod,
+				vdd->vp_offs.vpconfig);
+		vdd->vp_reg.vpconfig_errorgain = volt_data-
Quoted 1 line

vp_errgain;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vp_errgain_val &= ~vdd-
Quoted 1 line

vp_reg.vpconfig_errorgain_mask;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vp_errgain_val |= vdd->vp_reg.vpconfig_errorgain

<<

arch/arm/mach-omap2/voltage.c new file +1 -0
+				vdd-
Quoted 1 line

vp_reg.vpconfig_errorgain_shift;

arch/arm/mach-omap2/voltage.c line 410

Quoted 3 lines
arch/arm/mach-omap2/voltage.c new file +3 -0
+		vdd->write_reg(vp_errgain_val, vp_mod,
+				vdd->vp_offs.vpconfig);
+	}

Recommend to take a snapshot of current vsel, cmdval_reg & errgain before setting the new values. Think of a mechanism to restore them in case the scaling function (called after _pre_volt_scale()) fails midway.

Check related comments in vp_forceupdate_scale_voltage() & vc_bypass_scale_voltage().

arch/arm/mach-omap2/voltage.c line 414

Quoted 4 lines
arch/arm/mach-omap2/voltage.c new file +4 -0
+
+	return 0;
+}
+

Add comment for _post_volt_scale.

Quoted 30 lines
arch/arm/mach-omap2/voltage.c new file +2 -0
+static void _post_volt_scale(struct omap_vdd_info *vdd,
+		unsigned long target_volt, u8 target_vsel, u8

current_vsel)

arch/arm/mach-omap2/voltage.c new file +6 -0
+{
+	u32 smps_steps = 0, smps_delay = 0;
+
+	smps_steps = abs(target_vsel - current_vsel);
+	/* SMPS slew rate / step size. 2us added as buffer. */
+	smps_delay = ((smps_steps * vdd->pmic_info->step_size)

/

arch/arm/mach-omap2/voltage.c new file +7 -0
+			vdd->pmic_info->slew_rate) + 2;
+	udelay(smps_delay);
+
+	vdd->curr_volt = target_volt;
+}
+
+/* vc_bypass_scale_voltage - VC bypass method of voltage

scaling */
+static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,

arch/arm/mach-omap2/voltage.c new file +9 -0
+		unsigned long target_volt)
+{
+	u32 loop_cnt = 0, retries_cnt = 0;
+	u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
+	u16 mod;
+	u8 target_vsel, current_vsel;
+	int ret;
+
+	ret = _pre_volt_scale(vdd, target_volt, &target_vsel,

&current_vsel);

arch/arm/mach-omap2/voltage.c

Quoted 2 lines
arch/arm/mach-omap2/voltage.c new file +2 -0
+	if (ret)
+		return ret;

This check is ineffective to handle error in case volt_data corresponding to the target voltage is not found as it returns 0.

Quoted 31 lines
arch/arm/mach-omap2/voltage.c new file +6 -0
+
+	mod = vdd->vc_reg.prm_mod;
+
+	vc_valid = vdd->vc_reg.valid;
+	vc_bypass_val_reg = vdd->vc_reg.bypass_val_reg;
+	vc_bypass_value = (target_vsel << vdd-
Quoted 1 line

vc_reg.data_shift) |

arch/arm/mach-omap2/voltage.c new file +6 -0
+			(vdd->pmic_info->pmic_reg <<
+			vdd->vc_reg.regaddr_shift) |
+			(vdd->pmic_info->i2c_slave_addr <<
+			vdd->vc_reg.slaveaddr_shift);
+
+	vdd->write_reg(vc_bypass_value, mod,

vc_bypass_val_reg);

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->write_reg(vc_bypass_value | vc_valid, mod,

vc_bypass_val_reg);

arch/arm/mach-omap2/voltage.c new file +2 -0
+
+	vc_bypass_value = vdd->read_reg(mod,

vc_bypass_val_reg);

arch/arm/mach-omap2/voltage.c new file +2 -0
+	/*
+	 * Loop till the bypass command is acknowledged from

the SMPS.

arch/arm/mach-omap2/voltage.c new file +1 -0
+	 * NOTE: This is legacy code. The loop count and retry

count needs

arch/arm/mach-omap2/voltage.c new file +7 -0
+	 * to be revisited.
+	 */
+	while (!(vc_bypass_value & vc_valid)) {
+		loop_cnt++;
+
+		if (retries_cnt > 10) {
+			pr_warning("%s: Retry count exceeded\n",
Quoted 1 line

__func__);

Recommend to restore the snapshot of vsel, cmdval_reg & errgain in _pre_volt_scale before returning an error.

This can be bit complicated as HW's exact state is not known.

Quoted 29 lines
arch/arm/mach-omap2/voltage.c new file +9 -0
+			return -ETIMEDOUT;
+		}
+
+		if (loop_cnt > 50) {
+			retries_cnt++;
+			loop_cnt = 0;
+			udelay(10);
+		}
+		vc_bypass_value = vdd->read_reg(mod,

vc_bypass_val_reg);

arch/arm/mach-omap2/voltage.c new file +3 -0
+	}
+
+	_post_volt_scale(vdd, target_volt, target_vsel,

current_vsel);

arch/arm/mach-omap2/voltage.c new file +5 -0
+	return 0;
+}
+
+/* VP force update method of voltage scaling */
+static int vp_forceupdate_scale_voltage(struct

omap_vdd_info *vdd,

arch/arm/mach-omap2/voltage.c new file +8 -0
+		unsigned long target_volt)
+{
+	u32 vpconfig;
+	u16 mod, ocp_mod;
+	u8 target_vsel, current_vsel, prm_irqst_reg;
+	int ret, timeout = 0;
+
+	ret = _pre_volt_scale(vdd, target_volt, &target_vsel,

&current_vsel);

arch/arm/mach-omap2/voltage.c

Quoted 2 lines
arch/arm/mach-omap2/voltage.c new file +2 -0
+	if (ret)
+		return ret;

This check is ineffective to handle error in case volt_data corresponding to the target voltage is not found as it returns 0.

Quoted 22 lines
arch/arm/mach-omap2/voltage.c new file +7 -0
+
+	mod = vdd->vp_reg.prm_mod;
+	ocp_mod = vdd->ocp_mod;
+	prm_irqst_reg = vdd->prm_irqst_reg;
+
+	/*
+	 * Clear all pending TransactionDone interrupt/status.

Typical latency

arch/arm/mach-omap2/voltage.c new file +12 -0
+	 * is <3us
+	 */
+	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+		vdd->write_reg(vdd->vp_reg.tranxdone_status,
+				ocp_mod, prm_irqst_reg);
+		if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) &
+				vdd->vp_reg.tranxdone_status))
+				break;
+		udelay(1);
+	}
+	if (timeout >= VP_TRANXDONE_TIMEOUT) {
+		pr_warning("%s: vdd_%s TRANXDONE timeout

exceeded."

arch/arm/mach-omap2/voltage.c new file +1 -0
+			"Voltage change aborted", __func__, vdd-
Quoted 1 line
Quoted 1 line

voltdm.name);

Recommend to restore the snapshot of vsel, cmdval_reg & errgain in _pre_volt_scale before returning an error.

This can be bit complicated as HW's exact state is not known.

Quoted 37 lines
arch/arm/mach-omap2/voltage.c new file +22 -0
+		return -ETIMEDOUT;
+	}
+
+	/* Configure for VP-Force Update */
+	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
+	vpconfig &= ~(vdd->vp_reg.vpconfig_initvdd |
+			vdd->vp_reg.vpconfig_forceupdate |
+			vdd->vp_reg.vpconfig_initvoltage_mask);
+	vpconfig |= ((target_vsel <<
+			vdd->vp_reg.vpconfig_initvoltage_shift));
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+
+	/* Trigger initVDD value copy to voltage processor */
+	vpconfig |= vdd->vp_reg.vpconfig_initvdd;
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+
+	/* Force update of voltage */
+	vpconfig |= vdd->vp_reg.vpconfig_forceupdate;
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+
+	/*
+	 * Wait for TransactionDone. Typical latency is

<200us.

arch/arm/mach-omap2/voltage.c new file +4 -0
+	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
+	 */
+	timeout = 0;
+	omap_test_timeout((vdd->read_reg(ocp_mod,

prm_irqst_reg) &

arch/arm/mach-omap2/voltage.c new file +5 -0
+			vdd->vp_reg.tranxdone_status),
+			VP_TRANXDONE_TIMEOUT, timeout);
+	if (timeout >= VP_TRANXDONE_TIMEOUT)
+		pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
+			"TRANXDONE never got set after the voltage

update\n",

arch/arm/mach-omap2/voltage.c new file +3 -0
+			__func__, vdd->voltdm.name);
+
+	_post_volt_scale(vdd, target_volt, target_vsel,
Quoted 1 line

current_vsel);

It is risky to assume voltage change has been successful in case TRANXDONE never got set after voltage update. Recommend to do a read of SMPS voltage for confirmation before proceeding further.

arch/arm/mach-omap2/voltage.c

Quoted 6 lines
arch/arm/mach-omap2/voltage.c new file +3 -0
+
+	/*
+	 * Disable TransactionDone interrupt , clear all

status, clear

arch/arm/mach-omap2/voltage.c new file +2 -0
+	 * control registers
+	 */

Check whether it is safe to disable TRANXDONE interrupt even if it didn't get set.

Quoted 294 lines
arch/arm/mach-omap2/voltage.c new file +12 -0
+	timeout = 0;
+	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+		vdd->write_reg(vdd->vp_reg.tranxdone_status,
+				ocp_mod, prm_irqst_reg);
+		if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) &
+				vdd->vp_reg.tranxdone_status))
+				break;
+		udelay(1);
+	}
+
+	if (timeout >= VP_TRANXDONE_TIMEOUT)
+		pr_warning("%s: vdd_%s TRANXDONE timeout

exceeded while trying"

arch/arm/mach-omap2/voltage.c new file +18 -0
+			"to clear the TRANXDONE status\n",
+			__func__, vdd->voltdm.name);
+
+	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
+	/* Clear initVDD copy trigger bit */
+	vpconfig &= ~vdd->vp_reg.vpconfig_initvdd;;
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	/* Clear force bit */
+	vpconfig &= ~vdd->vp_reg.vpconfig_forceupdate;
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+
+	return 0;
+}
+
+/* OMAP3 specific voltage init functions */
+
+/*
+ * Intializes the voltage controller registers with the

PMIC and board
+ * specific parameters and voltage setup times for OMAP3.
+ */

arch/arm/mach-omap2/voltage.c new file +9 -0
+static void __init omap3_vc_init(struct omap_vdd_info *vdd)
+{
+	u32 vc_val;
+	u16 mod;
+	u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
+	static bool is_initialized;
+
+	if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
+		pr_err("%s: PMIC info requried to configure vc

for"

arch/arm/mach-omap2/voltage.c new file +1 -0
+			"vdd_%s not populated.Hence cannot

initialize vc\n",

arch/arm/mach-omap2/voltage.c new file +6 -0
+			__func__, vdd->voltdm.name);
+		return;
+	}
+
+	if (!vdd->read_reg || !vdd->write_reg) {
+		pr_err("%s: No read/write API for accessing

vdd_%s regs\n",

arch/arm/mach-omap2/voltage.c new file +10 -0
+			__func__, vdd->voltdm.name);
+		return;
+	}
+
+	mod = vdd->vc_reg.prm_mod;
+
+	/* Set up the SMPS_SA(i2c slave address in VC */
+	vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_sa_reg);
+	vc_val &= ~vdd->vc_reg.smps_sa_mask;
+	vc_val |= vdd->pmic_info->i2c_slave_addr << vdd-
Quoted 1 line

vc_reg.smps_sa_shift;

arch/arm/mach-omap2/voltage.c new file +4 -0
+	vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_sa_reg);
+
+	/* Setup the VOLRA(pmic reg addr) in VC */
+	vc_val = vdd->read_reg(mod, vdd-
Quoted 1 line

vc_reg.smps_volra_reg);

arch/arm/mach-omap2/voltage.c new file +2 -0
+	vc_val &= ~vdd->vc_reg.smps_volra_mask;
+	vc_val |= vdd->pmic_info->pmic_reg << vdd-
Quoted 1 line

vc_reg.smps_volra_shift;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->write_reg(vc_val, mod, vdd-
Quoted 1 line

vc_reg.smps_volra_reg);

arch/arm/mach-omap2/voltage.c new file +3 -0
+
+	/*Configure the setup times */
+	vc_val = vdd->read_reg(mod, vdd-
Quoted 1 line

vc_reg.voltsetup_reg);

arch/arm/mach-omap2/voltage.c new file +4 -0
+	vc_val &= ~vdd->vc_reg.voltsetup_mask;
+	vc_val |= vdd->pmic_info->volt_setup_time <<
+			vdd->vc_reg.voltsetup_shift;
+	vdd->write_reg(vc_val, mod, vdd-
Quoted 1 line

vc_reg.voltsetup_reg);

arch/arm/mach-omap2/voltage.c new file +2 -0
+
+	/* Set up the on, inactive, retention and off voltage

*/

arch/arm/mach-omap2/voltage.c new file +1 -0
+	on_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info-
Quoted 1 line

on_volt);

arch/arm/mach-omap2/voltage.c new file +1 -0
+	onlp_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info-
Quoted 1 line

onlp_volt);

arch/arm/mach-omap2/voltage.c new file +1 -0
+	ret_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info-
Quoted 1 line

ret_volt);

arch/arm/mach-omap2/voltage.c new file +1 -0
+	off_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info-
Quoted 1 line

off_volt);

arch/arm/mach-omap2/voltage.c new file +11 -0
+	vc_val	= ((on_vsel << vdd->vc_reg.cmd_on_shift) |
+		(onlp_vsel << vdd->vc_reg.cmd_onlp_shift) |
+		(ret_vsel << vdd->vc_reg.cmd_ret_shift) |
+		(off_vsel << vdd->vc_reg.cmd_off_shift));
+	vdd->write_reg(vc_val, mod, vdd->vc_reg.cmdval_reg);
+
+	if (is_initialized)
+		return;
+
+	/* Generic VC parameters init */
+	vdd->write_reg(OMAP3430_CMD1_MASK |

OMAP3430_RAV1_MASK, mod,

arch/arm/mach-omap2/voltage.c new file +2 -0
+			OMAP3_PRM_VC_CH_CONF_OFFSET);
+	vdd->write_reg(OMAP3430_MCODE_SHIFT |

OMAP3430_HSEN_MASK, mod,

arch/arm/mach-omap2/voltage.c new file +2 -0
+			OMAP3_PRM_VC_I2C_CFG_OFFSET);
+	vdd->write_reg(OMAP3_CLKSETUP, mod,

OMAP3_PRM_CLKSETUP_OFFSET);

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->write_reg(OMAP3_VOLTOFFSET, mod,

OMAP3_PRM_VOLTOFFSET_OFFSET);

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->write_reg(OMAP3_VOLTSETUP2, mod,

OMAP3_PRM_VOLTSETUP2_OFFSET);

arch/arm/mach-omap2/voltage.c new file +5 -0
+	is_initialized = true;
+}
+
+/* Sets up all the VDD related info for OMAP3 */
+static int __init omap3_vdd_data_configure(struct

omap_vdd_info *vdd)

arch/arm/mach-omap2/voltage.c new file +6 -0
+{
+	struct clk *sys_ck;
+	u32 sys_clk_speed, timeout_val, waittime;
+
+	if (!vdd->pmic_info) {
+		pr_err("%s: PMIC info requried to configure

vdd_%s not"

arch/arm/mach-omap2/voltage.c new file +1 -0
+			"populated.Hence cannot initialize

vdd_%s\n",

arch/arm/mach-omap2/voltage.c new file +1 -0
+			__func__, vdd->voltdm.name, vdd-
Quoted 1 line

voltdm.name);

arch/arm/mach-omap2/voltage.c new file +6 -0
+		return -EINVAL;
+	}
+
+	if (!strcmp(vdd->voltdm.name, "mpu")) {
+		if (cpu_is_omap3630())
+			vdd->volt_data =

omap36xx_vddmpu_volt_data;

arch/arm/mach-omap2/voltage.c new file +2 -0
+		else
+			vdd->volt_data =

omap34xx_vddmpu_volt_data;

arch/arm/mach-omap2/voltage.c new file +2 -0
+
+		vdd->vp_reg.tranxdone_status =

OMAP3430_VP1_TRANXDONE_ST_MASK;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.cmdval_reg =

OMAP3_PRM_VC_CMD_VAL_0_OFFSET;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.smps_sa_shift =

OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.smps_sa_mask =

OMAP3430_PRM_VC_SMPS_SA_SA0_MASK;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.smps_volra_shift =

OMAP3430_VOLRA0_SHIFT;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.smps_volra_mask =

OMAP3430_VOLRA0_MASK;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.voltsetup_shift =

OMAP3430_SETUP_TIME1_SHIFT;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.voltsetup_mask =

OMAP3430_SETUP_TIME1_MASK;

arch/arm/mach-omap2/voltage.c new file +3 -0
+	} else if (!strcmp(vdd->voltdm.name, "core")) {
+		if (cpu_is_omap3630())
+			vdd->volt_data =

omap36xx_vddcore_volt_data;

arch/arm/mach-omap2/voltage.c new file +2 -0
+		else
+			vdd->volt_data =

omap34xx_vddcore_volt_data;

arch/arm/mach-omap2/voltage.c new file +2 -0
+
+		vdd->vp_reg.tranxdone_status =

OMAP3430_VP2_TRANXDONE_ST_MASK;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.cmdval_reg =

OMAP3_PRM_VC_CMD_VAL_1_OFFSET;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.smps_sa_shift =

OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.smps_sa_mask =

OMAP3430_PRM_VC_SMPS_SA_SA1_MASK;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.smps_volra_shift =

OMAP3430_VOLRA1_SHIFT;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.smps_volra_mask =

OMAP3430_VOLRA1_MASK;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.voltsetup_shift =

OMAP3430_SETUP_TIME2_SHIFT;

arch/arm/mach-omap2/voltage.c new file +1 -0
+		vdd->vc_reg.voltsetup_mask =

OMAP3430_SETUP_TIME2_MASK;

arch/arm/mach-omap2/voltage.c new file +2 -0
+	} else {
+		pr_warning("%s: vdd_%s does not exisit in

OMAP3\n",

arch/arm/mach-omap2/voltage.c new file +6 -0
+			__func__, vdd->voltdm.name);
+		return -EINVAL;
+	}
+
+	/*
+	 * Sys clk rate is require to calculate vp timeout

value and

arch/arm/mach-omap2/voltage.c new file +5 -0
+	 * smpswaittimemin and smpswaittimemax.
+	 */
+	sys_ck = clk_get(NULL, "sys_ck");
+	if (IS_ERR(sys_ck)) {
+		pr_warning("%s: Could not get the sys clk to

calculate"

arch/arm/mach-omap2/voltage.c new file +1 -0
+			"various vdd_%s params\n", __func__, vdd-
Quoted 1 line

voltdm.name);

arch/arm/mach-omap2/voltage.c new file +20 -0
+		return -EINVAL;
+	}
+	sys_clk_speed = clk_get_rate(sys_ck);
+	clk_put(sys_ck);
+	/* Divide to avoid overflow */
+	sys_clk_speed /= 1000;
+
+	/* Generic voltage parameters */
+	vdd->curr_volt = 1200000;
+	vdd->ocp_mod = OCP_MOD;
+	vdd->prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET;
+	vdd->read_reg = omap3_voltage_read_reg;
+	vdd->write_reg = omap3_voltage_write_reg;
+	vdd->volt_scale = vp_forceupdate_scale_voltage;
+	vdd->vp_enabled = false;
+
+	/* VC parameters */
+	vdd->vc_reg.prm_mod = OMAP3430_GR_MOD;
+	vdd->vc_reg.smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET;
+	vdd->vc_reg.smps_volra_reg =

OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->vc_reg.bypass_val_reg =

OMAP3_PRM_VC_BYPASS_VAL_OFFSET;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->vc_reg.voltsetup_reg =

OMAP3_PRM_VOLTSETUP1_OFFSET;

arch/arm/mach-omap2/voltage.c new file +2 -0
+	vdd->vc_reg.data_shift = OMAP3430_DATA_SHIFT;
+	vdd->vc_reg.slaveaddr_shift =

OMAP3430_SLAVEADDR_SHIFT;

arch/arm/mach-omap2/voltage.c new file +5 -0
+	vdd->vc_reg.regaddr_shift = OMAP3430_REGADDR_SHIFT;
+	vdd->vc_reg.valid = OMAP3430_VALID_MASK;
+	vdd->vc_reg.cmd_on_shift = OMAP3430_VC_CMD_ON_SHIFT;
+	vdd->vc_reg.cmd_on_mask = OMAP3430_VC_CMD_ON_MASK;
+	vdd->vc_reg.cmd_onlp_shift =

OMAP3430_VC_CMD_ONLP_SHIFT;

arch/arm/mach-omap2/voltage.c new file +7 -0
+	vdd->vc_reg.cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT;
+	vdd->vc_reg.cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT;
+
+	vdd->vp_reg.prm_mod = OMAP3430_GR_MOD;
+
+	/* VPCONFIG bit fields */
+	vdd->vp_reg.vpconfig_erroroffset = (vdd->pmic_info-
Quoted 1 line

vp_erroroffset <<

arch/arm/mach-omap2/voltage.c new file +2 -0
+				 OMAP3430_ERROROFFSET_SHIFT);
+	vdd->vp_reg.vpconfig_errorgain_mask =

OMAP3430_ERRORGAIN_MASK;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->vp_reg.vpconfig_errorgain_shift =

OMAP3430_ERRORGAIN_SHIFT;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->vp_reg.vpconfig_initvoltage_shift =

OMAP3430_INITVOLTAGE_SHIFT;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->vp_reg.vpconfig_initvoltage_mask =

OMAP3430_INITVOLTAGE_MASK;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->vp_reg.vpconfig_timeouten =

OMAP3430_TIMEOUTEN_MASK;

arch/arm/mach-omap2/voltage.c new file +2 -0
+	vdd->vp_reg.vpconfig_initvdd = OMAP3430_INITVDD_MASK;
+	vdd->vp_reg.vpconfig_forceupdate =

OMAP3430_FORCEUPDATE_MASK;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->vp_reg.vpconfig_vpenable =

OMAP3430_VPENABLE_MASK;

arch/arm/mach-omap2/voltage.c new file +3 -0
+
+	/* VSTEPMIN VSTEPMAX bit fields */
+	waittime = ((vdd->pmic_info->step_size / vdd-
Quoted 1 line

pmic_info->slew_rate) *

arch/arm/mach-omap2/voltage.c new file +4 -0
+				sys_clk_speed) / 1000;
+	vdd->vp_reg.vstepmin_smpswaittimemin = waittime;
+	vdd->vp_reg.vstepmax_smpswaittimemax = waittime;
+	vdd->vp_reg.vstepmin_stepmin = vdd->pmic_info-
Quoted 1 line

vp_vstepmin;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->vp_reg.vstepmax_stepmax = vdd->pmic_info-
Quoted 1 line

vp_vstepmax;

arch/arm/mach-omap2/voltage.c new file +5 -0
+	vdd->vp_reg.vstepmin_smpswaittimemin_shift =
+				OMAP3430_SMPSWAITTIMEMIN_SHIFT;
+	vdd->vp_reg.vstepmax_smpswaittimemax_shift =
+				OMAP3430_SMPSWAITTIMEMAX_SHIFT;
+	vdd->vp_reg.vstepmin_stepmin_shift =

OMAP3430_VSTEPMIN_SHIFT;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->vp_reg.vstepmax_stepmax_shift =

OMAP3430_VSTEPMAX_SHIFT;

arch/arm/mach-omap2/voltage.c new file +3 -0
+
+	/* VLIMITTO bit fields */
+	timeout_val = (sys_clk_speed * vdd->pmic_info-
Quoted 1 line

vp_timeout_us) / 1000;

arch/arm/mach-omap2/voltage.c new file +2 -0
+	vdd->vp_reg.vlimitto_timeout = timeout_val;
+	vdd->vp_reg.vlimitto_vddmin = vdd->pmic_info-
Quoted 1 line

vp_vddmin;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->vp_reg.vlimitto_vddmax = vdd->pmic_info-
Quoted 1 line

vp_vddmax;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->vp_reg.vlimitto_vddmin_shift =

OMAP3430_VDDMIN_SHIFT;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->vp_reg.vlimitto_vddmax_shift =

OMAP3430_VDDMAX_SHIFT;

arch/arm/mach-omap2/voltage.c new file +1 -0
+	vdd->vp_reg.vlimitto_timeout_shift =

OMAP3430_TIMEOUT_SHIFT;

arch/arm/mach-omap2/voltage.c

Quoted 3 lines
arch/arm/mach-omap2/voltage.c new file +3 -0
+
+	return 0;
+}

Big function. Recommend to simplify it by creating two data configure functions, one for vp and one for vc. And call them from omap3_vdd_data_configure().

Quoted 104 lines
arch/arm/mach-omap2/voltage.c new file +4 -0
+
+/* Public functions */
+/**
+ * omap_voltage_get_nom_volt() - Gets the current non-auto-

compensated voltage
+ * @voltdm: pointer to the VDD for which current
voltage info is needed
+ *
+ * API to get the current non-auto-compensated voltage for a VDD.
+ * Returns 0 in case of error else returns the current voltage for the VDD.
+ */
+unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm)

arch/arm/mach-omap2/voltage.c new file +5 -0
+{
+	struct omap_vdd_info *vdd;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not

exist!\n", __func__);

arch/arm/mach-omap2/voltage.c new file +4 -0
+		return 0;
+	}
+
+	vdd = container_of(voltdm, struct omap_vdd_info,

voltdm);

arch/arm/mach-omap2/voltage.c new file +6 -0
+
+	return vdd->curr_volt;
+}
+
+/**
+ * omap_vp_get_curr_volt() - API to get the current vp

voltage.
+ * @voltdm: pointer to the VDD.
+ *
+ * This API returns the current voltage for the specified voltage processor
+ */
+unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)

arch/arm/mach-omap2/voltage.c new file +6 -0
+{
+	struct omap_vdd_info *vdd;
+	u8 curr_vsel;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not

exist!\n", __func__);

arch/arm/mach-omap2/voltage.c new file +4 -0
+		return 0;
+	}
+
+	vdd = container_of(voltdm, struct omap_vdd_info,

voltdm);

arch/arm/mach-omap2/voltage.c new file +2 -0
+	if (!vdd->read_reg) {
+		pr_err("%s: No read API for reading vdd_%s

regs\n",

arch/arm/mach-omap2/voltage.c new file +9 -0
+			__func__, voltdm->name);
+		return 0;
+	}
+
+	curr_vsel = vdd->read_reg(vdd->vp_reg.prm_mod,
+			vdd->vp_offs.voltage);
+
+	if (!vdd->pmic_info || !vdd->pmic_info->vsel_to_uv) {
+		pr_warning("%s: PMIC function to convert vsel to

voltage"

arch/arm/mach-omap2/voltage.c new file +10 -0
+			"in uV not registerd\n", __func__);
+		return 0;
+	}
+
+	return vdd->pmic_info->vsel_to_uv(curr_vsel);
+}
+
+/**
+ * omap_vp_enable() - API to enable a particular VP
+ * @voltdm:	pointer to the VDD whose VP is to be

enabled.
+ *
+ * This API enables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */

arch/arm/mach-omap2/voltage.c new file +8 -0
+void omap_vp_enable(struct voltagedomain *voltdm)
+{
+	struct omap_vdd_info *vdd;
+	u32 vpconfig;
+	u16 mod;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not

exist!\n", __func__);

arch/arm/mach-omap2/voltage.c new file +4 -0
+		return;
+	}
+
+	vdd = container_of(voltdm, struct omap_vdd_info,

voltdm);

arch/arm/mach-omap2/voltage.c new file +2 -0
+	if (!vdd->read_reg || !vdd->write_reg) {
+		pr_err("%s: No read/write API for accessing

vdd_%s regs\n",

arch/arm/mach-omap2/voltage.c new file +6 -0
+			__func__, voltdm->name);
+		return;
+	}
+
+	mod = vdd->vp_reg.prm_mod;
+

arch/arm/mach-omap2/voltage.c line 871

Quoted 10 lines
arch/arm/mach-omap2/voltage.c new file +10 -0
+	/* If VP is already enabled, do nothing. Return */
+	if (vdd->vp_enabled)
+		return;
+
+	vp_latch_vsel(vdd);
+
+	/* Enable VP */
+	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
+	vpconfig |= vdd->vp_reg.vpconfig_vpenable;
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);

Check if there is a need for delay or status check (similar to omap_vp_disable) before flipping the status to true.

Quoted 314 lines
arch/arm/mach-omap2/voltage.c new file +6 -0
+	vdd->vp_enabled = true;
+}
+
+/**
+ * omap_vp_disable() - API to disable a particular VP
+ * @voltdm:	pointer to the VDD whose VP is to be

disabled.
+ *
+ * This API disables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */

arch/arm/mach-omap2/voltage.c new file +9 -0
+void omap_vp_disable(struct voltagedomain *voltdm)
+{
+	struct omap_vdd_info *vdd;
+	u32 vpconfig;
+	u16 mod;
+	int timeout;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not

exist!\n", __func__);

arch/arm/mach-omap2/voltage.c new file +4 -0
+		return;
+	}
+
+	vdd = container_of(voltdm, struct omap_vdd_info,

voltdm);

arch/arm/mach-omap2/voltage.c new file +2 -0
+	if (!vdd->read_reg || !vdd->write_reg) {
+		pr_err("%s: No read/write API for accessing

vdd_%s regs\n",

arch/arm/mach-omap2/voltage.c new file +9 -0
+			__func__, voltdm->name);
+		return;
+	}
+
+	mod = vdd->vp_reg.prm_mod;
+
+	/* If VP is already disabled, do nothing. Return */
+	if (!vdd->vp_enabled) {
+		pr_warning("%s: Trying to disable VP for vdd_%s

when"

arch/arm/mach-omap2/voltage.c new file +1 -0
+			"it is already disabled\n", __func__,

voltdm->name);

arch/arm/mach-omap2/voltage.c new file +10 -0
+		return;
+	}
+
+	/* Disable VP */
+	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
+	vpconfig &= ~vdd->vp_reg.vpconfig_vpenable;
+	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+
+	/*
+	 * Wait for VP idle Typical latency is <2us. Maximum

latency is ~100us

arch/arm/mach-omap2/voltage.c new file +2 -0
+	 */
+	omap_test_timeout((vdd->read_reg(mod, vdd-
Quoted 1 line

vp_offs.vstatus)),

arch/arm/mach-omap2/voltage.c new file +13 -0
+				VP_IDLE_TIMEOUT, timeout);
+
+	if (timeout >= VP_IDLE_TIMEOUT)
+		pr_warning("%s: vdd_%s idle timedout\n",
+			__func__, voltdm->name);
+
+	vdd->vp_enabled = false;
+
+	return;
+}
+
+/**
+ * omap_voltage_scale_vdd() - API to scale voltage of a

particular
+ * voltage domain.
+ * @voltdm: pointer to the VDD which is to be scaled.
+ * @target_volt: The target 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.
+ */

arch/arm/mach-omap2/voltage.c new file +7 -0
+int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
+		unsigned long target_volt)
+{
+	struct omap_vdd_info *vdd;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not

exist!\n", __func__);

arch/arm/mach-omap2/voltage.c new file +4 -0
+		return -EINVAL;
+	}
+
+	vdd = container_of(voltdm, struct omap_vdd_info,

voltdm);

arch/arm/mach-omap2/voltage.c new file +3 -0
+
+	if (!vdd->volt_scale) {
+		pr_err("%s: No voltage scale API registered for

vdd_%s\n",

arch/arm/mach-omap2/voltage.c new file +9 -0
+			__func__, voltdm->name);
+		return -ENODATA;
+	}
+
+	return vdd->volt_scale(vdd, target_volt);
+}
+
+/**
+ * omap_voltage_reset() - Resets the voltage of a

particular voltage domain
+ * to that of the current OPP.
+ * @voltdm: pointer to the VDD 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.
+ */

arch/arm/mach-omap2/voltage.c new file +6 -0
+void omap_voltage_reset(struct voltagedomain *voltdm)
+{
+	unsigned long target_uvdc;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not

exist!\n", __func__);

arch/arm/mach-omap2/voltage.c new file +6 -0
+		return;
+	}
+
+	target_uvdc = omap_voltage_get_nom_volt(voltdm);
+	if (!target_uvdc) {
+		pr_err("%s: unable to find current voltage for

vdd_%s\n",

arch/arm/mach-omap2/voltage.c new file +9 -0
+			__func__, voltdm->name);
+		return;
+	}
+
+	omap_voltage_scale_vdd(voltdm, target_uvdc);
+}
+
+/**
+ * omap_voltage_get_volttable() - API to get the voltage

table associated with a
+ * particular voltage domain.
+ * @voltdm: pointer to the VDD for which the voltage
table is required
+ * @volt_data: the voltage table for the particular vdd
which is to be
+ * populated by this API
+ *
+ * This API populates the voltage table associated with a VDD into the
+ * passed parameter pointer. Returns the count of distinct voltages
+ * supported by this vdd.
+ *
+ */
+void omap_voltage_get_volttable(struct voltagedomain *voltdm,

arch/arm/mach-omap2/voltage.c new file +6 -0
+		struct omap_volt_data **volt_data)
+{
+	struct omap_vdd_info *vdd;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not

exist!\n", __func__);

arch/arm/mach-omap2/voltage.c new file +4 -0
+		return;
+	}
+
+	vdd = container_of(voltdm, struct omap_vdd_info,

voltdm);

arch/arm/mach-omap2/voltage.c new file +6 -0
+
+	*volt_data = vdd->volt_data;
+}
+
+/**
+ * omap_voltage_get_voltdata() - API to get the voltage

table entry for a
+ * particular voltage
+ * @voltdm: pointer to the VDD whose voltage table has
to be searched
+ * @volt: the voltage to be searched in the voltage table
+ *
+ * This API searches through the voltage table for the required voltage
+ * domain and tries to find a matching entry for the passed voltage volt.
+ * If a matching entry is found volt_data is populated with that entry.
+ * This API searches only through the non-compensated voltages int the
+ * voltage table.
+ * Returns pointer to the voltage table entry corresponding to volt on
+ * sucess. Returns -ENODATA if no voltage table exisits for the passed voltage
+ * domain or if there is no matching entry.
+ */
+struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,

arch/arm/mach-omap2/voltage.c new file +7 -0
+		unsigned long volt)
+{
+	struct omap_vdd_info *vdd;
+	int i;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not

exist!\n", __func__);

arch/arm/mach-omap2/voltage.c new file +4 -0
+		return ERR_PTR(-EINVAL);
+	}
+
+	vdd = container_of(voltdm, struct omap_vdd_info,

voltdm);

arch/arm/mach-omap2/voltage.c new file +3 -0
+
+	if (!vdd->volt_data) {
+		pr_warning("%s: voltage table does not exist for

vdd_%s\n",

arch/arm/mach-omap2/voltage.c new file +5 -0
+			__func__, voltdm->name);
+		return ERR_PTR(-ENODATA);
+	}
+
+	for (i = 0; vdd->volt_data[i].volt_nominal != 0; i++)

{

arch/arm/mach-omap2/voltage.c new file +5 -0
+		if (vdd->volt_data[i].volt_nominal == volt)
+			return &vdd->volt_data[i];
+	}
+
+	pr_notice("%s: Unable to match the current voltage

with the voltage"

arch/arm/mach-omap2/voltage.c new file +7 -0
+		"table for vdd_%s\n", __func__, voltdm->name);
+
+	return ERR_PTR(-ENODATA);
+}
+
+/**
+ * omap_voltage_register_pmic() - API to register PMIC

specific data
+ * @voltdm: pointer to the VDD for which the PMIC
specific data is
+ * to be registered
+ * @pmic_info: the structure containing pmic info
+ *
+ * This API is to be called by the SOC/PMIC file to specify the
+ * pmic specific info as present in omap_volt_pmic_info structure.
+ */
+int omap_voltage_register_pmic(struct voltagedomain *voltdm,

arch/arm/mach-omap2/voltage.c new file +6 -0
+		struct omap_volt_pmic_info *pmic_info)
+{
+	struct omap_vdd_info *vdd;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not

exist!\n", __func__);

arch/arm/mach-omap2/voltage.c new file +4 -0
+		return -EINVAL;
+	}
+
+	vdd = container_of(voltdm, struct omap_vdd_info,

voltdm);

arch/arm/mach-omap2/voltage.c new file +8 -0
+
+	vdd->pmic_info = pmic_info;
+
+	return 0;
+}
+
+/**
+ * omap_voltage_get_dbgdir() - API to get pointer to the

debugfs directory
+ * corresponding to a voltage domain.
+ *
+ * @voltdm: pointer to the VDD whose debug directory
is required.
+ *
+ * This API returns pointer to the debugfs directory corresponding
+ * to the voltage domain. Should be used by drivers requiring to
+ * add any debug entry for a particular voltage domain. Returns NULL
+ * in case of error.
+ */
+struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm)

arch/arm/mach-omap2/voltage.c new file +5 -0
+{
+	struct omap_vdd_info *vdd;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not

exist!\n", __func__);

arch/arm/mach-omap2/voltage.c new file +4 -0
+		return NULL;
+	}
+
+	vdd = container_of(voltdm, struct omap_vdd_info,

voltdm);

arch/arm/mach-omap2/voltage.c new file +6 -0
+
+	return vdd->debug_dir;
+}
+
+/**
+ * omap_change_voltscale_method() - API to change the

voltage scaling method.
+ * @voltdm: pointer to the VDD whose voltage scaling
method
+ * has to be changed.
+ * @voltscale_method: the method to be used for voltage
scaling.
+ *
+ * This API can be used by the board files to change the method of voltage
+ * scaling between vpforceupdate and vcbypass. The parameter values are
+ * defined in voltage.h
+ */
+void omap_change_voltscale_method(struct voltagedomain *voltdm,

arch/arm/mach-omap2/voltage.c line 1122

Quoted 1 line
arch/arm/mach-omap2/voltage.c new file +1 -0
+		int voltscale_method)

Recommend to change the return type to int for better error handling.

Quoted 53 lines
arch/arm/mach-omap2/voltage.c new file +5 -0
+{
+	struct omap_vdd_info *vdd;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not

exist!\n", __func__);

arch/arm/mach-omap2/voltage.c new file +4 -0
+		return;
+	}
+
+	vdd = container_of(voltdm, struct omap_vdd_info,

voltdm);

arch/arm/mach-omap2/voltage.c new file +10 -0
+
+	switch (voltscale_method) {
+	case VOLTSCALE_VPFORCEUPDATE:
+		vdd->volt_scale = vp_forceupdate_scale_voltage;
+		return;
+	case VOLTSCALE_VCBYPASS:
+		vdd->volt_scale = vc_bypass_scale_voltage;
+		return;
+	default:
+		pr_warning("%s: Trying to change the method of

voltage scaling"

arch/arm/mach-omap2/voltage.c new file +6 -0
+			"to an unsupported one!\n", __func__);
+	}
+}
+
+/**
+ * omap_voltage_domain_lookup() - API to get the voltage

domain pointer
+ * @name: Name of the voltage domain
+ *
+ * This API looks up in the global vdd_info struct for the
+ * existence of voltage domain <name>. If it exists, the API returns
+ * a pointer to the voltage domain structure corresponding to the
+ * VDD<name>. Else retuns error pointer.
+ */
+struct voltagedomain *omap_voltage_domain_lookup(char *name)

arch/arm/mach-omap2/voltage.c new file +5 -0
+{
+	int i;
+
+	if (!vdd_info) {
+		pr_err("%s: Voltage driver init not yet

happened.Faulting!\n",

arch/arm/mach-omap2/voltage.c new file +6 -0
+			__func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!name) {
+		pr_err("%s: No name to get the votage

domain!\n", __func__);

arch/arm/mach-omap2/voltage.c line 1173

Quoted 7 lines
arch/arm/mach-omap2/voltage.c new file +7 -0
+		return ERR_PTR(-EINVAL);
+	}
+
+	for (i = 0; i < nr_scalable_vdd; i++) {
+		if (!(strcmp(name, vdd_info[i].voltdm.name)))
+			return &vdd_info[i].voltdm;
+	}

Print an error before returning.

Quoted 26 lines
arch/arm/mach-omap2/voltage.c new file +6 -0
+
+	return ERR_PTR(-EINVAL);
+}
+
+/**
+ * omap_voltage_late_init() - Init the various voltage

parameters
+ *
+ * This API is to be called in the later stages of the
+ * system boot to init the voltage controller and
+ * voltage processors.
+ */

arch/arm/mach-omap2/voltage.c new file +13 -0
+int __init omap_voltage_late_init(void)
+{
+	int i;
+
+	if (!vdd_info) {
+		pr_err("%s: Voltage driver support not added\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	voltage_dir = debugfs_create_dir("voltage", NULL);
+	if (IS_ERR(voltage_dir))
+		pr_err("%s: Unable to create voltage debugfs

main dir\n",

arch/arm/mach-omap2/voltage.c line 1201

Quoted 4 lines
arch/arm/mach-omap2/voltage.c new file +4 -0
+			__func__);
+	for (i = 0; i < nr_scalable_vdd; i++) {
+		if (vdd_data_configure(&vdd_info[i]))
+			continue;

Do error checking and print success/ fail message (especially fail) for each of vc_init, vp_init & vdd_debugfs_init. May need to change the return types of those functions.

A failure should stop further initialization.

Quoted 21 lines
arch/arm/mach-omap2/voltage.c new file +20 -0
+		vc_init(&vdd_info[i]);
+		vp_init(&vdd_info[i]);
+		vdd_debugfs_init(&vdd_info[i]);
+	}
+
+	return 0;
+}
+
+/**
+ * omap_voltage_early_init()- Volatage driver early init
+ */
+static int __init omap_voltage_early_init(void)
+{
+	if (cpu_is_omap34xx()) {
+		vdd_info = omap3_vdd_info;
+		nr_scalable_vdd = OMAP3_NR_SCALABLE_VDD;
+		vc_init = omap3_vc_init;
+		vdd_data_configure = omap3_vdd_data_configure;
+	} else {
+		pr_warning("%s: voltage driver support not

added\n", __func__);

arch/arm/mach-omap2/voltage.c line 413

Quoted 4 lines
arch/arm/mach-omap2/voltage.c new file +4 -0
+	}
+
+	return 0;
+}

Recommend to reorder the functions based on logical grouping of related functionalities e.g. all init/ configure functions can be listed together. A comment explaining these different groups and their constituent functions (located near the beginning) will be useful.

Quoted 22 lines
arch/arm/mach-omap2/voltage.c new file +1 -0
+core_initcall(omap_voltage_early_init);
arch/arm/plat-omap/include/plat/voltage.h new file +9 -0
new file mode 100644
index 0000000..2f4f59a
@@ -0,0 +1,134 @@
+/*
+ * OMAP Voltage Management Routines
+ *
+ * Author: Thara Gopinath	<[email protected]>
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ * Thara Gopinath <[email protected]>
+ *
+ * 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.
+ */

arch/arm/plat-omap/include/plat/voltage.h line 18

Quoted 6 lines
arch/arm/plat-omap/include/plat/voltage.h new file +6 -0
+
+#ifndef __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
+#define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
+
+#define VOLTSCALE_VPFORCEUPDATE		1
+#define VOLTSCALE_VCBYPASS		2

Add comment explaining the above #defines

Quoted 72 lines
arch/arm/plat-omap/include/plat/voltage.h new file +3 -0
+
+/*
+ * OMAP3 GENERIC setup times. Revisit to see if these needs

to be
+ * passed from board or PMIC file
+ */

arch/arm/plat-omap/include/plat/voltage.h new file +25 -0
+#define OMAP3_CLKSETUP		0xff
+#define OMAP3_VOLTOFFSET	0xff
+#define OMAP3_VOLTSETUP2	0xff
+
+/* Voltage value defines */
+#define OMAP3430_VDD_MPU_OPP1_UV		975000
+#define OMAP3430_VDD_MPU_OPP2_UV		1075000
+#define OMAP3430_VDD_MPU_OPP3_UV		1200000
+#define OMAP3430_VDD_MPU_OPP4_UV		1270000
+#define OMAP3430_VDD_MPU_OPP5_UV		1350000
+
+#define OMAP3430_VDD_CORE_OPP1_UV		975000
+#define OMAP3430_VDD_CORE_OPP2_UV		1050000
+#define OMAP3430_VDD_CORE_OPP3_UV		1150000
+
+#define OMAP3630_VDD_MPU_OPP50_UV		1012500
+#define OMAP3630_VDD_MPU_OPP100_UV		1200000
+#define OMAP3630_VDD_MPU_OPP120_UV		1325000
+#define OMAP3630_VDD_MPU_OPP1G_UV		1375000
+
+#define OMAP3630_VDD_CORE_OPP50_UV		1000000
+#define OMAP3630_VDD_CORE_OPP100_UV		1200000
+
+/**
+ * struct voltagedomain - omap voltage domain global

structure.
+ * @name: Name of the voltage domain which can be used as
a unique
+ * identifier.
+ */

arch/arm/plat-omap/include/plat/voltage.h new file +6 -0
+struct voltagedomain {
+	char *name;
+};
+
+/* API to get the voltagedomain pointer */
+struct voltagedomain *omap_voltage_domain_lookup(char

*name);

arch/arm/plat-omap/include/plat/voltage.h new file +5 -0
+
+/**
+ * struct omap_volt_data - Omap voltage specific data.
+ * @voltage_nominal:	The possible voltage value in uV
+ * @sr_efuse_offs:	The offset of the efuse

register(from system
+ * control module base address) from where to
read
+ * the n-target value for the smartreflex
module.
+ * @sr_errminlimit: Error min limit value for
smartreflex. This value
+ * differs at differnet opp and thus is
linked
+ * with voltage.
+ * @vp_errorgain: Error gain value for the voltage
processor. This
+ * field also differs according to the
voltage/opp.
+ */

arch/arm/plat-omap/include/plat/voltage.h new file +9 -0
+struct omap_volt_data {
+	u32	volt_nominal;
+	u32	sr_efuse_offs;
+	u8	sr_errminlimit;
+	u8	vp_errgain;
+};
+
+/**
+ * struct omap_volt_pmic_info - PMIC specific data required
Quoted 7 lines

by voltage driver.
+ * @slew_rate: PMIC slew rate (in uv/us)
+ * @step_size: PMIC voltage step size (in uv)
+ * @vsel_to_uv: PMIC API to convert vsel value to actual
voltage in uV.
+ * @uv_to_vsel: PMIC API to convert voltage in uV to vsel
value.

Add comments for the remaining data members.

Best Regards,

Anand Sawant

Quoted 62 lines

+ */

arch/arm/plat-omap/include/plat/voltage.h new file +21 -0
+struct omap_volt_pmic_info {
+	int slew_rate;
+	int step_size;
+	u32 on_volt;
+	u32 onlp_volt;
+	u32 ret_volt;
+	u32 off_volt;
+	u16 volt_setup_time;
+	u8 vp_erroroffset;
+	u8 vp_vstepmin;
+	u8 vp_vstepmax;
+	u8 vp_vddmin;
+	u8 vp_vddmax;
+	u8 vp_timeout_us;
+	u8 i2c_slave_addr;
+	u8 pmic_reg;
+	unsigned long (*vsel_to_uv) (const u8 vsel);
+	u8 (*uv_to_vsel) (unsigned long uV);
+};
+
+unsigned long omap_vp_get_curr_volt(struct voltagedomain

*voltdm);

arch/arm/plat-omap/include/plat/voltage.h new file +6 -0
+void omap_vp_enable(struct voltagedomain *voltdm);
+void omap_vp_disable(struct voltagedomain *voltdm);
+int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
+		unsigned long target_volt);
+void omap_voltage_reset(struct voltagedomain *voltdm);
+void omap_voltage_get_volttable(struct voltagedomain

*voltdm,

arch/arm/plat-omap/include/plat/voltage.h new file +2 -0
+		struct omap_volt_data **volt_data);
+struct omap_volt_data *omap_voltage_get_voltdata(struct

voltagedomain *voltdm,

arch/arm/plat-omap/include/plat/voltage.h new file +2 -0
+		unsigned long volt);
+unsigned long omap_voltage_get_nom_volt(struct

voltagedomain *voltdm);
+struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);

arch/arm/plat-omap/include/plat/voltage.h new file +2 -0
+#ifdef CONFIG_PM
+int omap_voltage_register_pmic(struct voltagedomain

*voltdm,

arch/arm/plat-omap/include/plat/voltage.h new file +2 -0
+		struct omap_volt_pmic_info *pmic_info);
+void omap_change_voltscale_method(struct voltagedomain

*voltdm,

arch/arm/plat-omap/include/plat/voltage.h new file +4 -0
+		int voltscale_method);
+int omap_voltage_late_init(void);
+#else
+static inline int omap_voltage_register_pmic(struct

voltagedomain *voltdm,

arch/arm/plat-omap/include/plat/voltage.h new file +2 -0
+		struct omap_volt_pmic_info *pmic_info) {}
+static inline  void omap_change_voltscale_method(struct

voltagedomain *voltdm,

arch/arm/plat-omap/include/plat/voltage.h new file +8 -1
+		int voltscale_method) {}
+static inline int omap_voltage_late_init(void)
+{
+	return -EINVAL;
+}
+#endif
+
+#endif
--

1.7.0.4

#4 lore raw

PATCH v6 2/10 OMAP: Introduce voltage domain information in the hwmod structures

In reply to Thara Gopinath

This patch extends the device hwmod structure to contain info about the voltage domain to which the device belongs to. This is needed to support a device based DVFS where the device knows which voltage domain it belongs to.

---
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
arch/arm/plat-omap/include/plat/omap_hwmod.h +5 -0
index 62bdb23..09c46c1 100644
@@ -34,6 +34,7 @@
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
 #include <plat/cpu.h>
+#include <plat/voltage.h>
 
 struct omap_device;
 
@@ -449,6 +450,8 @@ struct omap_hwmod_class {
  * @main_clk: main clock: OMAP clock name
  * @_clk: pointer to the main struct clk (filled in at runtime)
  * @opt_clks: other device clocks that drivers can request (0..*)
+ * @vdd_name: voltage domain name
+ * @voltdm: pointer to voltage domain (filled in at runtime)
  * @masters: ptr to array of OCP ifs that this hwmod can initiate on
  * @slaves: ptr to array of OCP ifs that this hwmod can respond on
  * @dev_attr: arbitrary device attributes that can be passed to the driver
@@ -491,6 +494,8 @@ struct omap_hwmod {
 	const char			*main_clk;
 	struct clk			*_clk;
 	struct omap_hwmod_opt_clk	*opt_clks;
+	char				*vdd_name;
+	struct voltagedomain		*voltdm;
 	struct omap_hwmod_ocp_if	**masters; /* connect to *_IA */
 	struct omap_hwmod_ocp_if	**slaves;  /* connect to *_TA */
 	void				*dev_attr;
Signature · 1 line
1.7.0.4
#5 lore raw

PATCH v6 3/10 OMAP3: PM: Adding smartreflex driver support.

In reply to Thara Gopinath

SmartReflex modules do adaptive voltage control for real-time voltage adjustments. With Smartreflex the power supply voltage can be adapted to the silicon performance(manufacturing process, temperature induced performance, age induced performance etc).

There are differnet classes of smartreflex implementation.
Class-0: Manufacturing Test Calibration
Class-1: Boot-Time Software Calibration
Class-2: Continuous Software Calibration
Class-3: Continuous Hardware Calibration
Class-4: Fully Integrated Power Management

OMAP3 has two smartreflex modules one associated with VDD MPU and the other associated with VDD CORE.
This patch adds support for smartreflex driver. The driver is designed for Class-1 , Class-2 and Class-3 support and is a platform driver. Smartreflex driver can be enabled through a Kconfig option "SmartReflex support" under "System type"->"TI OMAP implementations" menu.

Smartreflex autocompensation feature can be enabled runtime through a debug fs option.
To enable smartreflex autocompensation feature
echo 1 > /debug/voltage/vdd_<X>/smartreflex/autocomp
To disable smartreflex autocompensation feature
echo 0 > /debug/voltage/vdd_<X>/smartreflex/autocomp

where X can be mpu, core , iva etc.

This patch contains code originally in linux omap pm branch. Major contributors to this driver are
Lesly A M, Rajendra Nayak, Kalle Jokiniemi, Paul Walmsley, Nishant Menon, Kevin Hilman.

---
 arch/arm/mach-omap2/Makefile                  |    1 +
 arch/arm/mach-omap2/smartreflex.c             |  983 +++++++++++++++++++++++++
 arch/arm/plat-omap/Kconfig                    |   22 +
 arch/arm/plat-omap/include/plat/smartreflex.h |  245 ++++++
 4 files changed, 1251 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/smartreflex.c
 create mode 100644 arch/arm/plat-omap/include/plat/smartreflex.h
arch/arm/mach-omap2/Makefile +1 -0
index 5034797..b1bead0 100644
@@ -61,6 +61,7 @@ obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o voltage.o \
 					   cpuidle34xx.o pm_bus.o
 obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o pm_bus.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
+obj-$(CONFIG_OMAP_SMARTREFLEX)          += smartreflex.o
 
 AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
 AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a
arch/arm/mach-omap2/smartreflex.c new file +983 -0

983 lines not on this page · raw message

arch/arm/plat-omap/Kconfig +22 -0
index 92c5bb7..95ceca0 100644
@@ -35,6 +35,28 @@ config OMAP_DEBUG_LEDS
 	depends on OMAP_DEBUG_DEVICES
 	default y if LEDS_CLASS
 
+config OMAP_SMARTREFLEX
+	bool "SmartReflex support"
+	depends on ARCH_OMAP3 && PM
+	help
+	  Say Y if you want to enable SmartReflex.
+
+	  SmartReflex can perform continuous dynamic voltage
+	  scaling around the nominal operating point voltage
+	  according to silicon characteristics and operating
+	  conditions. Enabling SmartReflex reduces power
+	  consumption.
+
+	  Please note, that by default SmartReflex is only
+	  initialized. To enable the automatic voltage
+	  compensation for vdd mpu  and vdd core from user space,
+	  user must write 1 to
+		/debug/voltage/vdd_<X>/smartreflex/autocomp,
+	  where X is mpu or core for OMAP3.
+	  Optionallly autocompensation can be enabled in the kernel
+	  by default during system init via the enable_on_init flag
+	  which an be passed as platform data to the smartreflex driver.
+
 config OMAP_RESET_CLOCKS
 	bool "Reset unused clocks during boot"
 	depends on ARCH_OMAP
arch/arm/plat-omap/include/plat/smartreflex.h new file +245 -0

245 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#6 lore raw

PATCH v6 4/10 OMAP3: PM: Adding smartreflex device file.

In reply to Thara Gopinath

This patch adds support for device registration of various smartreflex module present in the system. This patch introduces the platform data for smartreflex devices which include the efused n-target vaules, a parameter to indicate whether smartreflex autocompensation needs to be enabled on init or not. An API omap_enable_smartreflex_on_init is provided for the board files to enable smartreflex autocompensation during system boot up.

---
 arch/arm/mach-omap2/Makefile    |    2 +-
 arch/arm/mach-omap2/pm.c        |    2 +
 arch/arm/mach-omap2/pm.h        |   13 ++++
 arch/arm/mach-omap2/sr_device.c |  131 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 147 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/sr_device.c
arch/arm/mach-omap2/Makefile +1 -1
index b1bead0..4e6adbd 100644
@@ -61,7 +61,7 @@ obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o voltage.o \
 					   cpuidle34xx.o pm_bus.o
 obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o pm_bus.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
-obj-$(CONFIG_OMAP_SMARTREFLEX)          += smartreflex.o
+obj-$(CONFIG_OMAP_SMARTREFLEX)          += sr_device.o smartreflex.o
 
 AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
 AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a
arch/arm/mach-omap2/pm.c +2 -0
index 22adfb2..a05f590 100644
@@ -21,6 +21,7 @@
 
 #include "powerdomain.h"
 #include "clockdomain.h"
+#include "pm.h"
 
 static struct omap_device_pm_latency *pm_lats;
 
@@ -149,6 +150,7 @@ postcore_initcall(omap2_common_pm_init);
 static int __init omap2_common_pm_late_init(void)
 {
 	omap_voltage_late_init();
+	omap_devinit_smartreflex();
 
 	return 0;
 }
arch/arm/mach-omap2/pm.h +13 -0
index 419c9d4..77d3ec2 100644
@@ -11,6 +11,8 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_PM_H
 #define __ARCH_ARM_MACH_OMAP2_PM_H
 
+#include <linux/err.h>
+
 #include "powerdomain.h"
 
 extern void *omap3_secure_ram_storage;
@@ -99,4 +101,15 @@ extern unsigned int save_secure_ram_context_sz;
 extern unsigned int omap24xx_cpu_suspend_sz;
 extern unsigned int omap34xx_cpu_suspend_sz;
 
+#ifdef CONFIG_OMAP_SMARTREFLEX
+extern int omap_devinit_smartreflex(void);
+extern void omap_enable_smartreflex_on_init(void);
+#else
+static inline int omap_devinit_smartreflex(void)
+{
+	return -EINVAL;
+}
+
+static inline void omap_enable_smartreflex_on_init(void) {}
+#endif
 #endif
arch/arm/mach-omap2/sr_device.c new file +131 -0

131 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#7 lore raw

PATCH v6 5/10 OMAP3: PM: Adding smartreflex hwmod data

In reply to Thara Gopinath

This patch adds the smartreflex hwmod data for OMAP3430 and OMAP3630.

---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |  176 ++++++++++++++++++++++++++++
 1 files changed, 176 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +176 -0
index 8eb81b4..c98cfc0 100644
@@ -21,6 +21,8 @@
 #include <plat/l4_3xxx.h>
 #include <plat/i2c.h>
 #include <plat/gpio.h>
+#include <plat/smartreflex.h>
+#include <plat/smartreflex.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -52,6 +54,8 @@ static struct omap_hwmod omap3xxx_gpio3_hwmod;
 static struct omap_hwmod omap3xxx_gpio4_hwmod;
 static struct omap_hwmod omap3xxx_gpio5_hwmod;
 static struct omap_hwmod omap3xxx_gpio6_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 omap3xxx_l3_main__l4_core = {
@@ -260,9 +264,47 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> SR1 interface */
+static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = {
+	{
+		.pa_start	= OMAP34XX_SR1_BASE,
+		.pa_end		= OMAP34XX_SR1_BASE + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__sr1 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap34xx_sr1_hwmod,
+	.clk		= "sr_l4_ick",
+	.addr		= omap3_sr1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3_sr1_addr_space),
+	.user		= OCP_USER_MPU,
+};
+
+/* L4 CORE -> SR1 interface */
+static struct omap_hwmod_addr_space omap3_sr2_addr_space[] = {
+	{
+		.pa_start	= OMAP34XX_SR2_BASE,
+		.pa_end		= OMAP34XX_SR2_BASE + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__sr2 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap34xx_sr2_hwmod,
+	.clk		= "sr_l4_ick",
+	.addr		= omap3_sr2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3_sr2_addr_space),
+	.user		= OCP_USER_MPU,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
 	&omap3xxx_l3_main__l4_core,
+	&omap3_l4_core__sr1,
+	&omap3_l4_core__sr2,
 };
 
 /* Master interfaces on the L4_CORE interconnect */
@@ -1092,6 +1134,135 @@ static struct omap_hwmod omap3xxx_gpio6_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
+/* SR common */
+static struct omap_hwmod_sysc_fields omap34xx_sr_sysc_fields = {
+	.clkact_shift	= 20,
+};
+
+static struct omap_hwmod_class_sysconfig omap34xx_sr_sysc = {
+	.sysc_offs	= 0x24,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_NO_CACHE),
+	.clockact	= CLOCKACT_TEST_ICLK,
+	.sysc_fields	= &omap34xx_sr_sysc_fields,
+};
+
+static struct omap_hwmod_class omap34xx_smartreflex_hwmod_class = {
+	.name = "smartreflex",
+	.sysc = &omap34xx_sr_sysc,
+	.rev  = 1,
+};
+
+static struct omap_hwmod_sysc_fields omap36xx_sr_sysc_fields = {
+	.sidle_shift	= 24,
+	.enwkup_shift	= 26
+};
+
+static struct omap_hwmod_class_sysconfig omap36xx_sr_sysc = {
+	.sysc_offs	= 0x38,
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
+			SYSC_NO_CACHE),
+	.sysc_fields	= &omap36xx_sr_sysc_fields,
+};
+
+static struct omap_hwmod_class omap36xx_smartreflex_hwmod_class = {
+	.name = "smartreflex",
+	.sysc = &omap36xx_sr_sysc,
+	.rev  = 2,
+};
+
+/* SR1 */
+static struct omap_hwmod_ocp_if *omap3_sr1_slaves[] = {
+	&omap3_l4_core__sr1,
+};
+
+static struct omap_hwmod omap34xx_sr1_hwmod = {
+	.name		= "sr1_hwmod",
+	.class		= &omap34xx_smartreflex_hwmod_class,
+	.main_clk	= "sr1_fck",
+	.vdd_name	= "mpu",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_SR1_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_SR1_SHIFT,
+		},
+	},
+	.slaves		= omap3_sr1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3_sr1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
+					CHIP_IS_OMAP3430ES3_0 |
+					CHIP_IS_OMAP3430ES3_1),
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
+};
+
+static struct omap_hwmod omap36xx_sr1_hwmod = {
+	.name		= "sr1_hwmod",
+	.class		= &omap36xx_smartreflex_hwmod_class,
+	.main_clk	= "sr1_fck",
+	.vdd_name	= "mpu",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_SR1_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_SR1_SHIFT,
+		},
+	},
+	.slaves		= omap3_sr1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3_sr1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+};
+
+/* SR2 */
+static struct omap_hwmod_ocp_if *omap3_sr2_slaves[] = {
+	&omap3_l4_core__sr2,
+};
+
+static struct omap_hwmod omap34xx_sr2_hwmod = {
+	.name		= "sr2_hwmod",
+	.class		= &omap34xx_smartreflex_hwmod_class,
+	.main_clk	= "sr2_fck",
+	.vdd_name	= "core",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_SR2_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_SR2_SHIFT,
+		},
+	},
+	.slaves		= omap3_sr2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3_sr2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
+					CHIP_IS_OMAP3430ES3_0 |
+					CHIP_IS_OMAP3430ES3_1),
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
+};
+
+static struct omap_hwmod omap36xx_sr2_hwmod = {
+	.name		= "sr2_hwmod",
+	.class		= &omap36xx_smartreflex_hwmod_class,
+	.main_clk	= "sr2_fck",
+	.vdd_name	= "core",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_SR2_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_SR2_SHIFT,
+		},
+	},
+	.slaves		= omap3_sr2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3_sr2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+};
+
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_l3_main_hwmod,
 	&omap3xxx_l4_core_hwmod,
@@ -1107,6 +1278,11 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_i2c1_hwmod,
 	&omap3xxx_i2c2_hwmod,
 	&omap3xxx_i2c3_hwmod,
+	&omap34xx_sr1_hwmod,
+	&omap34xx_sr2_hwmod,
+	&omap36xx_sr1_hwmod,
+	&omap36xx_sr2_hwmod,
+
 
 	/* gpio class */
 	&omap3xxx_gpio1_hwmod,
Signature · 1 line
1.7.0.4
#8 lore raw

PATCH v6 6/10 OMAP3: PM: Adding smartreflex class3 driver

In reply to Thara Gopinath

Smartreflex Class3 implementation continuously monitors silicon performance and instructs the Voltage Processors to increase or decrease the voltage.
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.

Class3 driver is chosen as the default class driver for smartreflex. If any other class driver needs to be implemented, the init of that driver should be called from the board file. That way the new class driver will over-ride the Class3 driver.

---
 arch/arm/mach-omap2/Makefile             |    1 +
 arch/arm/mach-omap2/smartreflex-class3.c |   59 ++++++++++++++++++++++++++++++
 arch/arm/plat-omap/Kconfig               |    9 +++++
 3 files changed, 69 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
arch/arm/mach-omap2/Makefile +1 -0
index 4e6adbd..1963f9e 100644
@@ -62,6 +62,7 @@ obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o voltage.o \
 obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o pm_bus.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 obj-$(CONFIG_OMAP_SMARTREFLEX)          += sr_device.o smartreflex.o
+obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)	+= smartreflex-class3.o
 
 AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
 AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a
arch/arm/mach-omap2/smartreflex-class3.c new file +59 -0

59 lines not on this page · raw message

arch/arm/plat-omap/Kconfig +9 -0
index 95ceca0..4029e6a 100644
@@ -57,6 +57,15 @@ config OMAP_SMARTREFLEX
 	  by default during system init via the enable_on_init flag
 	  which an be passed as platform data to the smartreflex driver.
 
+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 calibration.
+
 config OMAP_RESET_CLOCKS
 	bool "Reset unused clocks during boot"
 	depends on ARCH_OMAP
Signature · 1 line
1.7.0.4
#9 lore raw

PATCH v6 7/10 OMAP3: PM: Adding T2 enabling of smartreflex support

In reply to Thara Gopinath

This patch adds support in the twl4030 driver to enable smartreflex. The smartreflex bit on twl4030 needs to be enabled by default irrespective of whether smartreflex module is enabled on the OMAP side or not. This is because without this bit enabled the voltage scaling through vp forceupdate does not function properly.

---
 drivers/mfd/twl-core.c  |   13 +++++++++++++
 include/linux/i2c/twl.h |   11 +++++++++++
 2 files changed, 24 insertions(+), 0 deletions(-)
drivers/mfd/twl-core.c +13 -0
index 35275ba..b895ceb 100644
@@ -1046,6 +1046,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	/* Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface.
 	 * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0,
 	 * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0.
+	 * Also enable the smartreflex I2S bit.
 	 */
 
 	if (twl_class_is_4030()) {
@@ -1053,6 +1054,18 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \
 		I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU);
 		twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
+
+		/* The smartreflex bit on twl4030 needs to be enabled by
+		 * default irrespective of whether smartreflex module is
+		 * enabled on the OMAP side or not. This is because without
+		 * this bit enabled the voltage scaling through
+		 * vp forceupdate does not function properly.
+		 */
+		twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &temp,
+			TWL4030_PM_RECEIVER_DCDC_GLOBAL_CFG);
+		temp |= SMARTREFLEX_ENABLE;
+		twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, temp,
+			TWL4030_PM_RECEIVER_DCDC_GLOBAL_CFG);
 	}
 
 	status = add_children(pdata, id->driver_data);
include/linux/i2c/twl.h +11 -0
index c760991..d392f06 100644
@@ -434,6 +434,17 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
 
 /*----------------------------------------------------------------------*/
 
+/*
+ * PM Receiver module register offsets (use TWL4030_MODULE_PM_RECEIVER)
+ */
+
+#define TWL4030_PM_RECEIVER_DCDC_GLOBAL_CFG	0x06
+
+/* Smartreflex I2S bus enable/ vmode enable bit */
+#define SMARTREFLEX_ENABLE			BIT(3)
+
+/*----------------------------------------------------------------------*/
+
 /* Power bus message definitions */
 
 /* The TWL4030/5030 splits its power-management resources (the various
Signature · 1 line
1.7.0.4
#10 lore raw

PATCH v6 7/10 OMAP3: PM: Adding T2 enabling of smartreflex support

Hi Thara,

Quoted 5 lines · Thara Gopinath

This patch adds support in the twl4030 driver to enable smartreflex. The smartreflex bit on twl4030 needs to be enabled by default irrespective of whether smartreflex module is enabled on the OMAP side or not. This is because without this bit enabled the voltage scaling through vp forceupdate does not function properly.

Is this true for OMAP2 as well?

This patch actually hangs the boot on 2430SDP.

For now, I'll be dropping this patch from my pull request. Also, this patch will also need an Ack from the MFD maintainers, or possibly even merge through their tree. Please also Cc the MFD list on the fix.

While fixing this issue, another CodingStyle comment below...

Quoted 19 lines
---
 drivers/mfd/twl-core.c  |   13 +++++++++++++
 include/linux/i2c/twl.h |   11 +++++++++++
 2 files changed, 24 insertions(+), 0 deletions(-)
drivers/mfd/twl-core.c +1 -0
index 35275ba..b895ceb 100644
@@ -1046,6 +1046,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	/* Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface.
 	 * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0,
 	 * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0.
+	 * Also enable the smartreflex I2S bit.
 	 */
 
 	if (twl_class_is_4030()) {

drivers/mfd/twl-core.c twl_probe(struct i2c_client *client, const struct i2c_device_id *id) · line 1063

Quoted 10 lines
drivers/mfd/twl-core.c +7 -0
@@ -1053,6 +1054,18 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \
 		I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU);
 		twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
+
+		/* The smartreflex bit on twl4030 needs to be enabled by
+		 * default irrespective of whether smartreflex module is
+		 * enabled on the OMAP side or not. This is because without
+		 * this bit enabled the voltage scaling through
+		 * vp forceupdate does not function properly.
+		 */

please update multi-line coding style.

Kevin

Quoted 30 lines
drivers/mfd/twl-core.c +5 -0
+		twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &temp,
+			TWL4030_PM_RECEIVER_DCDC_GLOBAL_CFG);
+		temp |= SMARTREFLEX_ENABLE;
+		twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, temp,
+			TWL4030_PM_RECEIVER_DCDC_GLOBAL_CFG);
 	}
 
 	status = add_children(pdata, id->driver_data);
include/linux/i2c/twl.h +11 -0
index c760991..d392f06 100644
@@ -434,6 +434,17 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
 
 /*----------------------------------------------------------------------*/
 
+/*
+ * PM Receiver module register offsets (use TWL4030_MODULE_PM_RECEIVER)
+ */
+
+#define TWL4030_PM_RECEIVER_DCDC_GLOBAL_CFG	0x06
+
+/* Smartreflex I2S bus enable/ vmode enable bit */
+#define SMARTREFLEX_ENABLE			BIT(3)
+
+/*----------------------------------------------------------------------*/
+
 /* Power bus message definitions */
 
 /* The TWL4030/5030 splits its power-management resources (the various
#11 lore raw

PATCH v6 7/10 OMAP3: PM: Adding T2 enabling of smartreflex support

Quoted 18 lines
Quoted 18 lines

-----Original Message-----
From: Kevin Hilman [mailto:khilman at deeprootsystems.com]
Sent: Thursday, December 23, 2010 2:01 AM
To: Gopinath, Thara
Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org; paul at pwsan.com; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand; Menon, Nishanth
Subject: Re: [PATCH v6 07/10] OMAP3: PM: Adding T2 enabling of smartreflex support

Hi Thara,

Quoted 2 lines · Thara Gopinath

This patch adds support in the twl4030 driver to enable smartreflex. The smartreflex bit on twl4030 needs to be enabled by default

Quoted 8 lines
Quoted 8 lines

irrespective

Quoted 3 lines

of whether smartreflex module is enabled on the OMAP side or not. This is because without this bit enabled the voltage scaling through vp forceupdate does not function properly.

Is this true for OMAP2 as well?

This patch actually hangs the boot on 2430SDP.

Hello Kevin,

I tried the latest lo master with smartreflex module compiled in using
omap2plus_defconfig and this patch on OMAP2430 SDP and it boots
fine for me. Your pm-core branch does not boot for me with or without this
patch on OMAP2430 SDP. But then I am not sure if this is needed for OMAP2
also. Considering this might be a omap and twl4030 dependent setting, my idea is to move this code to mach-omap2/omap_twl.c. I will post a patch for the same shortly.

Regards
Thara

#12 lore raw

PATCH v6 7/10 OMAP3: PM: Adding T2 enabling of smartreflex support

Quoted 6 lines

From: linux-omap-owner at vger.kernel.org [mailto:linux-omap- owner at vger.kernel.org] On Behalf Of Gopinath, Thara
Sent: Friday, December 31, 2010 2:02 AM

Quoted 1 line
Quoted 1 line

Is this true for OMAP2 as well?

OMAP2 used VSEL for direct and VMODE for voltage control not SR path methods. I don't recall OMAP2 ever need to enable this as that path is not hooked up. I've not double checked details but that is recollection.

Quoted 1 line
Quoted 1 line
Quoted 1 line

This patch actually hangs the boot on 2430SDP.

There were a lot of versions of 2430SDP boards PMIC-boards which created a variety of issues of someone is really watching the details.

Issues which stopped booting as I recall in the past were:
- Initial state of interrupts not good allowing boot to livelock
- Old boards had poor power routing and min voltages needed to be higher.
- General i2c service thread issues.

I'd guess Thara has some random board with issues and Kevin's system is newer. Probably Kevin is seeing patch issue as SR doesn't seem to follow for OMAP2.

Regards,
Richard W.

#13 lore raw

PATCH v6 8/10 OMAP3: PM: Register TWL4030 pmic info with the voltage driver.

In reply to Thara Gopinath

This patch registers the TWL4030 PMIC specific informtion with the voltage driver. Failing this patch the voltage driver is unware of the formula to use for vsel to voltage and vice versa conversion and lot of other PMIC dependent parameters.

This file is based on the arch/arm/plat-omap opp_twl_tpl.c file by Paul Walmsley. The original file is replaced by this file.

---
 arch/arm/mach-omap2/Makefile   |    2 +
 arch/arm/mach-omap2/omap_twl.c |  111 ++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/pm.c       |    4 ++
 arch/arm/mach-omap2/pm.h       |   10 ++++
 4 files changed, 127 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/omap_twl.c
arch/arm/mach-omap2/Makefile +2 -0
index 1963f9e..ae29a00 100644
@@ -18,6 +18,8 @@ obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common)
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
+obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
+
 # SMP support ONLY available for OMAP4
 obj-$(CONFIG_SMP)			+= omap-smp.o omap-headsmp.o
 obj-$(CONFIG_LOCAL_TIMERS)		+= timer-mpu.o
arch/arm/mach-omap2/omap_twl.c new file +111 -0

111 lines not on this page · raw message

arch/arm/mach-omap2/pm.c +4 -0
index a05f590..e84f46b 100644
@@ -149,7 +149,11 @@ postcore_initcall(omap2_common_pm_init);
 
 static int __init omap2_common_pm_late_init(void)
 {
+	/* Init the OMAP TWL parameters */
+	omap3_twl_init();
+	/* Init the voltage layer */
 	omap_voltage_late_init();
+	/* Smartreflex device init */
 	omap_devinit_smartreflex();
 
 	return 0;
arch/arm/mach-omap2/pm.h +10 -0
index 77d3ec2..619db1b 100644
@@ -112,4 +112,14 @@ static inline int omap_devinit_smartreflex(void)
 
 static inline void omap_enable_smartreflex_on_init(void) {}
 #endif
+
+#ifdef CONFIG_TWL4030_CORE
+extern int omap3_twl_init(void);
+#else
+static inline int omap3_twl_init(void)
+{
+	return -EINVAL;
+}
+#endif
+
 #endif
Signature · 1 line
1.7.0.4
#14 lore raw

PATCH v6 9/10 OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

In reply to Thara Gopinath

This patch adds debug support to the voltage and smartreflex drivers. This means a whole bunch of voltage processor and smartreflex parameters are now visible through the pm debugfs.
The voltage parameters can be viewed at

        /debug/voltage/vdd_<x>/<parameter>

and the smartreflex parameters can be viewed at
/debug/voltage/vdd_<x>/smartreflex/<parameter>

Also smartreflex n-target values are now exposed out at
/debug/voltage/vdd_<x>/smartreflex/nvalue/<voltage>

The interface to access smartreflex n-target values is a read-write interface which means user has the flexibility to change the n-target values for any opp.

---
 arch/arm/mach-omap2/smartreflex.c |   46 ++++++++++++++++++++++++-
 arch/arm/mach-omap2/voltage.c     |   66 +++++++++++++++++++++++++++++++++++++
 2 files changed, 110 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/smartreflex.c +44 -2
index eee23d0..52a05b3 100644
@@ -31,6 +31,7 @@
 #include "pm.h"
 
 #define SMARTREFLEX_NAME_LEN	16
+#define NVALUE_NAME_LEN		40
 #define SR_DISABLE_TIMEOUT	200
 
 struct omap_sr {
@@ -817,8 +818,9 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 	struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
 	struct omap_sr_data *pdata = pdev->dev.platform_data;
 	struct resource *mem, *irq;
-	struct dentry *vdd_dbg_dir, *dbg_dir;
-	int ret = 0;
+	struct dentry *vdd_dbg_dir, *dbg_dir, *nvalue_dir;
+	struct omap_volt_data *volt_data;
+	int i, ret = 0;
 
 	if (!sr_info) {
 		dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
@@ -897,6 +899,46 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 
 	(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUGO, dbg_dir,
 				(void *)sr_info, &pm_sr_fops);
+	(void) debugfs_create_x32("errweight", S_IRUGO, dbg_dir,
+			&sr_info->err_weight);
+	(void) debugfs_create_x32("errmaxlimit", S_IRUGO, dbg_dir,
+			&sr_info->err_maxlimit);
+	(void) debugfs_create_x32("errminlimit", S_IRUGO, dbg_dir,
+			&sr_info->err_minlimit);
+
+	nvalue_dir = debugfs_create_dir("nvalue", dbg_dir);
+	if (IS_ERR(nvalue_dir)) {
+		dev_err(&pdev->dev, "%s: Unable to create debugfs directory"
+			"for n-values\n", __func__);
+		return PTR_ERR(nvalue_dir);
+	}
+
+	omap_voltage_get_volttable(sr_info->voltdm, &volt_data);
+	if (!volt_data) {
+		dev_warn(&pdev->dev, "%s: No Voltage table for the"
+			" corresponding vdd vdd_%s. Cannot create debugfs"
+			"entries for n-values\n",
+			__func__, sr_info->voltdm->name);
+		return -ENODATA;
+	}
+
+	for (i = 0; i < sr_info->nvalue_count; i++) {
+		char *name;
+		char volt_name[32];
+
+		name = kzalloc(NVALUE_NAME_LEN + 1, GFP_KERNEL);
+		if (!name) {
+			dev_err(&pdev->dev, "%s: Unable to allocate memory"
+				" for n-value directory name\n",  __func__);
+			return -ENOMEM;
+		}
+
+		strcpy(name, "volt_");
+		sprintf(volt_name, "%d", volt_data[i].volt_nominal);
+		strcat(name, volt_name);
+		(void) debugfs_create_x32(name, S_IRUGO | S_IWUGO, nvalue_dir,
+				&(sr_info->nvalue_table[i].nvalue));
+	}
 
 	return ret;
 
arch/arm/mach-omap2/voltage.c +66 -0

79 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#15 lore raw

PATCH v6 9/10 OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

Thara,

Few comments on the changes in voltage layer ...

Quoted 130 lines

-----Original Message-----
From: Thara Gopinath [mailto:thara at ti.com]
Sent: Monday, December 20, 2010 10:29 PM
To: linux-omap at vger.kernel.org; linux-arm- kernel at lists.infradead.org
Cc: khilman at deeprootsystems.com; paul at pwsan.com; b- cousson at ti.com; vishwanath.bs at ti.com; sawant at ti.com; nm at ti.com; Thara Gopinath
Subject: [PATCH v6 09/10] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

This patch adds debug support to the voltage and smartreflex drivers.
This means a whole bunch of voltage processor and smartreflex
parameters are now visible through the pm debugfs. The voltage parameters can be viewed at

        /debug/voltage/vdd_<x>/<parameter>

and the smartreflex parameters can be viewed at
/debug/voltage/vdd_<x>/smartreflex/<parameter>

Also smartreflex n-target values are now exposed out at
/debug/voltage/vdd_<x>/smartreflex/nvalue/<voltage>

The interface to access smartreflex n-target values is a read-write interface which means user has the flexibility to change the n-target values for any opp.

---
 arch/arm/mach-omap2/smartreflex.c |   46
++++++++++++++++++++++++-
 arch/arm/mach-omap2/voltage.c     |   66
+++++++++++++++++++++++++++++++++++++
 2 files changed, 110 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/smartreflex.c +4 -2
index eee23d0..52a05b3 100644
@@ -31,6 +31,7 @@
 #include "pm.h"
 
 #define SMARTREFLEX_NAME_LEN	16
+#define NVALUE_NAME_LEN		40
 #define SR_DISABLE_TIMEOUT	200
 
 struct omap_sr {
@@ -817,8 +818,9 @@ static int __init omap_sr_probe(struct
 platform_device *pdev)
 	struct omap_sr *sr_info = kzalloc(sizeof(struct
 omap_sr), GFP_KERNEL);
 	struct omap_sr_data *pdata = pdev->dev.platform_data;
 	struct resource *mem, *irq;
-	struct dentry *vdd_dbg_dir, *dbg_dir;
-	int ret = 0;
+	struct dentry *vdd_dbg_dir, *dbg_dir, *nvalue_dir;
+	struct omap_volt_data *volt_data;
+	int i, ret = 0;
 
arch/arm/mach-omap2/smartreflex.c +0 -0
 	if (!sr_info) {
 		dev_err(&pdev->dev, "%s: unable to allocate

sr_info\n",

arch/arm/mach-omap2/smartreflex.c +3 -0
@@ -897,6 +899,46 @@ static int __init omap_sr_probe(struct
 platform_device *pdev)
 
 	(void) debugfs_create_file("autocomp", S_IRUGO |
 S_IWUGO, dbg_dir,
 				(void *)sr_info, &pm_sr_fops);
+	(void) debugfs_create_x32("errweight", S_IRUGO,
 dbg_dir,
+			&sr_info->err_weight);
+	(void) debugfs_create_x32("errmaxlimit", S_IRUGO,

dbg_dir,

arch/arm/mach-omap2/smartreflex.c +2 -0
+			&sr_info->err_maxlimit);
+	(void) debugfs_create_x32("errminlimit", S_IRUGO,

dbg_dir,

arch/arm/mach-omap2/smartreflex.c +5 -0
+			&sr_info->err_minlimit);
+
+	nvalue_dir = debugfs_create_dir("nvalue", dbg_dir);
+	if (IS_ERR(nvalue_dir)) {
+		dev_err(&pdev->dev, "%s: Unable to create

debugfs directory"

arch/arm/mach-omap2/smartreflex.c +5 -0
+			"for n-values\n", __func__);
+		return PTR_ERR(nvalue_dir);
+	}
+
+	omap_voltage_get_volttable(sr_info->voltdm,

&volt_data);

arch/arm/mach-omap2/smartreflex.c +2 -0
+	if (!volt_data) {
+		dev_warn(&pdev->dev, "%s: No Voltage table for

the"

arch/arm/mach-omap2/smartreflex.c +1 -0
+			" corresponding vdd vdd_%s. Cannot create

debugfs"

arch/arm/mach-omap2/smartreflex.c +12 -0
+			"entries for n-values\n",
+			__func__, sr_info->voltdm->name);
+		return -ENODATA;
+	}
+
+	for (i = 0; i < sr_info->nvalue_count; i++) {
+		char *name;
+		char volt_name[32];
+
+		name = kzalloc(NVALUE_NAME_LEN + 1, GFP_KERNEL);
+		if (!name) {
+			dev_err(&pdev->dev, "%s: Unable to

allocate memory"

arch/arm/mach-omap2/smartreflex.c +1 -0
+				" for n-value directory name\n",

__func__);

arch/arm/mach-omap2/smartreflex.c +5 -0
+			return -ENOMEM;
+		}
+
+		strcpy(name, "volt_");
+		sprintf(volt_name, "%d",

volt_data[i].volt_nominal);

arch/arm/mach-omap2/smartreflex.c +2 -0
+		strcat(name, volt_name);
+		(void) debugfs_create_x32(name, S_IRUGO |

S_IWUGO, nvalue_dir,

arch/arm/mach-omap2/smartreflex.c +2 -0
+				&(sr_info->nvalue_table[i].nvalue));
+	}
 
 	return ret;
arch/arm/mach- renamed from arch/arm/mach-omap2/voltage.c +0 -0

omap2/voltage.c
index 875667f..b27fa4f 100644

arch/arm/mach-omap2/voltage.c static void omap3_voltage_write_reg(u32 · line 254

Quoted 5 lines
arch/arm/mach-omap2/voltage.c +1 -0
@@ -250,6 +250,47 @@ static void omap3_voltage_write_reg(u32
 val, u16 mod, u8 offset)
 	omap2_prm_write_mod_reg(val, mod, offset);
 }
 
+/* Voltage debugfs support */

Add comment for the function.

Quoted 18 lines
arch/arm/mach-omap2/voltage.c +15 -0
+static int vp_volt_debug_get(void *data, u64 *val)
+{
+	struct omap_vdd_info *vdd = (struct omap_vdd_info *)
 data;
+	u8 vsel;
+
+	if (!vdd) {
+		pr_warning("Wrong paramater passed\n");
+		return -EINVAL;
+	}
+
+	vsel = vdd->read_reg(vdd->vp_reg.prm_mod, vdd-
 >vp_offs.voltage);
+	pr_notice("curr_vsel = %x\n", vsel);
+
+	if (!vdd->pmic_info->vsel_to_uv) {
+		pr_warning("PMIC function to convert vsel to

voltage"

arch/arm/mach-omap2/voltage.c static void omap3_voltage_write_reg(u32 val, u16 mod, u8 offset) · line 276

Quoted 8 lines
arch/arm/mach-omap2/voltage.c +8 -0
+			"in uV not registerd\n");
+		return -EINVAL;
+	}
+
+	*val = vdd->pmic_info->vsel_to_uv(vsel);
+	return 0;
+}
+

Add comment for the function.

Quoted 65 lines
arch/arm/mach-omap2/voltage.c +3 -0
+static int nom_volt_debug_get(void *data, u64 *val)
+{
+	struct omap_vdd_info *vdd = (struct omap_vdd_info *)

data;

arch/arm/mach-omap2/voltage.c +12 -0
+
+	if (!vdd) {
+		pr_warning("Wrong paramater passed\n");
+		return -EINVAL;
+	}
+
+	*val = omap_voltage_get_nom_volt(&vdd->voltdm);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(vp_volt_debug_fops,

vp_volt_debug_get, NULL, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops,
nom_volt_debug_get, NULL,

arch/arm/mach-omap2/voltage.c +1 -0
+								"%llu\n");
 static void vp_latch_vsel(struct omap_vdd_info *vdd)
 {
 	u32 vpconfig;
@@ -349,7 +390,32 @@ static void __init
 vdd_debugfs_init(struct omap_vdd_info *vdd)
 		pr_warning("%s: Unable to create debugfs

directory for"

arch/arm/mach-omap2/voltage.c +3 -0
 			" vdd_%s\n", __func__, vdd->voltdm.name);
 		vdd->debug_dir = NULL;
+		return;
 	}
+
+	(void) debugfs_create_x16("vp_errorgain", S_IRUGO,

vdd->debug_dir,

arch/arm/mach-omap2/voltage.c +2 -0
+				&(vdd->vp_reg.vpconfig_errorgain));
+	(void) debugfs_create_x16("vp_smpswaittimemin",

S_IRUGO,

arch/arm/mach-omap2/voltage.c +2 -0
+				vdd->debug_dir,
+				&(vdd-
Quoted 1 line

vp_reg.vstepmin_smpswaittimemin));

arch/arm/mach-omap2/voltage.c +1 -0
+	(void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd-
Quoted 1 line

debug_dir,

arch/arm/mach-omap2/voltage.c +2 -0
+				&(vdd->vp_reg.vstepmin_stepmin));
+	(void) debugfs_create_x16("vp_smpswaittimemax",

S_IRUGO,

arch/arm/mach-omap2/voltage.c +2 -0
+				vdd->debug_dir,
+				&(vdd-
Quoted 1 line

vp_reg.vstepmax_smpswaittimemax));

arch/arm/mach-omap2/voltage.c +1 -0
+	(void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd-
Quoted 1 line

debug_dir,

arch/arm/mach-omap2/voltage.c +2 -0
+				&(vdd->vp_reg.vstepmax_stepmax));
+	(void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd-
Quoted 1 line

debug_dir,

arch/arm/mach-omap2/voltage.c +2 -0
+				&(vdd->vp_reg.vlimitto_vddmax));
+	(void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd-
Quoted 1 line

debug_dir,

arch/arm/mach-omap2/voltage.c +2 -0
+				&(vdd->vp_reg.vlimitto_vddmin));
+	(void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd-
Quoted 1 line

debug_dir,

arch/arm/mach-omap2/voltage.c +2 -0
+				&(vdd->vp_reg.vlimitto_timeout));
+	(void) debugfs_create_file("curr_vp_volt", S_IRUGO,

vdd->debug_dir,

arch/arm/mach-omap2/voltage.c +2 -0
+				(void *) vdd, &vp_volt_debug_fops);
+	(void) debugfs_create_file("curr_nominal_volt",

S_IRUGO,

arch/arm/mach-omap2/voltage.c static void __init vdd_debugfs_init(struct omap_vdd_info *vdd) · line 418

Quoted 2 lines
arch/arm/mach-omap2/voltage.c +2 -0
+				vdd->debug_dir, (void *) vdd,
+				&nom_volt_debug_fops);

Recommend to add support for vc cmdval & vc bypass_val.

Best Regards,

Anand Sawant

Quoted 5 lines

}

/* Voltage scale and accessory APIs */
--
1.7.0.4

#16 lore raw

PATCH v6 10/10 OMAP3: PM: Program correct init voltages for VDD1 and VDD2

In reply to Thara Gopinath

By default the system boots up at nominal voltage for every voltage domain in the system. This patch puts VDD1 and VDD2 to the correct boot up voltage as per the opp tables specified. This patch implements this by matching the rate of the main clock of the voltage domain with the opp table and picking up the correct voltage.

---
 arch/arm/mach-omap2/pm.c |   76 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 76 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/pm.c +76 -0
index e84f46b..cee86a5 100644
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/err.h>
+#include <linux/opp.h>
 
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
@@ -138,6 +139,76 @@ err:
 	return ret;
 }
 
+/*
+ * This API is to be called during init to put the various voltage
+ * domains to the voltage as per the opp table. Typically we boot up
+ * at the nominal voltage. So this function finds out the rate of
+ * the clock associated with the voltage domain, finds out the correct
+ * opp entry and puts the voltage domain to the voltage specifies
+ * in the opp entry
+ */
+static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
+						struct device *dev)
+{
+	struct voltagedomain *voltdm;
+	struct clk *clk;
+	struct opp *opp;
+	unsigned long freq, bootup_volt;
+
+	if (!vdd_name || !clk_name || !dev) {
+		printk(KERN_ERR "%s: Invalid parameters!\n", __func__);
+		goto exit;
+	}
+
+	voltdm = omap_voltage_domain_lookup(vdd_name);
+	if (IS_ERR(voltdm)) {
+		printk(KERN_ERR "%s: Unable to get vdd pointer for vdd_%s\n",
+			__func__, vdd_name);
+		goto exit;
+	}
+
+	clk =  clk_get(NULL, clk_name);
+	if (IS_ERR(clk)) {
+		printk(KERN_ERR "%s: unable to get clk %s\n",
+			__func__, clk_name);
+		goto exit;
+	}
+
+	freq = clk->rate;
+	clk_put(clk);
+
+	opp = opp_find_freq_ceil(dev, &freq);
+	if (IS_ERR(opp)) {
+		printk(KERN_ERR "%s: unable to find boot up OPP for vdd_%s\n",
+			__func__, vdd_name);
+		goto exit;
+	}
+
+	bootup_volt = opp_get_voltage(opp);
+	if (!bootup_volt) {
+		printk(KERN_ERR "%s: unable to find voltage corresponding"
+			"to the bootup OPP for vdd_%s\n", __func__, vdd_name);
+		goto exit;
+	}
+
+	omap_voltage_scale_vdd(voltdm, bootup_volt);
+	return 0;
+
+exit:
+	printk(KERN_ERR "%s: Unable to put vdd_%s to its init voltage\n\n",
+		__func__, vdd_name);
+	return -EINVAL;
+}
+
+static void __init omap3_init_voltages(void)
+{
+	if (!cpu_is_omap34xx())
+		return;
+
+	omap2_set_init_voltage("mpu", "dpll1_ck", mpu_dev);
+	omap2_set_init_voltage("core", "l3_ick", l3_dev);
+}
+
 static int __init omap2_common_pm_init(void)
 {
 	omap2_init_processor_devices();
@@ -151,8 +222,13 @@ static int __init omap2_common_pm_late_init(void)
 {
 	/* Init the OMAP TWL parameters */
 	omap3_twl_init();
+
 	/* Init the voltage layer */
 	omap_voltage_late_init();
+
+	/* Initialize the voltages */
+	omap3_init_voltages();
+
 	/* Smartreflex device init */
 	omap_devinit_smartreflex();
 
Signature · 1 line
1.7.0.4
#17 lore raw

v6 cover OMAP: Adding Smartreflex and Voltage driver support

In reply to Thara Gopinath
Quoted 3 lines · Thara Gopinath

This patch series introduces smartreflex and voltage driver support for OMAP3430 and OMAP3630. SmartReflex modules do adaptive voltage control for real-time voltage adjustments.

Thanks Thara, these are looking good for 2.6.38.

Tony, unless there are major objections, I'll be queuing these two SR series for 2.6.38. They have dependencies on Paul's integration branch so will wait 'til that stabilizies before sending pull request.

Kevin

Quoted 125 lines

Originally all the functionalities introduced in this patch were present in arch/arm/mach-omap2/smartreflex.c file in Kevin's pm tree. This patch series does a major rewrite of this file and introduces a separate voltage driver. Major contributors to the original driver are

Eduardo Valentin (1):
OMAP3: PM: SmartReflex: Fix scheduled while atomic problem

Kalle Jokiniemi (1):
OMAP3: PM: SmartReflex driver integration

Kevin Hilman (2):
temp: SR: IO_ADDRESS conversion
OMAP: SR: OPP interfaces removed from OMAP PM layer

Nishanth Menon (1):
omap3: pm: sr: replace get_opp with freq_to_opp

Paul Walmsley (2):
OMAP SR: use opp_find_opp_by_opp_id()
OMAP SR: use OPP API for OPP ID, remove direct access

Phil Carmody (2):
OMAP3: PM: Don't do unnecessary searches in omap_sr_vdd*_autocomp_store
OMAP3: PM: Early exit on invalid parameters

Rajendra Nayak (9):
OMAP3: SR: Fix init voltage on OPP change
OMAP3: SR: Update VDD1/2 voltages at boot
OMAP3: SR: Use sysclk for SR CLKLENGTH calc
OMAP3: SR: Reset voltage level on SR disable
OMAP3: SR: Replace printk's with pr_* calls
OMAP3: SR: Remove redundant defines
OMAP3: SR: Fix SR driver to check for omap-pm return values
OMAP3: PM: Put optimal SMPS stabilization delay
OMAP3: SR: Wait for VP idle before a VP disable

Roger Quadros (4):
OMAP3: PM: Fix Smartreflex when used with PM_NOOP layer
OMAP3: PM: Make Smartreflex driver independent of SRF
OMAP3: PM: Do not Enable SmartReflex if OPP tables not defined
OMAP3: PM: Smartreflex: Fix VDD2 OPP determining logic

Romit Dasgupta (1):
omap: pm: SR: use enum for OPP types

Teerth Reddy (1):
OMAP3: SR: Replace SR_PASS/FAIL,SR_TRUE/FALSE

Tero Kristo (1):
Smartreflex: Avoid unnecessary spam

This patch series is against pm-core branch of Kevin Hilman's OMAP PM tree with the following additional patch applied.

	https://patchwork.kernel.org/patch/421351/

The entire series with the dependencies are available at
http://dev.omapzoom.org/?p=thara/omap-dvfs.git;a=summary
head: kevin-pm-sr

This patch series has been tested on OMAP3430 SDP with omap2plus_defconfig with the following menuconfig options enabled.
System type -> TI OMAP Implementations -> Smartreflex Support System type -> TI OMAP Implementations ->
Class 3 mode of Smartreflex Implementation

Major Changes in v6
-Rebased to pm-core branch of Kevin Hilman's OMAP PM tree.

Major Changes in v5
- Rebased to k.org 2.6.37-rc3
- Rebased to Nishant Menon's latest opp patches
- Voltage pmic info structure extended to include a vast set of PMIC dependent parameters.
- Smartreflex software n-target values support removed from the kernel. Instead n-target values are exposed as debugfs entries which can be written into by the user if needed.
- Introduced a new file arch/arm/mach-omap2/omap_twl.c for specifying OMAP and TWL related info for the voltage layer.
- Remove default enabling of smartreflex autocompensation during boot on OMAP3430 ES3.1 chips. Instead an API is provided that can be called from board files in case autocompensation needs to be enabled during boot up itself.
- Other review comments on v4

Thara Gopinath (10):
OMAP3: PM: Adding voltage driver support.
OMAP: Introduce voltage domain information in the hwmod structures
OMAP3: PM: Adding smartreflex driver support.
OMAP3: PM: Adding smartreflex device file.
OMAP3: PM: Adding smartreflex hwmod data
OMAP3: PM: Adding smartreflex class3 driver
OMAP3: PM: Adding T2 enabling of smartreflex support
OMAP3: PM: Register TWL4030 pmic info with the voltage driver.
OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers
OMAP3: PM: Program correct init voltages for VDD1 and VDD2

 arch/arm/mach-omap2/Makefile                  |    7 +-
 arch/arm/mach-omap2/control.h                 |   17 +
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c    |  176 ++++
 arch/arm/mach-omap2/omap_twl.c                |  111 +++
 arch/arm/mach-omap2/pm.c                      |   90 ++
 arch/arm/mach-omap2/pm.h                      |   23 +
 arch/arm/mach-omap2/smartreflex-class3.c      |   59 ++
 arch/arm/mach-omap2/smartreflex.c             | 1025 ++++++++++++++++++++
 arch/arm/mach-omap2/sr_device.c               |  131 +++
 arch/arm/mach-omap2/voltage.c                 | 1292 +++++++++++++++++++++++++
 arch/arm/plat-omap/Kconfig                    |   31 +
 arch/arm/plat-omap/include/plat/omap_hwmod.h  |    5 +
 arch/arm/plat-omap/include/plat/smartreflex.h |  245 +++++
 arch/arm/plat-omap/include/plat/voltage.h     |  134 +++
 drivers/mfd/twl-core.c                        |   13 +
 include/linux/i2c/twl.h                       |   11 +
 16 files changed, 3369 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/omap_twl.c
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
 create mode 100644 arch/arm/mach-omap2/smartreflex.c
 create mode 100644 arch/arm/mach-omap2/sr_device.c
 create mode 100644 arch/arm/mach-omap2/voltage.c
 create mode 100644 arch/arm/plat-omap/include/plat/smartreflex.h
 create mode 100644 arch/arm/plat-omap/include/plat/voltage.h
maintainer
#18 lore raw

v6 cover OMAP: Adding Smartreflex and Voltage driver support

Quoted 10 lines · Kevin Hilman
Quoted 3 lines · Thara Gopinath

This patch series introduces smartreflex and voltage driver support for OMAP3430 and OMAP3630. SmartReflex modules do adaptive voltage control for real-time voltage adjustments.

Thanks Thara, these are looking good for 2.6.38.

Tony, unless there are major objections, I'll be queuing these two SR series for 2.6.38. They have dependencies on Paul's integration branch

Well looking at patch 3/6 I think it should live under drivers somewhere and mostly be compiled as a module. Probably the only change needed for that is to not call cpu_is_omapxxxx but instead use some flags passed in the platform_data. Otherwise the whole series looks OK to me.

Regards,

Tony

maintainer
#19 lore raw

v6 cover OMAP: Adding Smartreflex and Voltage driver support

Quoted 9 lines · Tony Lindgren
Quoted 8 lines · Kevin Hilman
Quoted 3 lines · Thara Gopinath

This patch series introduces smartreflex and voltage driver support for OMAP3430 and OMAP3630. SmartReflex modules do adaptive voltage control for real-time voltage adjustments.

Thanks Thara, these are looking good for 2.6.38.

Quoted 7 lines
Quoted 2 lines

Tony, unless there are major objections, I'll be queuing these two SR series for 2.6.38. They have dependencies on Paul's integration branch

Well looking at patch 3/6 I think it should live under drivers somewhere and mostly be compiled as a module. Probably the only change needed for that is to not call cpu_is_omapxxxx but instead use some flags passed in the platform_data. Otherwise the whole series looks OK to me.

Considering the short time left, maybe you can leave out the driver part for now and merge all the platform related part for smartreflex?

Sorry I really should have made that driver comment way earlier..

Regards,

Tony

#20 lore raw

v6 cover OMAP: Adding Smartreflex and Voltage driver support

In reply to Tony Lindgren
Quoted 9 lines · Tony Lindgren
Quoted 8 lines · Kevin Hilman
Quoted 3 lines · Thara Gopinath

This patch series introduces smartreflex and voltage driver support for OMAP3430 and OMAP3630. SmartReflex modules do adaptive voltage control for real-time voltage adjustments.

Thanks Thara, these are looking good for 2.6.38.

Quoted 7 lines
Quoted 2 lines

Tony, unless there are major objections, I'll be queuing these two SR series for 2.6.38. They have dependencies on Paul's integration branch

Well looking at patch 3/6 I think it should live under drivers somewhere and mostly be compiled as a module. Probably the only change needed for that is to not call cpu_is_omapxxxx but instead use some flags passed in the platform_data. Otherwise the whole series looks OK to me.

Moving this to be a regulator driver is part of the medium-term plan, and is already under development. For this phase, we just split up the current driver into device and driver code and left under mach-omap2. We are investigating (and making) changes to the regulator core so that SmartReflex can be converted into a real regulator driver, but that is still under development.

So, in the mean time, I'd like to merge this version so that other development that depends on this (the regulator work mentioned above, the DVFS work, etc.) can have a stable starting point.

Kevin

maintainer
#21 lore raw

v6 cover OMAP: Adding Smartreflex and Voltage driver support

Quoted 26 lines · Kevin Hilman
Quoted 9 lines · Tony Lindgren
Quoted 8 lines · Kevin Hilman
Quoted 3 lines · Thara Gopinath

This patch series introduces smartreflex and voltage driver support for OMAP3430 and OMAP3630. SmartReflex modules do adaptive voltage control for real-time voltage adjustments.

Thanks Thara, these are looking good for 2.6.38.

Quoted 7 lines
Quoted 2 lines

Tony, unless there are major objections, I'll be queuing these two SR series for 2.6.38. They have dependencies on Paul's integration branch

Well looking at patch 3/6 I think it should live under drivers somewhere and mostly be compiled as a module. Probably the only change needed for that is to not call cpu_is_omapxxxx but instead use some flags passed in the platform_data. Otherwise the whole series looks OK to me.

Moving this to be a regulator driver is part of the medium-term plan, and is already under development. For this phase, we just split up the current driver into device and driver code and left under mach-omap2. We are investigating (and making) changes to the regulator core so that SmartReflex can be converted into a real regulator driver, but that is still under development.

Quoted 3 lines

So, in the mean time, I'd like to merge this version so that other development that depends on this (the regulator work mentioned above, the DVFS work, etc.) can have a stable starting point.

OK up to you.

Tony