Skip to contentSkip to conversation

OMAP3: Adding Smartreflex and Voltage driver support

PATCH Superseded Thara Gopinath 5 participants 56 messages Sep 22, 2010 – Nov 10, 2010 1 message not in the archive

Subsystems (6)

v3 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

v3 cover OMAP3: Adding Smartreflex and Voltage driver support

From: thara gopinath <[email protected]>

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 based against origin/pm-core branch off Kevin's pm tree which in turn is based off lo-master. This series will apply against lo-master also but will break compilation due to lack of opp framework support on lo-master.

This patch series has been tested on OMAP3430 SDP with the extra five patches from origin/cpufreq branch off Kevin's pm tree applied. This series has been tested with with omap3_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

Thara Gopinath (11):
OMAP: PM: Export the main pm debugfs directory
OMAP3: PM: Adding voltage driver support for OMAP3
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: Adding debug support to Voltage and Smartreflex drivers
OMAP3: PM: Smartreflex Class3 initialization from board files.
OMAP3: PM: Program correct init voltages for VDD1 and VDD2
OMAP3: PM: Register TWL4030 pmic info with the voltage driver.

 arch/arm/mach-omap2/Makefile                  |    5 +-
 arch/arm/mach-omap2/board-3430sdp.c           |    2 +
 arch/arm/mach-omap2/board-zoom-peripherals.c  |    2 +
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c    |  249 +++++
 arch/arm/mach-omap2/pm-debug.c                |   18 +
 arch/arm/mach-omap2/pm.c                      |   67 ++-
 arch/arm/mach-omap2/pm.h                      |    1 +
 arch/arm/mach-omap2/smartreflex-class3.c      |   61 ++
 arch/arm/mach-omap2/smartreflex-class3.h      |   23 +
 arch/arm/mach-omap2/smartreflex.c             | 1039 +++++++++++++++++++
 arch/arm/mach-omap2/sr_device.c               |  174 ++++
 arch/arm/mach-omap2/voltage.c                 | 1319 +++++++++++++++++++++++++
 arch/arm/plat-omap/Kconfig                    |   41 +
 arch/arm/plat-omap/include/plat/control.h     |   27 +
 arch/arm/plat-omap/include/plat/smartreflex.h |  276 ++++++
 arch/arm/plat-omap/include/plat/voltage.h     |  141 +++
 arch/arm/plat-omap/opp_twl_tps.c              |   17 +
 drivers/mfd/twl-core.c                        |    7 +-
 drivers/mfd/twl4030-power.c                   |   29 +
 include/linux/i2c/twl.h                       |    1 +
 20 files changed, 3495 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.h
 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
Signature · 1 line
1.7.1.GIT
#1 lore raw

PATCH v3 1/11 OMAP: PM: Export the main pm debugfs directory

This patch makes generic pm_debug directory global so that other drivers can include it and use it to create sub-entries.

---
 arch/arm/mach-omap2/pm-debug.c |    3 +++
 arch/arm/mach-omap2/pm.h       |    1 +
 2 files changed, 4 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/pm-debug.c +3 -0
index af00c17..390f1c6 100644
@@ -42,6 +42,7 @@ u32 enable_off_mode;
 u32 sleep_while_idle;
 u32 wakeup_timer_seconds;
 u32 wakeup_timer_milliseconds;
+struct dentry *pm_dbg_main_dir;
 
 #define DUMP_PRM_MOD_REG(mod, reg)    \
 	regs[reg_count].name = #mod "." #reg; \
@@ -641,6 +642,8 @@ static int __init pm_dbg_init(void)
 	(void) debugfs_create_file("wakeup_timer_milliseconds",
 			S_IRUGO | S_IWUGO, d, &wakeup_timer_milliseconds,
 			&pm_dbg_option_fops);
+
+	pm_dbg_main_dir = d;
 	pm_dbg_init_done = 1;
 
 	return 0;
arch/arm/mach-omap2/pm.h +1 -0
index f3ba1e6..c06cedd 100644
@@ -55,6 +55,7 @@ extern int omap2_pm_debug;
 #define omap2_pm_dump(mode, resume, us)		do {} while (0);
 #define omap2_pm_wakeup_on_timer(seconds, milliseconds)	do {} while (0);
 #define omap2_pm_debug				0
+#define pm_dbg_main_dir				0
 #endif
 
 #if defined(CONFIG_CPU_IDLE)
Signature · 1 line
1.7.1.GIT
#2 lore raw

Re: [PATCH v3 01/11] OMAP: PM: Export the main pm debugfs directory

Quoted 3 lines · Thara

This patch makes generic pm_debug directory global so that other drivers can include it and use it to create sub-entries.

That should not be needed, if we expose voltage debugfs entry in the top level directly.

Benoit

Quoted 40 lines
---
  arch/arm/mach-omap2/pm-debug.c |    3 +++
  arch/arm/mach-omap2/pm.h       |    1 +
  2 files changed, 4 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/pm-debug.c +3 -0
index af00c17..390f1c6 100644
@@ -42,6 +42,7 @@ u32 enable_off_mode;
  u32 sleep_while_idle;
  u32 wakeup_timer_seconds;
  u32 wakeup_timer_milliseconds;
+struct dentry *pm_dbg_main_dir;
 
  #define DUMP_PRM_MOD_REG(mod, reg)    \
  	regs[reg_count].name = #mod "." #reg; \
@@ -641,6 +642,8 @@ static int __init pm_dbg_init(void)
  	(void) debugfs_create_file("wakeup_timer_milliseconds",
  			S_IRUGO | S_IWUGO, d,&wakeup_timer_milliseconds,
  			&pm_dbg_option_fops);
+
+	pm_dbg_main_dir = d;
  	pm_dbg_init_done = 1;
 
  	return 0;
arch/arm/mach-omap2/pm.h +1 -0
index f3ba1e6..c06cedd 100644
@@ -55,6 +55,7 @@ extern int omap2_pm_debug;
  #define omap2_pm_dump(mode, resume, us)		do {} while (0);
  #define omap2_pm_wakeup_on_timer(seconds, milliseconds)	do {} while (0);
  #define omap2_pm_debug				0
+#define pm_dbg_main_dir				0
  #endif
 
  #if defined(CONFIG_CPU_IDLE)
#3 lore raw

RE: [PATCH v3 01/11] OMAP: PM: Export the main pm debugfs directory

Quoted 10 lines
Quoted 10 lines

-----Original Message-----
From: Cousson, Benoit
Sent: Monday, October 25, 2010 3:00 PM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; [email protected]; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 01/11] OMAP: PM: Export the main pm debugfs directory

Quoted 7 lines
Quoted 7 lines · Thara
Quoted 3 lines

This patch makes generic pm_debug directory global so that other drivers can include it and use it to create sub-entries.

That should not be needed, if we expose voltage debugfs entry in the top level directly.

Agreed. I am ok with exposing the voltage debugfs entry at the top level.

Regards
Thara

Quoted 44 lines
Quoted 44 lines

Benoit

arch/arm/mach-omap2/pm-

Quoted 8 lines
---
  arch/arm/mach-omap2/pm-debug.c |    3 +++
  arch/arm/mach-omap2/pm.h       |    1 +
  2 files changed, 4 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/pm- renamed from arch/arm/mach-omap2/pm-debug.c +0 -0

debug.c

Quoted 32 lines

index af00c17..390f1c6 100644

arch/arm/mach-omap2/pm-debug.c +3 -0
@@ -42,6 +42,7 @@ u32 enable_off_mode;
  u32 sleep_while_idle;
  u32 wakeup_timer_seconds;
  u32 wakeup_timer_milliseconds;
+struct dentry *pm_dbg_main_dir;
 
  #define DUMP_PRM_MOD_REG(mod, reg)    \
  	regs[reg_count].name = #mod "." #reg; \
@@ -641,6 +642,8 @@ static int __init pm_dbg_init(void)
  	(void) debugfs_create_file("wakeup_timer_milliseconds",
  			S_IRUGO | S_IWUGO, d,&wakeup_timer_milliseconds,
  			&pm_dbg_option_fops);
+
+	pm_dbg_main_dir = d;
  	pm_dbg_init_done = 1;
 
  	return 0;
arch/arm/mach-omap2/pm.h +1 -0
index f3ba1e6..c06cedd 100644
@@ -55,6 +55,7 @@ extern int omap2_pm_debug;
  #define omap2_pm_dump(mode, resume, us)		do {} while (0);
  #define omap2_pm_wakeup_on_timer(seconds, milliseconds)	do {} while (0);
  #define omap2_pm_debug				0
+#define pm_dbg_main_dir				0
  #endif
 
  #if defined(CONFIG_CPU_IDLE)
#4 lore raw

PATCH v3 2/11 OMAP3: PM: Adding voltage driver support for OMAP3

In reply to 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 also 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 n-target value, errminlimit and voltage processor errorgain. 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.

---
 arch/arm/mach-omap2/Makefile              |    3 +-
 arch/arm/mach-omap2/voltage.c             | 1117 +++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/voltage.h |  136 ++++
 3 files changed, 1255 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 a88b75a..4f74f2b 100644
@@ -52,7 +52,8 @@ obj-$(CONFIG_ARCH_OMAP2)		+= sdrc2xxx.o
 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/voltage.c new file +1117 -0

1,117 lines not on this page · raw message

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

136 lines not on this page · raw message

Signature · 1 line
1.7.1.GIT
#5 lore raw

Re: [PATCH v3 02/11] OMAP3: PM: Adding voltage driver support for OMAP3

Quoted 18 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 also 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 n-target value, errminlimit and voltage processor errorgain. 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.

[...]

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

Quoted 11 lines
arch/arm/mach-omap2/voltage.c new file +11 -0
+static void __init vdd_data_configure(struct omap_vdd_info *vdd)
+{
+	if (cpu_is_omap34xx())
+		omap3_vdd_data_configure(vdd);
+}
+
+static void __init init_voltagecontroller(void)
+{
+	if (cpu_is_omap34xx())
+		omap3_init_voltagecontroller();
+}

Drop these two functions...

[...]

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

Quoted 6 lines
arch/arm/mach-omap2/voltage.c new file +6 -0
+/**
+ * omap_voltage_init : Volatage init API which does VP and VC init.
+ */
+static int __init omap_voltage_init(void)
+{
+	int i;

...and setup function pointers in these cpu_is checks. Something like the below (not even compile tested.)

       void (*vdd_data_configure)(void);
       void (*init_voltageprocessor)(void);

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

Quoted 5 lines
arch/arm/mach-omap2/voltage.c new file +5 -0
+
+	if (cpu_is_omap34xx()) {
+		volt_mod = OMAP3430_GR_MOD;
+		vdd_info = omap3_vdd_info;
+		nr_scalable_vdd = OMAP3_NR_SCALABLE_VDD;
                vdd_data_configure = omap3_vdd_data_configure;
                init_voltageprocessor = omap3_init_voltageprocessor;

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

Quoted 12 lines
arch/arm/mach-omap2/voltage.c new file +12 -0
+	} else {
+		pr_warning("%s: voltage driver support not added\n", __func__);
+		return 0;
+	}
+	init_voltagecontroller();
+	for (i = 0; i < nr_scalable_vdd; i++) {
+		vdd_data_configure(&vdd_info[i]);
+		init_voltageprocessor(&vdd_info[i]);
+	}
+	return 0;
+}
+core_initcall(omap_voltage_init);

We really want to minimize the cpu_is_* checks, and ideally they should only be present in the first __init function.

Kevin

#6 lore raw

Re: [PATCH v3 02/11] OMAP3: PM: Adding voltage driver support for OMAP3

In reply to Thara Gopinath
Quoted 18 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 also 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 n-target value, errminlimit and voltage processor errorgain. 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.

[...]

Quoted 8 lines
arch/arm/mach-omap2/voltage.c new file +8 -0
+static void vp_latch_vsel(struct omap_vdd_info *vdd)
+{
+	u32 vpconfig;
+	unsigned long uvdc;
+	char vsel;
+
+	uvdc = omap_voltage_get_nom_volt(&vdd->voltdm);
+	if (!uvdc) {

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

Quoted 10 lines
arch/arm/mach-omap2/voltage.c new file +10 -0
+		pr_warning("%s: unable to find current voltage for vdd_%s\n",
+			__func__, vdd->voltdm.name);
+		return;
+	}
+
+	if (!volt_pmic_info.uv_to_vsel) {
+		pr_warning("%s: PMIC function to convert voltage in uV to"
+			" vsel not registered\n", __func__);
+		return;
+	}

Should return an error condition to the caller here...

Quoted 16 lines
arch/arm/mach-omap2/voltage.c new file +16 -0
+	vsel = volt_pmic_info.uv_to_vsel(uvdc);
+
+	vpconfig = voltage_read_reg(vdd->vp_offs.vpconfig);
+	vpconfig &= ~(vdd->vp_reg.vpconfig_initvoltage_mask |
+			vdd->vp_reg.vpconfig_initvdd);
+	vpconfig |= vsel << vdd->vp_reg.vpconfig_initvoltage_shift;
+
+	voltage_write_reg(vdd->vp_offs.vpconfig, vpconfig);
+
+	/* Trigger initVDD value copy to voltage processor */
+	voltage_write_reg(vdd->vp_offs.vpconfig,
+			(vpconfig | vdd->vp_reg.vpconfig_initvdd));
+
+	/* Clear initVDD copy trigger bit */
+	voltage_write_reg(vdd->vp_offs.vpconfig, vpconfig);
+}

[...]

Quoted 23 lines
arch/arm/mach-omap2/voltage.c new file +23 -0
+static void __init init_voltageprocessor(struct omap_vdd_info *vdd)
+{
+	u32 vpconfig;
+
+	vpconfig = vdd->vp_reg.vpconfig_erroroffset |
+			(vdd->vp_reg.vpconfig_errorgain <<
+			vdd->vp_reg.vpconfig_errorgain_shift) |
+			vdd->vp_reg.vpconfig_timeouten;
+
+	voltage_write_reg(vdd->vp_offs.vpconfig, vpconfig);
+
+	voltage_write_reg(vdd->vp_offs.vstepmin,
+			(vdd->vp_reg.vstepmin_smpswaittimemin <<
+			vdd->vp_reg.vstepmin_smpswaittimemin_shift) |
+			(vdd->vp_reg.vstepmin_stepmin <<
+			vdd->vp_reg.vstepmin_stepmin_shift));
+
+	voltage_write_reg(vdd->vp_offs.vstepmax,
+			(vdd->vp_reg.vstepmax_smpswaittimemax <<
+			vdd->vp_reg.vstepmax_smpswaittimemax_shift) |
+			(vdd->vp_reg.vstepmax_stepmax <<
+			vdd->vp_reg.vstepmax_stepmax_shift));
+

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

Quoted 10 lines
arch/arm/mach-omap2/voltage.c new file +10 -0
+	voltage_write_reg(vdd->vp_offs.vlimitto,
+			(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));
+
+	/* Set the init voltage */
+	vp_latch_vsel(vdd);

On OMAP4/panda, the boot hangs after this.

Since there is no PMIC registered, this call returns early but there is no error checking done. I think the init needs a little more error checking and graceful failure, especially when there is no PMIC present.

Kevin

A message that is not in the archive (sent off-list or not yet received): [email protected]

maintainer
#8 lore raw

Re: [PATCH v3 02/11] OMAP3: PM: Adding voltage driver support for OMAP3

Hi Benoît, Thara,

Quoted 7 lines · Kevin Hilman

Also, I'm still seeing this on boot:

omap_hwmod: sr1_fck: missing clockdomain for sr1_fck.
omap_hwmod: sr2_fck: missing clockdomain for sr2_fck.

We need a final solution for this problem as a prerequisite for this series as well.

I guess we need to figure out the appropriate clockdomains for sr1_fck and sr2_fck.

Probably the strictly correct thing to do, vis-a-vis the hardware, is to place them into their own SmartReflex clockdomain/powerdomain. But the PRCM doesn't export separate control registers for those, and as I understand it, that clockdomain/powerdomain follows the CORE clockdomains/powerdomain.

Another option would be to place them into the WKUP clockdomain. The source of these functional clocks in SR_ALWON_FCLK which in turn is generated by the PRM from SYS_CLK. But that won't increment the CORE clockdomains' use-counter when the SR functional clocks are running, which seems desirable if the SmartReflex clockdomain/powerdomain really does follow CORE.

So it seems to me that the best thing to do might be to place these clocks into the CORE_L4 clockdomain. But perhaps you might have a different view?

regards,

- Paul

#9 lore raw

Re: [PATCH v3 02/11] OMAP3: PM: Adding voltage driver support for OMAP3

Hi Paul,

Quoted 12 lines · Paul Walmsley

Hi Benoît, Thara,

Quoted 7 lines · Kevin Hilman

Also, I'm still seeing this on boot:

omap_hwmod: sr1_fck: missing clockdomain for sr1_fck.
omap_hwmod: sr2_fck: missing clockdomain for sr2_fck.

We need a final solution for this problem as a prerequisite for this series as well.

Quoted 8 lines

I guess we need to figure out the appropriate clockdomains for sr1_fck and sr2_fck.

Probably the strictly correct thing to do, vis-a-vis the hardware, is to place them into their own SmartReflex clockdomain/powerdomain. But the PRCM doesn't export separate control registers for those, and as I understand it, that clockdomain/powerdomain follows the CORE clockdomains/powerdomain.

More or less. In theory the smartreflex power domain goes to OFF only when the device goes to OFF. In device RET the SR power domain is still active. That's why the FCLK is marked as always ON.

Quoted 10 lines

Another option would be to place them into the WKUP clockdomain. The source of these functional clocks in SR_ALWON_FCLK which in turn is generated by the PRM from SYS_CLK. But that won't increment the CORE clockdomains' use-counter when the SR functional clocks are running, which seems desirable if the SmartReflex clockdomain/powerdomain really does follow CORE.

So it seems to me that the best thing to do might be to place these clocks into the CORE_L4 clockdomain. But perhaps you might have a different view?

That's should be the proper place, but after several discussion with Vincent then Leo, it appears that the gating of the CORE_L4 interface clock is triggered by a transition of the WKUP clock domain to idle... Yeah, that's a mess... that IP does not follow any PRCM standard :-)

Originally I thought the SR_EN bits were located in the wkup register because Vincent was too lazy to create a new register for these 2 bits :-). But in fact because of that hidden dependency with the wkup, it is almost normal to put these bits there.

Bottom-line is that we should tie them to the "wkup_clkdm".

Another important point we already discussed a little bit, but that will require more thoughts, is that the clock domain definition is first: quite fuzzy and then does not belong do the clock itself, but to the modules that are sharing the same interface clock. It means that some clocks will not belong to any clock domains, and this is fine.
On OMAP4, that definition is clearly tied to the modules, and thus should be an hwmod attribute more than a clock node attribute.

Regards,
Benoit
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#10 lore raw

Re: [PATCH v3 02/11] OMAP3: PM: Adding voltage driver support for OMAP3

In reply to Thara Gopinath
Quoted 18 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 also 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 n-target value, errminlimit and voltage processor errorgain. 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.

[...]

Quoted 9 lines
arch/arm/plat-omap/include/plat/voltage.h new file +9 -0
+/*
+ * Omap3630 specific VP register values. Maybe these need to come from
+ * board file or PMIC data structure
+ */
+#define OMAP3630_VP1_VLIMITTO_VDDMIN		0x18
+#define OMAP3630_VP1_VLIMITTO_VDDMAX		0x3C
+#define OMAP3630_VP2_VLIMITTO_VDDMIN		0x18
+#define OMAP3630_VP2_VLIMITTO_VDDMAX		0x30
+

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

Quoted 10 lines
arch/arm/plat-omap/include/plat/voltage.h new file +10 -0
+/* TODO OMAP4 VP register values if the same file is used for OMAP4*/
+
+/**
+ * voltagedomain - omap voltage domain global structure
+ * @name       : Name of the voltage domain which can be used as a unique
+ *               identifier.
+ */
+struct voltagedomain {
+	char *name;
+};

Minor: to keep the voltagedomain stuff somewhat separate from the rest of the voltage layer API, I suggest putting the voltage domain APIs here:

struct voltagedomain *omap_voltage_domain_get(char *name);

However, I think this function shoul be called _lookup instead of _get to continue the naming conventions of the powerdomain and clockdomain code.

Kevin

#11 lore raw

RE: [PATCH v3 02/11] OMAP3: PM: Adding voltage driver support for OMAP3

Quoted 58 lines
Quoted 58 lines

-----Original Message-----
From: [email protected] [mailto:linux-omap- [email protected]] On Behalf Of Kevin Hilman
Sent: Thursday, October 14, 2010 11:35 PM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 02/11] OMAP3: PM: Adding voltage driver support for OMAP3

Quoted 18 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 also 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 n-target value, errminlimit and voltage processor errorgain. 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.

[...]

Quoted 9 lines
arch/arm/plat-omap/include/plat/voltage.h new file +9 -0
+/*
+ * Omap3630 specific VP register values. Maybe these need to come from
+ * board file or PMIC data structure
+ */
+#define OMAP3630_VP1_VLIMITTO_VDDMIN		0x18
+#define OMAP3630_VP1_VLIMITTO_VDDMAX		0x3C
+#define OMAP3630_VP2_VLIMITTO_VDDMIN		0x18
+#define OMAP3630_VP2_VLIMITTO_VDDMAX		0x30
+

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

Quoted 10 lines
arch/arm/plat-omap/include/plat/voltage.h new file +10 -0
+/* TODO OMAP4 VP register values if the same file is used for OMAP4*/
+
+/**
+ * voltagedomain - omap voltage domain global structure
+ * @name       : Name of the voltage domain which can be used as a unique
+ *               identifier.
+ */
+struct voltagedomain {
+	char *name;
+};

Minor: to keep the voltagedomain stuff somewhat separate from the rest of the voltage layer API, I suggest putting the voltage domain APIs here:

Quoted 1 line
Quoted 1 line

struct voltagedomain *omap_voltage_domain_get(char *name);

You mean just move up the signature, right? I do not think the entire API can be moved here as it uses some static data structures in voltage.c

Quoted 4 lines
Quoted 4 lines

However, I think this function shoul be called _lookup instead of _get to continue the naming conventions of the powerdomain and clockdomain code.

I will rename the API.

Regards
Thara

Quoted 8 lines
Quoted 8 lines

Kevin

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

#12 lore raw

Re: [PATCH v3 02/11] OMAP3: PM: Adding voltage driver support for OMAP3

Quoted 46 lines · Thara
Quoted 46 lines
Quoted 46 lines · Thara Gopinath
Quoted 18 lines

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 also 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 n-target value, errminlimit and voltage processor errorgain. 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.

[...]

Quoted 9 lines
arch/arm/plat-omap/include/plat/voltage.h new file +9 -0
+/*
+ * Omap3630 specific VP register values. Maybe these need to come from
+ * board file or PMIC data structure
+ */
+#define OMAP3630_VP1_VLIMITTO_VDDMIN		0x18
+#define OMAP3630_VP1_VLIMITTO_VDDMAX		0x3C
+#define OMAP3630_VP2_VLIMITTO_VDDMIN		0x18
+#define OMAP3630_VP2_VLIMITTO_VDDMAX		0x30
+

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

Quoted 10 lines
arch/arm/plat-omap/include/plat/voltage.h new file +10 -0
+/* TODO OMAP4 VP register values if the same file is used for OMAP4*/
+
+/**
+ * voltagedomain - omap voltage domain global structure
+ * @name       : Name of the voltage domain which can be used as a unique
+ *               identifier.
+ */
+struct voltagedomain {
+	char *name;
+};

Minor: to keep the voltagedomain stuff somewhat separate from the rest of the voltage layer API, I suggest putting the voltage domain APIs here:

Quoted 3 lines
Quoted 1 line
Quoted 1 line

struct voltagedomain *omap_voltage_domain_get(char *name);

You mean just move up the signature, right?

Right.

Quoted 2 lines

I do not think the entire API can be moved here as it uses some static data structures in voltage.c

Agreed.

Quoted 7 lines
Quoted 4 lines
Quoted 4 lines

However, I think this function shoul be called _lookup instead of _get to continue the naming conventions of the powerdomain and clockdomain code.

I will rename the API.

Thanks,

Kevin

#13 lore raw

PATCH v3 3/11 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 VDD1 and the other associated with VDD2.
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 > /debugfs/pm_debug/smartreflex/sr_<X>/autocomp
To disable smartreflex autocompensation feature
echo 0 > /debugfs/pm_debug/smartreflex/sr_<X>/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             | 1003 +++++++++++++++++++++++++
 arch/arm/plat-omap/Kconfig                    |   32 +
 arch/arm/plat-omap/include/plat/smartreflex.h |  277 +++++++
 4 files changed, 1313 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 4f74f2b..8dd32a7 100644
@@ -56,6 +56,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 +1003 -0

1,003 lines not on this page · raw message

arch/arm/plat-omap/Kconfig +32 -0
index e39a417..8056349 100644
@@ -35,6 +35,38 @@ config OMAP_DEBUG_LEDS
 	depends on OMAP_DEBUG_DEVICES
 	default y if LEDS
 
+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 VDD1 and VDD2, user must write 1 to
+	  /debug/pm_debug/Smartreflex/SR<X>/autocomp,
+	  where X is 1 or 2 for OMAP3
+
+config OMAP_SMARTREFLEX_TESTING
+	bool "Smartreflex testing support"
+	depends on OMAP_SMARTREFLEX
+	default n
+	help
+	  Say Y if you want to enable SmartReflex testing with SW hardcoded
+	  NVALUES intead of E-fuse NVALUES set in factory silicon testing.
+
+	  In some devices the E-fuse values have not been set, even though
+	  SmartReflex modules are included. Using these hardcoded values set
+	  in software, one can test the SmartReflex features without E-fuse.
+
+	  WARNING: Enabling this option may cause your device to hang!
+
 config OMAP_RESET_CLOCKS
 	bool "Reset unused clocks during boot"
 	depends on ARCH_OMAP
arch/arm/plat-omap/include/plat/smartreflex.h new file +277 -0

277 lines not on this page · raw message

Signature · 1 line
1.7.1.GIT
#14 lore raw

Re: [PATCH v3 03/11] OMAP3: PM: Adding smartreflex driver support.

Quoted 28 lines · 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 VDD1 and the other associated with VDD2.
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 > /debugfs/pm_debug/smartreflex/sr_<X>/autocomp
To disable smartreflex autocompensation feature
echo 0 > /debugfs/pm_debug/smartreflex/sr_<X>/autocomp

where X can be mpu, core , iva etc.

[...]

Quoted 11 lines
arch/arm/mach-omap2/smartreflex.c new file +11 -0
+static void sr_set_regfields(struct omap_sr *sr)
+{
+	/*
+	 * For time being these values are defined in smartreflex.h
+	 * and populated during init. May be they can be moved to board
+	 * file or pmic specific data structure. In that case these structure
+	 * fields will have to be populated using the pdata or pmic structure.
+	 */
+	if (cpu_is_omap34xx()) {
+		sr->err_weight = OMAP3430_SR_ERRWEIGHT;
+		sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;

arch/arm/mach-omap2/smartreflex.c line 207

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+		sr->accum_data = OMAP3430_SR_ACCUMDATA;
+		if (!(strcmp(sr->voltdm->name, "mpu"))) {
+			sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
+			sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
+		} else {
+			sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
+			sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
+		}
+	}
+	/* TODO: 3630 and Omap4 specific bit field values */

This comment is still present even after the OMAP4 series is applied.

[...]

Quoted 6 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +6 -0
+/*
+ * 3430 specific values. Maybe these should be passed from board file or
+ * pmic structures.
+ */
+#define OMAP3430_SR_ACCUMDATA		0x1f4
+

arch/arm/plat-omap/include/plat/smartreflex.h line 149

Quoted 10 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +10 -0
+#define OMAP3430_SR1_SENPAVGWEIGHT	0x03
+#define OMAP3430_SR1_SENNAVGWEIGHT	0x03
+
+#define OMAP3430_SR2_SENPAVGWEIGHT	0x01
+#define OMAP3430_SR2_SENNAVGWEIGHT	0x01
+
+#define OMAP3430_SR_ERRWEIGHT		0x04
+#define OMAP3430_SR_ERRMAXLIMIT		0x02
+
+/* TODO:3630/OMAP4 values if it has to come from this file */

ditto

It's best to just not put these kind of things into the code in the first place, they tend to be forgotten and stale quickly.

Kevin

#15 lore raw

RE: [PATCH v3 03/11] OMAP3: PM: Adding smartreflex driver support.

Quoted 88 lines
Quoted 88 lines

-----Original Message-----
From: Kevin Hilman [mailto:[email protected]]
Sent: Wednesday, September 29, 2010 5:01 AM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 03/11] OMAP3: PM: Adding smartreflex driver support.

Quoted 28 lines · 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 VDD1 and the other associated with VDD2.
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 > /debugfs/pm_debug/smartreflex/sr_<X>/autocomp
To disable smartreflex autocompensation feature
echo 0 > /debugfs/pm_debug/smartreflex/sr_<X>/autocomp

where X can be mpu, core , iva etc.

[...]

Quoted 11 lines
arch/arm/mach-omap2/smartreflex.c new file +11 -0
+static void sr_set_regfields(struct omap_sr *sr)
+{
+	/*
+	 * For time being these values are defined in smartreflex.h
+	 * and populated during init. May be they can be moved to board
+	 * file or pmic specific data structure. In that case these structure
+	 * fields will have to be populated using the pdata or pmic structure.
+	 */
+	if (cpu_is_omap34xx()) {
+		sr->err_weight = OMAP3430_SR_ERRWEIGHT;
+		sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;

arch/arm/mach-omap2/smartreflex.c line 207

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+		sr->accum_data = OMAP3430_SR_ACCUMDATA;
+		if (!(strcmp(sr->voltdm->name, "mpu"))) {
+			sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
+			sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
+		} else {
+			sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
+			sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
+		}
+	}
+	/* TODO: 3630 and Omap4 specific bit field values */

This comment is still present even after the OMAP4 series is applied.

[...]

Quoted 6 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +6 -0
+/*
+ * 3430 specific values. Maybe these should be passed from board file or
+ * pmic structures.
+ */
+#define OMAP3430_SR_ACCUMDATA		0x1f4
+

arch/arm/plat-omap/include/plat/smartreflex.h line 149

Quoted 10 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +10 -0
+#define OMAP3430_SR1_SENPAVGWEIGHT	0x03
+#define OMAP3430_SR1_SENNAVGWEIGHT	0x03
+
+#define OMAP3430_SR2_SENPAVGWEIGHT	0x01
+#define OMAP3430_SR2_SENNAVGWEIGHT	0x01
+
+#define OMAP3430_SR_ERRWEIGHT		0x04
+#define OMAP3430_SR_ERRMAXLIMIT		0x02
+
+/* TODO:3630/OMAP4 values if it has to come from this file */

ditto

Quoted 2 lines
Quoted 2 lines

It's best to just not put these kind of things into the code in the first place, they tend to be forgotten and stale quickly.

Will fix this and post V4.

Quoted 2 lines
Quoted 2 lines

Kevin

#16 lore raw

Re: [PATCH v3 03/11] OMAP3: PM: Adding smartreflex driver support.

In reply to Thara Gopinath
Quoted 12 lines · 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

Quoted 2 lines

OMAP3 has two smartreflex modules one associated with VDD1 and the other associated with VDD2.

s/VDD1/MPU/
s/VDD2/CORE/

Quoted 78 lines

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 > /debugfs/pm_debug/smartreflex/sr_<X>/autocomp
To disable smartreflex autocompensation feature
echo 0 > /debugfs/pm_debug/smartreflex/sr_<X>/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             | 1003 +++++++++++++++++++++++++
 arch/arm/plat-omap/Kconfig                    |   32 +
 arch/arm/plat-omap/include/plat/smartreflex.h |  277 +++++++
 4 files changed, 1313 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 4f74f2b..8dd32a7 100644
@@ -56,6 +56,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 +31 -0
new file mode 100644
index 0000000..7fc3138
@@ -0,0 +1,1003 @@
+/*
+ * OMAP SmartReflex Voltage Control
+ *
+ * Author: Thara Gopinath	<[email protected]>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <[email protected]>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <[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.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+#include <plat/omap_device.h>
+#include <plat/common.h>
+#include <plat/smartreflex.h>
+

arch/arm/mach-omap2/smartreflex.c line 41

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+#include "pm.h"
+
+#define SMARTREFLEX_NAME_LEN	16
+#define SR_DISABLE_TIMEOUT	200
+
+struct dentry *sr_dbg_dir;
+
+struct omap_sr {
+	int			srid;
+	bool			sr_enable;

sr_enabled is a better name

Quoted 33 lines
arch/arm/mach-omap2/smartreflex.c new file +33 -0
+	bool			autocomp_active;
+	int			ip_type;
+	u32			clk_length;
+	u32			err_weight;
+	u32			err_minlimit;
+	u32			err_maxlimit;
+	u32			accum_data;
+	u32			senn_avgweight;
+	u32			senp_avgweight;
+	unsigned int		irq;
+	void __iomem		*base;
+	struct platform_device	*pdev;
+	struct list_head	node;
+	struct voltagedomain	*voltdm;
+};
+
+/* sr_list contains all the instances of smartreflex module */
+static LIST_HEAD(sr_list);
+
+static struct omap_smartreflex_class_data *sr_class;
+static struct omap_smartreflex_pmic_data *sr_pmic_data;
+
+static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
+{
+	__raw_writel(value, (sr->base + offset));
+}
+
+static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
+					u32 value)
+{
+	u32 reg_val;
+	u32 errconfig_offs, errconfig_mask;
+

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

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+	reg_val = __raw_readl(sr->base + offset);
+	reg_val &= ~mask;
+
+	/*
+	 * Smartreflex error config register is special as it contains
+	 * certain status bits which if written a 1 into means a clear
+	 * of those bits. So in order to make sure no accidental write of
+	 * 1 happens to those status bits, do a clear of them in the read
+	 * value. Now if there is an actual reguest to write to these bits
+	 * they will be set in the nex step.

s/nex/next/

that being said, it's not clear what "the next step" is in this context. There is only one write.

This should be rephrased to say (something like) it doesn't rewrite values in these bits if they are currently set, but does allow the caller to write those bits.

Quoted 30 lines
arch/arm/mach-omap2/smartreflex.c new file +30 -0
+	 */
+	if (sr->ip_type == SR_TYPE_V1) {
+		errconfig_offs = ERRCONFIG_V1;
+		errconfig_mask = ERRCONFIG_STATUS_V1_MASK;
+	} else if (sr->ip_type == SR_TYPE_V2) {
+		errconfig_offs = ERRCONFIG_V2;
+		errconfig_mask = ERRCONFIG_VPBOUNDINTST_V2;
+	}
+
+	if (offset == errconfig_offs)
+		reg_val &= ~errconfig_mask;
+
+	reg_val |= value;
+
+	__raw_writel(reg_val, (sr->base + offset));
+}
+
+static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
+{
+	return __raw_readl(sr->base + offset);
+}
+
+static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm)
+{
+	struct omap_sr *sr_info;
+
+	if (!voltdm) {
+		pr_err("%s: Null voltage domain passed!\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}

arch/arm/mach-omap2/smartreflex.c line 124

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +9 -0
+
+	list_for_each_entry(sr_info, &sr_list, node) {
+		if (voltdm == sr_info->voltdm)
+			return sr_info;
+	}
+
+	return ERR_PTR(-ENODATA);
+}
 
+static irqreturn_t sr_omap_isr(int irq, void *data)

Please rename to sr_interrupt

arch/arm/mach-omap2/smartreflex.c line 134

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+{
+	struct omap_sr *sr_info = (struct omap_sr *)data;
+	u32 status = 0;
+
+	if (sr_info->ip_type == SR_TYPE_V1) {
+		/* Read the status bits */
+		status = sr_read_reg(sr_info, ERRCONFIG_V1);
+
+		/* Clear them by writing back */
+		sr_write_reg(sr_info, ERRCONFIG_V1, status);

Shouldn't you be using sr_modify_reg for ERRCONFIG_V1?

arch/arm/mach-omap2/smartreflex.c line 141

Quoted 7 lines
arch/arm/mach-omap2/smartreflex.c new file +7 -0
+	} else if (sr_info->ip_type == SR_TYPE_V2) {
+		/* Read the status bits */
+		sr_read_reg(sr_info, IRQSTATUS);
+
+		/* Clear them by writing back */
+		sr_write_reg(sr_info, IRQSTATUS, status);
+	}

Might as well use it for both.

arch/arm/mach-omap2/smartreflex.c

Quoted 2 lines
arch/arm/mach-omap2/smartreflex.c new file +2 -0
+
+	/* Call the class driver notify function if registered*/

This comment does not add anything the code doesn't make clear, and is not fully correct: it has to be registered, and be class 2.

IMO, you can just remove comments like this that aren't be

Quoted 109 lines
arch/arm/mach-omap2/smartreflex.c new file +109 -0
+	if (sr_class->class_type == SR_CLASS2 && sr_class->notify)
+		sr_class->notify(sr_info->voltdm, status);
+
+	return IRQ_HANDLED;
+}
+
+static void sr_set_clk_length(struct omap_sr *sr)
+{
+	struct clk *sys_ck;
+	u32 sys_clk_speed;
+
+	sys_ck = clk_get(NULL, "sys_ck");
+	if (IS_ERR(sys_ck)) {
+		dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n",
+			__func__);
+		return;
+	}
+	sys_clk_speed = clk_get_rate(sys_ck);
+	clk_put(sys_ck);
+
+	switch (sys_clk_speed) {
+	case 12000000:
+		sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
+		break;
+	case 13000000:
+		sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK;
+		break;
+	case 19200000:
+		sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK;
+		break;
+	case 26000000:
+		sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK;
+		break;
+	case 38400000:
+		sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
+		break;
+	default:
+		dev_err(&sr->pdev->dev, "%s: Invalid sysclk value: %d\n",
+			__func__, sys_clk_speed);
+		break;
+	}
+}
+
+static void sr_set_regfields(struct omap_sr *sr)
+{
+	/*
+	 * For time being these values are defined in smartreflex.h
+	 * and populated during init. May be they can be moved to board
+	 * file or pmic specific data structure. In that case these structure
+	 * fields will have to be populated using the pdata or pmic structure.
+	 */
+	if (cpu_is_omap34xx()) {
+		sr->err_weight = OMAP3430_SR_ERRWEIGHT;
+		sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
+		sr->accum_data = OMAP3430_SR_ACCUMDATA;
+		if (!(strcmp(sr->voltdm->name, "mpu"))) {
+			sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
+			sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
+		} else {
+			sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
+			sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
+		}
+	}
+	/* TODO: 3630 and Omap4 specific bit field values */
+}
+
+static void sr_start_vddautocomp(struct omap_sr *sr)
+{
+	if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
+		dev_warn(&sr->pdev->dev,
+			"%s: smartreflex class driver not registered\n",
+			__func__);
+		return;
+	}
+
+	if (!sr_class->enable(sr->voltdm))
+		sr->autocomp_active = true;
+}
+
+static void sr_stop_vddautocomp(struct omap_sr *sr)
+{
+	if (!sr_class || !(sr_class->disable)) {
+		dev_warn(&sr->pdev->dev,
+			"%s: smartreflex class driver not registered\n",
+			__func__);
+		return;
+	}
+
+	if (sr->autocomp_active) {
+		sr_class->disable(sr->voltdm, 1);
+		sr->autocomp_active = false;
+	}
+}
+
+/*
+ * This function handles the intializations which have to be done
+ * only when both sr device and class driver regiter has
+ * completed. This will be attempted to be called from both sr class
+ * driver register and sr device intializtion API's. Only one call
+ * will ultimately succeed.
+ *
+ * Currenly this function registers interrrupt handler for a particular SR
+ * if smartreflex class driver is already registered and has
+ * requested for interrupts and the SR interrupt line in present.
+ */
+static int sr_late_init(struct omap_sr *sr_info)
+{
+	char *name;
+	struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data;

arch/arm/mach-omap2/smartreflex.c line 262

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+	int ret = 0;
+
+	if (sr_class->class_type == SR_CLASS2 &&
+		sr_class->notify_flags && sr_info->irq) {
+
+		name = kzalloc(SMARTREFLEX_NAME_LEN + 1, GFP_KERNEL);
+		strcpy(name, "sr_");
+		strcat(name, sr_info->voltdm->name);
+		ret = request_irq(sr_info->irq, sr_omap_isr,
+				IRQF_DISABLED, name, (void *)sr_info);

Why does this have to be IRQF_DISABLED? This capability will be
disappearing from the kernel soon.

Because there are no current users, I cannot tell, but I suspect this could be use request_threaded_irq. If not, please justify.

arch/arm/mach-omap2/smartreflex.c

Quoted 1 line
arch/arm/mach-omap2/smartreflex.c new file +1 -0
+		if (ret) {
                         goto error;
Quoted 4 lines
arch/arm/mach-omap2/smartreflex.c new file +4 -0
+			struct resource *mem;
+
+			iounmap(sr_info->base);
+			mem = platform_get_resource(sr_info->pdev,

arch/arm/mach-omap2/smartreflex.c line 277

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+				IORESOURCE_MEM, 0);
+			release_mem_region(mem->start, resource_size(mem));
+			list_del(&sr_info->node);
+			dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
+				"interrupt handler. Smartreflex will"
+				"not function as desired\n", __func__);
+
+			kfree(sr_info);
+			return ret;
+		}

and move this after the return...

arch/arm/mach-omap2/smartreflex.c line 283

Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c new file +6 -0
+	}
+
+	if (pdata && pdata->enable_on_init)
+		sr_start_vddautocomp(sr_info);
+
+	return ret;

error:

(here.)

Quoted 103 lines
arch/arm/mach-omap2/smartreflex.c new file +103 -0
+}
+
+static void sr_v1_disable(struct omap_sr *sr)
+{
+	int timeout = 0;
+
+	/* Enable MCUDisableAcknowledge interrupt */
+	sr_modify_reg(sr, ERRCONFIG_V1,
+			ERRCONFIG_MCUDISACKINTEN, ERRCONFIG_MCUDISACKINTEN);
+
+	/* SRCONFIG - disable SR */
+	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
+
+	/* Disable all other SR interrupts and clear the status */
+	sr_modify_reg(sr, ERRCONFIG_V1,
+			(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
+			ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1),
+			(ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
+			ERRCONFIG_MCUBOUNDINTST |
+			ERRCONFIG_VPBOUNDINTST_V1));
+
+	/*
+	 * Wait for SR to be disabled.
+	 * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us.
+	 */
+	omap_test_timeout((sr_read_reg(sr, ERRCONFIG_V1) &
+			ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT,
+			timeout);
+
+	if (timeout >= SR_DISABLE_TIMEOUT)
+		dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
+			__func__);
+
+	/* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
+	sr_modify_reg(sr, ERRCONFIG_V1, ERRCONFIG_MCUDISACKINTEN,
+			ERRCONFIG_MCUDISACKINTST);
+}
+
+static void sr_v2_disable(struct omap_sr *sr)
+{
+	int timeout = 0;
+
+	/* Enable MCUDisableAcknowledge interrupt */
+	sr_write_reg(sr, IRQENABLE_SET, IRQENABLE_MCUDISABLEACKINT);
+
+	/* SRCONFIG - disable SR */
+	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
+
+	/* Disable all other SR interrupts and clear the status */
+	sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
+			ERRCONFIG_VPBOUNDINTST_V2);
+	sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT |
+			IRQENABLE_MCUVALIDINT |
+			IRQENABLE_MCUBOUNDSINT));
+	sr_write_reg(sr, IRQSTATUS, (IRQSTATUS_MCUACCUMINT |
+			IRQSTATUS_MCVALIDINT |
+			IRQSTATUS_MCBOUNDSINT));
+
+	/*
+	 * Wait for SR to be disabled.
+	 * wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us.
+	 */
+	omap_test_timeout((sr_read_reg(sr, IRQSTATUS) &
+			IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT,
+			timeout);
+
+	if (timeout >= SR_DISABLE_TIMEOUT)
+		dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
+			__func__);
+
+	/* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
+	sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT);
+	sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
+}
+
+/* Public Functions */
+
+/**
+ * sr_configure_errgen() - Configures the smrtreflex to perform AVS using the
+ *			 error generator module.
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * configure the error generator module inside the smartreflex module.
+ * SR settings if using the ERROR module inside Smartreflex.
+ * SR CLASS 3 by default uses only the ERROR module where as
+ * SR CLASS 2 can choose between ERROR module and MINMAXAVG
+ * module. Returns 0 on success and error value in case of failure.
+ */
+int sr_configure_errgen(struct voltagedomain *voltdm)
+{
+	u32 sr_config, sr_errconfig, errconfig_offs, vpboundint_en;
+	u32 vpboundint_st, senp_en = 0, senn_en = 0;
+	u8 senp_shift, senn_shift;
+	struct omap_sr *sr = _sr_lookup(voltdm);
+	struct omap_sr_data *pdata;
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return -EINVAL;
+	}
+

arch/arm/mach-omap2/smartreflex.c line 396

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+	pdata = sr->pdev->dev.platform_data;
+
+	if (!sr->clk_length)
+		sr_set_clk_length(sr);
+
+	if (pdata) {
+		senp_en = pdata->senp_mod;
+		senn_en = pdata->senn_mod;
+	} else {
+		dev_warn(&sr->pdev->dev, "%s: Missing pdata\n", __func__);

This is more of an error condition, and should probably return here with an error. Otherwise undefined values are used below.

Quoted 66 lines
arch/arm/mach-omap2/smartreflex.c new file +66 -0
+	}
+
+	sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
+		SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN;
+
+	if (sr->ip_type == SR_TYPE_V1) {
+		sr_config |= SRCONFIG_DELAYCTRL;
+		senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
+		senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
+		errconfig_offs = ERRCONFIG_V1;
+		vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
+		vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
+	} else if (sr->ip_type == SR_TYPE_V2) {
+		senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
+		senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
+		errconfig_offs = ERRCONFIG_V2;
+		vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
+		vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
+	} else {
+		dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
+			"module without specifying the ip\n", __func__);
+		return -EINVAL;
+	}
+
+	sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
+	sr_write_reg(sr, SRCONFIG, sr_config);
+	sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
+		(sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
+		(sr->err_minlimit <<  ERRCONFIG_ERRMINLIMIT_SHIFT);
+	sr_modify_reg(sr, errconfig_offs, (SR_ERRWEIGHT_MASK |
+		SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
+		sr_errconfig);
+
+	/* Enabling the interrupts if the ERROR module is used */
+	sr_modify_reg(sr, errconfig_offs,
+		vpboundint_en, (vpboundint_en | vpboundint_st));
+
+	return 0;
+}
+
+/**
+ * sr_configure_minmax() - Configures the smrtreflex to perform AVS using the
+ *			 minmaxavg module.
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * configure the minmaxavg module inside the smartreflex module.
+ * SR settings if using the ERROR module inside Smartreflex.
+ * SR CLASS 3 by default uses only the ERROR module where as
+ * SR CLASS 2 can choose between ERROR module and MINMAXAVG
+ * module. Returns 0 on success and error value in case of failure.
+ */
+int sr_configure_minmax(struct voltagedomain *voltdm)
+{
+	u32 sr_config, sr_avgwt;
+	u32 senp_en = 0, senn_en = 0;
+	u8 senp_shift, senn_shift;
+	struct omap_sr *sr = _sr_lookup(voltdm);
+	struct omap_sr_data *pdata;
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return -EINVAL;
+	}
+

arch/arm/mach-omap2/smartreflex.c line 472

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+	pdata = sr->pdev->dev.platform_data;
+
+	if (!sr->clk_length)
+		sr_set_clk_length(sr);
+
+	if (pdata) {
+		senp_en = pdata->senp_mod;
+		senn_en = pdata->senn_mod;
+	} else {
+		dev_warn(&sr->pdev->dev, "%s: Missing pdata\n", __func__);

same as above

Quoted 82 lines
arch/arm/mach-omap2/smartreflex.c new file +82 -0
+	}
+
+	sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
+		SRCONFIG_SENENABLE |
+		(sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
+
+	if (sr->ip_type == SR_TYPE_V1) {
+		sr_config |= SRCONFIG_DELAYCTRL;
+		senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
+		senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
+	} else if (sr->ip_type == SR_TYPE_V2) {
+		senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
+		senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
+	} else {
+		dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
+			"module without specifying the ip\n", __func__);
+		return -EINVAL;
+	}
+
+	sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
+	sr_write_reg(sr, SRCONFIG, sr_config);
+	sr_avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
+		(sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT);
+	sr_write_reg(sr, AVGWEIGHT, sr_avgwt);
+
+	/*
+	 * Enabling the interrupts if MINMAXAVG module is used.
+	 * TODO: check if all the interrupts are mandatory
+	 */
+	if (sr->ip_type == SR_TYPE_V1) {
+		sr_modify_reg(sr, ERRCONFIG_V1,
+			(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
+			ERRCONFIG_MCUBOUNDINTEN),
+			(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST |
+			 ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST |
+			 ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST));
+	} else if (sr->ip_type == SR_TYPE_V2) {
+		sr_write_reg(sr, IRQSTATUS,
+			IRQSTATUS_MCUACCUMINT | IRQSTATUS_MCVALIDINT |
+			IRQSTATUS_MCBOUNDSINT | IRQSTATUS_MCUDISABLEACKINT);
+		sr_write_reg(sr, IRQENABLE_SET,
+			IRQENABLE_MCUACCUMINT | IRQENABLE_MCUVALIDINT |
+			IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT);
+	}
+
+	return 0;
+}
+
+/**
+ * sr_enable() - Enables the smartreflex module.
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ * @volt:	The voltage at which the Voltage domain associated with
+ *		the smartreflex module is operating at.
+ *		This is required only to program the correct Ntarget value.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * enable a smartreflex module. Returns 0 on success. Returns error
+ * value if the voltage passed is wrong or if ntarget value is wrong.
+ */
+int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
+{
+	u32 nvalue_reciprocal;
+	struct omap_volt_data *volt_data;
+	struct omap_sr *sr = _sr_lookup(voltdm);
+	int ret;
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return -EINVAL;
+	}
+
+	volt_data = omap_voltage_get_voltdata(voltdm, volt);
+
+	if (IS_ERR(volt_data)) {
+		dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table"
+			" for nominal voltage %ld\n", __func__, volt);
+		return -ENODATA;
+	}
+
+	nvalue_reciprocal = volt_data->sr_nvalue;
+

arch/arm/mach-omap2/smartreflex.c line 564

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+	if (!nvalue_reciprocal) {
+		dev_warn(&sr->pdev->dev, "%s: NVALUE = 0 at voltage %ld\n",
+			__func__, volt);
+		return -ENODATA;
+	}
+
+	/* errminlimit is opp dependent and hence linked to voltage */
+	sr->err_minlimit = volt_data->sr_errminlimit;
+
+	/* Enable the clocks */

not just clocs are enabled by pm_runtime_get(). Again, probably just removing the comment is better.

arch/arm/mach-omap2/smartreflex.c line 568

Quoted 4 lines
arch/arm/mach-omap2/smartreflex.c new file +4 -0
+	if (!sr->sr_enable) {
+		pm_runtime_get_sync(&sr->pdev->dev);
+		sr->sr_enable = true;
+	}

But, I'm not sure why you need this sr_enabled flag. Here, you could just do pm_runtime_get_sync() and rely on the usecounting done in the runtime PM core...

Quoted 25 lines
arch/arm/mach-omap2/smartreflex.c new file +25 -0
+	/* Check if SR is already enabled. If yes do nothing */
+	if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE)
+		return 0;
+
+	/* Configure SR */
+	ret = sr_class->configure(voltdm);
+	if (ret)
+		return ret;
+
+	sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
+
+	/* SRCONFIG - enable SR */
+	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
+	return 0;
+}
+
+/**
+ * sr_disable() - Disables the smartreflex module.
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * disable a smartreflex module.
+ */
+void sr_disable(struct voltagedomain *voltdm)
+{

arch/arm/mach-omap2/smartreflex.c line 604

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+	struct omap_sr *sr = _sr_lookup(voltdm);
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	/* Check if SR clocks are already disabled. If yes do nothing */
+	if (!sr->sr_enable)

...and here you just check pm_runtime_is_suspended()

arch/arm/mach-omap2/smartreflex.c line 609

Quoted 5 lines
arch/arm/mach-omap2/smartreflex.c new file +5 -0
+		return;
+
+	/* Check if SR is already disabled. If yes just disable the clocks */
+	if (!(sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE))
+		goto disable_clocks;

drop the goto and just indent the next block

Quoted 275 lines
arch/arm/mach-omap2/smartreflex.c new file +275 -0
+
+	if (sr->ip_type == SR_TYPE_V1)
+		sr_v1_disable(sr);
+	else if (sr->ip_type == SR_TYPE_V2)
+		sr_v2_disable(sr);
+
+disable_clocks:
+	pm_runtime_put_sync(&sr->pdev->dev);
+	sr->sr_enable = false;
+}
+
+/**
+ * sr_register_class() - API to register a smartreflex class parameters.
+ * @class_data:	The structure containing various sr class specific data.
+ *
+ * This API is to be called by the smartreflex class driver to register itself
+ * with the smartreflex driver during init. Returns 0 on success else the
+ * error value.
+ */
+int sr_register_class(struct omap_smartreflex_class_data *class_data)
+{
+	struct omap_sr *sr_info;
+
+	if (!class_data) {
+		pr_warning("%s:, Smartreflex class data passed is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (sr_class) {
+		pr_warning("%s: Smartreflex class driver already registered\n",
+			__func__);
+		return -EBUSY;
+	}
+
+	sr_class = class_data;
+
+	/*
+	 * Call into late init to do intializations that require
+	 * both sr driver and sr class driver to be initiallized.
+	 */
+	list_for_each_entry(sr_info, &sr_list, node)
+		sr_late_init(sr_info);
+
+	return 0;
+}
+
+/**
+ * omap_sr_enable() -  API to enable SR clocks and to call into the
+ *			registered smartreflex class enable API.
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the kernel in order to enable
+ * a particular smartreflex module. This API will do the initial
+ * configurations to turn on the smartreflex module and in turn call
+ * into the registered smartreflex class enable API.
+ */
+void omap_sr_enable(struct voltagedomain *voltdm)
+{
+	struct omap_sr *sr = _sr_lookup(voltdm);
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	if (!sr->autocomp_active)
+		return;
+
+	if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
+		dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
+			"registered\n", __func__);
+		return;
+	}
+
+	sr_class->enable(voltdm);
+}
+
+/**
+ * omap_sr_disable() - API to disable SR without resetting the voltage
+ *			processor voltage
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the kernel in order to disable
+ * a particular smartreflex module. This API will in turn call
+ * into the registered smartreflex class disable API. This API will tell
+ * the smartreflex class disable not to reset the VP voltage after
+ * disabling smartreflex.
+ */
+void omap_sr_disable(struct voltagedomain *voltdm)
+{
+	struct omap_sr *sr = _sr_lookup(voltdm);
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	if (!sr->autocomp_active)
+		return;
+
+	if (!sr_class || !(sr_class->disable)) {
+		dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
+			"registered\n", __func__);
+		return;
+	}
+
+	sr_class->disable(voltdm, 0);
+}
+
+/**
+ * omap_sr_disable_reset_volt() - API to disable SR and reset the
+ *				voltage processor voltage
+ * @voltdm:	VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the kernel in order to disable
+ * a particular smartreflex module. This API will in turn call
+ * into the registered smartreflex class disable API. This API will tell
+ * the smartreflex class disable to reset the VP voltage after
+ * disabling smartreflex.
+ */
+void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
+{
+	struct omap_sr *sr = _sr_lookup(voltdm);
+
+	if (IS_ERR(sr)) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	if (!sr->autocomp_active)
+		return;
+
+	if (!sr_class || !(sr_class->disable)) {
+		dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
+			"registered\n", __func__);
+		return;
+	}
+
+	sr_class->disable(voltdm, 1);
+}
+
+/**
+ * omap_sr_register_pmic() - API to register pmic specific info.
+ * @pmic_data:	The structure containing pmic specific data.
+ *
+ * This API is to be called from the PMIC specific code to register with
+ * smartreflex driver pmic specific info. Currently the only info required
+ * is the smartreflex init on the PMIC side.
+ */
+void omap_sr_register_pmic(struct omap_smartreflex_pmic_data *pmic_data)
+{
+	if (!pmic_data) {
+		pr_warning("%s: Trying to register NULL PMIC data structure"
+			"with smartreflex\n", __func__);
+		return;
+	}
+
+	sr_pmic_data = pmic_data;
+}
+
+/* PM Debug Fs enteries to enable disable smartreflex. */
+static int omap_sr_autocomp_show(void *data, u64 *val)
+{
+	struct omap_sr *sr_info = (struct omap_sr *) data;
+
+	if (!sr_info) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, sr_info->voltdm->name);
+		return -EINVAL;
+	}
+
+	*val = sr_info->autocomp_active;
+
+	return 0;
+}
+
+static int omap_sr_autocomp_store(void *data, u64 val)
+{
+	struct omap_sr *sr_info = (struct omap_sr *) data;
+
+	if (!sr_info) {
+		pr_warning("%s: omap_sr struct for sr_%s not found\n",
+			__func__, sr_info->voltdm->name);
+		return -EINVAL;
+	}
+
+	/* Sanity check */
+	if (val && (val != 1)) {
+		pr_warning("%s: Invalid argument %lld\n", __func__, val);
+		return -EINVAL;
+	}
+
+	if (!val)
+		sr_stop_vddautocomp(sr_info);
+	else
+		sr_start_vddautocomp(sr_info);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
+		omap_sr_autocomp_store, "%llu\n");
+
+static int __init omap_smartreflex_probe(struct platform_device *pdev)
+{
+	struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
+	struct omap_device *odev = to_omap_device(pdev);
+	struct omap_sr_data *pdata = pdev->dev.platform_data;
+	struct resource *mem, *irq;
+	struct dentry *dbg_dir;
+	char *name;
+	int ret = 0;
+
+	if (!sr_info) {
+		dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+		return -EINVAL;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
+		ret = -ENODEV;
+		goto err_free_devinfo;
+	}
+
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+	pm_runtime_enable(&pdev->dev);
+
+	sr_info->pdev = pdev;
+	sr_info->srid = pdev->id;
+	sr_info->voltdm = pdata->voltdm;
+	sr_info->autocomp_active = false;
+	sr_info->ip_type = odev->hwmods[0]->class->rev;
+	sr_info->base = ioremap(mem->start, resource_size(mem));
+	if (!sr_info->base) {
+		dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
+		ret = -ENOMEM;
+		goto err_release_region;
+	}
+
+	if (irq)
+		sr_info->irq = irq->start;
+
+	sr_set_clk_length(sr_info);
+	sr_set_regfields(sr_info);
+
+	list_add(&sr_info->node, &sr_list);
+
+	/*
+	 * Call into late init to do intializations that require
+	 * both sr driver and sr class driver to be initiallized.
+	 */
+	if (sr_class) {
+		ret = sr_late_init(sr_info);
+		if (ret) {
+			pr_warning("%s: Error in SR late init\n", __func__);
+			return ret;
+		}
+	}
+
+	dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
+
+	/*
+	 * If the Smartreflex main debugfs directory is not created, do

arch/arm/mach-omap2/smartreflex.c line 894

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+	 * not try to create rest of the debugfs entries.
+	 */
+	if (!sr_dbg_dir)
+		return ret;
+
+	name = kzalloc(SMARTREFLEX_NAME_LEN + 1, GFP_KERNEL);
+	if (!name) {
+		dev_err(&pdev->dev, "%s: Unable to allocate name for"
+			"debufs entry", __func__);
+		return ret;

what will 'ret' be here?

arch/arm/mach-omap2/smartreflex.c line 905

Quoted 11 lines
arch/arm/mach-omap2/smartreflex.c new file +11 -0
+	}
+
+	/* Create the debug fs enteries */
+	strcpy(name, "sr_");
+	strcat(name, sr_info->voltdm->name);
+
+	dbg_dir = debugfs_create_dir(name, sr_dbg_dir);
+	if (IS_ERR(dbg_dir)) {
+		dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
+			__func__);
+		return ret;

or here?

Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c new file +6 -0
+	}
+
+	(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUGO, dbg_dir,
+				(void *)sr_info, &pm_sr_fops);
+
+	return ret;

arch/arm/mach-omap2/smartreflex.c line 921

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+
+err_release_region:
+	release_mem_region(mem->start, resource_size(mem));
+err_free_devinfo:
+	kfree(sr_info);
+
+	return ret;
+}
+
+static int __devexit omap_smartreflex_remove(struct platform_device *pdev)

as an internal function, to be consistent with other naming, this should be sr_remove.

Quoted 8 lines
arch/arm/mach-omap2/smartreflex.c new file +8 -0
+{
+	struct omap_sr_data *pdata = pdev->dev.platform_data;
+	struct omap_sr *sr_info;
+	struct resource *mem;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+		return -EINVAL;

arch/arm/mach-omap2/smartreflex.c line 939

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+	}
+
+	sr_info = _sr_lookup(pdata->voltdm);
+	if (!sr_info) {
+		dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	/* Disable Autocompensation if enabled before removing the module */

surperfluous comment

Quoted 51 lines
arch/arm/mach-omap2/smartreflex.c new file +51 -0
+	if (sr_info->autocomp_active)
+		sr_stop_vddautocomp(sr_info);
+
+	list_del(&sr_info->node);
+	iounmap(sr_info->base);
+	kfree(sr_info);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+
+	return 0;
+}
+
+static struct platform_driver smartreflex_driver = {
+	.remove         = omap_smartreflex_remove,
+	.driver		= {
+		.name	= "smartreflex",
+	},
+};
+
+static int __init sr_init(void)
+{
+	int ret = 0;
+
+	/*
+	 * sr_init is a late init. If by then a pmic specific API is not
+	 * registered either there is no need for anything to be done on
+	 * the PMIC side or somebody has forgotten to register a PMIC
+	 * handler. Warn for the second condition.
+	 */
+	if (sr_pmic_data && sr_pmic_data->sr_pmic_init)
+		sr_pmic_data->sr_pmic_init();
+	else
+		pr_warning("%s: No PMIC hook to init smartreflex\n", __func__);
+
+	if (pm_dbg_main_dir) {
+		struct dentry *d;
+
+		d = debugfs_create_dir("smartreflex", pm_dbg_main_dir);
+		if (!IS_ERR(d))
+			sr_dbg_dir = d;
+	}
+
+	ret = platform_driver_probe(&smartreflex_driver,
+				omap_smartreflex_probe);
+	if (ret) {
+		pr_err("%s: platform driver register failed for SR\n",
+			__func__);
+		return ret;
+	}
+
+	return 0;

arch/arm/mach-omap2/smartreflex.c line 1000

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+}
+
+static void __exit sr_exit(void)
+{
+	platform_driver_unregister(&smartreflex_driver);
+}
+late_initcall(sr_init);
+module_exit(sr_exit);
+
+MODULE_DESCRIPTION("OMAP SMARTREFLEX DRIVER");

"OMAP SmartReflex driver"

Quoted 16 lines
arch/arm/mach-omap2/smartreflex.c new file +3 -0
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
arch/arm/plat-omap/Kconfig +5 -0
index e39a417..8056349 100644
@@ -35,6 +35,38 @@ config OMAP_DEBUG_LEDS
 	depends on OMAP_DEBUG_DEVICES
 	default y if LEDS
 
+config OMAP_SMARTREFLEX
+	bool "SmartReflex support"
+	depends on ARCH_OMAP3 && PM
+	help
+	  Say Y if you want to enable SmartReflex.

arch/arm/plat-omap/Kconfig config OMAP_DEBUG_LEDS · line 52

Quoted 10 lines
arch/arm/plat-omap/Kconfig +10 -0
+
+	  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 VDD1 and VDD2, user must write 1 to

s/VDD1/MPU/
s/VDD2/CORE/

arch/arm/plat-omap/Kconfig config OMAP_DEBUG_LEDS · line 54

Quoted 2 lines
arch/arm/plat-omap/Kconfig +2 -0
+	  /debug/pm_debug/Smartreflex/SR<X>/autocomp,
+	  where X is 1 or 2 for OMAP3

Not fully true, on some SoCs (ES3.1) it's also enabled by default.

Quoted 165 lines
arch/arm/plat-omap/Kconfig +14 -0
+config OMAP_SMARTREFLEX_TESTING
+	bool "Smartreflex testing support"
+	depends on OMAP_SMARTREFLEX
+	default n
+	help
+	  Say Y if you want to enable SmartReflex testing with SW hardcoded
+	  NVALUES intead of E-fuse NVALUES set in factory silicon testing.
+
+	  In some devices the E-fuse values have not been set, even though
+	  SmartReflex modules are included. Using these hardcoded values set
+	  in software, one can test the SmartReflex features without E-fuse.
+
+	  WARNING: Enabling this option may cause your device to hang!
+
 config OMAP_RESET_CLOCKS
 	bool "Reset unused clocks during boot"
 	depends on ARCH_OMAP
arch/arm/plat-omap/include/plat/smartreflex.h new file +142 -0
new file mode 100644
index 0000000..1ad03ea
@@ -0,0 +1,277 @@
+/*
+ * OMAP Smartreflex Defines and Routines
+ *
+ * Author: Thara Gopinath	<[email protected]>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <[email protected]>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <[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.
+ */
+
+#ifndef __ASM_ARM_OMAP_SMARTREFLEX_H
+#define __ASM_ARM_OMAP_SMARTREFLEX_H
+
+#include <linux/platform_device.h>
+#include <plat/voltage.h>
+
+#ifdef CONFIG_PM_DEBUG
+extern struct dentry *pm_dbg_main_dir;
+extern struct dentry *sr_dbg_dir;
+#endif
+
+/*
+ * Different Smartreflex IPs version. The v1 is the 65nm version used in
+ * OMAP3430. The v2 is the update for the 45nm version of the IP
+ * used in OMAP3630 and OMAP4430
+ */
+#define SR_TYPE_V1	1
+#define SR_TYPE_V2	2
+
+/* SMART REFLEX REG ADDRESS OFFSET */
+#define SRCONFIG		0x00
+#define SRSTATUS		0x04
+#define SENVAL			0x08
+#define SENMIN			0x0C
+#define SENMAX			0x10
+#define SENAVG			0x14
+#define AVGWEIGHT		0x18
+#define NVALUERECIPROCAL	0x1c
+#define SENERROR_V1		0x20
+#define ERRCONFIG_V1		0x24
+#define IRQ_EOI			0x20
+#define IRQSTATUS_RAW		0x24
+#define IRQSTATUS		0x28
+#define IRQENABLE_SET		0x2C
+#define IRQENABLE_CLR		0x30
+#define SENERROR_V2		0x34
+#define ERRCONFIG_V2		0x38
+
+/* Bit/Shift Positions */
+
+/* SRCONFIG */
+#define SRCONFIG_ACCUMDATA_SHIFT	22
+#define SRCONFIG_SRCLKLENGTH_SHIFT	12
+#define SRCONFIG_SENNENABLE_V1_SHIFT	5
+#define SRCONFIG_SENPENABLE_V1_SHIFT	3
+#define SRCONFIG_SENNENABLE_V2_SHIFT	1
+#define SRCONFIG_SENPENABLE_V2_SHIFT	0
+#define SRCONFIG_CLKCTRL_SHIFT		0
+
+#define SRCONFIG_ACCUMDATA_MASK		(0x3ff << 22)
+
+#define SRCONFIG_SRENABLE		BIT(11)
+#define SRCONFIG_SENENABLE		BIT(10)
+#define SRCONFIG_ERRGEN_EN		BIT(9)
+#define SRCONFIG_MINMAXAVG_EN		BIT(8)
+#define SRCONFIG_DELAYCTRL		BIT(2)
+
+/* AVGWEIGHT */
+#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT	2
+#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT	0
+
+/* NVALUERECIPROCAL */
+#define NVALUERECIPROCAL_SENPGAIN_SHIFT	20
+#define NVALUERECIPROCAL_SENNGAIN_SHIFT	16
+#define NVALUERECIPROCAL_RNSENP_SHIFT	8
+#define NVALUERECIPROCAL_RNSENN_SHIFT	0
+
+/* ERRCONFIG */
+#define ERRCONFIG_ERRWEIGHT_SHIFT	16
+#define ERRCONFIG_ERRMAXLIMIT_SHIFT	8
+#define ERRCONFIG_ERRMINLIMIT_SHIFT	0
+
+#define SR_ERRWEIGHT_MASK		(0x07 << 16)
+#define SR_ERRMAXLIMIT_MASK		(0xff << 8)
+#define SR_ERRMINLIMIT_MASK		(0xff << 0)
+
+#define ERRCONFIG_VPBOUNDINTEN_V1	BIT(31)
+#define ERRCONFIG_VPBOUNDINTST_V1	BIT(30)
+#define	ERRCONFIG_MCUACCUMINTEN		BIT(29)
+#define ERRCONFIG_MCUACCUMINTST		BIT(28)
+#define	ERRCONFIG_MCUVALIDINTEN		BIT(27)
+#define ERRCONFIG_MCUVALIDINTST		BIT(26)
+#define ERRCONFIG_MCUBOUNDINTEN		BIT(25)
+#define	ERRCONFIG_MCUBOUNDINTST		BIT(24)
+#define	ERRCONFIG_MCUDISACKINTEN	BIT(23)
+#define ERRCONFIG_VPBOUNDINTST_V2	BIT(23)
+#define ERRCONFIG_MCUDISACKINTST	BIT(22)
+#define ERRCONFIG_VPBOUNDINTEN_V2	BIT(22)
+
+#define ERRCONFIG_STATUS_V1_MASK	(ERRCONFIG_VPBOUNDINTST_V1 | \
+					ERRCONFIG_MCUACCUMINTST | \
+					ERRCONFIG_MCUVALIDINTST | \
+					ERRCONFIG_MCUBOUNDINTST | \
+					ERRCONFIG_MCUDISACKINTST)
+/* IRQSTATUS */
+#define IRQSTATUS_MCUACCUMINT		BIT(3)
+#define IRQSTATUS_MCVALIDINT		BIT(2)
+#define IRQSTATUS_MCBOUNDSINT		BIT(1)
+#define IRQSTATUS_MCUDISABLEACKINT	BIT(0)
+
+/* IRQENABLE_SET and IRQENABLE_CLEAR */
+#define IRQENABLE_MCUACCUMINT		BIT(3)
+#define IRQENABLE_MCUVALIDINT		BIT(2)
+#define IRQENABLE_MCUBOUNDSINT		BIT(1)
+#define IRQENABLE_MCUDISABLEACKINT	BIT(0)
+
+/* Common Bit values */
+
+#define SRCLKLENGTH_12MHZ_SYSCLK	0x3c
+#define SRCLKLENGTH_13MHZ_SYSCLK	0x41
+#define SRCLKLENGTH_19MHZ_SYSCLK	0x60
+#define SRCLKLENGTH_26MHZ_SYSCLK	0x82
+#define SRCLKLENGTH_38MHZ_SYSCLK	0xC0
+
+/*
+ * 3430 specific values. Maybe these should be passed from board file or
+ * pmic structures.
+ */
+#define OMAP3430_SR_ACCUMDATA		0x1f4
+
+#define OMAP3430_SR1_SENPAVGWEIGHT	0x03
+#define OMAP3430_SR1_SENNAVGWEIGHT	0x03
+

arch/arm/plat-omap/include/plat/smartreflex.h line 152

Quoted 10 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +10 -0
+#define OMAP3430_SR2_SENPAVGWEIGHT	0x01
+#define OMAP3430_SR2_SENNAVGWEIGHT	0x01
+
+#define OMAP3430_SR_ERRWEIGHT		0x04
+#define OMAP3430_SR_ERRMAXLIMIT		0x02
+
+/* TODO:3630/OMAP4 values if it has to come from this file */
+
+/**
+ * omap_smartreflex_dev_data - Smartreflex device specific data

omap_sr..

Quoted 32 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +32 -0
+ * @volts_supported	: Number of distinct voltages possible for the VDD
+ *			  associated with this smartreflex module.
+ * @efuse_sr_control	: The regisrter offset of control_fuse_sr efuse
+ *			  register from which sennenable and senpenable values
+ *			  are obtained.
+ * @sennenable_shift	: The shift in the control_fuse_sr register for
+ *			  obtaining the sennenable value for this smartreflex
+ *			  module.
+ * @senpenable_shift	: The shift in the control_fuse_sr register for
+ *			  obtaining the senpenable value for this smartreflex
+ *			  module.
+ * @efuse_nvalues_offs	: Array of efuse offsets from which ntarget values can
+ *			  be retrieved. Number of efuse offsets in this arrray
+ *			  is equal to the volts_supported value ie one efuse
+ *			  register per supported voltage.
+ * @test_sennenable	: SENNENABLE test value
+ * @test_senpenable	: SENPENABLE test value.
+ * @test_nvalues	: Array of test ntarget values.
+ * @vdd_name		: Name of the voltage domain associated with this
+ *			  Smartreflex device.
+ * @volt_data		: Voltage table associated with this smartreflex module
+ */
+struct omap_sr_dev_data {
+	int volts_supported;
+	u32 efuse_sr_control;
+	u32 sennenable_shift;
+	u32 senpenable_shift;
+	u32 *efuse_nvalues_offs;
+	u32 test_sennenable;
+	u32 test_senpenable;
+	u32 *test_nvalues;
+	char *vdd_name;

arch/arm/plat-omap/include/plat/smartreflex.h line 195

Quoted 10 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +10 -0
+	struct omap_volt_data *volt_data;
+};
+
+/**
+ * omap_smartreflex_pmic_data : Strucutre to be populated by pmic code to pass
+ * pmic specific info to smartreflex driver
+ *
+ * @sr_pmic_init - API to initialize smartreflex on the PMIC side.
+ */
+struct omap_smartreflex_pmic_data {

omap_sr..

Quoted 6 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +6 -0
+	void (*sr_pmic_init) (void);
+};
+
+#ifdef CONFIG_OMAP_SMARTREFLEX
+/*
+ * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.

arch/arm/plat-omap/include/plat/smartreflex.h line 211

Quoted 10 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +10 -0
+ * The smartreflex class driver should pass the class type.
+ * Should be used to populate the class_type field of the
+ * omap_smartreflex_class_data structure.
+ */
+#define SR_CLASS1	0x1
+#define SR_CLASS2	0x2
+#define SR_CLASS3	0x3
+
+/**
+ * omap_smartreflex_class_data : Structure to be populated by

omap_sr...

arch/arm/plat-omap/include/plat/smartreflex.h line 223

Quoted 12 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +12 -0
+ * Smartreflex class driver with corresponding class enable disable API's
+ *
+ * @enable - API to enable a particular class smaartreflex.
+ * @disable - API to disable a particular class smartreflex.
+ * @configure - API to configure a particular class smartreflex.
+ * @notify - API to notify the class driver about an event in SR. Not needed
+ *		for class3.
+ * @notify_flags - specify the events to be notified to the class driver
+ * @class_type - specify which smartreflex class. Can be used by the SR driver
+ *		to take any class based decisions.
+ */
+struct omap_smartreflex_class_data {

omap_sr

arch/arm/plat-omap/include/plat/smartreflex.h line 233

Quoted 10 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +10 -0
+	int (*enable)(struct voltagedomain *voltdm);
+	int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
+	int (*configure)(struct voltagedomain *voltdm);
+	int (*notify)(struct voltagedomain *voltdm, u32 status);
+	u8 notify_flags;
+	u8 class_type;
+};
+
+/**
+ * omap_smartreflex_data - Smartreflex platform data

omap_sr

Quoted 9 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +9 -0
+ * @senp_mod		: SENPENABLE value for the sr
+ * @senn_mod		: SENNENABLE value for sr
+ * @sr_nvalue		: array of n target values for sr
+ * @enable_on_init	: whether this sr module needs to enabled at
+ *			  boot up or not.
+ * @voltdm		: Pointer to the voltage domain associated with the SR
+ */
+struct omap_sr_data {
+	u32				senp_mod;

arch/arm/plat-omap/include/plat/smartreflex.h line 253

Quoted 10 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +10 -0
+	u32				senn_mod;
+	bool				enable_on_init;
+	struct voltagedomain		*voltdm;
+};
+
+/*
+ * Smartreflex module enable/disable interface.
+ * NOTE: if smartreflex is not enabled from sysfs, these functions will not
+ * do anything.
+ */

The 'NOTE' comment isn't quite accurate (and probably not needed here.) The 'enable_on_init' flag is another way besides sysfs for these functions to be activated.

This enable_on_init flag (also settable by board files) should probably be mentioned in the changelog too where you mention how SR can be enabled.

Quoted 14 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +14 -0
+void omap_sr_enable(struct voltagedomain *voltdm);
+void omap_sr_disable(struct voltagedomain *voltdm);
+void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
+
+/* API to register the pmic specific data with the smartreflex driver. */
+void omap_sr_register_pmic(struct omap_smartreflex_pmic_data *pmic_data);
+
+/* Smartreflex driver hooks to be called from Smartreflex class driver */
+int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
+void sr_disable(struct voltagedomain *voltdm);
+int sr_configure_errgen(struct voltagedomain *voltdm);
+int sr_configure_minmax(struct voltagedomain *voltdm);
+
+/* API to register the smartreflex class driver with the smartreflex driver */

arch/arm/plat-omap/include/plat/smartreflex.h line 277

Quoted 10 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +10 -0
+int sr_register_class(struct omap_smartreflex_class_data *class_data);
+#else
+static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
+static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
+static inline void omap_sr_disable_reset_volt(
+		struct voltagedomain *voltdm) {}
+static inline void omap_sr_register_pmic(
+		struct omap_smartreflex_pmic_data *pmic_data) {}
+#endif
+#endif

Kevin

#17 lore raw

RE: [PATCH v3 03/11] OMAP3: PM: Adding smartreflex driver support.

Quoted 24 lines
Quoted 24 lines

-----Original Message-----
From: Kevin Hilman [mailto:[email protected]]
Sent: Thursday, October 14, 2010 5:34 AM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 03/11] OMAP3: PM: Adding smartreflex driver support.

Quoted 12 lines · 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

Quoted 5 lines
Quoted 5 lines
Quoted 2 lines

OMAP3 has two smartreflex modules one associated with VDD1 and the other associated with VDD2.

s/VDD1/MPU/
s/VDD2/CORE/

Will correct.

Quoted 86 lines
Quoted 86 lines
Quoted 20 lines

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 > /debugfs/pm_debug/smartreflex/sr_<X>/autocomp
To disable smartreflex autocompensation feature
echo 0 > /debugfs/pm_debug/smartreflex/sr_<X>/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.

Quoted 4 lines
---
 arch/arm/mach-omap2/Makefile                  |    1 +
 arch/arm/mach-omap2/smartreflex.c             | 1003

+++++++++++++++++++++++++

arch/arm/mach-omap2/Makefile obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o

Quoted 11 lines
 arch/arm/plat-omap/Kconfig                    |   32 +
 arch/arm/plat-omap/include/plat/smartreflex.h |  277 +++++++
 4 files changed, 1313 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 +0 -0
index 4f74f2b..8dd32a7 100644
@@ -56,6 +56,7 @@ obj-$(CONFIG_ARCH_OMAP3)          += pm34xx.o sleep34xx.o

voltage.o \

arch/arm/mach-

Quoted 8 lines
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
+obj-$(CONFIG_OMAP_SMARTREFLEX)          += smartreflex.o
 
 AFLAGS_sleep24xx.o                 :=-Wa,-march=armv6
 AFLAGS_sleep34xx.o                 :=-Wa,-march=armv7-a
arch/arm/mach- renamed from arch/arm/mach-omap2/smartreflex.c +0 -0

omap2/smartreflex.c

Quoted 40 lines

new file mode 100644
index 0000000..7fc3138

arch/arm/mach-omap2/smartreflex.c new file +35 -0
@@ -0,0 +1,1003 @@
+/*
+ * OMAP SmartReflex Voltage Control
+ *
+ * Author: Thara Gopinath  <[email protected]>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <[email protected]>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <[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.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+#include <plat/omap_device.h>
+#include <plat/common.h>
+#include <plat/smartreflex.h>
+
+#include "pm.h"
+
+#define SMARTREFLEX_NAME_LEN       16
+#define SR_DISABLE_TIMEOUT 200
Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/smartreflex.c line 41

Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c new file +6 -0
+
+struct dentry *sr_dbg_dir;
+
+struct omap_sr {
+   int                     srid;
+   bool                    sr_enable;

sr_enabled is a better name

Ok.

Quoted 40 lines
Quoted 40 lines
Quoted 14 lines
arch/arm/mach-omap2/smartreflex.c new file +13 -0
+   bool                    autocomp_active;
+   int                     ip_type;
+   u32                     clk_length;
+   u32                     err_weight;
+   u32                     err_minlimit;
+   u32                     err_maxlimit;
+   u32                     accum_data;
+   u32                     senn_avgweight;
+   u32                     senp_avgweight;
+   unsigned int            irq;
+   void __iomem            *base;
+   struct platform_device  *pdev;
+   struct list_head        node;

arch/arm/mach-omap2/smartreflex.c

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+   struct voltagedomain    *voltdm;
+};
+
+/* sr_list contains all the instances of smartreflex module */
+static LIST_HEAD(sr_list);
+
+static struct omap_smartreflex_class_data *sr_class;
+static struct omap_smartreflex_pmic_data *sr_pmic_data;
+
+static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32

value)

arch/arm/mach-omap2/smartreflex.c

Quoted 5 lines
arch/arm/mach-omap2/smartreflex.c new file +5 -0
+{
+   __raw_writel(value, (sr->base + offset));
+}
+
+static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32

mask,

Quoted 9 lines
arch/arm/mach-omap2/smartreflex.c new file +9 -0
+                                   u32 value)
+{
+   u32 reg_val;
+   u32 errconfig_offs, errconfig_mask;
+
+   reg_val = __raw_readl(sr->base + offset);
+   reg_val &= ~mask;
+
+   /*
Quoted 8 lines
Quoted 8 lines

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

Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c new file +6 -0
+    * Smartreflex error config register is special as it contains
+    * certain status bits which if written a 1 into means a clear
+    * of those bits. So in order to make sure no accidental write of
+    * 1 happens to those status bits, do a clear of them in the read
+    * value. Now if there is an actual reguest to write to these bits
+    * they will be set in the nex step.

s/nex/next/

typo.. will correct

Quoted 7 lines
Quoted 7 lines

that being said, it's not clear what "the next step" is in this context. There is only one write.

This should be rephrased to say (something like) it doesn't rewrite values in these bits if they are currently set, but does allow the caller to write those bits.

I will rephrase this.

Quoted 40 lines
Quoted 40 lines
Quoted 40 lines
arch/arm/mach-omap2/smartreflex.c new file +38 -0
+    */
+   if (sr->ip_type == SR_TYPE_V1) {
+           errconfig_offs = ERRCONFIG_V1;
+           errconfig_mask = ERRCONFIG_STATUS_V1_MASK;
+   } else if (sr->ip_type == SR_TYPE_V2) {
+           errconfig_offs = ERRCONFIG_V2;
+           errconfig_mask = ERRCONFIG_VPBOUNDINTST_V2;
+   }
+
+   if (offset == errconfig_offs)
+           reg_val &= ~errconfig_mask;
+
+   reg_val |= value;
+
+   __raw_writel(reg_val, (sr->base + offset));
+}
+
+static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
+{
+   return __raw_readl(sr->base + offset);
+}
+
+static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm)
+{
+   struct omap_sr *sr_info;
+
+   if (!voltdm) {
+           pr_err("%s: Null voltage domain passed!\n", __func__);
+           return ERR_PTR(-EINVAL);
+   }
+
+   list_for_each_entry(sr_info, &sr_list, node) {
+           if (voltdm == sr_info->voltdm)
+                   return sr_info;
+   }
+
+   return ERR_PTR(-ENODATA);
+}
Quoted 3 lines
Quoted 3 lines

arch/arm/mach-omap2/smartreflex.c line 124

Quoted 1 line
arch/arm/mach-omap2/smartreflex.c new file +1 -0
+static irqreturn_t sr_omap_isr(int irq, void *data)

Please rename to sr_interrupt

Will do.

Quoted 13 lines
Quoted 13 lines

arch/arm/mach-omap2/smartreflex.c line 134

Quoted 11 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+{
+   struct omap_sr *sr_info = (struct omap_sr *)data;
+   u32 status = 0;
+
+   if (sr_info->ip_type == SR_TYPE_V1) {
+           /* Read the status bits */
+           status = sr_read_reg(sr_info, ERRCONFIG_V1);
+
+           /* Clear them by writing back */
+           sr_write_reg(sr_info, ERRCONFIG_V1, status);

Shouldn't you be using sr_modify_reg for ERRCONFIG_V1?

Nope. I am doing a read followed by writing the same value back. No need of using modify

Quoted 11 lines
Quoted 11 lines

arch/arm/mach-omap2/smartreflex.c line 141

Quoted 8 lines
arch/arm/mach-omap2/smartreflex.c new file +7 -0
+   } else if (sr_info->ip_type == SR_TYPE_V2) {
+           /* Read the status bits */
+           sr_read_reg(sr_info, IRQSTATUS);
+
+           /* Clear them by writing back */
+           sr_write_reg(sr_info, IRQSTATUS, status);
+   }

Might as well use it for both.

Quoted 7 lines
Quoted 7 lines

arch/arm/mach-omap2/smartreflex.c line 142

Quoted 2 lines
arch/arm/mach-omap2/smartreflex.c new file +2 -0
+
+   /* Call the class driver notify function if registered*/

This comment does not add anything the code doesn't make clear, and is not fully correct: it has to be registered, and be class 2.

IMO, you can just remove comments like this that aren't be

Will remove this comment

Quoted 124 lines
Quoted 124 lines
Quoted 110 lines
arch/arm/mach-omap2/smartreflex.c new file +109 -0
+   if (sr_class->class_type == SR_CLASS2 && sr_class->notify)
+           sr_class->notify(sr_info->voltdm, status);
+
+   return IRQ_HANDLED;
+}
+
+static void sr_set_clk_length(struct omap_sr *sr)
+{
+   struct clk *sys_ck;
+   u32 sys_clk_speed;
+
+   sys_ck = clk_get(NULL, "sys_ck");
+   if (IS_ERR(sys_ck)) {
+           dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n",
+                   __func__);
+           return;
+   }
+   sys_clk_speed = clk_get_rate(sys_ck);
+   clk_put(sys_ck);
+
+   switch (sys_clk_speed) {
+   case 12000000:
+           sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
+           break;
+   case 13000000:
+           sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK;
+           break;
+   case 19200000:
+           sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK;
+           break;
+   case 26000000:
+           sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK;
+           break;
+   case 38400000:
+           sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
+           break;
+   default:
+           dev_err(&sr->pdev->dev, "%s: Invalid sysclk value: %d\n",
+                   __func__, sys_clk_speed);
+           break;
+   }
+}
+
+static void sr_set_regfields(struct omap_sr *sr)
+{
+   /*
+    * For time being these values are defined in smartreflex.h
+    * and populated during init. May be they can be moved to board
+    * file or pmic specific data structure. In that case these structure
+    * fields will have to be populated using the pdata or pmic structure.
+    */
+   if (cpu_is_omap34xx()) {
+           sr->err_weight = OMAP3430_SR_ERRWEIGHT;
+           sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
+           sr->accum_data = OMAP3430_SR_ACCUMDATA;
+           if (!(strcmp(sr->voltdm->name, "mpu"))) {
+                   sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
+                   sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
+           } else {
+                   sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
+                   sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
+           }
+   }
+   /* TODO: 3630 and Omap4 specific bit field values */
+}
+
+static void sr_start_vddautocomp(struct omap_sr *sr)
+{
+   if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
+           dev_warn(&sr->pdev->dev,
+                   "%s: smartreflex class driver not registered\n",
+                   __func__);
+           return;
+   }
+
+   if (!sr_class->enable(sr->voltdm))
+           sr->autocomp_active = true;
+}
+
+static void sr_stop_vddautocomp(struct omap_sr *sr)
+{
+   if (!sr_class || !(sr_class->disable)) {
+           dev_warn(&sr->pdev->dev,
+                   "%s: smartreflex class driver not registered\n",
+                   __func__);
+           return;
+   }
+
+   if (sr->autocomp_active) {
+           sr_class->disable(sr->voltdm, 1);
+           sr->autocomp_active = false;
+   }
+}
+
+/*
+ * This function handles the intializations which have to be done
+ * only when both sr device and class driver regiter has
+ * completed. This will be attempted to be called from both sr class
+ * driver register and sr device intializtion API's. Only one call
+ * will ultimately succeed.
+ *
+ * Currenly this function registers interrrupt handler for a particular SR
+ * if smartreflex class driver is already registered and has
+ * requested for interrupts and the SR interrupt line in present.
+ */
+static int sr_late_init(struct omap_sr *sr_info)
+{
+   char *name;
+   struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data;

arch/arm/mach-omap2/smartreflex.c line 262

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+   int ret = 0;
+
+   if (sr_class->class_type == SR_CLASS2 &&
+           sr_class->notify_flags && sr_info->irq) {
+
+           name = kzalloc(SMARTREFLEX_NAME_LEN + 1, GFP_KERNEL);
+           strcpy(name, "sr_");
+           strcat(name, sr_info->voltdm->name);
+           ret = request_irq(sr_info->irq, sr_omap_isr,
+                           IRQF_DISABLED, name, (void *)sr_info);

Why does this have to be IRQF_DISABLED? This capability will be
disappearing from the kernel soon.

Quoted 2 lines
Quoted 2 lines

Because there are no current users, I cannot tell, but I suspect this could be use request_threaded_irq. If not, please justify.

Why should this be request_threaded_irq?? I have to check to learn the differnces.

Quoted 5 lines
Quoted 5 lines

arch/arm/mach-omap2/smartreflex.c line 262

Quoted 2 lines
arch/arm/mach-omap2/smartreflex.c new file +1 -0
+           if (ret) {
                        goto error;
Quoted 16 lines
Quoted 8 lines
Quoted 8 lines
arch/arm/mach-omap2/smartreflex.c new file +8 -0
+                   struct resource *mem;
+
+                   iounmap(sr_info->base);
+                   mem = platform_get_resource(sr_info->pdev,
+                           IORESOURCE_MEM, 0);
+                   release_mem_region(mem->start, resource_size(mem));
+                   list_del(&sr_info->node);
+                   dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
Quoted 8 lines

arch/arm/mach-omap2/smartreflex.c line 277

Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c new file +6 -0
+                           "interrupt handler. Smartreflex will"
+                           "not function as desired\n", __func__);
+
+                   kfree(sr_info);
+                   return ret;
+           }

and move this after the return...

I did not understand this comment.

Quoted 122 lines
Quoted 122 lines

arch/arm/mach-omap2/smartreflex.c line 283

Quoted 7 lines
arch/arm/mach-omap2/smartreflex.c new file +6 -0
+   }
+
+   if (pdata && pdata->enable_on_init)
+           sr_start_vddautocomp(sr_info);
+
+   return ret;

error:

(here.)

Quoted 69 lines
arch/arm/mach-omap2/smartreflex.c new file +69 -0
+}
+
+static void sr_v1_disable(struct omap_sr *sr)
+{
+   int timeout = 0;
+
+   /* Enable MCUDisableAcknowledge interrupt */
+   sr_modify_reg(sr, ERRCONFIG_V1,
+                   ERRCONFIG_MCUDISACKINTEN, ERRCONFIG_MCUDISACKINTEN);
+
+   /* SRCONFIG - disable SR */
+   sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
+
+   /* Disable all other SR interrupts and clear the status */
+   sr_modify_reg(sr, ERRCONFIG_V1,
+                   (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
+                   ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1),
+                   (ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
+                   ERRCONFIG_MCUBOUNDINTST |
+                   ERRCONFIG_VPBOUNDINTST_V1));
+
+   /*
+    * Wait for SR to be disabled.
+    * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us.
+    */
+   omap_test_timeout((sr_read_reg(sr, ERRCONFIG_V1) &
+                   ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT,
+                   timeout);
+
+   if (timeout >= SR_DISABLE_TIMEOUT)
+           dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
+                   __func__);
+
+   /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
+   sr_modify_reg(sr, ERRCONFIG_V1, ERRCONFIG_MCUDISACKINTEN,
+                   ERRCONFIG_MCUDISACKINTST);
+}
+
+static void sr_v2_disable(struct omap_sr *sr)
+{
+   int timeout = 0;
+
+   /* Enable MCUDisableAcknowledge interrupt */
+   sr_write_reg(sr, IRQENABLE_SET, IRQENABLE_MCUDISABLEACKINT);
+
+   /* SRCONFIG - disable SR */
+   sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
+
+   /* Disable all other SR interrupts and clear the status */
+   sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
+                   ERRCONFIG_VPBOUNDINTST_V2);
+   sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT |
+                   IRQENABLE_MCUVALIDINT |
+                   IRQENABLE_MCUBOUNDSINT));
+   sr_write_reg(sr, IRQSTATUS, (IRQSTATUS_MCUACCUMINT |
+                   IRQSTATUS_MCVALIDINT |
+                   IRQSTATUS_MCBOUNDSINT));
+
+   /*
+    * Wait for SR to be disabled.
+    * wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us.
+    */
+   omap_test_timeout((sr_read_reg(sr, IRQSTATUS) &
+                   IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT,
+                   timeout);
+
+   if (timeout >= SR_DISABLE_TIMEOUT)
+           dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
+                   __func__);

arch/arm/mach-omap2/smartreflex.c

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+
+   /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
+   sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT);
+   sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
+}
+
+/* Public Functions */
+
+/**
+ * sr_configure_errgen() - Configures the smrtreflex to perform AVS using

the

arch/arm/mach-omap2/smartreflex.c line 363

Quoted 2 lines
arch/arm/mach-omap2/smartreflex.c new file +2 -0
+ *                  error generator module.
+ * @voltdm:        VDD pointer to which the SR module to be configured belongs

to.

Quoted 27 lines
arch/arm/mach-omap2/smartreflex.c new file +27 -0
+ *
+ * This API is to be called from the smartreflex class driver to
+ * configure the error generator module inside the smartreflex module.
+ * SR settings if using the ERROR module inside Smartreflex.
+ * SR CLASS 3 by default uses only the ERROR module where as
+ * SR CLASS 2 can choose between ERROR module and MINMAXAVG
+ * module. Returns 0 on success and error value in case of failure.
+ */
+int sr_configure_errgen(struct voltagedomain *voltdm)
+{
+   u32 sr_config, sr_errconfig, errconfig_offs, vpboundint_en;
+   u32 vpboundint_st, senp_en = 0, senn_en = 0;
+   u8 senp_shift, senn_shift;
+   struct omap_sr *sr = _sr_lookup(voltdm);
+   struct omap_sr_data *pdata;
+
+   if (IS_ERR(sr)) {
+           pr_warning("%s: omap_sr struct for sr_%s not found\n",
+                   __func__, voltdm->name);
+           return -EINVAL;
+   }
+
+   pdata = sr->pdev->dev.platform_data;
+
+   if (!sr->clk_length)
+           sr_set_clk_length(sr);
+
Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/smartreflex.c line 396

Quoted 5 lines
arch/arm/mach-omap2/smartreflex.c new file +5 -0
+   if (pdata) {
+           senp_en = pdata->senp_mod;
+           senn_en = pdata->senn_mod;
+   } else {
+           dev_warn(&sr->pdev->dev, "%s: Missing pdata\n", __func__);

This is more of an error condition, and should probably return here with an error. Otherwise undefined values are used below.

Ok. Will return.

Quoted 73 lines
Quoted 73 lines
Quoted 33 lines
arch/arm/mach-omap2/smartreflex.c new file +32 -0
+   }
+
+   sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
+           SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN;
+
+   if (sr->ip_type == SR_TYPE_V1) {
+           sr_config |= SRCONFIG_DELAYCTRL;
+           senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
+           senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
+           errconfig_offs = ERRCONFIG_V1;
+           vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
+           vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
+   } else if (sr->ip_type == SR_TYPE_V2) {
+           senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
+           senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
+           errconfig_offs = ERRCONFIG_V2;
+           vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
+           vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
+   } else {
+           dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
+                   "module without specifying the ip\n", __func__);
+           return -EINVAL;
+   }
+
+   sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
+   sr_write_reg(sr, SRCONFIG, sr_config);
+   sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
+           (sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
+           (sr->err_minlimit <<  ERRCONFIG_ERRMINLIMIT_SHIFT);
+   sr_modify_reg(sr, errconfig_offs, (SR_ERRWEIGHT_MASK |
+           SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
+           sr_errconfig);

arch/arm/mach-omap2/smartreflex.c

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+
+   /* Enabling the interrupts if the ERROR module is used */
+   sr_modify_reg(sr, errconfig_offs,
+           vpboundint_en, (vpboundint_en | vpboundint_st));
+
+   return 0;
+}
+
+/**
+ * sr_configure_minmax() - Configures the smrtreflex to perform AVS using

the

arch/arm/mach-omap2/smartreflex.c line 439

Quoted 2 lines
arch/arm/mach-omap2/smartreflex.c new file +2 -0
+ *                  minmaxavg module.
+ * @voltdm:        VDD pointer to which the SR module to be configured belongs

to.

Quoted 26 lines
arch/arm/mach-omap2/smartreflex.c new file +26 -0
+ *
+ * This API is to be called from the smartreflex class driver to
+ * configure the minmaxavg module inside the smartreflex module.
+ * SR settings if using the ERROR module inside Smartreflex.
+ * SR CLASS 3 by default uses only the ERROR module where as
+ * SR CLASS 2 can choose between ERROR module and MINMAXAVG
+ * module. Returns 0 on success and error value in case of failure.
+ */
+int sr_configure_minmax(struct voltagedomain *voltdm)
+{
+   u32 sr_config, sr_avgwt;
+   u32 senp_en = 0, senn_en = 0;
+   u8 senp_shift, senn_shift;
+   struct omap_sr *sr = _sr_lookup(voltdm);
+   struct omap_sr_data *pdata;
+
+   if (IS_ERR(sr)) {
+           pr_warning("%s: omap_sr struct for sr_%s not found\n",
+                   __func__, voltdm->name);
+           return -EINVAL;
+   }
+
+   pdata = sr->pdev->dev.platform_data;
+
+   if (!sr->clk_length)
+           sr_set_clk_length(sr);
Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/smartreflex.c line 396

Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c new file +6 -0
+
+   if (pdata) {
+           senp_en = pdata->senp_mod;
+           senn_en = pdata->senn_mod;
+   } else {
+           dev_warn(&sr->pdev->dev, "%s: Missing pdata\n", __func__);

same as above

Will do the necessary

Quoted 89 lines
Quoted 89 lines
Quoted 42 lines
arch/arm/mach-omap2/smartreflex.c new file +41 -0
+   }
+
+   sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
+           SRCONFIG_SENENABLE |
+           (sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
+
+   if (sr->ip_type == SR_TYPE_V1) {
+           sr_config |= SRCONFIG_DELAYCTRL;
+           senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
+           senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
+   } else if (sr->ip_type == SR_TYPE_V2) {
+           senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
+           senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
+   } else {
+           dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
+                   "module without specifying the ip\n", __func__);
+           return -EINVAL;
+   }
+
+   sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
+   sr_write_reg(sr, SRCONFIG, sr_config);
+   sr_avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
+           (sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT);
+   sr_write_reg(sr, AVGWEIGHT, sr_avgwt);
+
+   /*
+    * Enabling the interrupts if MINMAXAVG module is used.
+    * TODO: check if all the interrupts are mandatory
+    */
+   if (sr->ip_type == SR_TYPE_V1) {
+           sr_modify_reg(sr, ERRCONFIG_V1,
+                   (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
+                   ERRCONFIG_MCUBOUNDINTEN),
+                   (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST |
+                    ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST |
+                    ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST));
+   } else if (sr->ip_type == SR_TYPE_V2) {
+           sr_write_reg(sr, IRQSTATUS,
+                   IRQSTATUS_MCUACCUMINT | IRQSTATUS_MCVALIDINT |
+                   IRQSTATUS_MCBOUNDSINT | IRQSTATUS_MCUDISABLEACKINT);
+           sr_write_reg(sr, IRQENABLE_SET,

arch/arm/mach-omap2/smartreflex.c

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+                   IRQENABLE_MCUACCUMINT | IRQENABLE_MCUVALIDINT |
+                   IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT);
+   }
+
+   return 0;
+}
+
+/**
+ * sr_enable() - Enables the smartreflex module.
+ * @voltdm:        VDD pointer to which the SR module to be configured belongs

to.

Quoted 36 lines
arch/arm/mach-omap2/smartreflex.c new file +36 -0
+ * @volt:  The voltage at which the Voltage domain associated with
+ *         the smartreflex module is operating at.
+ *         This is required only to program the correct Ntarget value.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * enable a smartreflex module. Returns 0 on success. Returns error
+ * value if the voltage passed is wrong or if ntarget value is wrong.
+ */
+int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
+{
+   u32 nvalue_reciprocal;
+   struct omap_volt_data *volt_data;
+   struct omap_sr *sr = _sr_lookup(voltdm);
+   int ret;
+
+   if (IS_ERR(sr)) {
+           pr_warning("%s: omap_sr struct for sr_%s not found\n",
+                   __func__, voltdm->name);
+           return -EINVAL;
+   }
+
+   volt_data = omap_voltage_get_voltdata(voltdm, volt);
+
+   if (IS_ERR(volt_data)) {
+           dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table"
+                   " for nominal voltage %ld\n", __func__, volt);
+           return -ENODATA;
+   }
+
+   nvalue_reciprocal = volt_data->sr_nvalue;
+
+   if (!nvalue_reciprocal) {
+           dev_warn(&sr->pdev->dev, "%s: NVALUE = 0 at voltage %ld\n",
+                   __func__, volt);
+           return -ENODATA;
+   }
Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/smartreflex.c line 564

Quoted 5 lines
arch/arm/mach-omap2/smartreflex.c new file +5 -0
+
+   /* errminlimit is opp dependent and hence linked to voltage */
+   sr->err_minlimit = volt_data->sr_errminlimit;
+
+   /* Enable the clocks */

not just clocs are enabled by pm_runtime_get(). Again, probably just removing the comment is better.

Will remove

Quoted 9 lines
Quoted 9 lines

arch/arm/mach-omap2/smartreflex.c line 568

Quoted 5 lines
arch/arm/mach-omap2/smartreflex.c new file +4 -0
+   if (!sr->sr_enable) {
+           pm_runtime_get_sync(&sr->pdev->dev);
+           sr->sr_enable = true;
+   }

But, I'm not sure why you need this sr_enabled flag. Here, you could just do pm_runtime_get_sync() and rely on the usecounting done in the runtime PM core...

sr_enable flag is used in sr_disable() API to check if we really need to disable sr or not.

Quoted 31 lines
Quoted 31 lines
Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +9 -0
+   /* Check if SR is already enabled. If yes do nothing */
+   if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE)
+           return 0;
+
+   /* Configure SR */
+   ret = sr_class->configure(voltdm);
+   if (ret)
+           return ret;
+

arch/arm/mach-omap2/smartreflex.c

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+   sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
+
+   /* SRCONFIG - enable SR */
+   sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
+   return 0;
+}
+
+/**
+ * sr_disable() - Disables the smartreflex module.
+ * @voltdm:        VDD pointer to which the SR module to be configured belongs

to.

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+ *
+ * This API is to be called from the smartreflex class driver to
+ * disable a smartreflex module.
+ */
+void sr_disable(struct voltagedomain *voltdm)
+{
+   struct omap_sr *sr = _sr_lookup(voltdm);
+
+   if (IS_ERR(sr)) {
+           pr_warning("%s: omap_sr struct for sr_%s not found\n",
Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/smartreflex.c line 604

Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c new file +6 -0
+                   __func__, voltdm->name);
+           return;
+   }
+
+   /* Check if SR clocks are already disabled. If yes do nothing */
+   if (!sr->sr_enable)

...and here you just check pm_runtime_is_suspended()

mmmm.. I will give this a try.

Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/smartreflex.c line 609

Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c new file +5 -0
+           return;
+
+   /* Check if SR is already disabled. If yes just disable the clocks */
+   if (!(sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE))
+           goto disable_clocks;

drop the goto and just indent the next block

Ok will do.

Quoted 285 lines
Quoted 285 lines
Quoted 5 lines
arch/arm/mach-omap2/smartreflex.c new file +4 -0
+
+   if (sr->ip_type == SR_TYPE_V1)
+           sr_v1_disable(sr);
+   else if (sr->ip_type == SR_TYPE_V2)

arch/arm/mach-omap2/smartreflex.c

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+           sr_v2_disable(sr);
+
+disable_clocks:
+   pm_runtime_put_sync(&sr->pdev->dev);
+   sr->sr_enable = false;
+}
+
+/**
+ * sr_register_class() - API to register a smartreflex class parameters.
+ * @class_data:    The structure containing various sr class specific

data.

arch/arm/mach-omap2/smartreflex.c line 623

Quoted 2 lines
arch/arm/mach-omap2/smartreflex.c new file +2 -0
+ *
+ * This API is to be called by the smartreflex class driver to register

itself

Quoted 25 lines
arch/arm/mach-omap2/smartreflex.c new file +25 -0
+ * with the smartreflex driver during init. Returns 0 on success else the
+ * error value.
+ */
+int sr_register_class(struct omap_smartreflex_class_data *class_data)
+{
+   struct omap_sr *sr_info;
+
+   if (!class_data) {
+           pr_warning("%s:, Smartreflex class data passed is NULL\n",
+                   __func__);
+           return -EINVAL;
+   }
+
+   if (sr_class) {
+           pr_warning("%s: Smartreflex class driver already registered\n",
+                   __func__);
+           return -EBUSY;
+   }
+
+   sr_class = class_data;
+
+   /*
+    * Call into late init to do intializations that require
+    * both sr driver and sr class driver to be initiallized.
+    */

arch/arm/mach-omap2/smartreflex.c

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+   list_for_each_entry(sr_info, &sr_list, node)
+           sr_late_init(sr_info);
+
+   return 0;
+}
+
+/**
+ * omap_sr_enable() -  API to enable SR clocks and to call into the
+ *                 registered smartreflex class enable API.
+ * @voltdm:        VDD pointer to which the SR module to be configured belongs

to.

Quoted 22 lines
arch/arm/mach-omap2/smartreflex.c new file +22 -0
+ *
+ * This API is to be called from the kernel in order to enable
+ * a particular smartreflex module. This API will do the initial
+ * configurations to turn on the smartreflex module and in turn call
+ * into the registered smartreflex class enable API.
+ */
+void omap_sr_enable(struct voltagedomain *voltdm)
+{
+   struct omap_sr *sr = _sr_lookup(voltdm);
+
+   if (IS_ERR(sr)) {
+           pr_warning("%s: omap_sr struct for sr_%s not found\n",
+                   __func__, voltdm->name);
+           return;
+   }
+
+   if (!sr->autocomp_active)
+           return;
+
+   if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
+           dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
+                   "registered\n", __func__);

arch/arm/mach-omap2/smartreflex.c

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+           return;
+   }
+
+   sr_class->enable(voltdm);
+}
+
+/**
+ * omap_sr_disable() - API to disable SR without resetting the voltage
+ *                 processor voltage
+ * @voltdm:        VDD pointer to which the SR module to be configured belongs

to.

Quoted 23 lines
arch/arm/mach-omap2/smartreflex.c new file +23 -0
+ *
+ * This API is to be called from the kernel in order to disable
+ * a particular smartreflex module. This API will in turn call
+ * into the registered smartreflex class disable API. This API will tell
+ * the smartreflex class disable not to reset the VP voltage after
+ * disabling smartreflex.
+ */
+void omap_sr_disable(struct voltagedomain *voltdm)
+{
+   struct omap_sr *sr = _sr_lookup(voltdm);
+
+   if (IS_ERR(sr)) {
+           pr_warning("%s: omap_sr struct for sr_%s not found\n",
+                   __func__, voltdm->name);
+           return;
+   }
+
+   if (!sr->autocomp_active)
+           return;
+
+   if (!sr_class || !(sr_class->disable)) {
+           dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
+                   "registered\n", __func__);

arch/arm/mach-omap2/smartreflex.c

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c new file +10 -0
+           return;
+   }
+
+   sr_class->disable(voltdm, 0);
+}
+
+/**
+ * omap_sr_disable_reset_volt() - API to disable SR and reset the
+ *                         voltage processor voltage
+ * @voltdm:        VDD pointer to which the SR module to be configured belongs

to.

Quoted 163 lines
arch/arm/mach-omap2/smartreflex.c new file +163 -0
+ *
+ * This API is to be called from the kernel in order to disable
+ * a particular smartreflex module. This API will in turn call
+ * into the registered smartreflex class disable API. This API will tell
+ * the smartreflex class disable to reset the VP voltage after
+ * disabling smartreflex.
+ */
+void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
+{
+   struct omap_sr *sr = _sr_lookup(voltdm);
+
+   if (IS_ERR(sr)) {
+           pr_warning("%s: omap_sr struct for sr_%s not found\n",
+                   __func__, voltdm->name);
+           return;
+   }
+
+   if (!sr->autocomp_active)
+           return;
+
+   if (!sr_class || !(sr_class->disable)) {
+           dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
+                   "registered\n", __func__);
+           return;
+   }
+
+   sr_class->disable(voltdm, 1);
+}
+
+/**
+ * omap_sr_register_pmic() - API to register pmic specific info.
+ * @pmic_data:     The structure containing pmic specific data.
+ *
+ * This API is to be called from the PMIC specific code to register with
+ * smartreflex driver pmic specific info. Currently the only info required
+ * is the smartreflex init on the PMIC side.
+ */
+void omap_sr_register_pmic(struct omap_smartreflex_pmic_data *pmic_data)
+{
+   if (!pmic_data) {
+           pr_warning("%s: Trying to register NULL PMIC data structure"
+                   "with smartreflex\n", __func__);
+           return;
+   }
+
+   sr_pmic_data = pmic_data;
+}
+
+/* PM Debug Fs enteries to enable disable smartreflex. */
+static int omap_sr_autocomp_show(void *data, u64 *val)
+{
+   struct omap_sr *sr_info = (struct omap_sr *) data;
+
+   if (!sr_info) {
+           pr_warning("%s: omap_sr struct for sr_%s not found\n",
+                   __func__, sr_info->voltdm->name);
+           return -EINVAL;
+   }
+
+   *val = sr_info->autocomp_active;
+
+   return 0;
+}
+
+static int omap_sr_autocomp_store(void *data, u64 val)
+{
+   struct omap_sr *sr_info = (struct omap_sr *) data;
+
+   if (!sr_info) {
+           pr_warning("%s: omap_sr struct for sr_%s not found\n",
+                   __func__, sr_info->voltdm->name);
+           return -EINVAL;
+   }
+
+   /* Sanity check */
+   if (val && (val != 1)) {
+           pr_warning("%s: Invalid argument %lld\n", __func__, val);
+           return -EINVAL;
+   }
+
+   if (!val)
+           sr_stop_vddautocomp(sr_info);
+   else
+           sr_start_vddautocomp(sr_info);
+
+   return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
+           omap_sr_autocomp_store, "%llu\n");
+
+static int __init omap_smartreflex_probe(struct platform_device *pdev)
+{
+   struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
+   struct omap_device *odev = to_omap_device(pdev);
+   struct omap_sr_data *pdata = pdev->dev.platform_data;
+   struct resource *mem, *irq;
+   struct dentry *dbg_dir;
+   char *name;
+   int ret = 0;
+
+   if (!sr_info) {
+           dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
+                   __func__);
+           return -ENOMEM;
+   }
+
+   if (!pdata) {
+           dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+           return -EINVAL;
+   }
+
+   mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   if (!mem) {
+           dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
+           ret = -ENODEV;
+           goto err_free_devinfo;
+   }
+
+   irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+   pm_runtime_enable(&pdev->dev);
+
+   sr_info->pdev = pdev;
+   sr_info->srid = pdev->id;
+   sr_info->voltdm = pdata->voltdm;
+   sr_info->autocomp_active = false;
+   sr_info->ip_type = odev->hwmods[0]->class->rev;
+   sr_info->base = ioremap(mem->start, resource_size(mem));
+   if (!sr_info->base) {
+           dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
+           ret = -ENOMEM;
+           goto err_release_region;
+   }
+
+   if (irq)
+           sr_info->irq = irq->start;
+
+   sr_set_clk_length(sr_info);
+   sr_set_regfields(sr_info);
+
+   list_add(&sr_info->node, &sr_list);
+
+   /*
+    * Call into late init to do intializations that require
+    * both sr driver and sr class driver to be initiallized.
+    */
+   if (sr_class) {
+           ret = sr_late_init(sr_info);
+           if (ret) {
+                   pr_warning("%s: Error in SR late init\n", __func__);
+                   return ret;
+           }
+   }
+
+   dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
+
+   /*
+    * If the Smartreflex main debugfs directory is not created, do
+    * not try to create rest of the debugfs entries.
+    */
+   if (!sr_dbg_dir)
+           return ret;
Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/smartreflex.c line 894

Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c new file +6 -0
+
+   name = kzalloc(SMARTREFLEX_NAME_LEN + 1, GFP_KERNEL);
+   if (!name) {
+           dev_err(&pdev->dev, "%s: Unable to allocate name for"
+                   "debufs entry", __func__);
+           return ret;

what will 'ret' be here?

Will correct this.

Quoted 14 lines
Quoted 14 lines

arch/arm/mach-omap2/smartreflex.c line 905

Quoted 12 lines
arch/arm/mach-omap2/smartreflex.c new file +11 -0
+   }
+
+   /* Create the debug fs enteries */
+   strcpy(name, "sr_");
+   strcat(name, sr_info->voltdm->name);
+
+   dbg_dir = debugfs_create_dir(name, sr_dbg_dir);
+   if (IS_ERR(dbg_dir)) {
+           dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
+                   __func__);
+           return ret;

or here?

Will correct this.

Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
arch/arm/mach-omap2/smartreflex.c new file +11 -0
+   }
+
+   (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUGO, dbg_dir,
+                           (void *)sr_info, &pm_sr_fops);
+
+   return ret;
+
+err_release_region:
+   release_mem_region(mem->start, resource_size(mem));
+err_free_devinfo:
+   kfree(sr_info);
Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/smartreflex.c line 921

Quoted 5 lines
arch/arm/mach-omap2/smartreflex.c new file +5 -0
+
+   return ret;
+}
+
+static int __devexit omap_smartreflex_remove(struct platform_device *pdev)

as an internal function, to be consistent with other naming, this should be sr_remove.

It is omap_smartreflex_probe and remove. Do you prefer omap_sr_probe and omap_sr_remove?

Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
arch/arm/mach-omap2/smartreflex.c new file +12 -0
+{
+   struct omap_sr_data *pdata = pdev->dev.platform_data;
+   struct omap_sr *sr_info;
+   struct resource *mem;
+
+   if (!pdata) {
+           dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+           return -EINVAL;
+   }
+
+   sr_info = _sr_lookup(pdata->voltdm);
+   if (!sr_info) {
Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/smartreflex.c line 939

Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c new file +6 -0
+           dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
+                   __func__);
+           return -EINVAL;
+   }
+
+   /* Disable Autocompensation if enabled before removing the module */

surperfluous comment

Ok. Will remove.

Quoted 56 lines
Quoted 56 lines
Quoted 56 lines
arch/arm/mach-omap2/smartreflex.c new file +55 -0
+   if (sr_info->autocomp_active)
+           sr_stop_vddautocomp(sr_info);
+
+   list_del(&sr_info->node);
+   iounmap(sr_info->base);
+   kfree(sr_info);
+   mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   release_mem_region(mem->start, resource_size(mem));
+
+   return 0;
+}
+
+static struct platform_driver smartreflex_driver = {
+   .remove         = omap_smartreflex_remove,
+   .driver         = {
+           .name   = "smartreflex",
+   },
+};
+
+static int __init sr_init(void)
+{
+   int ret = 0;
+
+   /*
+    * sr_init is a late init. If by then a pmic specific API is not
+    * registered either there is no need for anything to be done on
+    * the PMIC side or somebody has forgotten to register a PMIC
+    * handler. Warn for the second condition.
+    */
+   if (sr_pmic_data && sr_pmic_data->sr_pmic_init)
+           sr_pmic_data->sr_pmic_init();
+   else
+           pr_warning("%s: No PMIC hook to init smartreflex\n", __func__);
+
+   if (pm_dbg_main_dir) {
+           struct dentry *d;
+
+           d = debugfs_create_dir("smartreflex", pm_dbg_main_dir);
+           if (!IS_ERR(d))
+                   sr_dbg_dir = d;
+   }
+
+   ret = platform_driver_probe(&smartreflex_driver,
+                           omap_smartreflex_probe);
+   if (ret) {
+           pr_err("%s: platform driver register failed for SR\n",
+                   __func__);
+           return ret;
+   }
+
+   return 0;
+}
+
+static void __exit sr_exit(void)
+{
Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/smartreflex.c line 1000

Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c new file +6 -0
+   platform_driver_unregister(&smartreflex_driver);
+}
+late_initcall(sr_init);
+module_exit(sr_exit);
+
+MODULE_DESCRIPTION("OMAP SMARTREFLEX DRIVER");

"OMAP SmartReflex driver"

Ok.. Will Correct

Quoted 22 lines
Quoted 22 lines
Quoted 22 lines
arch/arm/mach-omap2/smartreflex.c new file +3 -0
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
arch/arm/plat-omap/Kconfig +10 -0
index e39a417..8056349 100644
@@ -35,6 +35,38 @@ config OMAP_DEBUG_LEDS
    depends on OMAP_DEBUG_DEVICES
    default y if LEDS
 
+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
Quoted 8 lines
Quoted 8 lines

arch/arm/plat-omap/Kconfig config OMAP_DEBUG_LEDS · line 52

Quoted 5 lines
arch/arm/plat-omap/Kconfig +5 -0
+     consumption.
+
+     Please note, that by default SmartReflex is only
+     initialized. To enable the automatic voltage
+     compensation for VDD1 and VDD2, user must write 1 to

s/VDD1/MPU/
s/VDD2/CORE/

Will correct

Quoted 5 lines
Quoted 5 lines

arch/arm/plat-omap/Kconfig config OMAP_DEBUG_LEDS · line 54

Quoted 3 lines
arch/arm/plat-omap/Kconfig +2 -0
+     /debug/pm_debug/Smartreflex/SR<X>/autocomp,
+     where X is 1 or 2 for OMAP3

Not fully true, on some SoCs (ES3.1) it's also enabled by default.

mmm.. Will update the commment

Quoted 171 lines
Quoted 171 lines

arch/arm/plat-

Quoted 19 lines
arch/arm/plat-omap/Kconfig +14 -0
+config OMAP_SMARTREFLEX_TESTING
+   bool "Smartreflex testing support"
+   depends on OMAP_SMARTREFLEX
+   default n
+   help
+     Say Y if you want to enable SmartReflex testing with SW hardcoded
+     NVALUES intead of E-fuse NVALUES set in factory silicon testing.
+
+     In some devices the E-fuse values have not been set, even though
+     SmartReflex modules are included. Using these hardcoded values set
+     in software, one can test the SmartReflex features without E-fuse.
+
+     WARNING: Enabling this option may cause your device to hang!
+
 config OMAP_RESET_CLOCKS
    bool "Reset unused clocks during boot"
    depends on ARCH_OMAP
arch/arm/plat- renamed from arch/arm/plat-omap/include/plat/smartreflex.h +0 -0

omap/include/plat/smartreflex.h

Quoted 151 lines

new file mode 100644
index 0000000..1ad03ea

arch/arm/plat-omap/include/plat/smartreflex.h new file +146 -0
@@ -0,0 +1,277 @@
+/*
+ * OMAP Smartreflex Defines and Routines
+ *
+ * Author: Thara Gopinath  <[email protected]>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <[email protected]>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <[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.
+ */
+
+#ifndef __ASM_ARM_OMAP_SMARTREFLEX_H
+#define __ASM_ARM_OMAP_SMARTREFLEX_H
+
+#include <linux/platform_device.h>
+#include <plat/voltage.h>
+
+#ifdef CONFIG_PM_DEBUG
+extern struct dentry *pm_dbg_main_dir;
+extern struct dentry *sr_dbg_dir;
+#endif
+
+/*
+ * Different Smartreflex IPs version. The v1 is the 65nm version used in
+ * OMAP3430. The v2 is the update for the 45nm version of the IP
+ * used in OMAP3630 and OMAP4430
+ */
+#define SR_TYPE_V1 1
+#define SR_TYPE_V2 2
+
+/* SMART REFLEX REG ADDRESS OFFSET */
+#define SRCONFIG           0x00
+#define SRSTATUS           0x04
+#define SENVAL                     0x08
+#define SENMIN                     0x0C
+#define SENMAX                     0x10
+#define SENAVG                     0x14
+#define AVGWEIGHT          0x18
+#define NVALUERECIPROCAL   0x1c
+#define SENERROR_V1                0x20
+#define ERRCONFIG_V1               0x24
+#define IRQ_EOI                    0x20
+#define IRQSTATUS_RAW              0x24
+#define IRQSTATUS          0x28
+#define IRQENABLE_SET              0x2C
+#define IRQENABLE_CLR              0x30
+#define SENERROR_V2                0x34
+#define ERRCONFIG_V2               0x38
+
+/* Bit/Shift Positions */
+
+/* SRCONFIG */
+#define SRCONFIG_ACCUMDATA_SHIFT   22
+#define SRCONFIG_SRCLKLENGTH_SHIFT 12
+#define SRCONFIG_SENNENABLE_V1_SHIFT       5
+#define SRCONFIG_SENPENABLE_V1_SHIFT       3
+#define SRCONFIG_SENNENABLE_V2_SHIFT       1
+#define SRCONFIG_SENPENABLE_V2_SHIFT       0
+#define SRCONFIG_CLKCTRL_SHIFT             0
+
+#define SRCONFIG_ACCUMDATA_MASK            (0x3ff << 22)
+
+#define SRCONFIG_SRENABLE          BIT(11)
+#define SRCONFIG_SENENABLE         BIT(10)
+#define SRCONFIG_ERRGEN_EN         BIT(9)
+#define SRCONFIG_MINMAXAVG_EN              BIT(8)
+#define SRCONFIG_DELAYCTRL         BIT(2)
+
+/* AVGWEIGHT */
+#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT      2
+#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT      0
+
+/* NVALUERECIPROCAL */
+#define NVALUERECIPROCAL_SENPGAIN_SHIFT    20
+#define NVALUERECIPROCAL_SENNGAIN_SHIFT    16
+#define NVALUERECIPROCAL_RNSENP_SHIFT      8
+#define NVALUERECIPROCAL_RNSENN_SHIFT      0
+
+/* ERRCONFIG */
+#define ERRCONFIG_ERRWEIGHT_SHIFT  16
+#define ERRCONFIG_ERRMAXLIMIT_SHIFT        8
+#define ERRCONFIG_ERRMINLIMIT_SHIFT        0
+
+#define SR_ERRWEIGHT_MASK          (0x07 << 16)
+#define SR_ERRMAXLIMIT_MASK                (0xff << 8)
+#define SR_ERRMINLIMIT_MASK                (0xff << 0)
+
+#define ERRCONFIG_VPBOUNDINTEN_V1  BIT(31)
+#define ERRCONFIG_VPBOUNDINTST_V1  BIT(30)
+#define    ERRCONFIG_MCUACCUMINTEN         BIT(29)
+#define ERRCONFIG_MCUACCUMINTST            BIT(28)
+#define    ERRCONFIG_MCUVALIDINTEN         BIT(27)
+#define ERRCONFIG_MCUVALIDINTST            BIT(26)
+#define ERRCONFIG_MCUBOUNDINTEN            BIT(25)
+#define    ERRCONFIG_MCUBOUNDINTST         BIT(24)
+#define    ERRCONFIG_MCUDISACKINTEN        BIT(23)
+#define ERRCONFIG_VPBOUNDINTST_V2  BIT(23)
+#define ERRCONFIG_MCUDISACKINTST   BIT(22)
+#define ERRCONFIG_VPBOUNDINTEN_V2  BIT(22)
+
+#define ERRCONFIG_STATUS_V1_MASK   (ERRCONFIG_VPBOUNDINTST_V1 | \
+                                   ERRCONFIG_MCUACCUMINTST | \
+                                   ERRCONFIG_MCUVALIDINTST | \
+                                   ERRCONFIG_MCUBOUNDINTST | \
+                                   ERRCONFIG_MCUDISACKINTST)
+/* IRQSTATUS */
+#define IRQSTATUS_MCUACCUMINT              BIT(3)
+#define IRQSTATUS_MCVALIDINT               BIT(2)
+#define IRQSTATUS_MCBOUNDSINT              BIT(1)
+#define IRQSTATUS_MCUDISABLEACKINT BIT(0)
+
+/* IRQENABLE_SET and IRQENABLE_CLEAR */
+#define IRQENABLE_MCUACCUMINT              BIT(3)
+#define IRQENABLE_MCUVALIDINT              BIT(2)
+#define IRQENABLE_MCUBOUNDSINT             BIT(1)
+#define IRQENABLE_MCUDISABLEACKINT BIT(0)
+
+/* Common Bit values */
+
+#define SRCLKLENGTH_12MHZ_SYSCLK   0x3c
+#define SRCLKLENGTH_13MHZ_SYSCLK   0x41
+#define SRCLKLENGTH_19MHZ_SYSCLK   0x60
+#define SRCLKLENGTH_26MHZ_SYSCLK   0x82
+#define SRCLKLENGTH_38MHZ_SYSCLK   0xC0
+
+/*
+ * 3430 specific values. Maybe these should be passed from board file or
+ * pmic structures.
+ */
+#define OMAP3430_SR_ACCUMDATA              0x1f4
+
+#define OMAP3430_SR1_SENPAVGWEIGHT 0x03
+#define OMAP3430_SR1_SENNAVGWEIGHT 0x03
+
+#define OMAP3430_SR2_SENPAVGWEIGHT 0x01
+#define OMAP3430_SR2_SENNAVGWEIGHT 0x01
+
+#define OMAP3430_SR_ERRWEIGHT              0x04
Quoted 8 lines
Quoted 8 lines

arch/arm/plat-omap/include/plat/smartreflex.h line 152

Quoted 6 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +6 -0
+#define OMAP3430_SR_ERRMAXLIMIT            0x02
+
+/* TODO:3630/OMAP4 values if it has to come from this file */
+
+/**
+ * omap_smartreflex_dev_data - Smartreflex device specific data

omap_sr..

Will correct

Quoted 41 lines
Quoted 41 lines

arch/arm/plat-omap/include/plat/smartreflex.h

Quoted 13 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +12 -0
+ * @volts_supported        : Number of distinct voltages possible for the VDD
+ *                   associated with this smartreflex module.
+ * @efuse_sr_control       : The regisrter offset of control_fuse_sr efuse
+ *                   register from which sennenable and senpenable values
+ *                   are obtained.
+ * @sennenable_shift       : The shift in the control_fuse_sr register for
+ *                   obtaining the sennenable value for this smartreflex
+ *                   module.
+ * @senpenable_shift       : The shift in the control_fuse_sr register for
+ *                   obtaining the senpenable value for this smartreflex
+ *                   module.
+ * @efuse_nvalues_offs     : Array of efuse offsets from which ntarget

values can

arch/arm/plat-omap/include/plat/smartreflex.h

Quoted 9 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +9 -0
+ *                   be retrieved. Number of efuse offsets in this arrray
+ *                   is equal to the volts_supported value ie one efuse
+ *                   register per supported voltage.
+ * @test_sennenable        : SENNENABLE test value
+ * @test_senpenable        : SENPENABLE test value.
+ * @test_nvalues   : Array of test ntarget values.
+ * @vdd_name               : Name of the voltage domain associated with this
+ *                   Smartreflex device.
+ * @volt_data              : Voltage table associated with this smartreflex

module

Quoted 6 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +6 -0
+ */
+struct omap_sr_dev_data {
+   int volts_supported;
+   u32 efuse_sr_control;
+   u32 sennenable_shift;
+   u32 senpenable_shift;

arch/arm/plat-omap/include/plat/smartreflex.h

Quoted 10 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +10 -0
+   u32 *efuse_nvalues_offs;
+   u32 test_sennenable;
+   u32 test_senpenable;
+   u32 *test_nvalues;
+   char *vdd_name;
+   struct omap_volt_data *volt_data;
+};
+
+/**
+ * omap_smartreflex_pmic_data : Strucutre to be populated by pmic code to

pass

Quoted 7 lines
Quoted 7 lines

arch/arm/plat-omap/include/plat/smartreflex.h line 195

Quoted 5 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +5 -0
+ * pmic specific info to smartreflex driver
+ *
+ * @sr_pmic_init - API to initialize smartreflex on the PMIC side.
+ */
+struct omap_smartreflex_pmic_data {

omap_sr..

Will correct.

Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +10 -0
+   void (*sr_pmic_init) (void);
+};
+
+#ifdef CONFIG_OMAP_SMARTREFLEX
+/*
+ * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
+ * The smartreflex class driver should pass the class type.
+ * Should be used to populate the class_type field of the
+ * omap_smartreflex_class_data structure.
+ */
Quoted 8 lines
Quoted 8 lines

arch/arm/plat-omap/include/plat/smartreflex.h line 211

Quoted 6 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +6 -0
+#define SR_CLASS1  0x1
+#define SR_CLASS2  0x2
+#define SR_CLASS3  0x3
+
+/**
+ * omap_smartreflex_class_data : Structure to be populated by

omap_sr...

Will correct.

Quoted 18 lines
Quoted 18 lines

arch/arm/plat-omap/include/plat/smartreflex.h

Quoted 7 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +6 -0
+ * Smartreflex class driver with corresponding class enable disable API's
+ *
+ * @enable - API to enable a particular class smaartreflex.
+ * @disable - API to disable a particular class smartreflex.
+ * @configure - API to configure a particular class smartreflex.
+ * @notify - API to notify the class driver about an event in SR. Not

needed

arch/arm/plat-omap/include/plat/smartreflex.h

Quoted 3 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +3 -0
+ *         for class3.
+ * @notify_flags - specify the events to be notified to the class driver
+ * @class_type - specify which smartreflex class. Can be used by the SR

driver

arch/arm/plat-omap/include/plat/smartreflex.h line 223

Quoted 3 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +3 -0
+ *         to take any class based decisions.
+ */
+struct omap_smartreflex_class_data {

omap_sr

Quoted 12 lines
Quoted 4 lines
Quoted 4 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +4 -0
+   int (*enable)(struct voltagedomain *voltdm);
+   int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
+   int (*configure)(struct voltagedomain *voltdm);
+   int (*notify)(struct voltagedomain *voltdm, u32 status);
Quoted 8 lines

arch/arm/plat-omap/include/plat/smartreflex.h line 233

Quoted 6 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +6 -0
+   u8 notify_flags;
+   u8 class_type;
+};
+
+/**
+ * omap_smartreflex_data - Smartreflex platform data

omap_sr

Will correct

Quoted 23 lines
Quoted 23 lines

arch/arm/plat-omap/include/plat/smartreflex.h

Quoted 7 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +6 -0
+ * @senp_mod               : SENPENABLE value for the sr
+ * @senn_mod               : SENNENABLE value for sr
+ * @sr_nvalue              : array of n target values for sr
+ * @enable_on_init : whether this sr module needs to enabled at
+ *                   boot up or not.
+ * @voltdm         : Pointer to the voltage domain associated with the

SR

arch/arm/plat-omap/include/plat/smartreflex.h

Quoted 11 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +11 -0
+ */
+struct omap_sr_data {
+   u32                             senp_mod;
+   u32                             senn_mod;
+   bool                            enable_on_init;
+   struct voltagedomain            *voltdm;
+};
+
+/*
+ * Smartreflex module enable/disable interface.
+ * NOTE: if smartreflex is not enabled from sysfs, these functions will

not

Quoted 2 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +2 -0
+ * do anything.
+ */
Quoted 7 lines
Quoted 7 lines

The 'NOTE' comment isn't quite accurate (and probably not needed here.) The 'enable_on_init' flag is another way besides sysfs for these functions to be activated.

This enable_on_init flag (also settable by board files) should probably be mentioned in the changelog too where you mention how SR can be enabled.

Will do this

Quoted 28 lines
Quoted 28 lines
Quoted 5 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +4 -0
+void omap_sr_enable(struct voltagedomain *voltdm);
+void omap_sr_disable(struct voltagedomain *voltdm);
+void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
+

arch/arm/plat-omap/include/plat/smartreflex.h

Quoted 10 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +10 -0
+/* API to register the pmic specific data with the smartreflex driver. */
+void omap_sr_register_pmic(struct omap_smartreflex_pmic_data *pmic_data);
+
+/* Smartreflex driver hooks to be called from Smartreflex class driver */
+int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
+void sr_disable(struct voltagedomain *voltdm);
+int sr_configure_errgen(struct voltagedomain *voltdm);
+int sr_configure_minmax(struct voltagedomain *voltdm);
+
+/* API to register the smartreflex class driver with the smartreflex

driver */

arch/arm/plat-omap/include/plat/smartreflex.h line 277

Quoted 10 lines
arch/arm/plat-omap/include/plat/smartreflex.h new file +10 -0
+int sr_register_class(struct omap_smartreflex_class_data *class_data);
+#else
+static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
+static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
+static inline void omap_sr_disable_reset_volt(
+           struct voltagedomain *voltdm) {}
+static inline void omap_sr_register_pmic(
+           struct omap_smartreflex_pmic_data *pmic_data) {}
+#endif
+#endif

Kevin

#18 lore raw

Re: [PATCH v3 03/11] OMAP3: PM: Adding smartreflex driver support.

"Gopinath, Thara" <[email protected]> writes:

[...]

Quoted 7 lines
Quoted 4 lines
Quoted 4 lines
Quoted 1 line

+static int __devexit omap_smartreflex_remove(struct platform_device *pdev)

as an internal function, to be consistent with other naming, this should be sr_remove.

It is omap_smartreflex_probe and remove. Do you prefer omap_sr_probe and omap_sr_remove?

Yes

#19 lore raw

Re: [PATCH v3 03/11] OMAP3: PM: Adding smartreflex driver support.

In reply to Gopinath, Thara
Quoted 23 lines
Quoted 6 lines
Quoted 6 lines
Quoted 1 line · Thara Gopinath

+           if (ret) {

                        goto error;

Quoted 16 lines
Quoted 8 lines
Quoted 8 lines

+                   struct resource *mem;
+
+                   iounmap(sr_info->base);
+                   mem = platform_get_resource(sr_info->pdev,
+                           IORESOURCE_MEM, 0);
+                   release_mem_region(mem->start, resource_size(mem));
+                   list_del(&sr_info->node);
+                   dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"

Quoted 8 lines
Quoted 6 lines

+                           "interrupt handler. Smartreflex will"
+                           "not function as desired\n", __func__); +
+                   kfree(sr_info);
+                   return ret;
+           }

and move this after the return...

Quoted 1 line

I did not understand this comment.

I guess he meant to move error handling to the end of function, and jump there with goto.
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#20 lore raw

PATCH v3 4/11 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 and test n-target vaules, module enable/disable pointers and a parameter to indicate whether smartreflex autocompensation needs to be enabled on init or not. Currently auocompensation is enabled on init by default for OMAP3430 ES3.1 chip.

---
 arch/arm/mach-omap2/Makefile    |    2 +-
 arch/arm/mach-omap2/sr_device.c |  174 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 175 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/sr_device.c
arch/arm/mach-omap2/Makefile +1 -1
index 8dd32a7..abc377a 100644
@@ -56,7 +56,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/sr_device.c new file +174 -0

174 lines not on this page · raw message

Signature · 1 line
1.7.1.GIT
#21 lore raw

Re: [PATCH v3 04/11] OMAP3: PM: Adding smartreflex device file.

Quoted 124 lines · 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 and test n-target vaules, module enable/disable pointers and a parameter to indicate whether smartreflex autocompensation needs to be enabled on init or not. Currently auocompensation is enabled on init by default for OMAP3430 ES3.1 chip.

---
 arch/arm/mach-omap2/Makefile    |    2 +-
 arch/arm/mach-omap2/sr_device.c |  174 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 175 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/sr_device.c
arch/arm/mach-omap2/Makefile +1 -1
index 8dd32a7..abc377a 100644
@@ -56,7 +56,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/sr_device.c new file +89 -0
new file mode 100644
index 0000000..606da59
@@ -0,0 +1,174 @@
+/*
+ * OMAP3/OMAP4 smartreflex device file
+ *
+ * Author: Thara Gopinath	<[email protected]>
+ *
+ * Based originally on code from smartreflex.c
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <[email protected]>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <[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.
+ */
+
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <plat/control.h>
+#include <plat/omap_device.h>
+#include <plat/smartreflex.h>
+#include <plat/voltage.h>
+
+static struct omap_device_pm_latency omap_sr_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func	 = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST
+	},
+};
+
+#ifdef OMAP_SMARTREFLEX_TESTING
+/*
+ * Hard coded nvalues for testing purposes for OMAP3430,
+ * may cause device to hang!
+ */
+static void __init sr_set_nvalues(struct omap_sr_dev_data *dev_data,
+				struct omap_sr_data *sr_data)
+{
+	int i;
+
+	if (!dev_data || !dev_data->volts_supported ||
+			!dev_data->volt_data || !dev_data->test_nvalues) {
+		pr_warning("%s: Bad parameters! dev_data = %x,"
+			"dev_data->volts_supported = %x,"
+			"dev_data->volt_data = %x,"
+			"dev_data->test_nvalues = %x\n", __func__,
+			(unsigned int)dev_data, dev_data->volts_supported,
+			(unsigned int)dev_data->volt_data,
+			(unsigned int)dev_data->test_nvalues);
+		return;
+	}
+
+	sr_data->senn_mod = dev_data->test_sennenable;
+	sr_data->senp_mod = dev_data->test_senpenable;
+	for (i = 0; i < dev_data->volts_supported; i++)
+		dev_data->volt_data[i].sr_nvalue = dev_data->test_nvalues[i];
+}
+#else
+/* Read EFUSE values from control registers for OMAP3430 */
+static void __init sr_set_nvalues(struct omap_sr_dev_data *dev_data,
+				struct omap_sr_data *sr_data)
+{
+	int i;
+
+	if (!dev_data || !dev_data->volts_supported || !dev_data->volt_data ||
+			!dev_data->efuse_nvalues_offs) {
+		pr_warning("%s: Bad parameters! dev_data = %x,"
+			"dev_data->volts_supported = %x,"
+			"dev_data->volt_data = %x,"
+			"dev_data->efuse_nvalues_offs = %x\n", __func__,
+			(unsigned int)dev_data, dev_data->volts_supported,
+			(unsigned int)dev_data->volt_data,
+			(unsigned int)dev_data->efuse_nvalues_offs);
+		return;
+	}
+
+	/*
+	 * From OMAP3630 onwards there are no efuse registers for senn_mod
+	 * and senp_mod. They have to be 0x1 by default.
+	 */
+	if (!dev_data->efuse_sr_control) {
+		sr_data->senn_mod = 0x1;
+		sr_data->senp_mod = 0x1;

arch/arm/mach-omap2/sr_device.c line 99

Quoted 10 lines
arch/arm/mach-omap2/sr_device.c new file +10 -0
+	} else {
+		sr_data->senn_mod =
+				((omap_ctrl_readl(dev_data->efuse_sr_control) &
+				(0x3 << dev_data->sennenable_shift)) >>
+				dev_data->sennenable_shift);
+		sr_data->senp_mod =
+				((omap_ctrl_readl(dev_data->efuse_sr_control) &
+				(0x3 << dev_data->senpenable_shift)) >>
+				dev_data->senpenable_shift);
+	}

For readbility, can you do the ctrl_read on one line, then the mask/shift on a separate line, e.g.:

		sr_data->senn_mod = omap_ctrl_readl...
		sr_data->senn_mod &= ....

arch/arm/mach-omap2/sr_device.c line 103

Quoted 3 lines
arch/arm/mach-omap2/sr_device.c new file +3 -0
+	for (i = 0; i < dev_data->volts_supported; i++)
+		dev_data->volt_data[i].sr_nvalue = omap_ctrl_readl(
+				dev_data->efuse_nvalues_offs[i]);

The wrapping here affects readability. It would be better to do this in two lines:

		v = omap_ctrl_readl...
		dev_data-... = v;

Similar readability problem this part of OMAP4 series.

Quoted 26 lines
arch/arm/mach-omap2/sr_device.c new file +26 -0
+}
+#endif
+
+static int sr_dev_init(struct omap_hwmod *oh, void *user)
+{
+	struct omap_sr_data *sr_data;
+	struct omap_sr_dev_data *sr_dev_data;
+	struct omap_device *od;
+	char *name = "smartreflex";
+	static int i;
+
+	sr_data = kzalloc(sizeof(struct omap_sr_data), GFP_KERNEL);
+	if (!sr_data) {
+		pr_err("%s: Unable to allocate memory for %s sr_data.Error!\n",
+			__func__, oh->name);
+		return -ENOMEM;
+	}
+
+	sr_dev_data = (struct omap_sr_dev_data *)oh->dev_attr;
+	if (unlikely(!sr_dev_data)) {
+		pr_err("%s: dev atrribute is NULL\n", __func__);
+		goto exit;
+	}
+
+	/*
+	 * OMAP3430 ES3.1 chips by default come with Efuse burnt

arch/arm/mach-omap2/sr_device.c line 139

Quoted 10 lines
arch/arm/mach-omap2/sr_device.c new file +10 -0
+	 * with parameters required for full functionality of
+	 * smartreflex AVS feature like ntarget values , sennenable
+	 * and senpenable. So enable the SR AVS feature during boot up
+	 * itself if it is a OMAP3430 ES3.1 chip.
+	 */
+	sr_data->enable_on_init = false;
+	if (cpu_is_omap343x()) {
+		if (omap_rev() == OMAP3430_REV_ES3_1)
+			sr_data->enable_on_init = true;
+	}

The braces are not needed here.

Quoted 7 lines
arch/arm/mach-omap2/sr_device.c new file +7 -0
+	sr_data->voltdm = omap_voltage_domain_get(sr_dev_data->vdd_name);
+	if (IS_ERR(sr_data->voltdm)) {
+		pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
+			__func__, sr_dev_data->vdd_name);
+		goto exit;
+	}
+

arch/arm/mach-omap2/sr_device.c line 156

Quoted 10 lines
arch/arm/mach-omap2/sr_device.c new file +9 -0
+	sr_dev_data->volts_supported = omap_voltage_get_volttable(
+			sr_data->voltdm, &sr_dev_data->volt_data);
 
+	if (!sr_dev_data->volts_supported) {
+		pr_warning("%s: No Voltage table registerd fo VDD%d."
+			"Something really wrong\n\n", __func__, i + 1);
+		goto exit;
+	}
+
+	sr_set_nvalues(sr_dev_data, sr_data);

First question: why does this N-value init need to be done in the device init? It seems better to be a part of the SR driver probe.

Second, this section took me quite some time to understand, as it seems to blur the lines of device and driver but also how it interacts with the voltage layer.

sr_set_nvalues() is directly manipulating structures that are internal to the voltage layer. It also makes assumptions about the ordering of volt_data structs in the voltage layer.

Strictly speaking neither the sr_nvalue or sr_errminlimit fields of volt_data are not used at all in the voltage layer, but only in the SR layer, so ideally they should really stay in the SR layer.

I think what is needed here is a cleaner way for the SR layer to connect the N-values to a voltage. The current method of manipulating voltage layer structs inside the SR layer is not acceptable. Since the n-values are fixed in HW (per SoC), what I suggest is simply having a field like 'efuse_id' or something in volt_data. Then, the smart reflex layer can lookup and index all the efuse values during probe, and when sr_enable is called, it looks up the nvalue based on efuse_id.

I assume that the sr_errminlimit could also be set based on efuse_id, and therefore remain contained within the SR layer, but I'm not sure I like that idea any better than keeping it inside volt_data. For now, I'll let you make the call on errminlimit, but I really want to see the N-value stuff isolated in the SR layer.

Kevin

Quoted 17 lines
arch/arm/mach-omap2/sr_device.c new file +17 -0
+	od = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
+			       omap_sr_latency,
+			       ARRAY_SIZE(omap_sr_latency), 0);
+	if (IS_ERR(od))
+		pr_warning("%s: Could not build omap_device for %s: %s.\n\n",
+			__func__, name, oh->name);
+exit:
+	i++;
+	kfree(sr_data);
+	return 0;
+}
+
+static int __init omap_devinit_smartreflex(void)
+{
+	return omap_hwmod_for_each_by_class("smartreflex", sr_dev_init, NULL);
+}
+device_initcall(omap_devinit_smartreflex);
#22 lore raw

RE: [PATCH v3 04/11] OMAP3: PM: Adding smartreflex device file.

Quoted 163 lines
Quoted 163 lines

-----Original Message-----
From: [email protected] [mailto:linux-omap- [email protected]] On Behalf Of Kevin Hilman
Sent: Friday, October 15, 2010 12:59 AM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 04/11] OMAP3: PM: Adding smartreflex device file.

Quoted 9 lines · 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 and test n-target vaules, module enable/disable pointers and a parameter to indicate whether smartreflex autocompensation needs to be enabled on init or not. Currently auocompensation is enabled on init by default for OMAP3430 ES3.1 chip.

Quoted 4 lines
---
 arch/arm/mach-omap2/Makefile    |    2 +-
 arch/arm/mach-omap2/sr_device.c |  174

+++++++++++++++++++++++++++++++++++++++

arch/arm/mach-omap2/Makefile obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o

Quoted 8 lines
 2 files changed, 175 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-omap2/sr_device.c
arch/arm/mach-omap2/Makefile +0 -0
index 8dd32a7..abc377a 100644
@@ -56,7 +56,7 @@ obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o

voltage.o \

arch/arm/mach-

Quoted 9 lines
arch/arm/mach-omap2/Makefile +1 -1
 					   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- renamed from arch/arm/mach-omap2/sr_device.c +0 -0

omap2/sr_device.c

Quoted 94 lines

new file mode 100644
index 0000000..606da59

arch/arm/mach-omap2/sr_device.c new file +89 -0
@@ -0,0 +1,174 @@
+/*
+ * OMAP3/OMAP4 smartreflex device file
+ *
+ * Author: Thara Gopinath	<[email protected]>
+ *
+ * Based originally on code from smartreflex.c
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <[email protected]>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <[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.
+ */
+
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <plat/control.h>
+#include <plat/omap_device.h>
+#include <plat/smartreflex.h>
+#include <plat/voltage.h>
+
+static struct omap_device_pm_latency omap_sr_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func	 = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST
+	},
+};
+
+#ifdef OMAP_SMARTREFLEX_TESTING
+/*
+ * Hard coded nvalues for testing purposes for OMAP3430,
+ * may cause device to hang!
+ */
+static void __init sr_set_nvalues(struct omap_sr_dev_data *dev_data,
+				struct omap_sr_data *sr_data)
+{
+	int i;
+
+	if (!dev_data || !dev_data->volts_supported ||
+			!dev_data->volt_data || !dev_data->test_nvalues) {
+		pr_warning("%s: Bad parameters! dev_data = %x,"
+			"dev_data->volts_supported = %x,"
+			"dev_data->volt_data = %x,"
+			"dev_data->test_nvalues = %x\n", __func__,
+			(unsigned int)dev_data, dev_data->volts_supported,
+			(unsigned int)dev_data->volt_data,
+			(unsigned int)dev_data->test_nvalues);
+		return;
+	}
+
+	sr_data->senn_mod = dev_data->test_sennenable;
+	sr_data->senp_mod = dev_data->test_senpenable;
+	for (i = 0; i < dev_data->volts_supported; i++)
+		dev_data->volt_data[i].sr_nvalue = dev_data->test_nvalues[i];
+}
+#else
+/* Read EFUSE values from control registers for OMAP3430 */
+static void __init sr_set_nvalues(struct omap_sr_dev_data *dev_data,
+				struct omap_sr_data *sr_data)
+{
+	int i;
+
+	if (!dev_data || !dev_data->volts_supported || !dev_data->volt_data ||
+			!dev_data->efuse_nvalues_offs) {
+		pr_warning("%s: Bad parameters! dev_data = %x,"
+			"dev_data->volts_supported = %x,"
+			"dev_data->volt_data = %x,"
+			"dev_data->efuse_nvalues_offs = %x\n", __func__,
+			(unsigned int)dev_data, dev_data->volts_supported,
+			(unsigned int)dev_data->volt_data,
+			(unsigned int)dev_data->efuse_nvalues_offs);
+		return;
+	}
+
+	/*
+	 * From OMAP3630 onwards there are no efuse registers for senn_mod
+	 * and senp_mod. They have to be 0x1 by default.
+	 */
+	if (!dev_data->efuse_sr_control) {
+		sr_data->senn_mod = 0x1;
+		sr_data->senp_mod = 0x1;

arch/arm/mach-omap2/sr_device.c line 99

Quoted 10 lines
arch/arm/mach-omap2/sr_device.c new file +10 -0
+	} else {
+		sr_data->senn_mod =
+				((omap_ctrl_readl(dev_data->efuse_sr_control) &
+				(0x3 << dev_data->sennenable_shift)) >>
+				dev_data->sennenable_shift);
+		sr_data->senp_mod =
+				((omap_ctrl_readl(dev_data->efuse_sr_control) &
+				(0x3 << dev_data->senpenable_shift)) >>
+				dev_data->senpenable_shift);
+	}

For readbility, can you do the ctrl_read on one line, then the mask/shift on a separate line, e.g.:

		sr_data->senn_mod = omap_ctrl_readl...
		sr_data->senn_mod &= ....

arch/arm/mach-omap2/sr_device.c line 103

Quoted 3 lines
arch/arm/mach-omap2/sr_device.c new file +3 -0
+	for (i = 0; i < dev_data->volts_supported; i++)
+		dev_data->volt_data[i].sr_nvalue = omap_ctrl_readl(
+				dev_data->efuse_nvalues_offs[i]);

The wrapping here affects readability. It would be better to do this in two lines:

Quoted 4 lines
Quoted 4 lines
		v = omap_ctrl_readl...
		dev_data-... = v;

Similar readability problem this part of OMAP4 series.

Will do.

Quoted 31 lines
Quoted 31 lines
Quoted 31 lines
arch/arm/mach-omap2/sr_device.c new file +30 -0
+}
+#endif
+
+static int sr_dev_init(struct omap_hwmod *oh, void *user)
+{
+	struct omap_sr_data *sr_data;
+	struct omap_sr_dev_data *sr_dev_data;
+	struct omap_device *od;
+	char *name = "smartreflex";
+	static int i;
+
+	sr_data = kzalloc(sizeof(struct omap_sr_data), GFP_KERNEL);
+	if (!sr_data) {
+		pr_err("%s: Unable to allocate memory for %s sr_data.Error!\n",
+			__func__, oh->name);
+		return -ENOMEM;
+	}
+
+	sr_dev_data = (struct omap_sr_dev_data *)oh->dev_attr;
+	if (unlikely(!sr_dev_data)) {
+		pr_err("%s: dev atrribute is NULL\n", __func__);
+		goto exit;
+	}
+
+	/*
+	 * OMAP3430 ES3.1 chips by default come with Efuse burnt
+	 * with parameters required for full functionality of
+	 * smartreflex AVS feature like ntarget values , sennenable
+	 * and senpenable. So enable the SR AVS feature during boot up
+	 * itself if it is a OMAP3430 ES3.1 chip.
Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/sr_device.c line 139

Quoted 6 lines
arch/arm/mach-omap2/sr_device.c new file +6 -0
+	 */
+	sr_data->enable_on_init = false;
+	if (cpu_is_omap343x()) {
+		if (omap_rev() == OMAP3430_REV_ES3_1)
+			sr_data->enable_on_init = true;
+	}

The braces are not needed here.

Ok

Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
arch/arm/mach-omap2/sr_device.c new file +9 -0
+	sr_data->voltdm = omap_voltage_domain_get(sr_dev_data->vdd_name);
+	if (IS_ERR(sr_data->voltdm)) {
+		pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
+			__func__, sr_dev_data->vdd_name);
+		goto exit;
+	}
+
+	sr_dev_data->volts_supported = omap_voltage_get_volttable(
+			sr_data->voltdm, &sr_dev_data->volt_data);
Quoted 10 lines
Quoted 10 lines

arch/arm/mach-omap2/sr_device.c line 156

Quoted 7 lines
arch/arm/mach-omap2/sr_device.c new file +7 -0
+	if (!sr_dev_data->volts_supported) {
+		pr_warning("%s: No Voltage table registerd fo VDD%d."
+			"Something really wrong\n\n", __func__, i + 1);
+		goto exit;
+	}
+
+	sr_set_nvalues(sr_dev_data, sr_data);

First question: why does this N-value init need to be done in the device init? It seems better to be a part of the SR driver probe.

OMAP3 and OMAP4 has different ways of reading the efuse registers. I would like it to be in device file so that we can have the necessary checks. The driver should not be bothered about getting of the n-values.

Quoted 21 lines
Quoted 21 lines

Second, this section took me quite some time to understand, as it seems to blur the lines of device and driver but also how it interacts with the voltage layer.

sr_set_nvalues() is directly manipulating structures that are internal to the voltage layer. It also makes assumptions about the ordering of volt_data structs in the voltage layer.

Strictly speaking neither the sr_nvalue or sr_errminlimit fields of volt_data are not used at all in the voltage layer, but only in the SR layer, so ideally they should really stay in the SR layer.

I think what is needed here is a cleaner way for the SR layer to connect the N-values to a voltage. The current method of manipulating voltage layer structs inside the SR layer is not acceptable. Since the n-values are fixed in HW (per SoC), what I suggest is simply having a field like 'efuse_id' or something in volt_data. Then, the smart reflex layer can lookup and index all the efuse values during probe, and when sr_enable is called, it looks up the nvalue based on efuse_id.

Quoted 5 lines
Quoted 5 lines

I assume that the sr_errminlimit could also be set based on efuse_id, and therefore remain contained within the SR layer, but I'm not sure I like that idea any better than keeping it inside volt_data. For now, I'll let you make the call on errminlimit, but I really want to see the N-value stuff isolated in the SR layer.

I do not understand your proposal here? What kind of variable is efuse-id??

Quoted 26 lines
Quoted 26 lines

Kevin

Quoted 7 lines
arch/arm/mach-omap2/sr_device.c new file +7 -0
+	od = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
+			       omap_sr_latency,
+			       ARRAY_SIZE(omap_sr_latency), 0);
+	if (IS_ERR(od))
+		pr_warning("%s: Could not build omap_device for %s: %s.\n\n",
+			__func__, name, oh->name);
+exit:

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

Quoted 10 lines
arch/arm/mach-omap2/sr_device.c new file +10 -0
+	i++;
+	kfree(sr_data);
+	return 0;
+}
+
+static int __init omap_devinit_smartreflex(void)
+{
+	return omap_hwmod_for_each_by_class("smartreflex", sr_dev_init, NULL);
+}
+device_initcall(omap_devinit_smartreflex);

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

#23 lore raw

Re: [PATCH v3 04/11] OMAP3: PM: Adding smartreflex device file.

Quoted 11 lines · Thara
Quoted 11 lines
Quoted 11 lines · Thara Gopinath
Quoted 10 lines

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 and test n-target vaules, module enable/disable pointers and a parameter to indicate whether smartreflex autocompensation needs to be enabled on init or not. Currently auocompensation is enabled on init by default for OMAP3430 ES3.1 chip.

[...]

Quoted 21 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
arch/arm/mach-omap2/sr_device.c new file +9 -0
+	sr_data->voltdm = omap_voltage_domain_get(sr_dev_data->vdd_name);
+	if (IS_ERR(sr_data->voltdm)) {
+		pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
+			__func__, sr_dev_data->vdd_name);
+		goto exit;
+	}
+
+	sr_dev_data->volts_supported = omap_voltage_get_volttable(
+			sr_data->voltdm, &sr_dev_data->volt_data);
Quoted 10 lines
Quoted 10 lines

arch/arm/mach-omap2/sr_device.c line 156

Quoted 7 lines
arch/arm/mach-omap2/sr_device.c new file +7 -0
+	if (!sr_dev_data->volts_supported) {
+		pr_warning("%s: No Voltage table registerd fo VDD%d."
+			"Something really wrong\n\n", __func__, i + 1);
+		goto exit;
+	}
+
+	sr_set_nvalues(sr_dev_data, sr_data);

First question: why does this N-value init need to be done in the device init? It seems better to be a part of the SR driver probe.

Quoted 4 lines

OMAP3 and OMAP4 has different ways of reading the efuse registers. I would like it to be in device file so that we can have the necessary checks. The driver should not be bothered about getting of the n-values.

Bothered? The driver's job is to probe the HW. The device code
can tell the driver where the N-values are located (register offsets, via platform_data), but IMO, should not be reading the values from HW.

Quoted 21 lines
Quoted 21 lines
Quoted 21 lines

Second, this section took me quite some time to understand, as it seems to blur the lines of device and driver but also how it interacts with the voltage layer.

sr_set_nvalues() is directly manipulating structures that are internal to the voltage layer. It also makes assumptions about the ordering of volt_data structs in the voltage layer.

Strictly speaking neither the sr_nvalue or sr_errminlimit fields of volt_data are not used at all in the voltage layer, but only in the SR layer, so ideally they should really stay in the SR layer.

I think what is needed here is a cleaner way for the SR layer to connect the N-values to a voltage. The current method of manipulating voltage layer structs inside the SR layer is not acceptable. Since the n-values are fixed in HW (per SoC), what I suggest is simply having a field like 'efuse_id' or something in volt_data. Then, the smart reflex layer can lookup and index all the efuse values during probe, and when sr_enable is called, it looks up the nvalue based on efuse_id.

Quoted 8 lines
Quoted 5 lines
Quoted 5 lines

I assume that the sr_errminlimit could also be set based on efuse_id, and therefore remain contained within the SR layer, but I'm not sure I like that idea any better than keeping it inside volt_data. For now, I'll let you make the call on errminlimit, but I really want to see the N-value stuff isolated in the SR layer.

I do not understand your proposal here? What kind of variable is efuse-id??

Sorry, it was kind of rambling. I'll try again...

Currently, omap_volt_data (in the voltage layer) includes SR N-value field:

struct omap_volt_data {
	u32	volt_nominal;
	u32	sr_nvalue;
	u8	sr_errminlimit;
	u8	vp_errgain;
};

but sr_nvalue is not used in the voltage layer at all.

This choice has led to the SR device init code having to populate internal structures of the voltage layer. That is what I don't like. (I have a similar problem with the presence of sr_errminlimit in the omap_volt_data, because it's not used in the voltage layer either.)

So my suggestion was to remove the sr_nvalue field and replace it with something like an efuse_id field. Since n-values are directly connected with HW registers, this is a simple mapping.

This way, the voltage layer does not know about the exact N-value (because it doesn't care), ll the voltage layer needs to know is which efuse to use for this voltage.

As for implementation, in the SR driver, probe could read the N-values from HW into a table. The enable/disable functiosn can look up the N-values from the table using the efuse_id from volt_data.

Did I explain any better this time?

Kevin

#24 lore raw

RE: [PATCH v3 04/11] OMAP3: PM: Adding smartreflex device file.

Quoted 48 lines
Quoted 48 lines

-----Original Message-----
From: Kevin Hilman [mailto:[email protected]]
Sent: Friday, October 22, 2010 10:02 PM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 04/11] OMAP3: PM: Adding smartreflex device file.

Quoted 11 lines · Thara
Quoted 11 lines
Quoted 11 lines · Thara Gopinath
Quoted 10 lines

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 and test n-target vaules, module enable/disable pointers and a parameter to indicate whether smartreflex autocompensation needs to be enabled on init or not. Currently auocompensation is enabled on init by default for OMAP3430 ES3.1 chip.

[...]

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

arch/arm/mach-omap2/sr_device.c

Quoted 3 lines
arch/arm/mach-omap2/sr_device.c new file +3 -0
+	sr_data->voltdm = omap_voltage_domain_get(sr_dev_data->vdd_name);
+	if (IS_ERR(sr_data->voltdm)) {
+		pr_err("%s: Unable to get voltage domain pointer for VDD

%s\n",

Quoted 18 lines
Quoted 17 lines
Quoted 17 lines
Quoted 4 lines
arch/arm/mach-omap2/sr_device.c new file +4 -0
+			__func__, sr_dev_data->vdd_name);
+		goto exit;
+	}
+

arch/arm/mach-omap2/sr_device.c line 156

Quoted 10 lines
arch/arm/mach-omap2/sr_device.c new file +9 -0
+	sr_dev_data->volts_supported = omap_voltage_get_volttable(
+			sr_data->voltdm, &sr_dev_data->volt_data);
 
+	if (!sr_dev_data->volts_supported) {
+		pr_warning("%s: No Voltage table registerd fo VDD%d."
+			"Something really wrong\n\n", __func__, i + 1);
+		goto exit;
+	}
+
+	sr_set_nvalues(sr_dev_data, sr_data);

First question: why does this N-value init need to be done in the device init? It seems better to be a part of the SR driver probe.

Quoted 8 lines
Quoted 8 lines
Quoted 4 lines

OMAP3 and OMAP4 has different ways of reading the efuse registers. I would like it to be in device file so that we can have the necessary checks. The driver should not be bothered about getting of the n-values.

Bothered? The driver's job is to probe the HW. The device code
can tell the driver where the N-values are located (register offsets, via platform_data), but IMO, should not be reading the values from HW.

But then we will have to put cpu_is_omap34xx() and cpu_is_omap44xx() checks in the driver. Also omap_ctrl_readl API will have to be used from the driver.

Quoted 50 lines
Quoted 50 lines
Quoted 22 lines
Quoted 22 lines
Quoted 22 lines

Second, this section took me quite some time to understand, as it seems to blur the lines of device and driver but also how it interacts with the voltage layer.

sr_set_nvalues() is directly manipulating structures that are internal to the voltage layer. It also makes assumptions about the ordering of volt_data structs in the voltage layer.

Strictly speaking neither the sr_nvalue or sr_errminlimit fields of volt_data are not used at all in the voltage layer, but only in the SR layer, so ideally they should really stay in the SR layer.

I think what is needed here is a cleaner way for the SR layer to connect the N-values to a voltage. The current method of manipulating voltage layer structs inside the SR layer is not acceptable. Since the n-values are fixed in HW (per SoC), what I suggest is simply having a field like 'efuse_id' or something in volt_data. Then, the smart reflex layer can lookup and index all the efuse values during probe, and when sr_enable is called, it looks up the nvalue based on efuse_id.

Quoted 8 lines
Quoted 5 lines
Quoted 5 lines

I assume that the sr_errminlimit could also be set based on efuse_id, and therefore remain contained within the SR layer, but I'm not sure I like that idea any better than keeping it inside volt_data. For now, I'll let you make the call on errminlimit, but I really want to see the N-value stuff isolated in the SR layer.

I do not understand your proposal here? What kind of variable is efuse-id??

Sorry, it was kind of rambling. I'll try again...

Currently, omap_volt_data (in the voltage layer) includes SR N-value field:

struct omap_volt_data {
	u32	volt_nominal;
	u32	sr_nvalue;
	u8	sr_errminlimit;
	u8	vp_errgain;
};

but sr_nvalue is not used in the voltage layer at all.

This choice has led to the SR device init code having to populate internal structures of the voltage layer. That is what I don't like. (I have a similar problem with the presence of sr_errminlimit in the omap_volt_data, because it's not used in the voltage layer either.)

Quoted 7 lines
Quoted 7 lines

So my suggestion was to remove the sr_nvalue field and replace it with something like an efuse_id field. Since n-values are directly connected with HW registers, this is a simple mapping.

This way, the voltage layer does not know about the exact N-value (because it doesn't care), ll the voltage layer needs to know is which efuse to use for this voltage.

Yes. But then voltage layer will not know about the efuse id as well. They are passed as dev attribute from hwmod file today. Are you telling remove them and hardcode them in voltage layer?

Quoted 4 lines
Quoted 4 lines

As for implementation, in the SR driver, probe could read the N-values from HW into a table. The enable/disable functiosn can look up the N-values from the table using the efuse_id from volt_data.

You mean maintain a efuse-id n-value table per SR basis??

Regards
Thara

Quoted 12 lines
Quoted 12 lines

Did I explain any better this time?

Kevin

#25 lore raw

Re: [PATCH v3 04/11] OMAP3: PM: Adding smartreflex device file.

Quoted 43 lines · Thara
Quoted 43 lines
Quoted 43 lines
Quoted 11 lines · Thara
Quoted 11 lines
Quoted 11 lines · Thara Gopinath
Quoted 10 lines

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 and test n-target vaules, module enable/disable pointers and a parameter to indicate whether smartreflex autocompensation needs to be enabled on init or not. Currently auocompensation is enabled on init by default for OMAP3430 ES3.1 chip.

[...]

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

arch/arm/mach-omap2/sr_device.c

Quoted 3 lines
arch/arm/mach-omap2/sr_device.c new file +3 -0
+	sr_data->voltdm = omap_voltage_domain_get(sr_dev_data->vdd_name);
+	if (IS_ERR(sr_data->voltdm)) {
+		pr_err("%s: Unable to get voltage domain pointer for VDD

%s\n",

Quoted 22 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
arch/arm/mach-omap2/sr_device.c new file +6 -0
+			__func__, sr_dev_data->vdd_name);
+		goto exit;
+	}
+
+	sr_dev_data->volts_supported = omap_voltage_get_volttable(
+			sr_data->voltdm, &sr_dev_data->volt_data);
Quoted 10 lines
Quoted 10 lines

arch/arm/mach-omap2/sr_device.c line 156

Quoted 7 lines
arch/arm/mach-omap2/sr_device.c new file +7 -0
+	if (!sr_dev_data->volts_supported) {
+		pr_warning("%s: No Voltage table registerd fo VDD%d."
+			"Something really wrong\n\n", __func__, i + 1);
+		goto exit;
+	}
+
+	sr_set_nvalues(sr_dev_data, sr_data);

First question: why does this N-value init need to be done in the device init? It seems better to be a part of the SR driver probe.

OMAP3 and OMAP4 has different ways of reading the efuse registers. I would like it to be in device file so that we can have the necessary checks. The driver should not be bothered about getting of the n-values.

Quoted 7 lines
Quoted 3 lines
Quoted 3 lines

Bothered? The driver's job is to probe the HW. The device code
can tell the driver where the N-values are located (register offsets, via platform_data), but IMO, should not be reading the values from HW.

But then we will have to put cpu_is_omap34xx() and cpu_is_omap44xx() checks in the driver. Also omap_ctrl_readl API will have to be used from the driver.

OK, so read them in the device file, and register the values with the SR layer (not the voltage layer.) They should be registered using some register function, not by directly manipulating structures internal to that layer.

Also, I don't see why sr_dev_data->volts_supported has to be determined at runtime. That could be set in the hwmod data using ARRAY_SIZE of the efuse offsets.

Kevin

#26 lore raw

PATCH v3 5/11 OMAP3: PM: Adding smartreflex hwmod data

In reply to Thara Gopinath

This patch adds the smartreflex hwmod data for OMAP3430 and OMAP3630. A dev_attr is also added to the hwmod structure for each smartreflex module which contains SoC specific info like the efuse offsets, test n-values etc.

---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |  249 ++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/control.h  |   27 +++
 2 files changed, 276 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +249 -0
index 5d8eb58..c9f0948 100644
@@ -17,6 +17,8 @@
 #include <mach/irqs.h>
 #include <plat/cpu.h>
 #include <plat/dma.h>
+#include <plat/control.h>
+#include <plat/smartreflex.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -36,6 +38,8 @@ static struct omap_hwmod omap3xxx_iva_hwmod;
 static struct omap_hwmod omap3xxx_l3_main_hwmod;
 static struct omap_hwmod omap3xxx_l4_core_hwmod;
 static struct omap_hwmod omap3xxx_l4_per_hwmod;
+static struct omap_hwmod omap34xx_sr1_hwmod;
+static struct omap_hwmod omap34xx_sr2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
@@ -90,9 +94,47 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
 	.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 */
@@ -197,6 +239,209 @@ static struct omap_hwmod omap3xxx_iva_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 u32 omap34xx_sr1_efuse_offs[] = {
+	OMAP343X_CONTROL_FUSE_OPP1_VDD1, OMAP343X_CONTROL_FUSE_OPP2_VDD1,
+	OMAP343X_CONTROL_FUSE_OPP3_VDD1, OMAP343X_CONTROL_FUSE_OPP4_VDD1,
+	OMAP343X_CONTROL_FUSE_OPP5_VDD1,
+};
+
+static u32 omap34xx_sr1_test_nvalues[] = {
+	0x9A90E6, 0xAABE9A, 0xBBF5C5, 0xBBB292, 0xBBF5C5,
+};
+
+static struct omap_sr_dev_data omap34xx_sr1_dev_attr = {
+	.efuse_sr_control	= OMAP343X_CONTROL_FUSE_SR,
+	.sennenable_shift	= OMAP343X_SR1_SENNENABLE_SHIFT,
+	.senpenable_shift	= OMAP343X_SR1_SENPENABLE_SHIFT,
+	.efuse_nvalues_offs	= omap34xx_sr1_efuse_offs,
+	.test_sennenable	= 0x3,
+	.test_senpenable	= 0x3,
+	.test_nvalues		= omap34xx_sr1_test_nvalues,
+	.vdd_name		= "mpu",
+};
+
+static struct omap_hwmod omap34xx_sr1_hwmod = {
+	.name		= "sr1_hwmod",
+	.class		= &omap34xx_smartreflex_hwmod_class,
+	.main_clk	= "sr1_fck",
+	.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),
+	.dev_attr	= &omap34xx_sr1_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
+					CHIP_IS_OMAP3430ES3_0 |
+					CHIP_IS_OMAP3430ES3_1),
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
+};
+
+static u32 omap36xx_sr1_efuse_offs[] = {
+	OMAP3630_CONTROL_FUSE_OPP50_VDD1, OMAP3630_CONTROL_FUSE_OPP100_VDD1,
+	OMAP3630_CONTROL_FUSE_OPP120_VDD1, OMAP3630_CONTROL_FUSE_OPP1G_VDD1,
+};
+
+static u32 omap36xx_sr1_test_nvalues[] = {
+	0x898beb, 0x999b83, 0xaac5a8, 0xaab197,
+};
+
+static struct omap_sr_dev_data omap36xx_sr1_dev_attr = {
+	.efuse_nvalues_offs	= omap36xx_sr1_efuse_offs,
+	.test_sennenable	= 0x1,
+	.test_senpenable	= 0x1,
+	.test_nvalues		= omap36xx_sr1_test_nvalues,
+	.vdd_name		= "mpu",
+};
+
+static struct omap_hwmod omap36xx_sr1_hwmod = {
+	.name		= "sr1_hwmod",
+	.class		= &omap36xx_smartreflex_hwmod_class,
+	.main_clk	= "sr1_fck",
+	.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),
+	.dev_attr	= &omap36xx_sr1_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+};
+
+/* SR2 */
+static struct omap_hwmod_ocp_if *omap3_sr2_slaves[] = {
+	&omap3_l4_core__sr2,
+};
+
+static u32 omap34xx_sr2_efuse_offs[] = {
+	OMAP343X_CONTROL_FUSE_OPP1_VDD2, OMAP343X_CONTROL_FUSE_OPP2_VDD2,
+	OMAP343X_CONTROL_FUSE_OPP3_VDD2,
+};
+
+static u32 omap34xx_sr2_test_nvalues[] = {
+	0x0, 0xAAC098, 0xAB89D9
+};
+
+static struct omap_sr_dev_data omap34xx_sr2_dev_attr = {
+	.efuse_sr_control	= OMAP343X_CONTROL_FUSE_SR,
+	.sennenable_shift	= OMAP343X_SR2_SENNENABLE_SHIFT,
+	.senpenable_shift	= OMAP343X_SR2_SENPENABLE_SHIFT,
+	.efuse_nvalues_offs	= omap34xx_sr2_efuse_offs,
+	.test_sennenable	= 0x3,
+	.test_senpenable	= 0x3,
+	.test_nvalues		= omap34xx_sr2_test_nvalues,
+	.vdd_name		= "core",
+};
+
+static struct omap_hwmod omap34xx_sr2_hwmod = {
+	.name		= "sr2_hwmod",
+	.class		= &omap34xx_smartreflex_hwmod_class,
+	.main_clk	= "sr2_fck",
+	.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),
+	.dev_attr	= &omap34xx_sr2_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
+					CHIP_IS_OMAP3430ES3_0 |
+					CHIP_IS_OMAP3430ES3_1),
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
+};
+
+static u32 omap36xx_sr2_efuse_offs[] = {
+	OMAP3630_CONTROL_FUSE_OPP50_VDD2, OMAP3630_CONTROL_FUSE_OPP100_VDD2,
+};
+
+static u32 omap36xx_sr2_test_nvalues[] = {
+	0x898beb, 0x9a8cee,
+};
+
+static struct omap_sr_dev_data omap36xx_sr2_dev_attr = {
+	.efuse_nvalues_offs	= omap36xx_sr2_efuse_offs,
+	.test_sennenable	= 0x1,
+	.test_senpenable	= 0x1,
+	.test_nvalues		= omap36xx_sr2_test_nvalues,
+	.vdd_name		= "core",
+};
+
+static struct omap_hwmod omap36xx_sr2_hwmod = {
+	.name		= "sr2_hwmod",
+	.class		= &omap36xx_smartreflex_hwmod_class,
+	.main_clk	= "sr2_fck",
+	.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),
+	.dev_attr	= &omap36xx_sr2_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+};
+
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_l3_main_hwmod,
 	&omap3xxx_l4_core_hwmod,
@@ -204,6 +449,10 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_l4_wkup_hwmod,
 	&omap3xxx_mpu_hwmod,
 	&omap3xxx_iva_hwmod,
+	&omap34xx_sr1_hwmod,
+	&omap34xx_sr2_hwmod,
+	&omap36xx_sr1_hwmod,
+	&omap36xx_sr2_hwmod,
 	NULL,
 };
 
arch/arm/plat-omap/include/plat/control.h +27 -0
index 131bf40..46e166d 100644
@@ -144,6 +144,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 \
@@ -160,6 +169,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)
@@ -243,6 +260,16 @@
 #define OMAP2_SYSBOOT_1_MASK		(1 << 1)
 #define OMAP2_SYSBOOT_0_MASK		(1 << 0)
 
+/* CONTROL_FUSE_SR bits */
+#define OMAP343X_SR2_SENNENABLE_MASK    (0x3 << 10)
+#define OMAP343X_SR2_SENNENABLE_SHIFT   10
+#define OMAP343X_SR2_SENPENABLE_MASK    (0x3 << 8)
+#define OMAP343X_SR2_SENPENABLE_SHIFT   8
+#define OMAP343X_SR1_SENNENABLE_MASK    (0x3 << 2)
+#define OMAP343X_SR1_SENNENABLE_SHIFT   2
+#define OMAP343X_SR1_SENPENABLE_MASK    (0x3 << 0)
+#define OMAP343X_SR1_SENPENABLE_SHIFT   0
+
 /* CONTROL_PBIAS_LITE bits */
 #define OMAP343X_PBIASLITESUPPLY_HIGH1	(1 << 15)
 #define OMAP343X_PBIASLITEVMODEERROR1	(1 << 11)
Signature · 1 line
1.7.1.GIT
#27 lore raw

PATCH v3 6/11 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.

---
 arch/arm/mach-omap2/Makefile             |    1 +
 arch/arm/mach-omap2/smartreflex-class3.c |   61 ++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/smartreflex-class3.h |   23 +++++++++++
 arch/arm/plat-omap/Kconfig               |    9 ++++
 4 files changed, 94 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.h
arch/arm/mach-omap2/Makefile +1 -0
index abc377a..4f6139c 100644
@@ -57,6 +57,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 +61 -0

61 lines not on this page · raw message

arch/arm/mach-omap2/smartreflex-class3.h new file +23 -0
new file mode 100644
index 0000000..4d86037
@@ -0,0 +1,23 @@
+/*
+ * Smartreflex Class 3 Routines
+ *
+ * Author: Thara Gopinath      <[email protected]>
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_SMARTREFLEXCLASS3_H
+#define __ARCH_ARM_MACH_OMAP2_SMARTREFLEXCLASS3_H
+
+#ifdef CONFIG_OMAP_SMARTREFLEX_CLASS3
+int sr_class3_init(void);
+#else
+static int sr_class3_init(void) { return 0; }
+#endif
+
+#endif
arch/arm/plat-omap/Kconfig +9 -0
index 8056349..af7acc9 100644
@@ -67,6 +67,15 @@ config OMAP_SMARTREFLEX_TESTING
 
 	  WARNING: Enabling this option may cause your device to hang!
 
+config OMAP_SMARTREFLEX_CLASS3
+	bool "Class 3 mode of Smartreflex Implementation"
+	depends on OMAP_SMARTREFLEX && TWL4030_CORE
+	help
+	  Say Y to enable Class 3 implementation of Smartreflex
+
+	  Class 3 implementation of Smartreflex employs continuous hardware
+	  voltage caliberation.
+
 config OMAP_RESET_CLOCKS
 	bool "Reset unused clocks during boot"
 	depends on ARCH_OMAP
Signature · 1 line
1.7.1.GIT
#28 lore raw

Re: [PATCH v3 06/11] OMAP3: PM: Adding smartreflex class3 driver

Quoted 8 lines · 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.

Some minor comments below...

Quoted 37 lines
---
 arch/arm/mach-omap2/Makefile             |    1 +
 arch/arm/mach-omap2/smartreflex-class3.c |   61 ++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/smartreflex-class3.h |   23 +++++++++++
 arch/arm/plat-omap/Kconfig               |    9 ++++
 4 files changed, 94 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.h
arch/arm/mach-omap2/Makefile +1 -0
index abc377a..4f6139c 100644
@@ -57,6 +57,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 +10 -0
new file mode 100644
index 0000000..f1ade08
@@ -0,0 +1,61 @@
+/*
+ * Smart reflex Class 3 specific implementations
+ *
+ * Author: Thara Gopinath       <[email protected]>
+ *
+ * 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

arch/arm/mach-omap2/smartreflex-class3.c line 20

Quoted 10 lines
arch/arm/mach-omap2/smartreflex-class3.c new file +10 -0
+ * published by the Free Software Foundation.
+ */
+
+#include <plat/smartreflex.h>
+
+#include "smartreflex-class3.h"
+
+static int sr_class3_enable(struct voltagedomain *voltdm)
+{
+	unsigned long volt = 0;

minor: '= 0' assignment not needed as it's immediately assigned in the next line.

Quoted 25 lines
arch/arm/mach-omap2/smartreflex-class3.c new file +25 -0
+	volt = omap_voltage_get_nom_volt(voltdm);
+	if (!volt) {
+		pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
+				__func__, voltdm->name);
+		return -ENODATA;
+	}
+
+	omap_vp_enable(voltdm);
+	return sr_enable(voltdm, volt);
+}
+
+static int sr_class3_disable(struct voltagedomain *voltdm, int is_volt_reset)
+{
+	omap_vp_disable(voltdm);
+	sr_disable(voltdm);
+	if (is_volt_reset)
+		omap_voltage_reset(voltdm);
+
+	return 0;
+}
+
+static int sr_class3_configure(struct voltagedomain *voltdm)
+{
+	return sr_configure_errgen(voltdm);
+}

arch/arm/mach-omap2/smartreflex-class3.c line 56

Quoted 10 lines
arch/arm/mach-omap2/smartreflex-class3.c new file +10 -0
+
+/* SR class3 structure */
+static struct omap_smartreflex_class_data class3_data = {
+	.enable = sr_class3_enable,
+	.disable = sr_class3_disable,
+	.configure = sr_class3_configure,
+	.class_type = SR_CLASS3,
+};
+
+/* Smartreflex CLASS3 init API to be called from board file */

s/CLASS3/Class 3/

arch/arm/mach-omap2/smartreflex-class3.c line 59

Quoted 3 lines
arch/arm/mach-omap2/smartreflex-class3.c new file +3 -0
+int __init sr_class3_init(void)
+{
+	pr_info("SmartReflex CLASS3 initialized\n");

ditto

Quoted 37 lines
arch/arm/mach-omap2/smartreflex-class3.c new file +2 -0
+	return sr_register_class(&class3_data);
+}
arch/arm/mach-omap2/smartreflex-class3.h new file +23 -0
new file mode 100644
index 0000000..4d86037
@@ -0,0 +1,23 @@
+/*
+ * Smartreflex Class 3 Routines
+ *
+ * Author: Thara Gopinath      <[email protected]>
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_SMARTREFLEXCLASS3_H
+#define __ARCH_ARM_MACH_OMAP2_SMARTREFLEXCLASS3_H
+
+#ifdef CONFIG_OMAP_SMARTREFLEX_CLASS3
+int sr_class3_init(void);
+#else
+static int sr_class3_init(void) { return 0; }
+#endif
+
+#endif
arch/arm/plat-omap/Kconfig +0 -0
index 8056349..af7acc9 100644
@@ -67,6 +67,15 @@ config OMAP_SMARTREFLEX_TESTING
 

arch/arm/plat-omap/Kconfig config OMAP_SMARTREFLEX_TESTING · line 77

Quoted 10 lines
arch/arm/plat-omap/Kconfig +8 -0
 	  WARNING: Enabling this option may cause your device to hang!
 
+config OMAP_SMARTREFLEX_CLASS3
+	bool "Class 3 mode of Smartreflex Implementation"
+	depends on OMAP_SMARTREFLEX && TWL4030_CORE
+	help
+	  Say Y to enable Class 3 implementation of Smartreflex
+
+	  Class 3 implementation of Smartreflex employs continuous hardware
+	  voltage caliberation.

calibration

arch/arm/plat-omap/Kconfig config OMAP_SMARTREFLEX_TESTING · line 81

Quoted 4 lines
arch/arm/plat-omap/Kconfig +1 -0
+
 config OMAP_RESET_CLOCKS
 	bool "Reset unused clocks during boot"
 	depends on ARCH_OMAP

Kevin

#29 lore raw

RE: [PATCH v3 06/11] OMAP3: PM: Adding smartreflex class3 driver

Quoted 19 lines
Quoted 19 lines

-----Original Message-----
From: Kevin Hilman [mailto:[email protected]]
Sent: Friday, October 15, 2010 4:39 AM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 06/11] OMAP3: PM: Adding smartreflex class3 driver

Quoted 7 lines · 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.

Quoted 3 lines
Quoted 3 lines
Quoted 1 line

Some minor comments below...

Thanks for the review!

Quoted 46 lines
Quoted 46 lines
Quoted 4 lines
---
 arch/arm/mach-omap2/Makefile             |    1 +
 arch/arm/mach-omap2/smartreflex-class3.c |   61

++++++++++++++++++++++++++++++

arch/arm/mach-omap2/Makefile obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o

Quoted 11 lines
 arch/arm/mach-omap2/smartreflex-class3.h |   23 +++++++++++
 arch/arm/plat-omap/Kconfig               |    9 ++++
 4 files changed, 94 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.h
arch/arm/mach-omap2/Makefile +0 -0
index abc377a..4f6139c 100644
@@ -57,6 +57,7 @@ obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o

voltage.o \

arch/arm/mach-

Quoted 8 lines
arch/arm/mach-omap2/Makefile +1 -0
 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- renamed from arch/arm/mach-omap2/smartreflex-class3.c +0 -0

omap2/smartreflex-class3.c

Quoted 20 lines

new file mode 100644
index 0000000..f1ade08

arch/arm/mach-omap2/smartreflex-class3.c new file +15 -0
@@ -0,0 +1,61 @@
+/*
+ * Smart reflex Class 3 specific implementations
+ *
+ * Author: Thara Gopinath       <[email protected]>
+ *
+ * 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.
+ */
+
+#include <plat/smartreflex.h>
+
Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/smartreflex-class3.c line 20

Quoted 5 lines
arch/arm/mach-omap2/smartreflex-class3.c new file +5 -0
+#include "smartreflex-class3.h"
+
+static int sr_class3_enable(struct voltagedomain *voltdm)
+{
+	unsigned long volt = 0;

minor: '= 0' assignment not needed as it's immediately assigned in the next line.

Ok.

Quoted 31 lines
Quoted 31 lines

arch/arm/mach-omap2/smartreflex-class3.c

Quoted 13 lines
arch/arm/mach-omap2/smartreflex-class3.c new file +12 -0
+	volt = omap_voltage_get_nom_volt(voltdm);
+	if (!volt) {
+		pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
+				__func__, voltdm->name);
+		return -ENODATA;
+	}
+
+	omap_vp_enable(voltdm);
+	return sr_enable(voltdm, volt);
+}
+
+static int sr_class3_disable(struct voltagedomain *voltdm, int

is_volt_reset)

Quoted 17 lines
arch/arm/mach-omap2/smartreflex-class3.c new file +17 -0
+{
+	omap_vp_disable(voltdm);
+	sr_disable(voltdm);
+	if (is_volt_reset)
+		omap_voltage_reset(voltdm);
+
+	return 0;
+}
+
+static int sr_class3_configure(struct voltagedomain *voltdm)
+{
+	return sr_configure_errgen(voltdm);
+}
+
+/* SR class3 structure */
+static struct omap_smartreflex_class_data class3_data = {
+	.enable = sr_class3_enable,
Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/smartreflex-class3.c line 56

Quoted 6 lines
arch/arm/mach-omap2/smartreflex-class3.c new file +6 -0
+	.disable = sr_class3_disable,
+	.configure = sr_class3_configure,
+	.class_type = SR_CLASS3,
+};
+
+/* Smartreflex CLASS3 init API to be called from board file */

s/CLASS3/Class 3/

Will correct

Quoted 6 lines
Quoted 6 lines

arch/arm/mach-omap2/smartreflex-class3.c line 59

Quoted 4 lines
arch/arm/mach-omap2/smartreflex-class3.c new file +3 -0
+int __init sr_class3_init(void)
+{
+	pr_info("SmartReflex CLASS3 initialized\n");

ditto

Will correct

Quoted 41 lines
Quoted 41 lines

arch/arm/mach-

Quoted 4 lines
arch/arm/mach-omap2/smartreflex-class3.c new file +2 -0
+	return sr_register_class(&class3_data);
+}
arch/arm/mach- renamed from arch/arm/mach-omap2/smartreflex-class3.h +0 -0

omap2/smartreflex-class3.h

Quoted 36 lines

new file mode 100644
index 0000000..4d86037

arch/arm/mach-omap2/smartreflex-class3.h new file +23 -0
@@ -0,0 +1,23 @@
+/*
+ * Smartreflex Class 3 Routines
+ *
+ * Author: Thara Gopinath      <[email protected]>
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_SMARTREFLEXCLASS3_H
+#define __ARCH_ARM_MACH_OMAP2_SMARTREFLEXCLASS3_H
+
+#ifdef CONFIG_OMAP_SMARTREFLEX_CLASS3
+int sr_class3_init(void);
+#else
+static int sr_class3_init(void) { return 0; }
+#endif
+
+#endif
arch/arm/plat-omap/Kconfig +0 -0
index 8056349..af7acc9 100644
@@ -67,6 +67,15 @@ config OMAP_SMARTREFLEX_TESTING
 
 	  WARNING: Enabling this option may cause your device to hang!
 
Quoted 10 lines
Quoted 10 lines

arch/arm/plat-omap/Kconfig config OMAP_SMARTREFLEX_TESTING · line 77

Quoted 8 lines
arch/arm/plat-omap/Kconfig +8 -0
+config OMAP_SMARTREFLEX_CLASS3
+	bool "Class 3 mode of Smartreflex Implementation"
+	depends on OMAP_SMARTREFLEX && TWL4030_CORE
+	help
+	  Say Y to enable Class 3 implementation of Smartreflex
+
+	  Class 3 implementation of Smartreflex employs continuous hardware
+	  voltage caliberation.

calibration

Will correct

Quoted 7 lines
Quoted 7 lines

arch/arm/plat-omap/Kconfig config OMAP_SMARTREFLEX_TESTING · line 81

Quoted 5 lines
arch/arm/plat-omap/Kconfig +1 -0
+
 config OMAP_RESET_CLOCKS
 	bool "Reset unused clocks during boot"
 	depends on ARCH_OMAP

Kevin

#30 lore raw

PATCH v3 7/11 OMAP3: PM: Adding T2 enabling of smartreflex support

In reply to Thara Gopinath

This patch adds support in the twl4030 driver to hook up the API enabling smartreflex support on PMIC side with the smartreflex driver. Without this the OMAP smartreflex modules will not function.

---
 drivers/mfd/twl-core.c      |    7 +++++--
 drivers/mfd/twl4030-power.c |   29 +++++++++++++++++++++++++++++
 include/linux/i2c/twl.h     |    1 +
 3 files changed, 35 insertions(+), 2 deletions(-)
drivers/mfd/twl-core.c +5 -2
index 720e099..677b903 100644
@@ -1009,8 +1009,11 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	clocks_init(&client->dev, pdata->clock);
 
 	/* load power event scripts */
-	if (twl_has_power() && pdata->power)
-		twl4030_power_init(pdata->power);
+	if (twl_has_power()) {
+		twl4030_power_sr_init();
+		 if (pdata->power)
+			twl4030_power_init(pdata->power);
+	}
 
 	/* Maybe init the T2 Interrupt subsystem */
 	if (client->irq
drivers/mfd/twl4030-power.c +29 -0
index 7efa878..6d0ad2d 100644
@@ -31,6 +31,8 @@
 
 #include <asm/mach-types.h>
 
+#include <plat/smartreflex.h>
+
 static u8 twl4030_start_script_address = 0x2b;
 
 #define PWR_P1_SW_EVENTS	0x10
@@ -63,6 +65,10 @@ static u8 twl4030_start_script_address = 0x2b;
 #define R_MEMORY_ADDRESS	PHY_TO_OFF_PM_MASTER(0x59)
 #define R_MEMORY_DATA		PHY_TO_OFF_PM_MASTER(0x5a)
 
+/* Smartreflex Control */
+#define R_DCDC_GLOBAL_CFG	PHY_TO_OFF_PM_RECEIVER(0x61)
+#define CFG_ENABLE_SRFLX	0x08
+
 #define R_PROTECT_KEY		0x0E
 #define R_KEY_1			0xC0
 #define R_KEY_2			0x0C
@@ -511,6 +517,29 @@ int twl4030_remove_script(u8 flags)
 	return err;
 }
 
+/* API to enable smrtreflex on Triton side */
+static void twl4030_smartreflex_init(void)
+{
+	int ret = 0;
+	u8 read_val;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &read_val,
+			R_DCDC_GLOBAL_CFG);
+	read_val |= CFG_ENABLE_SRFLX;
+	ret |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, read_val,
+			R_DCDC_GLOBAL_CFG);
+}
+
+struct omap_smartreflex_pmic_data twl4030_sr_data = {
+	.sr_pmic_init   = twl4030_smartreflex_init,
+};
+
+void __init twl4030_power_sr_init()
+{
+	/* Register the SR init API with the Smartreflex driver */
+	omap_sr_register_pmic(&twl4030_sr_data);
+}
+
 void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
 {
 	int err = 0;
include/linux/i2c/twl.h +1 -0
index 6de90bf..b02011e 100644
@@ -550,6 +550,7 @@ struct twl4030_power_data {
 };
 
 extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
+extern void twl4030_power_sr_init(void);
 extern int twl4030_remove_script(u8 flags);
 
 struct twl4030_codec_audio_data {
Signature · 1 line
1.7.1.GIT
#31 lore raw

Re: [PATCH v3 07/11] OMAP3: PM: Adding T2 enabling of smartreflex support

Quoted 6 lines · Thara Gopinath

This patch adds support in the twl4030 driver to hook up the API enabling smartreflex support on PMIC side with the smartreflex driver. Without this the OMAP smartreflex modules will not function.

This one should be a separate patch with a subject something like

mfd: twl4030: add SmartReflex support

and the changelog should indicate its dependency on this SR/voltage series.

Kevin

Quoted 90 lines
---
 drivers/mfd/twl-core.c      |    7 +++++--
 drivers/mfd/twl4030-power.c |   29 +++++++++++++++++++++++++++++
 include/linux/i2c/twl.h     |    1 +
 3 files changed, 35 insertions(+), 2 deletions(-)
drivers/mfd/twl-core.c +5 -2
index 720e099..677b903 100644
@@ -1009,8 +1009,11 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	clocks_init(&client->dev, pdata->clock);
 
 	/* load power event scripts */
-	if (twl_has_power() && pdata->power)
-		twl4030_power_init(pdata->power);
+	if (twl_has_power()) {
+		twl4030_power_sr_init();
+		 if (pdata->power)
+			twl4030_power_init(pdata->power);
+	}
 
 	/* Maybe init the T2 Interrupt subsystem */
 	if (client->irq
drivers/mfd/twl4030-power.c +29 -0
index 7efa878..6d0ad2d 100644
@@ -31,6 +31,8 @@
 
 #include <asm/mach-types.h>
 
+#include <plat/smartreflex.h>
+
 static u8 twl4030_start_script_address = 0x2b;
 
 #define PWR_P1_SW_EVENTS	0x10
@@ -63,6 +65,10 @@ static u8 twl4030_start_script_address = 0x2b;
 #define R_MEMORY_ADDRESS	PHY_TO_OFF_PM_MASTER(0x59)
 #define R_MEMORY_DATA		PHY_TO_OFF_PM_MASTER(0x5a)
 
+/* Smartreflex Control */
+#define R_DCDC_GLOBAL_CFG	PHY_TO_OFF_PM_RECEIVER(0x61)
+#define CFG_ENABLE_SRFLX	0x08
+
 #define R_PROTECT_KEY		0x0E
 #define R_KEY_1			0xC0
 #define R_KEY_2			0x0C
@@ -511,6 +517,29 @@ int twl4030_remove_script(u8 flags)
 	return err;
 }
 
+/* API to enable smrtreflex on Triton side */
+static void twl4030_smartreflex_init(void)
+{
+	int ret = 0;
+	u8 read_val;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &read_val,
+			R_DCDC_GLOBAL_CFG);
+	read_val |= CFG_ENABLE_SRFLX;
+	ret |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, read_val,
+			R_DCDC_GLOBAL_CFG);
+}
+
+struct omap_smartreflex_pmic_data twl4030_sr_data = {
+	.sr_pmic_init   = twl4030_smartreflex_init,
+};
+
+void __init twl4030_power_sr_init()
+{
+	/* Register the SR init API with the Smartreflex driver */
+	omap_sr_register_pmic(&twl4030_sr_data);
+}
+
 void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
 {
 	int err = 0;
include/linux/i2c/twl.h +1 -0
index 6de90bf..b02011e 100644
@@ -550,6 +550,7 @@ struct twl4030_power_data {
 };
 
 extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
+extern void twl4030_power_sr_init(void);
 extern int twl4030_remove_script(u8 flags);
 
 struct twl4030_codec_audio_data {
#32 lore raw

RE: [PATCH v3 07/11] OMAP3: PM: Adding T2 enabling of smartreflex support

Quoted 18 lines
Quoted 18 lines

-----Original Message-----
From: Kevin Hilman [mailto:[email protected]]
Sent: Wednesday, September 29, 2010 5:38 AM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 07/11] OMAP3: PM: Adding T2 enabling of smartreflex support

Quoted 5 lines · Thara Gopinath

This patch adds support in the twl4030 driver to hook up the API enabling smartreflex support on PMIC side with the smartreflex driver. Without this the OMAP smartreflex modules will not function.

Quoted 8 lines
Quoted 8 lines
Quoted 1 line

This one should be a separate patch with a subject something like

mfd: twl4030: add SmartReflex support

and the changelog should indicate its dependency on this SR/voltage series.

Do you mean to say this patch should not be a part of this series at all ??

Regards
Thara

Quoted 95 lines
Quoted 95 lines

Kevin

drivers/mfd/twl-core.c twl_probe(struct i2c_client *client, const struct

Quoted 11 lines
---
 drivers/mfd/twl-core.c      |    7 +++++--
 drivers/mfd/twl4030-power.c |   29 +++++++++++++++++++++++++++++
 include/linux/i2c/twl.h     |    1 +
 3 files changed, 35 insertions(+), 2 deletions(-)
drivers/mfd/twl-core.c +0 -0
index 720e099..677b903 100644
@@ -1009,8 +1009,11 @@ twl_probe(struct i2c_client *client, const struct

i2c_device_id *id)

Quoted 72 lines
drivers/mfd/twl-core.c +5 -2
 	clocks_init(&client->dev, pdata->clock);
 
 	/* load power event scripts */
-	if (twl_has_power() && pdata->power)
-		twl4030_power_init(pdata->power);
+	if (twl_has_power()) {
+		twl4030_power_sr_init();
+		 if (pdata->power)
+			twl4030_power_init(pdata->power);
+	}
 
 	/* Maybe init the T2 Interrupt subsystem */
 	if (client->irq
drivers/mfd/twl4030-power.c +29 -0
index 7efa878..6d0ad2d 100644
@@ -31,6 +31,8 @@
 
 #include <asm/mach-types.h>
 
+#include <plat/smartreflex.h>
+
 static u8 twl4030_start_script_address = 0x2b;
 
 #define PWR_P1_SW_EVENTS	0x10
@@ -63,6 +65,10 @@ static u8 twl4030_start_script_address = 0x2b;
 #define R_MEMORY_ADDRESS	PHY_TO_OFF_PM_MASTER(0x59)
 #define R_MEMORY_DATA		PHY_TO_OFF_PM_MASTER(0x5a)
 
+/* Smartreflex Control */
+#define R_DCDC_GLOBAL_CFG	PHY_TO_OFF_PM_RECEIVER(0x61)
+#define CFG_ENABLE_SRFLX	0x08
+
 #define R_PROTECT_KEY		0x0E
 #define R_KEY_1			0xC0
 #define R_KEY_2			0x0C
@@ -511,6 +517,29 @@ int twl4030_remove_script(u8 flags)
 	return err;
 }
 
+/* API to enable smrtreflex on Triton side */
+static void twl4030_smartreflex_init(void)
+{
+	int ret = 0;
+	u8 read_val;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &read_val,
+			R_DCDC_GLOBAL_CFG);
+	read_val |= CFG_ENABLE_SRFLX;
+	ret |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, read_val,
+			R_DCDC_GLOBAL_CFG);
+}
+
+struct omap_smartreflex_pmic_data twl4030_sr_data = {
+	.sr_pmic_init   = twl4030_smartreflex_init,
+};
+
+void __init twl4030_power_sr_init()
+{
+	/* Register the SR init API with the Smartreflex driver */
+	omap_sr_register_pmic(&twl4030_sr_data);
+}
+
 void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
 {
 	int err = 0;
include/linux/i2c/twl.h +0 -0
index 6de90bf..b02011e 100644

include/linux/i2c/twl.h struct twl4030_power_data { · line 552

Quoted 3 lines
include/linux/i2c/twl.h +0 -0
@@ -550,6 +550,7 @@ struct twl4030_power_data {
 };
 
 extern void twl4030_power_init(struct twl4030_power_data

*triton2_scripts);

Quoted 4 lines
include/linux/i2c/twl.h +1 -0
+extern void twl4030_power_sr_init(void);
 extern int twl4030_remove_script(u8 flags);
 
 struct twl4030_codec_audio_data {
#33 lore raw

Re: [PATCH v3 07/11] OMAP3: PM: Adding T2 enabling of smartreflex support

Quoted 9 lines · Thara
Quoted 9 lines
Quoted 9 lines
Quoted 6 lines · Thara Gopinath

This patch adds support in the twl4030 driver to hook up the API enabling smartreflex support on PMIC side with the smartreflex driver. Without this the OMAP smartreflex modules will not function.

Quoted 9 lines
Quoted 6 lines
Quoted 6 lines

This one should be a separate patch with a subject something like

mfd: twl4030: add SmartReflex support

and the changelog should indicate its dependency on this SR/voltage series.

Do you mean to say this patch should not be a part of this series at all ??

Yes, as it will need to be merged via the mfd tree once the SR core is merged.

Kevin

#34 lore raw

PATCH v3 8/11 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. By default only a read of these parameters are permitted. If you need to write into them then
echo 1 > /pm_debug/enable_sr_vp_debug

The voltage parameters can be viewed at

	/pm_debug/voltage/vdd_<x>/<parameter>

and the smartreflex parameters can be viewed at
/pm_debug/smartreflex/sr_<x>/<parameter>

where <x> is mpu or core for OMAP3.

---
 arch/arm/mach-omap2/pm-debug.c                |   15 ++
 arch/arm/mach-omap2/smartreflex.c             |   40 +++++-
 arch/arm/mach-omap2/voltage.c                 |  210 ++++++++++++++++++++++++-
 arch/arm/plat-omap/include/plat/smartreflex.h |    1 -
 arch/arm/plat-omap/include/plat/voltage.h     |    5 +
 5 files changed, 264 insertions(+), 7 deletions(-)
arch/arm/mach-omap2/pm-debug.c +15 -0
index 390f1c6..879efb2 100644
@@ -32,6 +32,7 @@
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
 #include <plat/dmtimer.h>
+#include <plat/voltage.h>
 
 #include "prm.h"
 #include "cm.h"
@@ -586,6 +587,18 @@ static int option_set(void *data, u64 val)
 			omap3_pm_off_mode_enable(val);
 	}
 
+	if (option == &enable_sr_vp_debug && val)
+		pr_notice("Beware that enabling this option will allow user "
+			"to override the system defined vp and sr parameters "
+			"All the updated parameters will take effect next "
+			"time smartreflex is enabled. Also this option "
+			"disables the automatic vp errorgain and sr errormin "
+			"limit changes as per the voltage. Users will have "
+			"to explicitly write values into the debug fs "
+			"entries corresponding to these if they want to see "
+			"them changing according to the VDD voltage\n");
+
+
 	return 0;
 }
 
@@ -642,6 +655,8 @@ static int __init pm_dbg_init(void)
 	(void) debugfs_create_file("wakeup_timer_milliseconds",
 			S_IRUGO | S_IWUGO, d, &wakeup_timer_milliseconds,
 			&pm_dbg_option_fops);
+	(void) debugfs_create_file("enable_sr_vp_debug",  S_IRUGO | S_IWUGO, d,
+				&enable_sr_vp_debug, &pm_dbg_option_fops);
 
 	pm_dbg_main_dir = d;
 	pm_dbg_init_done = 1;
arch/arm/mach-omap2/smartreflex.c +38 -2
index 7fc3138..b5a7878 100644
@@ -558,8 +558,13 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
 		return -ENODATA;
 	}
 
-	/* errminlimit is opp dependent and hence linked to voltage */
-	sr->err_minlimit = volt_data->sr_errminlimit;
+	/*
+	 * errminlimit is opp dependent and hence linked to voltage
+	 * if the debug option is enabled, the user might have over ridden
+	 * this parameter so do not get it from voltage table
+	 */
+	if (!enable_sr_vp_debug)
+		sr->err_minlimit = volt_data->sr_errminlimit;
 
 	/* Enable the clocks */
 	if (!sr->sr_enable) {
@@ -811,9 +816,34 @@ static int omap_sr_autocomp_store(void *data, u64 val)
 	return 0;
 }
 
+static int omap_sr_params_show(void *data, u64 *val)
+{
+	u32 *param = data;
+
+	*val = *param;
+	return 0;
+}
+
+static int omap_sr_params_store(void *data, u64 val)
+{
+	if (enable_sr_vp_debug) {
+		u32 *option = data;
+		*option = val;
+	} else {
+		pr_notice("%s: DEBUG option not enabled!\n	\
+			echo 1 > pm_debug/enable_sr_vp_debug - to enable\n",
+			__func__);
+	}
+
+	return 0;
+}
+
 DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
 		omap_sr_autocomp_store, "%llu\n");
 
+DEFINE_SIMPLE_ATTRIBUTE(sr_params_fops, omap_sr_params_show,
+		omap_sr_params_store, "%llu\n");
+
 static int __init omap_smartreflex_probe(struct platform_device *pdev)
 {
 	struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
@@ -907,6 +937,12 @@ static int __init omap_smartreflex_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_file("errweight", S_IRUGO | S_IWUGO, dbg_dir,
+			&sr_info->err_weight, &sr_params_fops);
+	(void) debugfs_create_file("errmaxlimit", S_IRUGO | S_IWUGO, dbg_dir,
+			&sr_info->err_maxlimit, &sr_params_fops);
+	(void) debugfs_create_file("errminlimit", S_IRUGO | S_IWUGO, dbg_dir,
+			&sr_info->err_minlimit, &sr_params_fops);
 
 	return ret;
 
arch/arm/mach-omap2/voltage.c +206 -4

264 lines not on this page · raw message

arch/arm/plat-omap/include/plat/smartreflex.h +0 -1
index 1ad03ea..4ee548d 100644
@@ -24,7 +24,6 @@
 #include <plat/voltage.h>
 
 #ifdef CONFIG_PM_DEBUG
-extern struct dentry *pm_dbg_main_dir;
 extern struct dentry *sr_dbg_dir;
 #endif
 
arch/arm/plat-omap/include/plat/voltage.h +5 -0
index 99836a1..8978d33 100644
@@ -14,6 +14,11 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
 #define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
 
+extern u32 enable_sr_vp_debug;
+#ifdef CONFIG_PM_DEBUG
+extern struct dentry *pm_dbg_main_dir;
+#endif
+
 #define VOLTSCALE_VPFORCEUPDATE		1
 #define VOLTSCALE_VCBYPASS		2
 
Signature · 1 line
1.7.1.GIT
#35 lore raw

Re: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

Thara Gopinath <[email protected]> writes:

[...]

Quoted 5 lines
arch/arm/plat-omap/include/plat/voltage.h +0 -0
index 99836a1..8978d33 100644

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

Quoted 10 lines
arch/arm/plat-omap/include/plat/voltage.h +5 -0
@@ -14,6 +14,11 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
 #define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
 
+extern u32 enable_sr_vp_debug;
+#ifdef CONFIG_PM_DEBUG
+extern struct dentry *pm_dbg_main_dir;
+#endif
+
 #define VOLTSCALE_VPFORCEUPDATE		1
 #define VOLTSCALE_VCBYPASS		2

This belongs in PATCH 1/11 and belongs in pm.h, not voltage.h as it's a feature of the PM debug layer, not the voltage layer.

Kevin

#36 lore raw

RE: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

Quoted 24 lines
Quoted 24 lines

-----Original Message-----
From: Kevin Hilman [mailto:[email protected]]
Sent: Thursday, September 30, 2010 4:50 AM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

Thara Gopinath <[email protected]> writes:

[...]

arch/arm/plat-

Quoted 1 line
arch/arm/plat- renamed from arch/arm/plat-omap/include/plat/voltage.h +0 -0

omap/include/plat/voltage.h

Quoted 7 lines

index 99836a1..8978d33 100644

arch/arm/plat-omap/include/plat/voltage.h +0 -0
@@ -14,6 +14,11 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
 #define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
 
Quoted 10 lines
Quoted 10 lines

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

Quoted 7 lines
arch/arm/plat-omap/include/plat/voltage.h +5 -0
+extern u32 enable_sr_vp_debug;
+#ifdef CONFIG_PM_DEBUG
+extern struct dentry *pm_dbg_main_dir;
+#endif
+
 #define VOLTSCALE_VPFORCEUPDATE		1
 #define VOLTSCALE_VCBYPASS		2

This belongs in PATCH 1/11 and belongs in pm.h, not voltage.h as it's a feature of the PM debug layer, not the voltage layer.

Yes indeed!! Will fix this in v4

Regards
Thara

#37 lore raw

Re: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

In reply to Thara Gopinath
Quoted 13 lines · Thara Gopinath
arch/arm/mach-omap2/smartreflex.c +3 -2
@@ -558,8 +558,13 @@ int sr_enable(struct voltagedomain *voltdm,
 unsigned long volt)
                return -ENODATA;
        }
 
-       /* errminlimit is opp dependent and hence linked to voltage */
-       sr->err_minlimit = volt_data->sr_errminlimit;
+       /*
+        * errminlimit is opp dependent and hence linked to voltage
+        * if the debug option is enabled, the user might have over

ridden

arch/arm/mach-omap2/smartreflex.c int sr_enable(struct voltagedomain *voltdm, unsigned long volt) · line 565

Quoted 2 lines
arch/arm/mach-omap2/smartreflex.c +2 -0
+        * this parameter so do not get it from voltage table
+        */

this comment needs better punctuation to be clearer

arch/arm/mach-omap2/smartreflex.c int sr_enable(struct voltagedomain *voltdm, unsigned long volt) · line 567

Quoted 2 lines
arch/arm/mach-omap2/smartreflex.c +2 -0
+       if (!enable_sr_vp_debug)
+               sr->err_minlimit = volt_data->sr_errminlimit;

Rather than checking if debug is enabled, you should create a flag specific to whether this value was overwritten by the user, and use that flag instead.

Kevin

#38 lore raw

RE: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

Quoted 20 lines
Quoted 20 lines

-----Original Message-----
From: [email protected] [mailto:linux-omap- [email protected]] On Behalf Of Kevin Hilman
Sent: Friday, October 15, 2010 12:51 AM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

Quoted 7 lines · Thara Gopinath
arch/arm/mach-omap2/smartreflex.c +0 -0
@@ -558,8 +558,13 @@ int sr_enable(struct voltagedomain *voltdm,
 unsigned long volt)
                return -ENODATA;
        }
 
Quoted 10 lines
Quoted 10 lines

arch/arm/mach-omap2/smartreflex.c int sr_enable(struct voltagedomain *voltdm, unsigned long volt) · line 565

Quoted 8 lines
arch/arm/mach-omap2/smartreflex.c +3 -2
-       /* errminlimit is opp dependent and hence linked to voltage */
-       sr->err_minlimit = volt_data->sr_errminlimit;
+       /*
+        * errminlimit is opp dependent and hence linked to voltage
+        * if the debug option is enabled, the user might have over

ridden

arch/arm/mach-omap2/smartreflex.c +2 -0
+        * this parameter so do not get it from voltage table
+        */

this comment needs better punctuation to be clearer

Will do

Quoted 7 lines
Quoted 7 lines

arch/arm/mach-omap2/smartreflex.c int sr_enable(struct voltagedomain *voltdm, unsigned long volt) · line 567

Quoted 3 lines
arch/arm/mach-omap2/smartreflex.c +2 -0
+       if (!enable_sr_vp_debug)
+               sr->err_minlimit = volt_data->sr_errminlimit;

Rather than checking if debug is enabled, you should create a flag specific to whether this value was overwritten by the user, and use that flag instead.

mmm.. See my comment regarding flag and enable_sr_vp_debug in the other patch

Regards
Thara

Quoted 8 lines
Quoted 8 lines

Kevin

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

#39 lore raw

Re: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

In reply to Thara Gopinath
Quoted 6 lines · 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. By default only a read of these parameters are permitted. If you need to write into them then
echo 1 > /pm_debug/enable_sr_vp_debug

Why a read-only interface by default? As a debug interface it seems
redundant to have to enable it.

Quoted 82 lines

The voltage parameters can be viewed at

	/pm_debug/voltage/vdd_<x>/<parameter>

and the smartreflex parameters can be viewed at
/pm_debug/smartreflex/sr_<x>/<parameter>

where <x> is mpu or core for OMAP3.

---
 arch/arm/mach-omap2/pm-debug.c                |   15 ++
 arch/arm/mach-omap2/smartreflex.c             |   40 +++++-
 arch/arm/mach-omap2/voltage.c                 |  210 ++++++++++++++++++++++++-
 arch/arm/plat-omap/include/plat/smartreflex.h |    1 -
 arch/arm/plat-omap/include/plat/voltage.h     |    5 +
 5 files changed, 264 insertions(+), 7 deletions(-)
arch/arm/mach-omap2/pm-debug.c +15 -0
index 390f1c6..879efb2 100644
@@ -32,6 +32,7 @@
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
 #include <plat/dmtimer.h>
+#include <plat/voltage.h>
 
 #include "prm.h"
 #include "cm.h"
@@ -586,6 +587,18 @@ static int option_set(void *data, u64 val)
 			omap3_pm_off_mode_enable(val);
 	}
 
+	if (option == &enable_sr_vp_debug && val)
+		pr_notice("Beware that enabling this option will allow user "
+			"to override the system defined vp and sr parameters "
+			"All the updated parameters will take effect next "
+			"time smartreflex is enabled. Also this option "
+			"disables the automatic vp errorgain and sr errormin "
+			"limit changes as per the voltage. Users will have "
+			"to explicitly write values into the debug fs "
+			"entries corresponding to these if they want to see "
+			"them changing according to the VDD voltage\n");
+
+
 	return 0;
 }
 
@@ -642,6 +655,8 @@ static int __init pm_dbg_init(void)
 	(void) debugfs_create_file("wakeup_timer_milliseconds",
 			S_IRUGO | S_IWUGO, d, &wakeup_timer_milliseconds,
 			&pm_dbg_option_fops);
+	(void) debugfs_create_file("enable_sr_vp_debug",  S_IRUGO | S_IWUGO, d,
+				&enable_sr_vp_debug, &pm_dbg_option_fops);
 
 	pm_dbg_main_dir = d;
 	pm_dbg_init_done = 1;
arch/arm/mach-omap2/smartreflex.c +9 -2
index 7fc3138..b5a7878 100644
@@ -558,8 +558,13 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
 		return -ENODATA;
 	}
 
-	/* errminlimit is opp dependent and hence linked to voltage */
-	sr->err_minlimit = volt_data->sr_errminlimit;
+	/*
+	 * errminlimit is opp dependent and hence linked to voltage
+	 * if the debug option is enabled, the user might have over ridden
+	 * this parameter so do not get it from voltage table
+	 */
+	if (!enable_sr_vp_debug)
+		sr->err_minlimit = volt_data->sr_errminlimit;
 
 	/* Enable the clocks */
 	if (!sr->sr_enable) {
@@ -811,9 +816,34 @@ static int omap_sr_autocomp_store(void *data, u64 val)
 	return 0;
 }
 
+static int omap_sr_params_show(void *data, u64 *val)
+{

arch/arm/mach-omap2/smartreflex.c static int omap_sr_autocomp_store(void *data, u64 val) · line 830

Quoted 10 lines
arch/arm/mach-omap2/smartreflex.c +10 -0
+	u32 *param = data;
+
+	*val = *param;
+	return 0;
+}
+
+static int omap_sr_params_store(void *data, u64 val)
+{
+	if (enable_sr_vp_debug) {
+		u32 *option = data;

insert blank line

arch/arm/mach-omap2/smartreflex.c static int omap_sr_autocomp_store(void *data, u64 val) · line 833

Quoted 3 lines
arch/arm/mach-omap2/smartreflex.c +3 -0
+		*option = val;
+	} else {
+		pr_notice("%s: DEBUG option not enabled!\n	\

you don't need a '\' to continue strings onto new lines. Just end the string, and start another on the next line, as you've done elsewhere in the patch.

Quoted 202 lines
arch/arm/mach-omap2/smartreflex.c +16 -0
+			echo 1 > pm_debug/enable_sr_vp_debug - to enable\n",
+			__func__);
+	}
+
+	return 0;
+}
+
 DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
 		omap_sr_autocomp_store, "%llu\n");
 
+DEFINE_SIMPLE_ATTRIBUTE(sr_params_fops, omap_sr_params_show,
+		omap_sr_params_store, "%llu\n");
+
 static int __init omap_smartreflex_probe(struct platform_device *pdev)
 {
 	struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
@@ -907,6 +937,12 @@ static int __init omap_smartreflex_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_file("errweight", S_IRUGO | S_IWUGO, dbg_dir,
+			&sr_info->err_weight, &sr_params_fops);
+	(void) debugfs_create_file("errmaxlimit", S_IRUGO | S_IWUGO, dbg_dir,
+			&sr_info->err_maxlimit, &sr_params_fops);
+	(void) debugfs_create_file("errminlimit", S_IRUGO | S_IWUGO, dbg_dir,
+			&sr_info->err_minlimit, &sr_params_fops);
 
 	return ret;
 
arch/arm/mach-omap2/voltage.c +138 -0
index 49013cb..70a645e 100644
@@ -22,15 +22,22 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
 
 #include <plat/common.h>
 #include <plat/voltage.h>
 
 #include "prm-regbits-34xx.h"
+#include "pm.h"
 
 #define VP_IDLE_TIMEOUT		200
 #define VP_TRANXDONE_TIMEOUT	300
+#define VOLTAGE_DIR_SIZE	16
 
+static struct dentry *voltage_dir;
+/* VP SR debug support */
+u32 enable_sr_vp_debug;
 /* PRM voltage module */
 static u32 volt_mod;
 
@@ -221,6 +228,82 @@ static inline void voltage_write_reg(u8 offset, u32 value)
 	prm_write_mod_reg(value, volt_mod, offset);
 }
 
+/* Voltage debugfs support */
+static int vp_debug_get(void *data, u64 *val)
+{
+	u16 *option = data;
+
+	if (!option) {
+		pr_warning("Wrong paramater passed\n");
+		return -EINVAL;
+	}
+
+	*val = *option;
+
+	return 0;
+}
+
+static int vp_debug_set(void *data, u64 val)
+{
+	if (enable_sr_vp_debug) {
+		u32 *option = data;
+
+		if (!option) {
+			pr_warning("Wrong paramater passed\n");
+			return -EINVAL;
+		}
+
+		*option = val;
+	} else {
+		pr_notice("DEBUG option not enabled!"
+			"echo 1 > pm_debug/enable_sr_vp_debug - to enable\n");
+	}
+
+	return 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 = voltage_read_reg(vdd->vp_offs.voltage);
+	pr_notice("curr_vsel = %x\n", vsel);
+
+	if (!volt_pmic_info.vsel_to_uv) {
+		pr_warning("PMIC function to convert vsel to voltage"
+			"in uV not registerd\n");
+		return -EINVAL;
+	}
+
+	*val = volt_pmic_info.vsel_to_uv(vsel);
+	return 0;
+}
+
+static int nom_volt_debug_get(void *data, u64 *val)
+{
+	struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
+
+	if (!vdd) {
+		pr_warning("Wrong paramater passed\n");
+		return -EINVAL;
+	}
+
+	*val = omap_voltage_get_nom_volt(&vdd->voltdm);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(vp_debug_fops, vp_debug_get, vp_debug_set, "%llu\n");
+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,
+								"%llu\n");
+
 static void vp_latch_vsel(struct omap_vdd_info *vdd)
 {
 	u32 vpconfig;
@@ -457,6 +540,61 @@ static void __init vdd_data_configure(struct omap_vdd_info *vdd)
 		omap3_vdd_data_configure(vdd);
 }
 
+static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
+{
+	struct dentry *vdd_debug;
+	char *name;
+
+	name = kzalloc(VOLTAGE_DIR_SIZE, GFP_KERNEL);
+	if (!name) {
+		pr_warning("%s: Unable to allocate memry for debugfs"
+			"directory name for vdd_%s",
+			__func__, vdd->voltdm.name);
+		return;
+	}
+	strcpy(name, "vdd_");
+	strcat(name, vdd->voltdm.name);
+
+	vdd_debug = debugfs_create_dir(name, voltage_dir);
+	if (IS_ERR(vdd_debug)) {
+		pr_warning("%s: Unable to create debugfs directory for"
+			"vdd_%s\n", __func__, vdd->voltdm.name);
+		return;
+	}
+
+	(void) debugfs_create_file("vp_errorgain", S_IRUGO | S_IWUGO,
+				vdd_debug,
+				&(vdd->vp_reg.vpconfig_errorgain),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_smpswaittimemin", S_IRUGO | S_IWUGO,
+				vdd_debug,
+				&(vdd->vp_reg.vstepmin_smpswaittimemin),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_stepmin", S_IRUGO | S_IWUGO, vdd_debug,
+				&(vdd->vp_reg.vstepmin_stepmin),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_smpswaittimemax", S_IRUGO | S_IWUGO,
+				vdd_debug,
+				&(vdd->vp_reg.vstepmax_smpswaittimemax),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_stepmax", S_IRUGO | S_IWUGO, vdd_debug,
+				&(vdd->vp_reg.vstepmax_stepmax),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_vddmax", S_IRUGO | S_IWUGO, vdd_debug,
+				&(vdd->vp_reg.vlimitto_vddmax),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_vddmin", S_IRUGO | S_IWUGO, vdd_debug,
+				&(vdd->vp_reg.vlimitto_vddmin),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_timeout", S_IRUGO | S_IWUGO, vdd_debug,
+				&(vdd->vp_reg.vlimitto_timeout),
+				&vp_debug_fops);
+	(void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd_debug,
+				(void *) vdd, &vp_volt_debug_fops);
+	(void) debugfs_create_file("curr_nominal_volt", S_IRUGO, vdd_debug,
+				(void *) vdd, &nom_volt_debug_fops);
+}
+
 static void __init init_voltagecontroller(void)
 {
 	if (cpu_is_omap34xx())

arch/arm/mach-omap2/voltage.c static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd, · line 669

Quoted 10 lines
arch/arm/mach-omap2/voltage.c +5 -2
@@ -524,8 +662,11 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
 	vc_cmdval |= (target_vsel << vc_cmd_on_shift);
 	voltage_write_reg(vdd->cmdval_reg, vc_cmdval);
 
-	/* Setting vp errorgain based on the voltage */
-	if (volt_data) {
+	/*
+	 * Setting vp errorgain based on the voltage. If the debug option is
+	 * enabled allow the override of errorgain from user side
+	 */
+	if (!enable_sr_vp_debug && volt_data) {

Doesn't this happen before the debugfs interface is ready?

arch/arm/mach-omap2/voltage.c static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd, · line 777

Quoted 13 lines
arch/arm/mach-omap2/voltage.c +4 -2
 		vp_errgain_val = voltage_read_reg(vdd->vp_offs.vpconfig);
 		vdd->vp_reg.vpconfig_errorgain = volt_data->vp_errgain;
 		vp_errgain_val &= ~vdd->vp_reg.vpconfig_errorgain_mask;
@@ -630,8 +771,11 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
 	vc_cmdval |= (target_vsel << vc_cmd_on_shift);
 	voltage_write_reg(vdd->cmdval_reg, vc_cmdval);
 
-	/* Getting  vp errorgain based on the voltage */
-	if (volt_data)
+	/*
+	 * Getting  vp errorgain based on the voltage. If the debug option is
+	 * enabled allow the override of errorgain from user side.
+	 */

As suggested in earlier comment, please use a specific flag that this has been overridden instead of the 'debug enabled' flag (which should disappear, IMO)

arch/arm/mach-omap2/voltage.c void omap_vp_enable(struct voltagedomain *voltdm) · line 956

Quoted 12 lines
arch/arm/mach-omap2/voltage.c +5 -0
+	if (!enable_sr_vp_debug && volt_data)
 		vdd->vp_reg.vpconfig_errorgain =
 					volt_data->vp_errgain;
 
@@ -806,6 +950,37 @@ void omap_vp_enable(struct voltagedomain *voltdm)
 	if (!voltscale_vpforceupdate)
 		vp_latch_vsel(vdd);
 
+	/*
+	 * If debug is enabled, it is likely that the following parameters
+	 * were set from user space so rewrite them.
+	 */

Again, use some sort of override flag, not just the debug enabled flag.

Quoted 31 lines
arch/arm/mach-omap2/voltage.c +27 -0
+	if (enable_sr_vp_debug) {
+		vpconfig = voltage_read_reg(vdd->vp_offs.vpconfig);
+		vpconfig |= (vdd->vp_reg.vpconfig_errorgain <<
+			vdd->vp_reg.vpconfig_errorgain_shift);
+		voltage_write_reg(vdd->vp_offs.vpconfig, vpconfig);
+
+		voltage_write_reg(vdd->vp_offs.vstepmin,
+			(vdd->vp_reg.vstepmin_smpswaittimemin <<
+			vdd->vp_reg.vstepmin_smpswaittimemin_shift) |
+			(vdd->vp_reg.vstepmin_stepmin <<
+			vdd->vp_reg.vstepmin_stepmin_shift));
+
+		voltage_write_reg(vdd->vp_offs.vstepmax,
+			(vdd->vp_reg.vstepmax_smpswaittimemax <<
+			vdd->vp_reg.vstepmax_smpswaittimemax_shift) |
+			(vdd->vp_reg.vstepmax_stepmax <<
+			vdd->vp_reg.vstepmax_stepmax_shift));
+
+		voltage_write_reg(vdd->vp_offs.vlimitto,
+			(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));
+	}
+
 	/* Enable VP */
 	vpconfig = voltage_read_reg(vdd->vp_offs.vpconfig);
 	voltage_write_reg(vdd->vp_offs.vpconfig,

arch/arm/mach-omap2/voltage.c static int __init omap_voltage_init(void) · line 1285

Quoted 4 lines
arch/arm/mach-omap2/voltage.c +1 -0
@@ -1107,6 +1282,7 @@ static int __init omap_voltage_init(void)
 		return 0;
 	}
 
+

stray whitespace change

Quoted 22 lines
arch/arm/mach-omap2/voltage.c +15 -0
 	init_voltagecontroller();
 	for (i = 0; i < nr_scalable_vdd; i++) {
 		vdd_data_configure(&vdd_info[i]);
@@ -1115,3 +1291,29 @@ static int __init omap_voltage_init(void)
 	return 0;
 }
 core_initcall(omap_voltage_init);
+
+static int __init omap_voltage_debugfs_init(void)
+{
+	int i;
+
+	/*
+	 * If pm debug main directory is not created,
+	 * do not create rest of the debugfs entries.
+	 */
+	if (!pm_dbg_main_dir)
+		return 0;
+
+	voltage_dir = debugfs_create_dir("voltage", pm_dbg_main_dir);
+	if (IS_ERR(voltage_dir)) {
+		pr_err("%s: Unable to create voltage debugfs main dir\n",

arch/arm/mach-omap2/voltage.c static int __init omap_voltage_init(void) · line 1318

Quoted 10 lines
arch/arm/mach-omap2/voltage.c +10 -0
+			__func__);
+		return 0;
+	}
+
+	for (i = 0; i < nr_scalable_vdd; i++)
+		vdd_debugfs_init(&vdd_info[i]);
+
+	return 0;
+}
+

Kevin

#40 lore raw

RE: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

Quoted 20 lines
Quoted 20 lines

-----Original Message-----
From: Kevin Hilman [mailto:[email protected]]
Sent: Friday, October 15, 2010 5:16 AM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

Quoted 6 lines · 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. By default only a read of these parameters are permitted. If you need to write into them then
echo 1 > /pm_debug/enable_sr_vp_debug

Quoted 2 lines
Quoted 2 lines

Why a read-only interface by default? As a debug interface it seems
redundant to have to enable it.

Read-only interface by default so that we can read these values from user space even if we do not want to manipulate it from user-side.

Quoted 85 lines
Quoted 85 lines
Quoted 6 lines

The voltage parameters can be viewed at

    /pm_debug/voltage/vdd_<x>/<parameter>

and the smartreflex parameters can be viewed at
/pm_debug/smartreflex/sr_<x>/<parameter>

Quoted 7 lines

where <x> is mpu or core for OMAP3.

---
 arch/arm/mach-omap2/pm-debug.c                |   15 ++
 arch/arm/mach-omap2/smartreflex.c             |   40 +++++-
 arch/arm/mach-omap2/voltage.c                 |  210

++++++++++++++++++++++++-

arch/arm/mach-omap2/pm-

Quoted 5 lines
 arch/arm/plat-omap/include/plat/smartreflex.h |    1 -
 arch/arm/plat-omap/include/plat/voltage.h     |    5 +
 5 files changed, 264 insertions(+), 7 deletions(-)
arch/arm/mach-omap2/pm- renamed from arch/arm/mach-omap2/pm-debug.c +0 -0

debug.c

arch/arm/mach-

Quoted 40 lines

index 390f1c6..879efb2 100644

arch/arm/mach-omap2/pm-debug.c +15 -0
@@ -32,6 +32,7 @@
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
 #include <plat/dmtimer.h>
+#include <plat/voltage.h>
 
 #include "prm.h"
 #include "cm.h"
@@ -586,6 +587,18 @@ static int option_set(void *data, u64 val)
                    omap3_pm_off_mode_enable(val);
    }
 
+   if (option == &enable_sr_vp_debug && val)
+           pr_notice("Beware that enabling this option will allow user "
+                   "to override the system defined vp and sr parameters "
+                   "All the updated parameters will take effect next "
+                   "time smartreflex is enabled. Also this option "
+                   "disables the automatic vp errorgain and sr errormin "
+                   "limit changes as per the voltage. Users will have "
+                   "to explicitly write values into the debug fs "
+                   "entries corresponding to these if they want to see "
+                   "them changing according to the VDD voltage\n");
+
+
    return 0;
 }
 
@@ -642,6 +655,8 @@ static int __init pm_dbg_init(void)
    (void) debugfs_create_file("wakeup_timer_milliseconds",
                    S_IRUGO | S_IWUGO, d, &wakeup_timer_milliseconds,
                    &pm_dbg_option_fops);
+   (void) debugfs_create_file("enable_sr_vp_debug",  S_IRUGO | S_IWUGO, d,
+                           &enable_sr_vp_debug, &pm_dbg_option_fops);
 
    pm_dbg_main_dir = d;
    pm_dbg_init_done = 1;
arch/arm/mach- renamed from arch/arm/mach-omap2/smartreflex.c +0 -0

omap2/smartreflex.c

arch/arm/mach-omap2/smartreflex.c int sr_enable(struct voltagedomain *voltdm, unsigned

Quoted 4 lines

index 7fc3138..b5a7878 100644

arch/arm/mach-omap2/smartreflex.c +0 -0
@@ -558,8 +558,13 @@ int sr_enable(struct voltagedomain *voltdm, unsigned

long volt)

Quoted 19 lines
arch/arm/mach-omap2/smartreflex.c +7 -2
            return -ENODATA;
    }
 
-   /* errminlimit is opp dependent and hence linked to voltage */
-   sr->err_minlimit = volt_data->sr_errminlimit;
+   /*
+    * errminlimit is opp dependent and hence linked to voltage
+    * if the debug option is enabled, the user might have over ridden
+    * this parameter so do not get it from voltage table
+    */
+   if (!enable_sr_vp_debug)
+           sr->err_minlimit = volt_data->sr_errminlimit;
 
    /* Enable the clocks */
    if (!sr->sr_enable) {
@@ -811,9 +816,34 @@ static int omap_sr_autocomp_store(void *data, u64 val)
    return 0;
 }
 
Quoted 14 lines
Quoted 6 lines
Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c +6 -0
+static int omap_sr_params_show(void *data, u64 *val)
+{
+   u32 *param = data;
+
+   *val = *param;
+   return 0;
Quoted 8 lines

arch/arm/mach-omap2/smartreflex.c static int omap_sr_autocomp_store(void *data, u64 val) · line 830

Quoted 6 lines
arch/arm/mach-omap2/smartreflex.c +6 -0
+}
+
+static int omap_sr_params_store(void *data, u64 val)
+{
+   if (enable_sr_vp_debug) {
+           u32 *option = data;

insert blank line

Will do

Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/smartreflex.c static int omap_sr_autocomp_store(void *data, u64 val) · line 833

Quoted 4 lines
arch/arm/mach-omap2/smartreflex.c +3 -0
+           *option = val;
+   } else {
+           pr_notice("%s: DEBUG option not enabled!\n      \

you don't need a '\' to continue strings onto new lines. Just end the string, and start another on the next line, as you've done elsewhere in the patch.

Will correct

Quoted 220 lines
Quoted 220 lines

arch/arm/mach-omap2/smartreflex.c static int __init omap_smartreflex_probe(struct

Quoted 18 lines
arch/arm/mach-omap2/smartreflex.c +10 -0
+                   echo 1 > pm_debug/enable_sr_vp_debug - to enable\n",
+                   __func__);
+   }
+
+   return 0;
+}
+
 DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
            omap_sr_autocomp_store, "%llu\n");
 
+DEFINE_SIMPLE_ATTRIBUTE(sr_params_fops, omap_sr_params_show,
+           omap_sr_params_store, "%llu\n");
+
 static int __init omap_smartreflex_probe(struct platform_device *pdev)
 {
    struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
@@ -907,6 +937,12 @@ static int __init omap_smartreflex_probe(struct

platform_device *pdev)

arch/arm/mach-omap2/voltage.c static inline void voltage_write_reg(u8 offset, u32

Quoted 40 lines
arch/arm/mach-omap2/smartreflex.c +6 -0
    (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUGO, dbg_dir,
                            (void *)sr_info, &pm_sr_fops);
+   (void) debugfs_create_file("errweight", S_IRUGO | S_IWUGO, dbg_dir,
+                   &sr_info->err_weight, &sr_params_fops);
+   (void) debugfs_create_file("errmaxlimit", S_IRUGO | S_IWUGO, dbg_dir,
+                   &sr_info->err_maxlimit, &sr_params_fops);
+   (void) debugfs_create_file("errminlimit", S_IRUGO | S_IWUGO, dbg_dir,
+                   &sr_info->err_minlimit, &sr_params_fops);
 
    return ret;
 
arch/arm/mach-omap2/voltage.c +7 -0
index 49013cb..70a645e 100644
@@ -22,15 +22,22 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
 
 #include <plat/common.h>
 #include <plat/voltage.h>
 
 #include "prm-regbits-34xx.h"
+#include "pm.h"
 
 #define VP_IDLE_TIMEOUT            200
 #define VP_TRANXDONE_TIMEOUT       300
+#define VOLTAGE_DIR_SIZE   16
 
+static struct dentry *voltage_dir;
+/* VP SR debug support */
+u32 enable_sr_vp_debug;
 /* PRM voltage module */
 static u32 volt_mod;
 
@@ -221,6 +228,82 @@ static inline void voltage_write_reg(u8 offset, u32

value)

Quoted 65 lines
arch/arm/mach-omap2/voltage.c +62 -0
    prm_write_mod_reg(value, volt_mod, offset);
 }
 
+/* Voltage debugfs support */
+static int vp_debug_get(void *data, u64 *val)
+{
+   u16 *option = data;
+
+   if (!option) {
+           pr_warning("Wrong paramater passed\n");
+           return -EINVAL;
+   }
+
+   *val = *option;
+
+   return 0;
+}
+
+static int vp_debug_set(void *data, u64 val)
+{
+   if (enable_sr_vp_debug) {
+           u32 *option = data;
+
+           if (!option) {
+                   pr_warning("Wrong paramater passed\n");
+                   return -EINVAL;
+           }
+
+           *option = val;
+   } else {
+           pr_notice("DEBUG option not enabled!"
+                   "echo 1 > pm_debug/enable_sr_vp_debug - to enable\n");
+   }
+
+   return 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 = voltage_read_reg(vdd->vp_offs.voltage);
+   pr_notice("curr_vsel = %x\n", vsel);
+
+   if (!volt_pmic_info.vsel_to_uv) {
+           pr_warning("PMIC function to convert vsel to voltage"
+                   "in uV not registerd\n");
+           return -EINVAL;
+   }
+
+   *val = volt_pmic_info.vsel_to_uv(vsel);
+   return 0;
+}
+
+static int nom_volt_debug_get(void *data, u64 *val)
+{
+   struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
+
+   if (!vdd) {

arch/arm/mach-omap2/voltage.c static inline void voltage_write_reg(u8 offset, u32 value)

Quoted 10 lines
arch/arm/mach-omap2/voltage.c +10 -0
+           pr_warning("Wrong paramater passed\n");
+           return -EINVAL;
+   }
+
+   *val = omap_voltage_get_nom_volt(&vdd->voltdm);
+
+   return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(vp_debug_fops, vp_debug_get, vp_debug_set,

"%llu\n");

arch/arm/mach-omap2/voltage.c static inline void voltage_write_reg(u8 offset, u32 · line 303

Quoted 1 line
arch/arm/mach-omap2/voltage.c +1 -0
+DEFINE_SIMPLE_ATTRIBUTE(vp_volt_debug_fops, vp_volt_debug_get, NULL,

"%llu\n");

arch/arm/mach-omap2/voltage.c static void __init vdd_data_configure(struct

Quoted 7 lines
arch/arm/mach-omap2/voltage.c +3 -0
+DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL,
+                                                           "%llu\n");
+
 static void vp_latch_vsel(struct omap_vdd_info *vdd)
 {
    u32 vpconfig;
@@ -457,6 +540,61 @@ static void __init vdd_data_configure(struct

omap_vdd_info *vdd)

arch/arm/mach-omap2/voltage.c static int vc_bypass_scale_voltage(struct

Quoted 62 lines
arch/arm/mach-omap2/voltage.c +55 -0
            omap3_vdd_data_configure(vdd);
 }
 
+static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
+{
+   struct dentry *vdd_debug;
+   char *name;
+
+   name = kzalloc(VOLTAGE_DIR_SIZE, GFP_KERNEL);
+   if (!name) {
+           pr_warning("%s: Unable to allocate memry for debugfs"
+                   "directory name for vdd_%s",
+                   __func__, vdd->voltdm.name);
+           return;
+   }
+   strcpy(name, "vdd_");
+   strcat(name, vdd->voltdm.name);
+
+   vdd_debug = debugfs_create_dir(name, voltage_dir);
+   if (IS_ERR(vdd_debug)) {
+           pr_warning("%s: Unable to create debugfs directory for"
+                   "vdd_%s\n", __func__, vdd->voltdm.name);
+           return;
+   }
+
+   (void) debugfs_create_file("vp_errorgain", S_IRUGO | S_IWUGO,
+                           vdd_debug,
+                           &(vdd->vp_reg.vpconfig_errorgain),
+                           &vp_debug_fops);
+   (void) debugfs_create_file("vp_smpswaittimemin", S_IRUGO | S_IWUGO,
+                           vdd_debug,
+                           &(vdd->vp_reg.vstepmin_smpswaittimemin),
+                           &vp_debug_fops);
+   (void) debugfs_create_file("vp_stepmin", S_IRUGO | S_IWUGO, vdd_debug,
+                           &(vdd->vp_reg.vstepmin_stepmin),
+                           &vp_debug_fops);
+   (void) debugfs_create_file("vp_smpswaittimemax", S_IRUGO | S_IWUGO,
+                           vdd_debug,
+                           &(vdd->vp_reg.vstepmax_smpswaittimemax),
+                           &vp_debug_fops);
+   (void) debugfs_create_file("vp_stepmax", S_IRUGO | S_IWUGO, vdd_debug,
+                           &(vdd->vp_reg.vstepmax_stepmax),
+                           &vp_debug_fops);
+   (void) debugfs_create_file("vp_vddmax", S_IRUGO | S_IWUGO, vdd_debug,
+                           &(vdd->vp_reg.vlimitto_vddmax),
+                           &vp_debug_fops);
+   (void) debugfs_create_file("vp_vddmin", S_IRUGO | S_IWUGO, vdd_debug,
+                           &(vdd->vp_reg.vlimitto_vddmin),
+                           &vp_debug_fops);
+   (void) debugfs_create_file("vp_timeout", S_IRUGO | S_IWUGO, vdd_debug,
+                           &(vdd->vp_reg.vlimitto_timeout),
+                           &vp_debug_fops);
+   (void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd_debug,
+                           (void *) vdd, &vp_volt_debug_fops);
+   (void) debugfs_create_file("curr_nominal_volt", S_IRUGO, vdd_debug,
+                           (void *) vdd, &nom_volt_debug_fops);
+}
+
 static void __init init_voltagecontroller(void)
 {
    if (cpu_is_omap34xx())
@@ -524,8 +662,11 @@ static int vc_bypass_scale_voltage(struct

omap_vdd_info *vdd,

Quoted 10 lines
arch/arm/mach-omap2/voltage.c +5 -2
    vc_cmdval |= (target_vsel << vc_cmd_on_shift);
    voltage_write_reg(vdd->cmdval_reg, vc_cmdval);
 
-   /* Setting vp errorgain based on the voltage */
-   if (volt_data) {
+   /*
+    * Setting vp errorgain based on the voltage. If the debug option is
+    * enabled allow the override of errorgain from user side
+    */
+   if (!enable_sr_vp_debug && volt_data) {
Quoted 1 line
Quoted 1 line

Doesn't this happen before the debugfs interface is ready?

Nope it will not. This is the voltage scaling API

Quoted 16 lines
Quoted 16 lines

arch/arm/mach-omap2/voltage.c static int vp_forceupdate_scale_voltage(struct

Quoted 5 lines
arch/arm/mach-omap2/voltage.c +0 -0
            vp_errgain_val = voltage_read_reg(vdd->vp_offs.vpconfig);
            vdd->vp_reg.vpconfig_errorgain = volt_data->vp_errgain;
            vp_errgain_val &= ~vdd->vp_reg.vpconfig_errorgain_mask;
@@ -630,8 +771,11 @@ static int vp_forceupdate_scale_voltage(struct

omap_vdd_info *vdd,

Quoted 9 lines
arch/arm/mach-omap2/voltage.c +4 -2
    vc_cmdval |= (target_vsel << vc_cmd_on_shift);
    voltage_write_reg(vdd->cmdval_reg, vc_cmdval);
 
-   /* Getting  vp errorgain based on the voltage */
-   if (volt_data)
+   /*
+    * Getting  vp errorgain based on the voltage. If the debug option is
+    * enabled allow the override of errorgain from user side.
+    */
Quoted 3 lines
Quoted 3 lines

As suggested in earlier comment, please use a specific flag that this has been overridden instead of the 'debug enabled' flag (which should disappear, IMO)

What do you mean by a separate flag. You want a flag to be maintained for just this purpose ?

Quoted 50 lines
Quoted 50 lines

arch/arm/mach-omap2/voltage.c void omap_vp_enable(struct voltagedomain *voltdm) · line 956

Quoted 13 lines
arch/arm/mach-omap2/voltage.c +5 -0
+   if (!enable_sr_vp_debug && volt_data)
            vdd->vp_reg.vpconfig_errorgain =
                                    volt_data->vp_errgain;
 
@@ -806,6 +950,37 @@ void omap_vp_enable(struct voltagedomain *voltdm)
    if (!voltscale_vpforceupdate)
            vp_latch_vsel(vdd);
 
+   /*
+    * If debug is enabled, it is likely that the following parameters
+    * were set from user space so rewrite them.
+    */

Again, use some sort of override flag, not just the debug enabled flag.

Quoted 34 lines
arch/arm/mach-omap2/voltage.c +27 -0
+   if (enable_sr_vp_debug) {
+           vpconfig = voltage_read_reg(vdd->vp_offs.vpconfig);
+           vpconfig |= (vdd->vp_reg.vpconfig_errorgain <<
+                   vdd->vp_reg.vpconfig_errorgain_shift);
+           voltage_write_reg(vdd->vp_offs.vpconfig, vpconfig);
+
+           voltage_write_reg(vdd->vp_offs.vstepmin,
+                   (vdd->vp_reg.vstepmin_smpswaittimemin <<
+                   vdd->vp_reg.vstepmin_smpswaittimemin_shift) |
+                   (vdd->vp_reg.vstepmin_stepmin <<
+                   vdd->vp_reg.vstepmin_stepmin_shift));
+
+           voltage_write_reg(vdd->vp_offs.vstepmax,
+                   (vdd->vp_reg.vstepmax_smpswaittimemax <<
+                   vdd->vp_reg.vstepmax_smpswaittimemax_shift) |
+                   (vdd->vp_reg.vstepmax_stepmax <<
+                   vdd->vp_reg.vstepmax_stepmax_shift));
+
+           voltage_write_reg(vdd->vp_offs.vlimitto,
+                   (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));
+   }
+
    /* Enable VP */
    vpconfig = voltage_read_reg(vdd->vp_offs.vpconfig);
    voltage_write_reg(vdd->vp_offs.vpconfig,
@@ -1107,6 +1282,7 @@ static int __init omap_voltage_init(void)
            return 0;
    }
 
Quoted 3 lines
Quoted 3 lines

arch/arm/mach-omap2/voltage.c static int __init omap_voltage_init(void) · line 1285

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

stray whitespace change

Will correct

Quoted 35 lines
Quoted 35 lines
Quoted 23 lines
arch/arm/mach-omap2/voltage.c +15 -0
    init_voltagecontroller();
    for (i = 0; i < nr_scalable_vdd; i++) {
            vdd_data_configure(&vdd_info[i]);
@@ -1115,3 +1291,29 @@ static int __init omap_voltage_init(void)
    return 0;
 }
 core_initcall(omap_voltage_init);
+
+static int __init omap_voltage_debugfs_init(void)
+{
+   int i;
+
+   /*
+    * If pm debug main directory is not created,
+    * do not create rest of the debugfs entries.
+    */
+   if (!pm_dbg_main_dir)
+           return 0;
+
+   voltage_dir = debugfs_create_dir("voltage", pm_dbg_main_dir);
+   if (IS_ERR(voltage_dir)) {
+           pr_err("%s: Unable to create voltage debugfs main dir\n",

arch/arm/mach-omap2/voltage.c static int __init omap_voltage_init(void) · line 1318

Quoted 10 lines
arch/arm/mach-omap2/voltage.c +10 -0
+                   __func__);
+           return 0;
+   }
+
+   for (i = 0; i < nr_scalable_vdd; i++)
+           vdd_debugfs_init(&vdd_info[i]);
+
+   return 0;
+}
+

Kevin

#41 lore raw

Re: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

Quoted 9 lines · Thara
Quoted 9 lines
Quoted 9 lines
Quoted 6 lines · 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. By default only a read of these parameters are permitted. If you need to write into them then
echo 1 > /pm_debug/enable_sr_vp_debug

Quoted 7 lines
Quoted 3 lines
Quoted 3 lines

Why a read-only interface by default? As a debug interface it seems
redundant to have to enable it.

Read-only interface by default so that we can read these values from user space even if we do not want to manipulate it from user-side.

If we do not want to manipulate it from the user-side, then simply don't
write to it. Remember, this is a debug interface, not a primary
interface.

I think the enable_sr_vp_debug flag should disappear, and it should be a read/write interface.

If the values are changed via debugfs, then set some per-SR instance flag that can be checked.

Basically, the current code is confusing because you're using the the flag called 'enable' to determine whether the user *might have* written the values.

[...]

Quoted 11 lines
Quoted 8 lines
Quoted 8 lines

arch/arm/mach-omap2/voltage.c static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd, · line 777

Quoted 4 lines
arch/arm/mach-omap2/voltage.c +4 -0
+   /*
+    * Getting  vp errorgain based on the voltage. If the debug option is
+    * enabled allow the override of errorgain from user side.
+    */

As suggested in earlier comment, please use a specific flag that this has been overridden instead of the 'debug enabled' flag (which should disappear, IMO)

What do you mean by a separate flag. You want a flag to be maintained for just this purpose ?

Yes. I want a flag to be maintained *specifically* for this purpose, instead of using a much more general flag that only means a user *might* have overridden the values, use one that specifically means a user *has* overridden the values.

Kevin

#42 lore raw

RE: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

Quoted 56 lines
Quoted 56 lines

-----Original Message-----
From: Kevin Hilman [mailto:[email protected]]
Sent: Friday, October 22, 2010 10:22 PM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

Quoted 9 lines · Thara
Quoted 9 lines
Quoted 9 lines
Quoted 6 lines · 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. By default only a read of these parameters are permitted. If you need to write into them then
echo 1 > /pm_debug/enable_sr_vp_debug

Quoted 7 lines
Quoted 3 lines
Quoted 3 lines

Why a read-only interface by default? As a debug interface it seems
redundant to have to enable it.

Read-only interface by default so that we can read these values from user space even if we do not want to manipulate it from user-side.

If we do not want to manipulate it from the user-side, then simply don't
write to it. Remember, this is a debug interface, not a primary
interface.

I think the enable_sr_vp_debug flag should disappear, and it should be a read/write interface.

If the values are changed via debugfs, then set some per-SR instance flag that can be checked.

Basically, the current code is confusing because you're using the the flag called 'enable' to determine whether the user *might have* written the values.

[...]

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+   /*
+    * Getting  vp errorgain based on the voltage. If the debug option

is

Quoted 7 lines
Quoted 6 lines
Quoted 6 lines

arch/arm/mach-omap2/voltage.c static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd, · line 777

Quoted 2 lines
arch/arm/mach-omap2/voltage.c +2 -0
+    * enabled allow the override of errorgain from user side.
+    */

As suggested in earlier comment, please use a specific flag that this has been overridden instead of the 'debug enabled' flag (which should disappear, IMO)

Quoted 7 lines
Quoted 7 lines
Quoted 2 lines

What do you mean by a separate flag. You want a flag to be maintained for just this purpose ?

Yes. I want a flag to be maintained *specifically* for this purpose, instead of using a much more general flag that only means a user *might* have overridden the values, use one that specifically means a user *has* overridden the values.

Hello Kevin,

I tried this. Couple of questions/concerns I have.
1. If you take a look at the definition of these debugfs parameters, the omap_vdd_info struct is not passed as an argument. The actual variables are the parameters. I am not sure how to extract omap_vdd_info from this. Maybe container_of will help, but then it will be clumsy. Same concern for smartreflex err_minlimit variable. There is no way to get the sr instance except use container of which I am not sure will work or not 2.Also in voltage layer we export out eight parameters tat can be over-ridden from the user side. I do not think we should be maintaining one flag per variable. The design will be too very clumsy.

Regards
Thara

Quoted 2 lines
Quoted 2 lines

Kevin

#43 lore raw

Re: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

Quoted 62 lines · Thara
Quoted 54 lines
Quoted 54 lines

-----Original Message-----
From: Kevin Hilman [mailto:[email protected]]
Sent: Friday, October 22, 2010 10:22 PM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

Quoted 9 lines · Thara
Quoted 9 lines
Quoted 9 lines
Quoted 6 lines · 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. By default only a read of these parameters are permitted. If you need to write into them then
echo 1 > /pm_debug/enable_sr_vp_debug

Quoted 7 lines
Quoted 3 lines
Quoted 3 lines

Why a read-only interface by default? As a debug interface it seems
redundant to have to enable it.

Read-only interface by default so that we can read these values from user space even if we do not want to manipulate it from user-side.

If we do not want to manipulate it from the user-side, then simply don't
write to it. Remember, this is a debug interface, not a primary
interface.

I think the enable_sr_vp_debug flag should disappear, and it should be a read/write interface.

If the values are changed via debugfs, then set some per-SR instance flag that can be checked.

Basically, the current code is confusing because you're using the the flag called 'enable' to determine whether the user *might have* written the values.

[...]

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+   /*
+    * Getting  vp errorgain based on the voltage. If the debug option

is

Quoted 7 lines
Quoted 6 lines
Quoted 6 lines

arch/arm/mach-omap2/voltage.c static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd, · line 777

Quoted 2 lines
arch/arm/mach-omap2/voltage.c +2 -0
+    * enabled allow the override of errorgain from user side.
+    */

As suggested in earlier comment, please use a specific flag that this has been overridden instead of the 'debug enabled' flag (which should disappear, IMO)

Quoted 7 lines
Quoted 7 lines
Quoted 2 lines

What do you mean by a separate flag. You want a flag to be maintained for just this purpose ?

Yes. I want a flag to be maintained *specifically* for this purpose, instead of using a much more general flag that only means a user *might* have overridden the values, use one that specifically means a user *has* overridden the values.

Quoted 5 lines

Hello Kevin,

I tried this. Couple of questions/concerns I have.
1. If you take a look at the definition of these debugfs parameters, the omap_vdd_info struct is not passed as an argument. The actual variables are the parameters. I am not sure how to extract omap_vdd_info from this. Maybe container_of will help, but then it will be clumsy. Same concern for smartreflex err_minlimit variable. There is no way to get the sr instance except use container of which I am not sure will work or not 2.Also in voltage layer we export out eight parameters tat can be over-ridden from the user side. I do not think we should be maintaining one flag per variable. The design will be too very clumsy.

I didn't mean to suggest one flag per varialble. Just one flag to indicate that the user *has* overridden the defaults.

Kevin

#44 lore raw

Re: [PATCH v3 08/11] OMAP3: PM: Adding debug support to Voltage and Smartreflex drivers

In reply to Thara Gopinath

Hi Thara,

Quoted 11 lines · Thara

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. By default only a read of these parameters are permitted. If you need to write into them then
echo 1> /pm_debug/enable_sr_vp_debug

The voltage parameters can be viewed at

	/pm_debug/voltage/vdd_<x>/<parameter>

and the smartreflex parameters can be viewed at
/pm_debug/smartreflex/sr_<x>/<parameter>

Can we start getting rid of this pm_debug miscellaneous directory?
Like powerdomain and clockdomain debug stuff, I think that voltage domain layer deserve its own entry in the debugfs top level directory.

I do not see the need to add a extra level a directory for that.
Moreover smartreflex should be under voltage entry and not in the same level as voltage.

/sys/kernel/debug/voltage/vdd_<x>/smartreflex/<parameter>

Regards,
Benoit

Quoted 424 lines

where<x> is mpu or core for OMAP3.

---
  arch/arm/mach-omap2/pm-debug.c                |   15 ++
  arch/arm/mach-omap2/smartreflex.c             |   40 +++++-
  arch/arm/mach-omap2/voltage.c                 |  210 ++++++++++++++++++++++++-
  arch/arm/plat-omap/include/plat/smartreflex.h |    1 -
  arch/arm/plat-omap/include/plat/voltage.h     |    5 +
  5 files changed, 264 insertions(+), 7 deletions(-)
arch/arm/mach-omap2/pm-debug.c +15 -0
index 390f1c6..879efb2 100644
@@ -32,6 +32,7 @@
  #include<plat/powerdomain.h>
  #include<plat/clockdomain.h>
  #include<plat/dmtimer.h>
+#include<plat/voltage.h>
 
  #include "prm.h"
  #include "cm.h"
@@ -586,6 +587,18 @@ static int option_set(void *data, u64 val)
  			omap3_pm_off_mode_enable(val);
  	}
 
+	if (option ==&enable_sr_vp_debug&&  val)
+		pr_notice("Beware that enabling this option will allow user "
+			"to override the system defined vp and sr parameters "
+			"All the updated parameters will take effect next "
+			"time smartreflex is enabled. Also this option "
+			"disables the automatic vp errorgain and sr errormin "
+			"limit changes as per the voltage. Users will have "
+			"to explicitly write values into the debug fs "
+			"entries corresponding to these if they want to see "
+			"them changing according to the VDD voltage\n");
+
+
  	return 0;
  }
 
@@ -642,6 +655,8 @@ static int __init pm_dbg_init(void)
  	(void) debugfs_create_file("wakeup_timer_milliseconds",
  			S_IRUGO | S_IWUGO, d,&wakeup_timer_milliseconds,
  			&pm_dbg_option_fops);
+	(void) debugfs_create_file("enable_sr_vp_debug",  S_IRUGO | S_IWUGO, d,
+				&enable_sr_vp_debug,&pm_dbg_option_fops);
 
  	pm_dbg_main_dir = d;
  	pm_dbg_init_done = 1;
arch/arm/mach-omap2/smartreflex.c +38 -2
index 7fc3138..b5a7878 100644
@@ -558,8 +558,13 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
  		return -ENODATA;
  	}
 
-	/* errminlimit is opp dependent and hence linked to voltage */
-	sr->err_minlimit = volt_data->sr_errminlimit;
+	/*
+	 * errminlimit is opp dependent and hence linked to voltage
+	 * if the debug option is enabled, the user might have over ridden
+	 * this parameter so do not get it from voltage table
+	 */
+	if (!enable_sr_vp_debug)
+		sr->err_minlimit = volt_data->sr_errminlimit;
 
  	/* Enable the clocks */
  	if (!sr->sr_enable) {
@@ -811,9 +816,34 @@ static int omap_sr_autocomp_store(void *data, u64 val)
  	return 0;
  }
 
+static int omap_sr_params_show(void *data, u64 *val)
+{
+	u32 *param = data;
+
+	*val = *param;
+	return 0;
+}
+
+static int omap_sr_params_store(void *data, u64 val)
+{
+	if (enable_sr_vp_debug) {
+		u32 *option = data;
+		*option = val;
+	} else {
+		pr_notice("%s: DEBUG option not enabled!\n	\
+			echo 1>  pm_debug/enable_sr_vp_debug - to enable\n",
+			__func__);
+	}
+
+	return 0;
+}
+
  DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
  		omap_sr_autocomp_store, "%llu\n");
 
+DEFINE_SIMPLE_ATTRIBUTE(sr_params_fops, omap_sr_params_show,
+		omap_sr_params_store, "%llu\n");
+
  static int __init omap_smartreflex_probe(struct platform_device *pdev)
  {
  	struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
@@ -907,6 +937,12 @@ static int __init omap_smartreflex_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_file("errweight", S_IRUGO | S_IWUGO, dbg_dir,
+			&sr_info->err_weight,&sr_params_fops);
+	(void) debugfs_create_file("errmaxlimit", S_IRUGO | S_IWUGO, dbg_dir,
+			&sr_info->err_maxlimit,&sr_params_fops);
+	(void) debugfs_create_file("errminlimit", S_IRUGO | S_IWUGO, dbg_dir,
+			&sr_info->err_minlimit,&sr_params_fops);
 
  	return ret;
 
arch/arm/mach-omap2/voltage.c +206 -4
index 49013cb..70a645e 100644
@@ -22,15 +22,22 @@
  #include<linux/io.h>
  #include<linux/clk.h>
  #include<linux/err.h>
+#include<linux/debugfs.h>
+#include<linux/slab.h>
 
  #include<plat/common.h>
  #include<plat/voltage.h>
 
  #include "prm-regbits-34xx.h"
+#include "pm.h"
 
  #define VP_IDLE_TIMEOUT		200
  #define VP_TRANXDONE_TIMEOUT	300
+#define VOLTAGE_DIR_SIZE	16
 
+static struct dentry *voltage_dir;
+/* VP SR debug support */
+u32 enable_sr_vp_debug;
  /* PRM voltage module */
  static u32 volt_mod;
 
@@ -221,6 +228,82 @@ static inline void voltage_write_reg(u8 offset, u32 value)
  	prm_write_mod_reg(value, volt_mod, offset);
  }
 
+/* Voltage debugfs support */
+static int vp_debug_get(void *data, u64 *val)
+{
+	u16 *option = data;
+
+	if (!option) {
+		pr_warning("Wrong paramater passed\n");
+		return -EINVAL;
+	}
+
+	*val = *option;
+
+	return 0;
+}
+
+static int vp_debug_set(void *data, u64 val)
+{
+	if (enable_sr_vp_debug) {
+		u32 *option = data;
+
+		if (!option) {
+			pr_warning("Wrong paramater passed\n");
+			return -EINVAL;
+		}
+
+		*option = val;
+	} else {
+		pr_notice("DEBUG option not enabled!"
+			"echo 1>  pm_debug/enable_sr_vp_debug - to enable\n");
+	}
+
+	return 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 = voltage_read_reg(vdd->vp_offs.voltage);
+	pr_notice("curr_vsel = %x\n", vsel);
+
+	if (!volt_pmic_info.vsel_to_uv) {
+		pr_warning("PMIC function to convert vsel to voltage"
+			"in uV not registerd\n");
+		return -EINVAL;
+	}
+
+	*val = volt_pmic_info.vsel_to_uv(vsel);
+	return 0;
+}
+
+static int nom_volt_debug_get(void *data, u64 *val)
+{
+	struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
+
+	if (!vdd) {
+		pr_warning("Wrong paramater passed\n");
+		return -EINVAL;
+	}
+
+	*val = omap_voltage_get_nom_volt(&vdd->voltdm);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(vp_debug_fops, vp_debug_get, vp_debug_set, "%llu\n");
+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,
+								"%llu\n");
+
  static void vp_latch_vsel(struct omap_vdd_info *vdd)
  {
  	u32 vpconfig;
@@ -457,6 +540,61 @@ static void __init vdd_data_configure(struct omap_vdd_info *vdd)
  		omap3_vdd_data_configure(vdd);
  }
 
+static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
+{
+	struct dentry *vdd_debug;
+	char *name;
+
+	name = kzalloc(VOLTAGE_DIR_SIZE, GFP_KERNEL);
+	if (!name) {
+		pr_warning("%s: Unable to allocate memry for debugfs"
+			"directory name for vdd_%s",
+			__func__, vdd->voltdm.name);
+		return;
+	}
+	strcpy(name, "vdd_");
+	strcat(name, vdd->voltdm.name);
+
+	vdd_debug = debugfs_create_dir(name, voltage_dir);
+	if (IS_ERR(vdd_debug)) {
+		pr_warning("%s: Unable to create debugfs directory for"
+			"vdd_%s\n", __func__, vdd->voltdm.name);
+		return;
+	}
+
+	(void) debugfs_create_file("vp_errorgain", S_IRUGO | S_IWUGO,
+				vdd_debug,
+				&(vdd->vp_reg.vpconfig_errorgain),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_smpswaittimemin", S_IRUGO | S_IWUGO,
+				vdd_debug,
+				&(vdd->vp_reg.vstepmin_smpswaittimemin),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_stepmin", S_IRUGO | S_IWUGO, vdd_debug,
+				&(vdd->vp_reg.vstepmin_stepmin),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_smpswaittimemax", S_IRUGO | S_IWUGO,
+				vdd_debug,
+				&(vdd->vp_reg.vstepmax_smpswaittimemax),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_stepmax", S_IRUGO | S_IWUGO, vdd_debug,
+				&(vdd->vp_reg.vstepmax_stepmax),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_vddmax", S_IRUGO | S_IWUGO, vdd_debug,
+				&(vdd->vp_reg.vlimitto_vddmax),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_vddmin", S_IRUGO | S_IWUGO, vdd_debug,
+				&(vdd->vp_reg.vlimitto_vddmin),
+				&vp_debug_fops);
+	(void) debugfs_create_file("vp_timeout", S_IRUGO | S_IWUGO, vdd_debug,
+				&(vdd->vp_reg.vlimitto_timeout),
+				&vp_debug_fops);
+	(void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd_debug,
+				(void *) vdd,&vp_volt_debug_fops);
+	(void) debugfs_create_file("curr_nominal_volt", S_IRUGO, vdd_debug,
+				(void *) vdd,&nom_volt_debug_fops);
+}
+
  static void __init init_voltagecontroller(void)
  {
  	if (cpu_is_omap34xx())
@@ -524,8 +662,11 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
  	vc_cmdval |= (target_vsel<<  vc_cmd_on_shift);
  	voltage_write_reg(vdd->cmdval_reg, vc_cmdval);
 
-	/* Setting vp errorgain based on the voltage */
-	if (volt_data) {
+	/*
+	 * Setting vp errorgain based on the voltage. If the debug option is
+	 * enabled allow the override of errorgain from user side
+	 */
+	if (!enable_sr_vp_debug&&  volt_data) {
  		vp_errgain_val = voltage_read_reg(vdd->vp_offs.vpconfig);
  		vdd->vp_reg.vpconfig_errorgain = volt_data->vp_errgain;
  		vp_errgain_val&= ~vdd->vp_reg.vpconfig_errorgain_mask;
@@ -630,8 +771,11 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
  	vc_cmdval |= (target_vsel<<  vc_cmd_on_shift);
  	voltage_write_reg(vdd->cmdval_reg, vc_cmdval);
 
-	/* Getting  vp errorgain based on the voltage */
-	if (volt_data)
+	/*
+	 * Getting  vp errorgain based on the voltage. If the debug option is
+	 * enabled allow the override of errorgain from user side.
+	 */
+	if (!enable_sr_vp_debug&&  volt_data)
  		vdd->vp_reg.vpconfig_errorgain =
  					volt_data->vp_errgain;
 
@@ -806,6 +950,37 @@ void omap_vp_enable(struct voltagedomain *voltdm)
  	if (!voltscale_vpforceupdate)
  		vp_latch_vsel(vdd);
 
+	/*
+	 * If debug is enabled, it is likely that the following parameters
+	 * were set from user space so rewrite them.
+	 */
+	if (enable_sr_vp_debug) {
+		vpconfig = voltage_read_reg(vdd->vp_offs.vpconfig);
+		vpconfig |= (vdd->vp_reg.vpconfig_errorgain<<
+			vdd->vp_reg.vpconfig_errorgain_shift);
+		voltage_write_reg(vdd->vp_offs.vpconfig, vpconfig);
+
+		voltage_write_reg(vdd->vp_offs.vstepmin,
+			(vdd->vp_reg.vstepmin_smpswaittimemin<<
+			vdd->vp_reg.vstepmin_smpswaittimemin_shift) |
+			(vdd->vp_reg.vstepmin_stepmin<<
+			vdd->vp_reg.vstepmin_stepmin_shift));
+
+		voltage_write_reg(vdd->vp_offs.vstepmax,
+			(vdd->vp_reg.vstepmax_smpswaittimemax<<
+			vdd->vp_reg.vstepmax_smpswaittimemax_shift) |
+			(vdd->vp_reg.vstepmax_stepmax<<
+			vdd->vp_reg.vstepmax_stepmax_shift));
+
+		voltage_write_reg(vdd->vp_offs.vlimitto,
+			(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));
+	}
+
  	/* Enable VP */
  	vpconfig = voltage_read_reg(vdd->vp_offs.vpconfig);
  	voltage_write_reg(vdd->vp_offs.vpconfig,
@@ -1107,6 +1282,7 @@ static int __init omap_voltage_init(void)
  		return 0;
  	}
 
+
  	init_voltagecontroller();
  	for (i = 0; i<  nr_scalable_vdd; i++) {
  		vdd_data_configure(&vdd_info[i]);
@@ -1115,3 +1291,29 @@ static int __init omap_voltage_init(void)
  	return 0;
  }
  core_initcall(omap_voltage_init);
+
+static int __init omap_voltage_debugfs_init(void)
+{
+	int i;
+
+	/*
+	 * If pm debug main directory is not created,
+	 * do not create rest of the debugfs entries.
+	 */
+	if (!pm_dbg_main_dir)
+		return 0;
+
+	voltage_dir = debugfs_create_dir("voltage", pm_dbg_main_dir);
+	if (IS_ERR(voltage_dir)) {
+		pr_err("%s: Unable to create voltage debugfs main dir\n",
+			__func__);
+		return 0;
+	}
+
+	for (i = 0; i<  nr_scalable_vdd; i++)
+		vdd_debugfs_init(&vdd_info[i]);
+
+	return 0;
+}
+
+late_initcall(omap_voltage_debugfs_init);
arch/arm/plat-omap/include/plat/smartreflex.h +0 -1
index 1ad03ea..4ee548d 100644
@@ -24,7 +24,6 @@
  #include<plat/voltage.h>
 
  #ifdef CONFIG_PM_DEBUG
-extern struct dentry *pm_dbg_main_dir;
  extern struct dentry *sr_dbg_dir;
  #endif
 
arch/arm/plat-omap/include/plat/voltage.h +5 -0
index 99836a1..8978d33 100644
@@ -14,6 +14,11 @@
  #ifndef __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
  #define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
 
+extern u32 enable_sr_vp_debug;
+#ifdef CONFIG_PM_DEBUG
+extern struct dentry *pm_dbg_main_dir;
+#endif
+
  #define VOLTSCALE_VPFORCEUPDATE		1
  #define VOLTSCALE_VCBYPASS		2
 
#45 lore raw

PATCH v3 9/11 OMAP3: PM: Smartreflex Class3 initialization from board files.

In reply to Thara Gopinath

This patch enables smartreflex class3 functionality for OMAP3430SDP, OMAP3630SDP, ZOOM2 and ZOOM3 boards.

---
 arch/arm/mach-omap2/board-3430sdp.c          |    2 ++
 arch/arm/mach-omap2/board-zoom-peripherals.c |    2 ++
 2 files changed, 4 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/board-3430sdp.c +2 -0
index 67b95b5f..9a04a2e 100644
@@ -47,6 +47,7 @@
 #include "sdram-qimonda-hyb18m512160af-6.h"
 #include "hsmmc.h"
 #include "pm.h"
+#include "smartreflex-class3.h"
 
 #define CONFIG_DISABLE_HFCLK 1
 
@@ -813,6 +814,7 @@ static void __init omap_3430sdp_init(void)
 	sdp3430_display_init();
 	enable_board_wakeup_source();
 	usb_ehci_init(&ehci_pdata);
+	sr_class3_init();
 }
 
 MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
arch/arm/mach-omap2/board-zoom-peripherals.c +2 -0
index 6b39849..98dffc6 100644
@@ -26,6 +26,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "smartreflex-class3.h"
 
 /* Zoom2 has Qwerty keyboard*/
 static int board_keymap[] = {
@@ -282,4 +283,5 @@ void __init zoom_peripherals_init(void)
 	omap_i2c_init();
 	usb_musb_init(&musb_board_data);
 	enable_board_wakeup_source();
+	sr_class3_init();
 }
Signature · 1 line
1.7.1.GIT
#46 lore raw

Re: [PATCH v3 09/11] OMAP3: PM: Smartreflex Class3 initialization from board files.

Quoted 2 lines · Thara Gopinath

This patch enables smartreflex class3 functionality for OMAP3430SDP, OMAP3630SDP, ZOOM2 and ZOOM3 boards.

This patch doesn't touch 3630sdp.

Quoted 1 line

I'm having some doubts about whether this should be done by board files or not. Seems like the general case will be that by default will be SoC specific, and only boards that want something other than the default class should need to override this.

Thoughts?

Kevin

Quoted 43 lines
---
 arch/arm/mach-omap2/board-3430sdp.c          |    2 ++
 arch/arm/mach-omap2/board-zoom-peripherals.c |    2 ++
 2 files changed, 4 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/board-3430sdp.c +2 -0
index 67b95b5f..9a04a2e 100644
@@ -47,6 +47,7 @@
 #include "sdram-qimonda-hyb18m512160af-6.h"
 #include "hsmmc.h"
 #include "pm.h"
+#include "smartreflex-class3.h"
 
 #define CONFIG_DISABLE_HFCLK 1
 
@@ -813,6 +814,7 @@ static void __init omap_3430sdp_init(void)
 	sdp3430_display_init();
 	enable_board_wakeup_source();
 	usb_ehci_init(&ehci_pdata);
+	sr_class3_init();
 }
 
 MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
arch/arm/mach-omap2/board-zoom-peripherals.c +2 -0
index 6b39849..98dffc6 100644
@@ -26,6 +26,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "smartreflex-class3.h"
 
 /* Zoom2 has Qwerty keyboard*/
 static int board_keymap[] = {
@@ -282,4 +283,5 @@ void __init zoom_peripherals_init(void)
 	omap_i2c_init();
 	usb_musb_init(&musb_board_data);
 	enable_board_wakeup_source();
+	sr_class3_init();
 }
#47 lore raw

RE: [PATCH v3 09/11] OMAP3: PM: Smartreflex Class3 initialization from board files.

Quoted 18 lines
Quoted 18 lines

-----Original Message-----
From: Kevin Hilman [mailto:[email protected]]
Sent: Friday, October 15, 2010 5:20 AM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 09/11] OMAP3: PM: Smartreflex Class3 initialization from board files.

Quoted 2 lines · Thara Gopinath

This patch enables smartreflex class3 functionality for OMAP3430SDP, OMAP3630SDP, ZOOM2 and ZOOM3 boards.

This patch doesn't touch 3630sdp.

Quoted 8 lines
Quoted 8 lines
Quoted 1 line

I'm having some doubts about whether this should be done by board files or not. Seems like the general case will be that by default will be SoC specific, and only boards that want something other than the default class should need to override this.

Thoughts?

I agree. I wanted this to be a default initcall and one to enable the menuconfig option for the required class driver.. But Nishant wanted this from board files. If we have consensus in removing this init from board file, I am cool with it.

Regards
Thara

Quoted 48 lines
Quoted 48 lines

Kevin

arch/arm/mach-

Quoted 6 lines
---
 arch/arm/mach-omap2/board-3430sdp.c          |    2 ++
 arch/arm/mach-omap2/board-zoom-peripherals.c |    2 ++
 2 files changed, 4 insertions(+), 0 deletions(-)
arch/arm/mach- renamed from arch/arm/mach-omap2/board-3430sdp.c +0 -0

omap2/board-3430sdp.c

arch/arm/mach-

Quoted 20 lines

index 67b95b5f..9a04a2e 100644

arch/arm/mach-omap2/board-3430sdp.c +2 -0
@@ -47,6 +47,7 @@
 #include "sdram-qimonda-hyb18m512160af-6.h"
 #include "hsmmc.h"
 #include "pm.h"
+#include "smartreflex-class3.h"
 
 #define CONFIG_DISABLE_HFCLK 1
 
@@ -813,6 +814,7 @@ static void __init omap_3430sdp_init(void)
 	sdp3430_display_init();
 	enable_board_wakeup_source();
 	usb_ehci_init(&ehci_pdata);
+	sr_class3_init();
 }
 
 MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
arch/arm/mach- renamed from arch/arm/mach-omap2/board-zoom-peripherals.c +0 -0

omap2/board-zoom-peripherals.c

Quoted 17 lines

index 6b39849..98dffc6 100644

arch/arm/mach-omap2/board-zoom-peripherals.c +2 -0
@@ -26,6 +26,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "smartreflex-class3.h"
 
 /* Zoom2 has Qwerty keyboard*/
 static int board_keymap[] = {
@@ -282,4 +283,5 @@ void __init zoom_peripherals_init(void)
 	omap_i2c_init();
 	usb_musb_init(&musb_board_data);
 	enable_board_wakeup_source();
+	sr_class3_init();
 }
#48 lore raw

Re: [PATCH v3 09/11] OMAP3: PM: Smartreflex Class3 initialization from board files.

Quoted 12 lines · Thara
Quoted 12 lines
Quoted 12 lines
Quoted 2 lines

This patch enables smartreflex class3 functionality for OMAP3430SDP, OMAP3630SDP, ZOOM2 and ZOOM3 boards.

This patch doesn't touch 3630sdp.

Quoted 1 line

I'm having some doubts about whether this should be done by board files or not. Seems like the general case will be that by default will be SoC specific, and only boards that want something other than the default class should need to override this.

Quoted 5 lines
Quoted 1 line
Quoted 1 line

Thoughts?

I agree. I wanted this to be a default initcall and one to enable the menuconfig option for the required class driver.. But Nishant wanted this from board files.

And I want both. :)

Quoted 2 lines

If we have consensus in removing this init from board file, I am cool with it.

I want to suport a kernel that could be built with all possible classes supported. e.g. an omap3/4 kernel that has both class 1.5 and class 3 support.

If both are enabled in Kconfig, then either could be used. We'll have to pick one as the default initcall (e.g. highest class present), but if a board file chooses to call a different one, that should override the default one.

Kevin

#49 lore raw

RE: [PATCH v3 09/11] OMAP3: PM: Smartreflex Class3 initialization from board files.

Quoted 36 lines
Quoted 36 lines

-----Original Message-----
From: Kevin Hilman [mailto:[email protected]]
Sent: Friday, October 22, 2010 10:08 PM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 09/11] OMAP3: PM: Smartreflex Class3 initialization from board files.

Quoted 12 lines · Thara
Quoted 12 lines
Quoted 12 lines
Quoted 2 lines

This patch enables smartreflex class3 functionality for OMAP3430SDP, OMAP3630SDP, ZOOM2 and ZOOM3 boards.

This patch doesn't touch 3630sdp.

Quoted 1 line

I'm having some doubts about whether this should be done by board files or not. Seems like the general case will be that by default will be SoC specific, and only boards that want something other than the default class should need to override this.

Quoted 5 lines
Quoted 1 line
Quoted 1 line

Thoughts?

I agree. I wanted this to be a default initcall and one to enable the menuconfig option for the required class driver.. But Nishant wanted this from board files.

And I want both. :)

Quoted 2 lines

If we have consensus in removing this init from board file, I am cool with it.

Quoted 8 lines
Quoted 8 lines

I want to suport a kernel that could be built with all possible classes supported. e.g. an omap3/4 kernel that has both class 1.5 and class 3 support.

If both are enabled in Kconfig, then either could be used. We'll have to pick one as the default initcall (e.g. highest class present), but if a board file chooses to call a different one, that should override the default one.

We can pick class 3 by default and make it a late_initcall. This way if the board files choose to call some other class init, that class ddriver would be registered. Smartreflex driver sr_register_class API will ensure that only one class is registered. The second registeration will fail. What say ??

Regards,
Thara

#50 lore raw

PATCH v3 10/11 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 |   67 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 66 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/pm.c +66 -1
index 71c5a77..86c7bf1 100644
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/err.h>
+#include <linux/clk.h>
 
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
@@ -20,6 +21,7 @@
 
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
+#include <plat/voltage.h>
 
 #include "pm.h"
 
@@ -138,12 +140,75 @@ err:
 	return ret;
 }
 
+/*
+ * This 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 omap_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_get(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;
+	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 int __init omap2_common_pm_init(void)
 {
 	omap2_init_processor_devices();
 
-	if (cpu_is_omap34xx())
+	if (cpu_is_omap34xx()) {
 		omap3_pm_init_opp_table();
+		omap2_set_init_voltage("mpu", "dpll1_ck", mpu_dev);
+		omap2_set_init_voltage("core", "l3_ick", l3_dev);
+	}
 
 	omap_pm_if_init();
 
Signature · 1 line
1.7.1.GIT
#51 lore raw

Re: [PATCH v3 10/11] OMAP3: PM: Program correct init voltages for VDD1 and VDD2

Quoted 8 lines · 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.

For de-coupling the init from OPP, I like this approach better. Thanks.

Minor comment below...

Quoted 31 lines
---
 arch/arm/mach-omap2/pm.c |   67 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 66 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/pm.c +5 -0
index 71c5a77..86c7bf1 100644
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/err.h>
+#include <linux/clk.h>
 
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
@@ -20,6 +21,7 @@
 
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
+#include <plat/voltage.h>
 
 #include "pm.h"
 
@@ -138,12 +140,75 @@ err:
 	return ret;
 }
 
+/*
+ * This is to be called during init to put the various voltage
+ * domains to the voltage as per the opp table. Typically we boot up

arch/arm/mach-omap2/pm.c err: · line 155

Quoted 10 lines
arch/arm/mach-omap2/pm.c +10 -0
+ * 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;

s/_clk/clk/

Quoted 59 lines
arch/arm/mach-omap2/pm.c +51 -1
+	struct omap_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_get(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;
+	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 int __init omap2_common_pm_init(void)
 {
 	omap2_init_processor_devices();
 
-	if (cpu_is_omap34xx())
+	if (cpu_is_omap34xx()) {
 		omap3_pm_init_opp_table();
+		omap2_set_init_voltage("mpu", "dpll1_ck", mpu_dev);
+		omap2_set_init_voltage("core", "l3_ick", l3_dev);
+	}
 
 	omap_pm_if_init();
#52 lore raw

RE: [PATCH v3 10/11] OMAP3: PM: Program correct init voltages for VDD1 and VDD2

Quoted 20 lines
Quoted 20 lines

-----Original Message-----
From: Kevin Hilman [mailto:[email protected]]
Sent: Friday, October 15, 2010 5:23 AM
To: Gopinath, Thara
Cc: [email protected]; [email protected]; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand
Subject: Re: [PATCH v3 10/11] OMAP3: PM: Program correct init voltages for VDD1 and VDD2

Quoted 7 lines · 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.

Quoted 3 lines
Quoted 3 lines
Quoted 1 line

For de-coupling the init from OPP, I like this approach better. Thanks.

Most welcome!!

Quoted 32 lines
Quoted 32 lines

Minor comment below...

Quoted 2 lines
---
 arch/arm/mach-omap2/pm.c |   67

+++++++++++++++++++++++++++++++++++++++++++++-

Quoted 26 lines
 1 files changed, 66 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/pm.c +2 -0
index 71c5a77..86c7bf1 100644
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/err.h>
+#include <linux/clk.h>
 
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
@@ -20,6 +21,7 @@
 
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
+#include <plat/voltage.h>
 
 #include "pm.h"
 
@@ -138,12 +140,75 @@ err:
 	return ret;
 }
 
Quoted 15 lines
Quoted 7 lines
Quoted 7 lines
arch/arm/mach-omap2/pm.c +7 -0
+/*
+ * This 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
Quoted 8 lines

arch/arm/mach-omap2/pm.c err: · line 155

Quoted 6 lines
arch/arm/mach-omap2/pm.c +6 -0
+ */
+static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
+						struct device *dev)
+{
+	struct voltagedomain *voltdm;
+	struct clk *_clk;

s/_clk/clk/

Will it not conflict with struct clk??

Regards
Thara

Quoted 60 lines
Quoted 60 lines
Quoted 60 lines
arch/arm/mach-omap2/pm.c +51 -1
+	struct omap_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_get(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;
+	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 int __init omap2_common_pm_init(void)
 {
 	omap2_init_processor_devices();
 
-	if (cpu_is_omap34xx())
+	if (cpu_is_omap34xx()) {
 		omap3_pm_init_opp_table();
+		omap2_set_init_voltage("mpu", "dpll1_ck", mpu_dev);
+		omap2_set_init_voltage("core", "l3_ick", l3_dev);
+	}
 
 	omap_pm_if_init();
#53 lore raw

Re: [PATCH v3 10/11] OMAP3: PM: Program correct init voltages for VDD1 and VDD2

"Gopinath, Thara" <[email protected]> writes:

[...]

Quoted 10 lines
Quoted 7 lines
Quoted 7 lines

arch/arm/mach-omap2/pm.c err: · line 155

Quoted 5 lines
arch/arm/mach-omap2/pm.c +5 -0
+static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
+						struct device *dev)
+{
+	struct voltagedomain *voltdm;
+	struct clk *_clk;

s/_clk/clk/

Will it not conflict with struct clk??

Nope.

$ find . -type f -print0 | xargs -0 -e grep -nH -e 'struct clk \*clk'
./clock2430.c:43:static void omap2430_clk_i2chs_find_idlest(struct clk *clk,
./clock34xx.c:42:static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
./clock34xx.c:76:static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
./clock34xx.c:108:static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
./clkt34xx_dpll3m2.c:50:int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
./clkt2xxx_osc.c:33:static int omap2_enable_osc_ck(struct clk *clk)
./clkt2xxx_osc.c:44:static void omap2_disable_osc_ck(struct clk *clk)
./clkt2xxx_osc.c:58:unsigned long omap2_osc_clk_recalc(struct clk *clk)
./clkt_dpll.c:72:static int _dpll_test_fint(struct clk *clk, u8 n)
./clkt_dpll.c:173:void omap2_init_dpll_parent(struct clk *clk)
./clkt_dpll.c:219:u32 omap2_get_dpll_rate(struct clk *clk)
./clkt_dpll.c:277:int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance)
./clkt_dpll.c:303:long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
./clkt_clksel.c:62:static const struct clksel *_get_clksel_by_parent(struct clk *clk,
./clkt_clksel.c:96:static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
./clkt_clksel.c:151:static void _write_clksel_reg(struct clk *clk, u32 field_val)
./clkt_clksel.c:174:static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
./clkt_clksel.c:211:static u32 _divisor_to_clksel(struct clk *clk, u32 div)
./clkt_clksel.c:248:static u32 _read_divisor(struct clk *clk)
./clkt_clksel.c:276:u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
./clkt_clksel.c:342:void omap2_init_clksel_parent(struct clk *clk)
./clkt_clksel.c:389:unsigned long omap2_clksel_recalc(struct clk *clk)
./clkt_clksel.c:417:long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
./clkt_clksel.c:439:int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
./clkt_clksel.c:483:int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
./clockdomain.c:892:int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
./clockdomain.c:947:int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
./clock2xxx.h:11:unsigned long omap2_table_mpu_recalc(struct clk *clk);
./clock2xxx.h:12:int omap2_select_table_rate(struct clk *clk, unsigned long rate);
./clock2xxx.h:13:long omap2_round_to_table_rate(struct clk *clk, unsigned long rate);
./clock2xxx.h:14:unsigned long omap2xxx_sys_clk_recalc(struct clk *clk);
./clock2xxx.h:15:unsigned long omap2_osc_clk_recalc(struct clk *clk);
./clock2xxx.h:16:unsigned long omap2_dpllcore_recalc(struct clk *clk);
./clock2xxx.h:17:int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate);
./clock2xxx.h:18:unsigned long omap2xxx_clk_get_core_rate(struct clk *clk);
./dpll3xxx.c:49:static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
./dpll3xxx.c:63:static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
./dpll3xxx.c:93:static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
./dpll3xxx.c:138:static int _omap3_noncore_dpll_lock(struct clk *clk)
./dpll3xxx.c:172:static int _omap3_noncore_dpll_bypass(struct clk *clk)
./dpll3xxx.c:206:static int _omap3_noncore_dpll_stop(struct clk *clk)
./dpll3xxx.c:240:static void lookup_dco_sddiv(struct clk *clk, u8 *dco, u8 *sd_div, u16 m,
./dpll3xxx.c:278:static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
./dpll3xxx.c:336:unsigned long omap3_dpll_recalc(struct clk *clk)
./dpll3xxx.c:357:int omap3_noncore_dpll_enable(struct clk *clk)
./dpll3xxx.c:390:void omap3_noncore_dpll_disable(struct clk *clk)
./dpll3xxx.c:409:int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
./dpll3xxx.c:494:u32 omap3_dpll_autoidle_read(struct clk *clk)
./dpll3xxx.c:520:void omap3_dpll_allow_idle(struct clk *clk)
./dpll3xxx.c:547:void omap3_dpll_deny_idle(struct clk *clk)
./dpll3xxx.c:573:unsigned long omap3_clkoutx2_recalc(struct clk *clk)
./clkt2xxx_virt_prcm_set.c:55:unsigned long omap2_table_mpu_recalc(struct clk *clk)
./clkt2xxx_virt_prcm_set.c:67:long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
./clkt2xxx_virt_prcm_set.c:90:int omap2_select_table_rate(struct clk *clk, unsigned long rate)
./clkt2xxx_sys.c:45:unsigned long omap2xxx_sys_clk_recalc(struct clk *clk)
./clock3xxx.h:12:int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate);
./clock3xxx.h:13:int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate);
./clkt2xxx_apll.c:46:static int omap2_clk_apll_enable(struct clk *clk, u32 status_mask)
./clkt2xxx_apll.c:71:static int omap2_clk_apll96_enable(struct clk *clk)
./clkt2xxx_apll.c:76:static int omap2_clk_apll54_enable(struct clk *clk)
./clkt2xxx_apll.c:82:static void omap2_clk_apll_disable(struct clk *clk)
./clkt2xxx_dpllcore.c:50:unsigned long omap2xxx_clk_get_core_rate(struct clk *clk)
./clkt2xxx_dpllcore.c:101:unsigned long omap2_dpllcore_recalc(struct clk *clk)
./clkt2xxx_dpllcore.c:106:int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
./clock.h:54:int omap2_clk_enable(struct clk *clk);
./clock.h:55:void omap2_clk_disable(struct clk *clk);
./clock.h:56:long omap2_clk_round_rate(struct clk *clk, unsigned long rate);
./clock.h:57:int omap2_clk_set_rate(struct clk *clk, unsigned long rate);
./clock.h:58:int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent);
./clock.h:59:int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance);
./clock.h:60:long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate);
./clock.h:61:unsigned long omap3_dpll_recalc(struct clk *clk);
./clock.h:62:unsigned long omap3_clkoutx2_recalc(struct clk *clk);
./clock.h:63:void omap3_dpll_allow_idle(struct clk *clk);
./clock.h:64:void omap3_dpll_deny_idle(struct clk *clk);
./clock.h:65:u32 omap3_dpll_autoidle_read(struct clk *clk);
./clock.h:66:int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
./clock.h:67:int omap3_noncore_dpll_enable(struct clk *clk);
./clock.h:68:void omap3_noncore_dpll_disable(struct clk *clk);
./clock.h:71:void omap2_clk_disable_unused(struct clk *clk);
./clock.h:76:void omap2_init_clk_clkdm(struct clk *clk);
./clock.h:79:u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
./clock.h:81:void omap2_init_clksel_parent(struct clk *clk);
./clock.h:82:unsigned long omap2_clksel_recalc(struct clk *clk);
./clock.h:83:long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
./clock.h:84:int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
./clock.h:85:int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent);
./clock.h:87:u32 omap2_get_dpll_rate(struct clk *clk);
./clock.h:88:void omap2_init_dpll_parent(struct clk *clk);
./clock.h:117:int omap2_dflt_clk_enable(struct clk *clk);
./clock.h:118:void omap2_dflt_clk_disable(struct clk *clk);
./clock.h:119:void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
./clock.h:121:void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
./clock.c:56:static void _omap2_module_wait_ready(struct clk *clk)
./clock.c:84:void omap2_init_clk_clkdm(struct clk *clk)
./clock.c:123:void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
./clock.c:152:void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
./clock.c:175:int omap2_dflt_clk_enable(struct clk *clk)
./clock.c:199:void omap2_dflt_clk_disable(struct clk *clk)
./clock.c:249:void omap2_clk_disable(struct clk *clk)
./clock.c:286:int omap2_clk_enable(struct clk *clk)
./clock.c:338:long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
./clock.c:347:int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
./clock.c:360:int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
./clock.c:388:void omap2_clk_disable_unused(struct clk *clk)
./clock36xx.c:42:static int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk *clk)
./clock3xxx.c:43:int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
./clock3517.c:52:static void am35xx_clk_find_idlest(struct clk *clk,
./clock3517.c:76:static void am35xx_clk_find_companion(struct clk *clk, void __iomem **other_reg,
./clock3517.c:104:static void am35xx_clk_ipss_find_idlest(struct clk *clk,
#54 lore raw

PATCH v3 11/11 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.

---
 arch/arm/plat-omap/opp_twl_tps.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)
arch/arm/plat-omap/opp_twl_tps.c +17 -0
index 112f106..4448fc5 100644
@@ -13,7 +13,10 @@
  * XXX This code should be part of some other TWL/TPS code.
  */
 
+#include <linux/module.h>
+
 #include <plat/opp_twl_tps.h>
+#include <plat/voltage.h>
 
 /**
  * omap_twl_vsel_to_vdc - convert TWL/TPS VSEL value to microvolts DC
@@ -39,3 +42,17 @@ u8 omap_twl_uv_to_vsel(unsigned long uv)
 	/* Round up to higher voltage */
 	return DIV_ROUND_UP(uv - 600000, 12500);
 }
+
+static struct omap_volt_pmic_info twl_volt_info = {
+	.slew_rate	= 4000,
+	.step_size	= 12500,
+	.vsel_to_uv	= omap_twl_vsel_to_uv,
+	.uv_to_vsel	= omap_twl_uv_to_vsel,
+};
+
+static int __init omap_twl_init(void)
+{
+	omap_voltage_register_pmic(&twl_volt_info);
+	return 0;
+}
+arch_initcall(omap_twl_init);
Signature · 1 line
1.7.1.GIT
#55 lore raw
In reply to Thara Gopinath
Quoted 5 lines · Thara Gopinath

From: thara gopinath <[email protected]>

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

[...]

Quoted 6 lines

This patch series is based against origin/pm-core branch off Kevin's pm tree which in turn is based off lo-master. This series will apply against lo-master also but will break compilation due to lack of opp framework support on lo-master.

Quoted 7 lines

This patch series has been tested on OMAP3430 SDP with the extra five patches from origin/cpufreq branch off Kevin's pm tree applied. This series has been tested with with omap3_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

Using the same baseline as you mention above (pm-core + pm-opp), I applied this series (and the OMAP4 series) and tested on 34xx/n900 and 36xx/Zoom3 using omap2plus_defconfig and it booted ok. (I also patched the n900 board file to call sr_class3_init(), which you should include as part of the series too.)

I then did some experiments, including updating the pm-sr branch to be this latest series and testing with omap3_pm_defconfig. With that, I notcied that within a few seconds of reaching the shell, the system rebooted.

I tracked this down to the fact that CONFIG_OMAP_WATCHDOG was not enabled in omap3_pm_defconfig. Enabling the watchdog, and it no longer
reboots. /me confused

Using just the pm-sr branch by itself and omap2plus_defconfig, even with the watchdog disabled, it doesn't reboot.

Do you have any ideas what else might be causing this reboot when using the PM branch + omap3_pm_defconfig?

Kevin

Quoted 41 lines

Thara Gopinath (11):
OMAP: PM: Export the main pm debugfs directory
OMAP3: PM: Adding voltage driver support for OMAP3
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: Adding debug support to Voltage and Smartreflex drivers
OMAP3: PM: Smartreflex Class3 initialization from board files.
OMAP3: PM: Program correct init voltages for VDD1 and VDD2
OMAP3: PM: Register TWL4030 pmic info with the voltage driver.

 arch/arm/mach-omap2/Makefile                  |    5 +-
 arch/arm/mach-omap2/board-3430sdp.c           |    2 +
 arch/arm/mach-omap2/board-zoom-peripherals.c  |    2 +
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c    |  249 +++++
 arch/arm/mach-omap2/pm-debug.c                |   18 +
 arch/arm/mach-omap2/pm.c                      |   67 ++-
 arch/arm/mach-omap2/pm.h                      |    1 +
 arch/arm/mach-omap2/smartreflex-class3.c      |   61 ++
 arch/arm/mach-omap2/smartreflex-class3.h      |   23 +
 arch/arm/mach-omap2/smartreflex.c             | 1039 +++++++++++++++++++
 arch/arm/mach-omap2/sr_device.c               |  174 ++++
 arch/arm/mach-omap2/voltage.c                 | 1319 +++++++++++++++++++++++++
 arch/arm/plat-omap/Kconfig                    |   41 +
 arch/arm/plat-omap/include/plat/control.h     |   27 +
 arch/arm/plat-omap/include/plat/smartreflex.h |  276 ++++++
 arch/arm/plat-omap/include/plat/voltage.h     |  141 +++
 arch/arm/plat-omap/opp_twl_tps.c              |   17 +
 drivers/mfd/twl-core.c                        |    7 +-
 drivers/mfd/twl4030-power.c                   |   29 +
 include/linux/i2c/twl.h                       |    1 +
 20 files changed, 3495 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
 create mode 100644 arch/arm/mach-omap2/smartreflex-class3.h
 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
#56 lore raw
Quoted 39 lines · Kevin Hilman
Quoted 5 lines · Thara Gopinath

From: thara gopinath <[email protected]>

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

[...]

Quoted 6 lines

This patch series is based against origin/pm-core branch off Kevin's pm tree which in turn is based off lo-master. This series will apply against lo-master also but will break compilation due to lack of opp framework support on lo-master.

Quoted 7 lines

This patch series has been tested on OMAP3430 SDP with the extra five patches from origin/cpufreq branch off Kevin's pm tree applied. This series has been tested with with omap3_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

Using the same baseline as you mention above (pm-core + pm-opp), I applied this series (and the OMAP4 series) and tested on 34xx/n900 and 36xx/Zoom3 using omap2plus_defconfig and it booted ok. (I also patched the n900 board file to call sr_class3_init(), which you should include as part of the series too.)

I then did some experiments, including updating the pm-sr branch to be this latest series and testing with omap3_pm_defconfig. With that, I notcied that within a few seconds of reaching the shell, the system rebooted.

I tracked this down to the fact that CONFIG_OMAP_WATCHDOG was not enabled in omap3_pm_defconfig. Enabling the watchdog, and it no longer
reboots. /me confused

Quoted 5 lines

Using just the pm-sr branch by itself and omap2plus_defconfig, even with the watchdog disabled, it doesn't reboot.

Do you have any ideas what else might be causing this reboot when using the PM branch + omap3_pm_defconfig?

So, I did a little more digging, and this has nothing to do with your series. It has to do with the watchdog hwmod series, which due to the new hwmods, resets the watchdog IP. So, if a watchdog driver isn't enabled, the watchdog will fire, and cause a reboot.

Kevin