[PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jean Pihet <j-pihet@xxxxxx>

Convert the existing OMAP code for SmartReflex into the AVS
(Adaptive Voltage Scaling) driver:
- split the code into common code, v1 IP driver, v2 IP driver and
   class driver for SmartReflex Class3,
- initialize the v1 driver for OMAP34xx platform and v2 driver for
   OMAP36xx and OMAP4xxx platforms,
- create CONFIG_AVS* config options accordingly,
- split the include files into generic and platform specific code.

This change makes the code ready to be moved to drivers/ without any
functional change.

Signed-off-by: Jean Pihet <j-pihet@xxxxxx>
---
 arch/arm/mach-omap2/Kconfig                   |   57 ++
 arch/arm/mach-omap2/Makefile                  |    7 +-
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c    |    2 +-
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c    |    2 +-
 arch/arm/mach-omap2/pm.h                      |    2 +-
 arch/arm/mach-omap2/smartreflex-class3.c      |    8 +-
 arch/arm/mach-omap2/smartreflex-common.c      |  543 ++++++++++++++++++
 arch/arm/mach-omap2/smartreflex.c             |  743 -------------------------
 arch/arm/mach-omap2/smartreflex.h             |  186 +++----
 arch/arm/mach-omap2/smartreflex_v1.c          |  183 ++++++
 arch/arm/mach-omap2/smartreflex_v2.c          |  186 ++++++
 arch/arm/mach-omap2/sr_device.c               |    2 +-
 arch/arm/plat-omap/Kconfig                    |   31 -
 arch/arm/plat-omap/include/plat/smartreflex.h |  106 ++++
 14 files changed, 1168 insertions(+), 890 deletions(-)
 create mode 100644 arch/arm/mach-omap2/smartreflex-common.c
 delete mode 100644 arch/arm/mach-omap2/smartreflex.c
 create mode 100644 arch/arm/mach-omap2/smartreflex_v1.c
 create mode 100644 arch/arm/mach-omap2/smartreflex_v2.c
 create mode 100644 arch/arm/plat-omap/include/plat/smartreflex.h

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 09ea525..3faf921 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -370,4 +370,61 @@ config OMAP3_SDRC_AC_TIMING
 
 endmenu
 
+menuconfig POWER_AVS
+	tristate "Adaptive Voltage Scaling class support"
+	help
+	  AVS is a power management technique which controls the operating
+	  voltage of a device in order to optimize (i.e. reduce) its power
+	  consumption. The voltage is adapted depending on static factors
+	  (chip manufacturing process) and dynamic factors (temperature
+	  depending performance). AVS is also called SmartReflex on OMAP
+	  devices.
+
+	  Say Y here to enable Adaptive Voltage Scaling class support.
+
+if POWER_AVS
+
+config POWER_AVS_DEBUG
+	bool "Adaptive Voltage Scaling debug"
+	depends on DEBUG_FS
+	help
+	  Say Y here to enable debugfs entries for the AVS class and drivers.
+
+config POWER_AVS_OMAP_V1
+	tristate "AVS support for the OMAP IP version 1"
+	depends on ARCH_OMAP3 && PM
+	help
+	  Say Y to enable AVS support on OMAP containing the version 1 of
+	  the SmartReflex IP.
+	  V1 is the 65nm version used in OMAP3430.
+
+	  Please note, that by default SmartReflex is only
+	  initialized. To enable the automatic voltage
+	  compensation for vdd mpu  and vdd core from user space,
+	  user must write 1 to
+		/debug/voltage/vdd_<X>/smartreflex/autocomp,
+	  where X is mpu or core for OMAP3.
+	  Optionally autocompensation can be enabled in the kernel
+	  by default during system init via the enable_on_init flag
+	  which an be passed as platform data to the smartreflex driver.
+
+config POWER_AVS_OMAP_V2
+	tristate "AVS support for the OMAP IP version 2"
+	depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM
+	help
+	  Say Y to enable AVS support on OMAP containing the version 2 of
+	  the SmartReflex IP.
+	  V2 is the update for the 45nm version of the IP used in OMAP3630
+	  and OMAP4430
+
+config POWER_AVS_OMAP_CLASS3
+	bool "Class 3 mode of Smartreflex Implementation"
+	depends on (POWER_AVS_OMAP_V1 || POWER_AVS_OMAP_V2) && TWL4030_CORE
+	help
+	  Say Y to enable Class 3 implementation of Smartreflex
+	  Class 3 implementation of Smartreflex employs continuous hardware
+	  voltage calibration.
+
+endif # POWER_AVS
+
 endif
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index b009f17..6673ec5 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -64,8 +64,11 @@ obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o \
 					   cpuidle34xx.o
 obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.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
+
+obj-$(CONFIG_POWER_AVS)			+= sr_device.o
+obj-$(CONFIG_POWER_AVS_OMAP_V1)		+= smartreflex-common.o smartreflex_v1.o
+obj-$(CONFIG_POWER_AVS_OMAP_V2)		+= smartreflex-common.o smartreflex_v2.o
+obj-$(CONFIG_POWER_AVS_OMAP_CLASS3)	+= smartreflex-class3.o
 
 AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
 AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a$(plus_sec)
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index cb8e78c..5a83741 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -32,7 +32,7 @@
 #include "prm-regbits-34xx.h"
 #include "cm-regbits-34xx.h"
 #include "wd_timer.h"
-#include "smartreflex.h"
+#include <plat/smartreflex.h>
 #include <mach/am35xx.h>
 
 /*
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 1b43ff1..cabc0c1 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -39,7 +39,7 @@
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
 #include "wd_timer.h"
-#include "smartreflex.h"
+#include <plat/smartreflex.h>
 
 /* Base offset for all OMAP4 interrupts external to MPUSS */
 #define OMAP44XX_IRQ_GIC_START	32
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 4e166ad..f94ba69 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -107,7 +107,7 @@ extern void enable_omap3630_toggle_l2_on_restore(void);
 static inline void enable_omap3630_toggle_l2_on_restore(void) { }
 #endif		/* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
 
-#ifdef CONFIG_OMAP_SMARTREFLEX
+#ifdef CONFIG_POWER_AVS
 extern int omap_devinit_smartreflex(void);
 extern void omap_enable_smartreflex_on_init(void);
 #else
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index 2d37f76..516901b 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -53,10 +53,12 @@ static struct smartreflex_class_data class3_data = {
 /* Smartreflex Class3 init API to be called from board file */
 static int __init sr_class3_init(void)
 {
-	/* XXX fix the registration of pdev */
 	struct platform_device *pdev = NULL;
+	int ret = sr_register_class(pdev, &class3_data);
 
-	pr_info("SmartReflex Class3 initialized\n");
-	return sr_register_class(pdev, &class3_data);
+	if (!ret)
+		pr_info("SmartReflex Class3 initialized\n");
+
+	return ret;
 }
 late_initcall(sr_class3_init);
diff --git a/arch/arm/mach-omap2/smartreflex-common.c b/arch/arm/mach-omap2/smartreflex-common.c
new file mode 100644
index 0000000..d693195
--- /dev/null
+++ b/arch/arm/mach-omap2/smartreflex-common.c
@@ -0,0 +1,543 @@
+/*
+ * Device driver for the SmartReflex IP blocks, common code
+ *
+ * Author: Thara Gopinath	<thara@xxxxxx>
+ *
+ * Copyright (C) 2007,2010 Texas Instruments, Inc.
+ * Lesly A M <x0080970@xxxxxx>
+ * Thara Gopinath <thara@xxxxxx>
+ *
+ * Copyright (C) 2008,2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * 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/module.h>
+#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/common.h>
+#include <plat/smartreflex.h>
+
+#include "smartreflex.h"
+
+#define NVALUE_NAME_LEN		40
+
+/*
+ * SR_CLK is the internal SmartReflex sensor sampling clock.  The OMAP34xx
+ * TRM Rev ZH Section 4.10.5.4.3 "SmartReflex Submodules" states that this
+ * should be 100KHz.
+ */
+#define SR_CLK			100000 /* Hz */
+
+static struct dentry		*sr_dbg_dir;
+
+int sr_calculate_clk_length(struct smartreflex *sr)
+{
+	struct clk *fck;
+	int fck_rate, clk_length;
+
+	fck = clk_get(&sr->pdev->dev, "fck");
+	if (IS_ERR(fck)) {
+		dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n",
+			__func__);
+		return 0;
+	}
+	fck_rate = clk_get_rate(fck);
+	clk_put(fck);
+
+	/*
+	 * This formula is from OMAP34xx TRM Rev ZH Section 4.10.5.4.3
+	 * "SmartReflex Submodules"
+	 */
+	clk_length = fck_rate / (2 * SR_CLK);
+
+	dev_dbg(&sr->pdev->dev, "%s: SRCLKLENGTH = %03x\n",
+		__func__, clk_length);
+
+	return clk_length;
+}
+
+static void sr_start_vddautocomp(struct smartreflex *sr)
+{
+	if (!sr->sr_class || !sr->sr_class->enable ||
+	    !sr->sr_class->configure) {
+		dev_warn(&sr->pdev->dev,
+			"%s: smartreflex class driver not registered\n",
+			__func__);
+		return;
+	}
+
+	if (!sr->sr_class->enable(sr))
+		sr->autocomp_active = true;
+}
+
+static void sr_stop_vddautocomp(struct smartreflex *sr)
+{
+	if (!sr->sr_class || !sr->sr_class->disable) {
+		dev_warn(&sr->pdev->dev,
+			"%s: smartreflex class driver not registered\n",
+			__func__);
+		return;
+	}
+
+	if (sr->autocomp_active) {
+		sr->sr_class->disable(sr, 1);
+		sr->autocomp_active = false;
+	}
+}
+
+static struct omap_sr_data_table *sr_retrieve_nvalue_row(
+				struct smartreflex *sr,
+				unsigned long volt_nominal)
+{
+	struct smartreflex_platform_data *pdata = sr->pdev->dev.platform_data;
+	int i;
+
+	if (!sr->data_table) {
+		dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
+			__func__);
+		return NULL;
+	}
+
+	for (i = 0; i < pdata->data_count; i++)
+		if (sr->data_table[i].volt_nominal == volt_nominal)
+			return &sr->data_table[i];
+
+	return NULL;
+}
+
+/**
+ * sr_configure_errgen() - Configures the smrtreflex to perform AVS using the
+ *			 error generator module.
+ * @sr: struct smartreflex *
+ *
+ * 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 smartreflex *sr)
+{
+	struct smartreflex_platform_data *pdata = sr->pdev->dev.platform_data;
+	u32 sr_config, sr_errconfig;
+
+	if (IS_ERR_OR_NULL(sr))
+		return -EINVAL;
+
+	if (!sr_calculate_clk_length(sr))
+		return -EINVAL;
+
+	sr_config = sr->proto_sr_config;
+	sr_config |=  SRCONFIG_ERRGEN_EN;
+	sr_write_reg(sr, SRCONFIG, sr_config);
+
+	sr_errconfig = (pdata->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
+		(pdata->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
+		(sr->err_minlimit <<  ERRCONFIG_ERRMINLIMIT_SHIFT);
+	sr_modify_reg(sr, 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, sr->errconfig_offs,
+		sr->vpboundint_en, (sr->vpboundint_en | sr->vpboundint_st));
+
+	return 0;
+}
+
+static int sr_common_configure_minmax(struct smartreflex *sr)
+{
+	struct smartreflex_platform_data *pdata = sr->pdev->dev.platform_data;
+	u32 sr_config, sr_avgwt;
+
+	sr_config = sr->proto_sr_config;
+	sr_config |= (pdata->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
+	sr_write_reg(sr, SRCONFIG, sr_config);
+
+	sr_avgwt = (pdata->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
+		(pdata->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT);
+	sr_write_reg(sr, AVGWEIGHT, sr_avgwt);
+
+	return 0;
+}
+
+/**
+ * sr_configure_minmax() - Configures the smrtreflex to perform AVS using the
+ *  minmaxavg module.
+ * @sr: struct smartreflex *
+ *
+ * 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 smartreflex *sr)
+{
+	int ret;
+
+	if (IS_ERR_OR_NULL(sr))
+		return -EINVAL;
+
+	ret = sr_common_configure_minmax(sr);
+	if (ret)
+		return ret;
+
+	return sr->configure_minmax(sr);
+}
+
+/**
+ * sr_enable() - Enables the smartreflex module.
+ * @sr: struct smartreflex *
+ * @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 smartreflex *sr, unsigned long volt)
+{
+	struct omap_sr_data_table *nvalue_row;
+	int ret;
+
+	if (IS_ERR_OR_NULL(sr))
+		return -EINVAL;
+
+	/* Check if SR clocks are already enabled. If yes do nothing */
+	if (!pm_runtime_suspended(&sr->pdev->dev))
+		return 0;
+
+	nvalue_row = sr_retrieve_nvalue_row(sr, volt);
+	if (!nvalue_row) {
+		dev_warn(&sr->pdev->dev, "%s: failure getting SR data for "
+			 "this voltage %ld\n",__func__, volt);
+		return -ENODATA;
+	}
+
+	/* errminlimit is opp dependent and hence linked to voltage */
+	sr->err_minlimit = nvalue_row->errminlimit;
+
+	pm_runtime_get_sync(&sr->pdev->dev);
+
+	/* Check if SR is already enabled. If yes do nothing */
+	if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE)
+		goto out;
+
+	/* Configure SR */
+	ret = sr->sr_class->configure(sr);
+	if (ret)
+		return ret;
+
+	sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue);
+
+	/* SRCONFIG - enable SR */
+	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
+
+out:
+	pm_runtime_put_sync(&sr->pdev->dev);
+	return 0;
+}
+
+/**
+ * sr_disable() - Disables the smartreflex module.
+ * @sr: struct smartreflex *
+ *
+ * This API is to be called from the smartreflex class driver to
+ * disable a smartreflex module.
+ */
+void sr_disable(struct smartreflex *sr)
+{
+	if (IS_ERR_OR_NULL(sr))
+		return;
+
+	/* Check if SR clocks are already disabled. If yes do nothing */
+	if (pm_runtime_suspended(&sr->pdev->dev))
+		return;
+
+	/*
+	 * Disable SR if only it is indeed enabled. Else just
+	 * disable the clocks.
+	 */
+	if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) {
+		sr->disable(sr);
+	}
+
+	pm_runtime_put_sync_suspend(&sr->pdev->dev);
+}
+
+/**
+ * sr_register_class() - API to register a smartreflex class parameters.
+ * @class_data:	The structure containing various sr class specific data.
+ *
+ * XXX FIX THIS DOCUMENTATION
+ *
+ * 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 platform_device *pdev, 
+		      struct smartreflex_class_data *class_data)
+{
+	struct smartreflex_platform_data *pdata = pdev->dev.platform_data;
+	struct smartreflex *sr;
+	int ret = 0;
+
+	if (!pdev || !class_data)
+		return -EINVAL;
+
+	sr = pdata->sr;
+	if (sr) {
+		dev_err(&pdev->dev, "%s: Smartreflex class driver already "
+				    "registered\n",
+		       __func__);
+		return -EBUSY; /* XXX -EEXIST seems better */
+	}
+
+	if (!sr->irq) {
+		dev_err(&pdev->dev, "%s: cannot register since class driver "
+				    "has an IRQ hook, but no SR IRQ "
+				    "specified\n", __func__);
+		ret = -EINVAL;
+		goto src_err;
+	}
+
+	sr->sr_class = class_data;
+
+	if (pdata->enable_on_init)
+		sr_start_vddautocomp(sr);
+
+src_err:
+	return ret;
+}
+
+#ifdef CONFIG_POWER_AVS_DEBUG
+static int omap_sr_autocomp_show(void *data, u64 *val)
+{
+	struct smartreflex *sr = (struct smartreflex *) data;
+
+	if (!sr) {
+		pr_warning("%s: smartreflex struct not found\n", __func__);
+		return -EINVAL;
+	}
+
+	*val = sr->autocomp_active;
+
+	return 0;
+}
+
+static int omap_sr_autocomp_store(void *data, u64 val)
+{
+	struct smartreflex *sr = (struct smartreflex *) data;
+
+	if (!sr) {
+		pr_warning("%s: smartreflex struct not found\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Sanity check */
+	if (val && (val != 1)) {
+		pr_warning("%s: Invalid argument %lld\n", __func__, val);
+		return -EINVAL;
+	}
+
+	/* control enable/disable only if there is a delta in value */
+	if (sr->autocomp_active != val) {
+		if (!val)
+			sr_stop_vddautocomp(sr);
+		else
+			sr_start_vddautocomp(sr);
+	}
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
+		omap_sr_autocomp_store, "%llu\n");
+
+int __init sr_debugfs_setup(struct platform_device *pdev,
+			    struct smartreflex *sr)
+{
+	int i, ret = 0;
+	struct dentry *nvalue_dir;
+	struct smartreflex_platform_data *pdata = pdev->dev.platform_data;
+
+	sr->dbg_dir = debugfs_create_dir(sr->name, sr_dbg_dir);
+	if (IS_ERR(sr->dbg_dir)) {
+		dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
+			__func__);
+		return PTR_ERR(sr->dbg_dir);
+	}
+
+	(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR,
+			sr->dbg_dir, (void *)sr, &pm_sr_fops);
+	(void) debugfs_create_x32("errweight", S_IRUGO, sr->dbg_dir,
+			&pdata->err_weight);
+	(void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr->dbg_dir,
+			&pdata->err_maxlimit);
+
+	/* XXX This should be per-OPP parameters, not just nvalue! */
+	nvalue_dir = debugfs_create_dir("nvalue", sr->dbg_dir);
+	if (IS_ERR(nvalue_dir)) {
+		dev_err(&pdev->dev, "%s: Unable to create debugfs directory for n-values\n", __func__);
+		ret = PTR_ERR(nvalue_dir);
+		goto err_debugfs;
+	}
+
+	if (pdata->data_count == 0 || !pdata->data_table) {
+		dev_warn(&pdev->dev, "%s: no SR data table\n", __func__);
+		ret = -ENODATA;
+		goto err_debugfs;
+	}
+
+	for (i = 0; i < pdata->data_count; i++) {
+		char name[NVALUE_NAME_LEN + 1];
+
+		/* XXX Also needs to include errminlimit! */
+		snprintf(name, sizeof(name), "volt_%lu",
+			 sr->data_table[i].volt_nominal);
+		(void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
+				&(sr->data_table[i].nvalue));
+	}
+
+	return ret;
+
+err_debugfs:
+	debugfs_remove_recursive(sr->dbg_dir);
+
+	return ret;
+}
+#else
+int __init sr_debugfs_setup(struct platform_device *pdev,
+			    struct smartreflex *sr)
+{
+	return 0;
+}
+#endif
+
+int __init sr_common_probe(struct platform_device *pdev,
+			   struct smartreflex *sr)
+{
+	struct smartreflex_platform_data *pdata = pdev->dev.platform_data;
+	struct resource *mem, *irq;
+	int ret = 0;
+
+	sr->name = kasprintf(GFP_KERNEL, "sr_%s", pdata->name);
+	if (!sr->name) {
+		dev_err(&pdev->dev, "%s: Unable to alloc debugfs name\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
+		return -ENODEV;
+	}
+
+	mem = request_mem_region(mem->start, resource_size(mem),
+					dev_name(&pdev->dev));
+	if (!mem) {
+		dev_err(&pdev->dev, "%s: no mem region\n", __func__);
+		return -EBUSY;
+	}
+
+	sr->base = ioremap(mem->start, resource_size(mem));
+	if (!sr->base) {
+		dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
+		ret = -ENOMEM;
+		goto err_release_region;
+	}
+
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!irq) {
+		dev_err(&pdev->dev, "%s: no IRQ resource defined\n", __func__);
+		ret = -ENODEV;
+		goto err_iounmap;
+	}
+	sr->irq = irq->start;
+
+	ret = request_irq(sr->irq, sr->isr, 0, sr->name, (void *)sr);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: could not register interrupt "
+				    "handler\n", __func__);
+		goto err_iounmap;
+	}
+
+	pdata->sr = sr;
+
+	sr->pdev = pdev;
+	sr->voltdm = pdata->voltdm;
+
+	sr->autocomp_active = false;
+
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_irq_safe(&pdev->dev);
+
+#ifdef CONFIG_POWER_AVS_DEBUG
+	ret = sr_debugfs_setup(pdev, sr);
+	if (ret)
+		goto err_free_irq;
+#endif
+
+	dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
+
+	return ret;
+
+err_free_irq:
+	free_irq(sr->irq, (void *)sr);
+err_iounmap:
+	iounmap(sr->base);
+err_release_region:
+	release_mem_region(mem->start, resource_size(mem));
+
+	return ret;
+}
+
+int __devexit sr_remove(struct platform_device *pdev)
+{
+	struct smartreflex_platform_data *pdata = pdev->dev.platform_data;
+	struct smartreflex *sr;
+	struct resource *mem;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+		return -EINVAL;
+	}
+
+	sr = pdata->sr;
+	if (IS_ERR(sr)) {
+		dev_warn(&pdev->dev, "%s: smartreflex struct not found\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (sr->autocomp_active)
+		sr_stop_vddautocomp(sr);
+#ifdef CONFIG_POWER_AVS_DEBUG
+	if (sr->dbg_dir)
+		debugfs_remove_recursive(sr->dbg_dir);
+#endif
+	free_irq(sr->irq, (void *)sr);
+	iounmap(sr->base);
+	kfree(sr);
+	pdata->sr = NULL;
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+
+	return 0;
+}
+
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
deleted file mode 100644
index f7d305d..0000000
--- a/arch/arm/mach-omap2/smartreflex.c
+++ /dev/null
@@ -1,743 +0,0 @@
-/*
- * Device driver for the SmartReflex IP block
- *
- * Author: Thara Gopinath	<thara@xxxxxx>
- *
- * Copyright (C) 2007,2010 Texas Instruments, Inc.
- * Lesly A M <x0080970@xxxxxx>
- * Thara Gopinath <thara@xxxxxx>
- *
- * Copyright (C) 2008,2011 Nokia Corporation
- * Kalle Jokiniemi
- * Paul Walmsley
- *
- * 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/module.h>
-#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/common.h>
-
-#include "pm.h"
-#include "smartreflex.h"
-
-#define NVALUE_NAME_LEN		40
-#define SR_DISABLE_TIMEOUT	200
-
-/*
- * SR_CLK is the internal SmartReflex sensor sampling clock.  The OMAP34xx
- * TRM Rev ZH Section 4.10.5.4.3 "SmartReflex Submodules" states that this
- * should be 100KHz.
- */
-#define SR_CLK			100000 /* Hz */
-
-static struct dentry		*sr_dbg_dir;
-
-static inline void sr_write_reg(struct smartreflex *sr, unsigned offset,
-				u32 value)
-{
-	__raw_writel(value, (sr->base + offset));
-}
-
-static inline void sr_modify_reg(struct smartreflex *sr, unsigned offset,
-				 u32 mask, u32 value)
-{
-	u32 reg_val;
-
-	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. This mean this API doesn't rewrite values in these bits
-	 * if they are currently set, but does allow the caller to write
-	 * those bits.
-	 */
-	if (offset == sr->errconfig_offs)
-		reg_val &= ~sr->errconfig_mask;
-
-	reg_val |= value;
-
-	__raw_writel(reg_val, (sr->base + offset));
-}
-
-static inline u32 sr_read_reg(struct smartreflex *sr, unsigned offset)
-{
-	return __raw_readl(sr->base + offset);
-}
-
-static irqreturn_t sr_interrupt(int irq, void *data)
-{
-	struct smartreflex *sr = (struct smartreflex *)data;
-	struct smartreflex_platform_data *pdata = sr->pdev->dev.platform_data;
-	u32 status = 0;
-
-	if (pdata->ip_type == SR_TYPE_V1) {
-		/* Read the status bits */
-		status = sr_read_reg(sr, ERRCONFIG_V1);
-
-		/* Clear them by writing back */
-		sr_write_reg(sr, ERRCONFIG_V1, status);
-	} else if (pdata->ip_type == SR_TYPE_V2) {
-		/* Read the status bits */
-		status = sr_read_reg(sr, IRQSTATUS);
-
-		/* Clear them by writing back */
-		sr_write_reg(sr, IRQSTATUS, status);
-	}
-
-	/*
-	 * XXX If the class driver needs to be notified here, it should
-	 * use an atomic notifier
-	 */
-
-	return IRQ_HANDLED;
-}
-
-static int sr_calculate_clk_length(struct smartreflex *sr)
-{
-	struct clk *fck;
-	int fck_rate, clk_length;
-
-	fck = clk_get(&sr->pdev->dev, "fck");
-	if (IS_ERR(fck)) {
-		dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n",
-			__func__);
-		return 0;
-	}
-	fck_rate = clk_get_rate(fck);
-	clk_put(fck);
-
-	/*
-	 * This formula is from OMAP34xx TRM Rev ZH Section 4.10.5.4.3
-	 * "SmartReflex Submodules"
-	 */
-	clk_length = fck_rate / (2 * SR_CLK);
-
-	dev_dbg(&sr->pdev->dev, "%s: SRCLKLENGTH = %03x\n",
-		__func__, clk_length);
-
-	return clk_length;
-}
-
-static void sr_start_vddautocomp(struct smartreflex *sr)
-{
-	if (!sr->sr_class || !sr->sr_class->enable ||
-	    !sr->sr_class->configure) {
-		dev_warn(&sr->pdev->dev,
-			"%s: smartreflex class driver not registered\n",
-			__func__);
-		return;
-	}
-
-	if (!sr->sr_class->enable(sr))
-		sr->autocomp_active = true;
-}
-
-static void sr_stop_vddautocomp(struct smartreflex *sr)
-{
-	if (!sr->sr_class || !sr->sr_class->disable) {
-		dev_warn(&sr->pdev->dev,
-			"%s: smartreflex class driver not registered\n",
-			__func__);
-		return;
-	}
-
-	if (sr->autocomp_active) {
-		sr->sr_class->disable(sr, 1);
-		sr->autocomp_active = false;
-	}
-}
-
-static void sr_v1_disable(struct smartreflex *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 smartreflex *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);
-}
-
-static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
-				struct smartreflex *sr,
-				unsigned long volt_nominal)
-{
-	struct smartreflex_platform_data *pdata = sr->pdev->dev.platform_data;
-	int i;
-
-	if (!sr->data_table) {
-		dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
-			__func__);
-		return NULL;
-	}
-
-	for (i = 0; i < pdata->data_count; i++) {
-		if (sr->data_table[i].volt_nominal == volt_nominal)
-			return &sr->data_table[i];
-	}
-
-	return NULL;
-}
-
-/* Public Functions */
-
-/**
- * sr_configure_errgen() - Configures the smrtreflex to perform AVS using the
- *			 error generator module.
- * @sr: struct smartreflex *
- *
- * 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 smartreflex *sr)
-{
-	struct smartreflex_platform_data *pdata = sr->pdev->dev.platform_data;
-	u32 sr_config, sr_errconfig;
-
-	if (IS_ERR_OR_NULL(sr))
-		return -EINVAL;
-
-	if (!sr_calculate_clk_length(sr))
-		return -EINVAL;
-	
-	sr_config = sr->proto_sr_config;
-	sr_config |=  SRCONFIG_ERRGEN_EN;
-	sr_write_reg(sr, SRCONFIG, sr_config);
-
-	sr_errconfig = (pdata->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
-		(pdata->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
-		(sr->err_minlimit <<  ERRCONFIG_ERRMINLIMIT_SHIFT);
-	sr_modify_reg(sr, 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, sr->errconfig_offs,
-		sr->vpboundint_en, (sr->vpboundint_en | sr->vpboundint_st));
-
-	return 0;
-}
-
-/**
- * sr_configure_minmax() - Configures the smrtreflex to perform AVS using the
- *			 minmaxavg module.
- * @sr: struct smartreflex *
- *
- * 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 smartreflex *sr)
-{
-	struct smartreflex_platform_data *pdata = sr->pdev->dev.platform_data;
-	u32 sr_config, sr_avgwt;
-
-	if (IS_ERR_OR_NULL(sr))
-		return -EINVAL;
-
-	sr_config = sr->proto_sr_config;
-	sr_config |= (pdata->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
-	sr_write_reg(sr, SRCONFIG, sr_config);
-
-	sr_avgwt = (pdata->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
-		(pdata->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 (pdata->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 (pdata->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.
- * @sr: struct smartreflex *
- * @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 smartreflex *sr, unsigned long volt)
-{
-	struct omap_sr_data_table *nvalue_row;
-	int ret;
-
-	if (IS_ERR_OR_NULL(sr))
-		return -EINVAL;
-
-	nvalue_row = sr_retrieve_nvalue_row(sr, volt);
-	if (!nvalue_row) {
-		dev_warn(&sr->pdev->dev, "%s: failure getting SR data for "
-					 "this voltage %ld\n",__func__, volt);
-		return -ENODATA;
-	}
-
-	/* errminlimit is opp dependent and hence linked to voltage */
-	sr->err_minlimit = nvalue_row->errminlimit;
-
-	pm_runtime_get_sync(&sr->pdev->dev);
-
-	/* Check if SR is already enabled. If yes do nothing */
-	if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE)
-		return 0;
-
-	/* Configure SR */
-	ret = sr->sr_class->configure(sr);
-	if (ret)
-		return ret;
-
-	sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue);
-
-	/* SRCONFIG - enable SR */
-	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
-	return 0;
-}
-
-/**
- * sr_disable() - Disables the smartreflex module.
- * @sr: struct smartreflex *
- *
- * This API is to be called from the smartreflex class driver to
- * disable a smartreflex module.
- */
-void sr_disable(struct smartreflex *sr)
-{
-	struct smartreflex_platform_data *pdata = sr->pdev->dev.platform_data;
-
-	if (IS_ERR_OR_NULL(sr))
-		return;
-
-	/* Check if SR clocks are already disabled. If yes do nothing */
-	if (pm_runtime_suspended(&sr->pdev->dev))
-		return;
-
-	/*
-	 * Disable SR if only it is indeed enabled. Else just
-	 * disable the clocks.
-	 */
-	if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) {
-		if (pdata->ip_type == SR_TYPE_V1)
-			sr_v1_disable(sr);
-		else if (pdata->ip_type == SR_TYPE_V2)
-			sr_v2_disable(sr);
-	}
-
-	pm_runtime_put_sync_suspend(&sr->pdev->dev);
-}
-
-/**
- * sr_register_class() - API to register a smartreflex class parameters.
- * @class_data:	The structure containing various sr class specific data.
- *
- * XXX FIX THIS DOCUMENTATION
- *
- * 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 platform_device *pdev, 
-		      struct smartreflex_class_data *class_data)
-{
-	struct smartreflex_platform_data *pdata = pdev->dev.platform_data;
-	struct smartreflex *sr;
-	int ret = 0;
-
-	if (!pdev || !class_data)
-		return -EINVAL;
-
-	sr = pdata->sr;
-	if (sr) {
-		dev_err(&pdev->dev, "%s: Smartreflex class driver already registered\n",
-		       __func__);
-		return -EBUSY; /* XXX -EEXIST seems better */
-	}
-
-	if (class_data->isr) {
-		if (!sr->irq) {
-			dev_err(&pdev->dev, "%s: cannot register since class driver has an IRQ hook, but no SR IRQ specified\n", __func__);
-			ret = -EINVAL;
-			goto src_err;
-		}
-
-		ret = request_irq(sr->irq, sr_interrupt, 0, pdata->name,
-				  (void *)sr);
-		if (ret) {
-			dev_err(&pdev->dev, "%s: could not register interrupt handler\n", __func__);
-			goto src_err;
-		}
-	}
-
-	sr->sr_class = class_data;
-
-	if (pdata->enable_on_init)
-		sr_start_vddautocomp(sr);
-
-src_err:
-	return ret;
-}
-
-/* PM Debug Fs enteries to enable disable smartreflex. */
-static int omap_sr_autocomp_show(void *data, u64 *val)
-{
-	struct smartreflex *sr = (struct smartreflex *) data;
-
-	if (!sr) {
-		pr_warning("%s: smartreflex struct not found\n", __func__);
-		return -EINVAL;
-	}
-
-	*val = sr->autocomp_active;
-
-	return 0;
-}
-
-static int omap_sr_autocomp_store(void *data, u64 val)
-{
-	struct smartreflex *sr = (struct smartreflex *) data;
-
-	if (!sr) {
-		pr_warning("%s: smartreflex struct not found\n", __func__);
-		return -EINVAL;
-	}
-
-	/* Sanity check */
-	if (val && (val != 1)) {
-		pr_warning("%s: Invalid argument %lld\n", __func__, val);
-		return -EINVAL;
-	}
-
-	/* control enable/disable only if there is a delta in value */
-	if (sr->autocomp_active != val) {
-		if (!val)
-			sr_stop_vddautocomp(sr);
-		else
-			sr_start_vddautocomp(sr);
-	}
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
-		omap_sr_autocomp_store, "%llu\n");
-
-static int __init omap_sr_probe(struct platform_device *pdev)
-{
-	struct smartreflex *sr = kzalloc(sizeof(struct smartreflex), GFP_KERNEL);
-	struct smartreflex_platform_data *pdata = pdev->dev.platform_data;
-	struct resource *mem, *irq;
-	struct dentry *nvalue_dir;
-	int srclklength, senn_shift, senp_shift;
-	int i, ret = 0;
-
-	if (!sr) {
-		dev_err(&pdev->dev, "%s: unable to allocate sr\n", __func__);
-		return -ENOMEM;
-	}
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
-		ret = -EINVAL;
-		goto err_free_devinfo;
-	}
-
-	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;
-	}
-
-	mem = request_mem_region(mem->start, resource_size(mem),
-					dev_name(&pdev->dev));
-	if (!mem) {
-		dev_err(&pdev->dev, "%s: no mem region\n", __func__);
-		ret = -EBUSY;
-		goto err_free_devinfo;
-	}
-
-	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-
-	pm_runtime_enable(&pdev->dev);
-	pm_runtime_irq_safe(&pdev->dev);
-
-	pdata->sr = sr;
-
-	sr->pdev = pdev;
-	sr->voltdm = pdata->voltdm;
-
-	sr->autocomp_active = false;
-	sr->base = ioremap(mem->start, resource_size(mem));
-	if (!sr->base) {
-		dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
-		ret = -ENOMEM;
-		goto err_release_region;
-	}
-
-	if (irq)
-		sr->irq = irq->start;
-
-	srclklength = sr_calculate_clk_length(sr);
-
-	sr->proto_sr_config = (srclklength << SRCONFIG_SRCLKLENGTH_SHIFT) |
-		SRCONFIG_SENENABLE;
-
-	if (pdata->ip_type == SR_TYPE_V1) {
-		senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
-		senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
-		sr->proto_sr_config |= SRCONFIG_DELAYCTRL;
-		sr->errconfig_offs = ERRCONFIG_V1;
-		sr->errconfig_mask = ERRCONFIG_STATUS_V1_MASK;
-		sr->vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
-		sr->vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
-	} else if (pdata->ip_type == SR_TYPE_V2) {
-		senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
-		senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
-		sr->errconfig_offs = ERRCONFIG_V2;
-		sr->errconfig_mask = ERRCONFIG_VPBOUNDINTST_V2;
-		sr->vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
-		sr->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->proto_sr_config |= ((pdata->senn_mod << senn_shift) |
-				(pdata->senp_mod << senp_shift));
-
-	dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
-	if (!sr_dbg_dir) {
-		sr_dbg_dir = debugfs_create_dir("smartreflex", NULL);
-		if (!sr_dbg_dir) {
-			ret = PTR_ERR(sr_dbg_dir);
-			pr_err("%s:sr debugfs dir creation failed(%d)\n",
-				__func__, ret);
-			goto err_iounmap;
-		}
-	}
-
-	sr->name = kasprintf(GFP_KERNEL, "sr_%s", pdata->name);
-	if (!sr->name) {
-		dev_err(&pdev->dev, "%s: Unable to alloc debugfs name\n",
-			__func__);
-		ret = -ENOMEM;
-		goto err_iounmap;
-	}
-	sr->dbg_dir = debugfs_create_dir(sr->name, sr_dbg_dir);
-	if (IS_ERR(sr->dbg_dir)) {
-		dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
-			__func__);
-		ret = PTR_ERR(sr->dbg_dir);
-		goto err_iounmap;
-	}
-
-	(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR,
-			sr->dbg_dir, (void *)sr, &pm_sr_fops);
-	(void) debugfs_create_x32("errweight", S_IRUGO, sr->dbg_dir,
-			&pdata->err_weight);
-	(void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr->dbg_dir,
-			&pdata->err_maxlimit);
-
-	nvalue_dir = debugfs_create_dir("nvalue", sr->dbg_dir);
-	if (IS_ERR(nvalue_dir)) {
-		dev_err(&pdev->dev, "%s: Unable to create debugfs directory for n-values\n", __func__);
-		ret = PTR_ERR(nvalue_dir);
-		goto err_debugfs;
-	}
-
-	if (pdata->data_count == 0 || !pdata->data_table) {
-		dev_warn(&pdev->dev, "%s: no SR data table\n", __func__);
-		ret = -ENODATA;
-		goto err_debugfs;
-	}
-
-	for (i = 0; i < pdata->data_count; i++) {
-		char name[NVALUE_NAME_LEN + 1];
-
-		/* XXX Also needs to include errminlimit! */
-		snprintf(name, sizeof(name), "volt_%lu",
-			 sr->data_table[i].volt_nominal);
-		(void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
-				&(sr->data_table[i].nvalue));
-	}
-
-	return ret;
-
-err_debugfs:
-	debugfs_remove_recursive(sr->dbg_dir);
-err_iounmap:
-	iounmap(sr->base);
-err_release_region:
-	release_mem_region(mem->start, resource_size(mem));
-err_free_devinfo:
-	kfree(sr);
-
-	return ret;
-}
-
-static int __devexit omap_sr_remove(struct platform_device *pdev)
-{
-	struct smartreflex_platform_data *pdata = pdev->dev.platform_data;
-	struct smartreflex *sr;
-	struct resource *mem;
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
-		return -EINVAL;
-	}
-
-	sr = pdata->sr;
-	if (IS_ERR(sr)) {
-		dev_warn(&pdev->dev, "%s: smartreflex struct not found\n",
-			__func__);
-		return -EINVAL;
-	}
-
-	if (sr->autocomp_active)
-		sr_stop_vddautocomp(sr);
-	if (sr->dbg_dir)
-		debugfs_remove_recursive(sr->dbg_dir);
-
-	iounmap(sr->base);
-	kfree(sr);
-	pdata->sr = NULL;
-	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_sr_remove,
-	.driver		= {
-		.name	= "smartreflex",
-	},
-};
-
-static int __init sr_init(void)
-{
-	int ret = 0;
-
-	ret = platform_driver_probe(&smartreflex_driver, omap_sr_probe);
-	if (ret) {
-		pr_err("%s: platform driver register failed for SR\n",
-			__func__);
-		return ret;
-	}
-
-	return 0;
-}
-
-static void __exit sr_exit(void)
-{
-	platform_driver_unregister(&smartreflex_driver);
-}
-late_initcall(sr_init);
-module_exit(sr_exit);
-
-MODULE_DESCRIPTION("SmartReflex device driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRIVER_NAME);
-MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 30b7179..3395a48 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -17,13 +17,16 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef __ASM_ARM_OMAP_SMARTREFLEX_H
-#define __ASM_ARM_OMAP_SMARTREFLEX_H
+#ifndef __DRIVERS_POWER_AVS_SMARTREFLEX_H
+#define __DRIVERS_POWER_AVS_SMARTREFLEX_H
 
-#include <linux/platform_device.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 
-#include "voltage.h"
+#include <plat/smartreflex.h>
+#include <plat/voltage.h>
+
+#include "smartreflex.h"
 
 /*
  * Different Smartreflex IPs version. The v1 is the 65nm version used in
@@ -33,6 +36,18 @@
 #define SR_TYPE_V1	1
 #define SR_TYPE_V2	2
 
+/*
+ * 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.
+ */
+#define SR_CLASS1	0x1
+#define SR_CLASS2	0x2
+#define SR_CLASS3	0x3
+
+#define SR_DISABLE_TIMEOUT	200
+
 /* SMART REFLEX REG ADDRESS OFFSET */
 #define SRCONFIG		0x00
 #define SRSTATUS		0x04
@@ -120,50 +135,28 @@
 #define IRQENABLE_MCUBOUNDSINT		BIT(1)
 #define IRQENABLE_MCUDISABLEACKINT	BIT(0)
 
-/*
- * 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
-#define OMAP3430_SR_ERRMAXLIMIT		0x02
-
-/*
- * 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.
- */
-#define SR_CLASS1	0x1
-#define SR_CLASS2	0x2
-#define SR_CLASS3	0x3
-
 /* XXX kerneldoc documentation needed */
 struct smartreflex {
-	char				*name;
-	int				ip_type;
-	bool				autocomp_active;
-	u32				err_minlimit;
-	u32				errconfig_mask;
-	u32				vpboundint_en;
-	u32				vpboundint_st;
-	u32				proto_sr_config;
-	unsigned int			irq;
-	void __iomem			*base;
-	struct platform_device		*pdev;
-	struct list_head		node;
+	char			*name;
+	int			ip_type;
+	bool			autocomp_active;
+	u32			err_minlimit;
+	u32			errconfig_mask;
+	u32			vpboundint_en;
+	u32			vpboundint_st;
+	u32			proto_sr_config;
+	void __iomem		*base;
+	struct platform_device	*pdev;
+	struct list_head	node;
 	struct omap_sr_data_table	*data_table;
 	struct smartreflex_class_data	*sr_class;
-	struct voltagedomain		*voltdm;
-	struct dentry			*dbg_dir;
-	u8				errconfig_offs;
+	struct voltagedomain	*voltdm;
+	struct dentry		*dbg_dir;
+	u8			errconfig_offs;
+	unsigned int		irq;
+	irqreturn_t		(*isr)(int irq, void *data);
+	void			(*disable)(struct smartreflex *sr);
+	int			(*configure_minmax)(struct smartreflex *sr);
 };
 
 /**
@@ -180,72 +173,50 @@ struct smartreflex_class_data {
 	int (*enable)(struct smartreflex *sr);
 	int (*disable)(struct smartreflex *sr, int is_volt_reset);
 	int (*configure)(struct smartreflex *sr);
-	irqreturn_t (*isr) (int irq, void *data);
 	u8 class_type;
 };
 
-/* XXX Kerneldoc documentation needed */
-struct omap_sr_dev_attr {
-	char *sensor_voltdm_name; /* XXX should be const */
-	u32 errweight;
-	u32 errmaxlimit;
-	u32 accumdata;
-	u32 senn_avgweight;
-	u32 senp_avgweight;
-	u8 pdev_inst_id;
-};
-
-/**
- * struct omap_sr_data_table	- Smartreflex n-target value info
- *
- * @efuse_offs:	The offset of the efuse where n-target values are stored.
- * @nvalue:	The n-target value.
- * @errminlimit: The value of the ERRMINLIMIT bitfield for this n-target
- * @volt_nominal: microvolts DC that the VDD is initially programmed to
- */
-struct omap_sr_data_table {
-	u32 efuse_offs;
-	u32 nvalue;
-	u32 errminlimit;
-	unsigned long volt_nominal;
-};
-
-/**
- * struct smartreflex_platform_data - Smartreflex platform data.
- *
- * @name: XXX
- * @ip_type:		Smartreflex IP type.
- * @err_weight: XXX
- * @err_maxlimit: XXX
- * @accum_data: XXX
- * @senp_mod:		SENPENABLE value for the sr
- * @senn_mod:		SENNENABLE value for sr
- * @senn_avgweight: XXX
- * @senp_avgweight: XXX
- * @data_count:	Number of rows in @data_table
- * @enable_on_init:	whether this sr module needs to enabled at
- *			boot up or not.
- * @data_table:	table containing SR parameters for each valid voltage
- * @voltdm:		Pointer to the voltage domain associated with the SR
- * @sr: struct smartreflex:
- *			associated with this SR device (allocated in *_probe())
- */
-struct smartreflex_platform_data {
-	const char			*name;
-	int				ip_type;
-	u32				err_weight;
-	u32				err_maxlimit;
-	u32				accum_data;
-	u32				senp_mod;
-	u32				senn_mod;
-	u32				senn_avgweight;
-	u32				senp_avgweight;
-	int				data_count;
-	bool				enable_on_init;
-	struct omap_sr_data_table	*data_table;
-	struct voltagedomain		*voltdm;
-	struct smartreflex		*sr;
-};
+/* Internal functions */
+static inline u32 sr_read_reg(struct smartreflex *sr, unsigned offset)
+{
+	return __raw_readl(sr->base + offset);
+}
+
+static inline void sr_write_reg(struct smartreflex *sr, unsigned offset,
+			 u32 value)
+{
+	__raw_writel(value, (sr->base + offset));
+}
+
+static inline void sr_modify_reg(struct smartreflex *sr, unsigned offset,
+			  u32 mask, u32 value)
+{
+	u32 reg_val;
+
+	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. This mean this API doesn't rewrite values in these bits
+	 * if they are currently set, but does allow the caller to write
+	 * those bits.
+	 */
+	if (offset == sr->errconfig_offs)
+		reg_val &= ~sr->errconfig_mask;
+
+	reg_val |= value;
+
+	__raw_writel(reg_val, (sr->base + offset));
+}
+
+extern int sr_calculate_clk_length(struct smartreflex *sr);
+extern int __devexit sr_remove(struct platform_device *pdev);
+extern int __init sr_common_probe(struct platform_device *pdev,
+				  struct smartreflex *sr);
 
 /* Smartreflex driver hooks to be called from Smartreflex class driver */
 int sr_enable(struct smartreflex *sr, unsigned long volt);
@@ -257,3 +228,4 @@ int sr_configure_minmax(struct smartreflex *sr);
 int sr_register_class(struct platform_device *pdev,
 		      struct smartreflex_class_data *class_data);
 #endif
+
diff --git a/arch/arm/mach-omap2/smartreflex_v1.c b/arch/arm/mach-omap2/smartreflex_v1.c
new file mode 100644
index 0000000..5629632
--- /dev/null
+++ b/arch/arm/mach-omap2/smartreflex_v1.c
@@ -0,0 +1,183 @@
+/*
+ * Device driver for the SmartReflex IP block v1
+ *
+ * Author: Thara Gopinath	<thara@xxxxxx>
+ *
+ * Copyright (C) 2007,2010 Texas Instruments, Inc.
+ * Lesly A M <x0080970@xxxxxx>
+ * Thara Gopinath <thara@xxxxxx>
+ *
+ * Copyright (C) 2008,2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * 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/module.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <plat/common.h>
+#include <plat/smartreflex.h>
+
+#include "smartreflex.h"
+
+static irqreturn_t _interrupt(int irq, void *data)
+{
+	struct smartreflex *sr = (struct smartreflex *)data;
+	u32 status = 0;
+
+	/* Read the status bits */
+	status = sr_read_reg(sr, ERRCONFIG_V1);
+
+	/* Clear them by writing back */
+	sr_write_reg(sr, ERRCONFIG_V1, status);
+
+	/*
+	 * XXX If the class driver needs to be notified here, it should
+	 * use an atomic notifier
+	 */
+
+	return IRQ_HANDLED;
+}
+
+static void _disable(struct smartreflex *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 int _configure_minmax(struct smartreflex *sr)
+{
+	/*
+	 * Enabling the interrupts if MINMAXAVG module is used.
+	 * TODO: check if all the interrupts are mandatory
+	 */
+	sr_modify_reg(sr, ERRCONFIG_V1,
+		(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
+		ERRCONFIG_MCUBOUNDINTEN),
+		(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST |
+		 ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST |
+		 ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST));
+
+	return 0;
+}
+
+static int __init sr_probe(struct platform_device *pdev)
+{
+	struct smartreflex *sr = kzalloc(sizeof(struct smartreflex), GFP_KERNEL);
+	struct smartreflex_platform_data *pdata = pdev->dev.platform_data;
+	u32 srclklength;
+	u8 senn_shift, senp_shift;
+	int ret = 0;
+
+	if (!sr) {
+		dev_err(&pdev->dev, "%s: unable to allocate sr\n", __func__);
+		return -ENOMEM;
+	}
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+		ret = -EINVAL;
+		goto err_free_devinfo;
+	}
+
+	srclklength = sr_calculate_clk_length(sr);
+
+	sr->proto_sr_config = (srclklength << SRCONFIG_SRCLKLENGTH_SHIFT) |
+		SRCONFIG_SENENABLE;
+
+	senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
+	senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
+	sr->proto_sr_config |= SRCONFIG_DELAYCTRL;
+	sr->errconfig_offs = ERRCONFIG_V1;
+	sr->errconfig_mask = ERRCONFIG_STATUS_V1_MASK;
+	sr->vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
+	sr->vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
+
+	sr->proto_sr_config |= ((pdata->senn_mod << senn_shift) |
+				(pdata->senp_mod << senp_shift));
+
+	sr->isr = _interrupt;
+	sr->disable = _disable;
+	sr->configure_minmax = _configure_minmax;
+
+	ret = sr_common_probe(pdev, sr);
+
+	return ret;
+
+err_free_devinfo:
+	kfree(sr);
+
+	return ret;
+}
+
+static struct platform_driver smartreflex_driver = {
+	.remove		= sr_remove,
+	.driver		= {
+		.name	= "smartreflex-v1",
+	},
+};
+
+/* SmartReflex IP v1 is the 65nm version used in OMAP3430 */
+static int __init sr_init(void)
+{
+	int ret = 0;
+
+	if (!(cpu_is_omap34xx() && !(cpu_is_omap3630() || cpu_is_omap44xx())))
+		return -ENODEV;
+
+	ret = platform_driver_probe(&smartreflex_driver, sr_probe);
+	if (ret) {
+		pr_err("%s: platform driver register failed for SR\n",
+			__func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __exit sr_exit(void)
+{
+	platform_driver_unregister(&smartreflex_driver);
+}
+late_initcall(sr_init);
+module_exit(sr_exit);
+
+MODULE_DESCRIPTION("SmartReflex v1 device driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/arch/arm/mach-omap2/smartreflex_v2.c b/arch/arm/mach-omap2/smartreflex_v2.c
new file mode 100644
index 0000000..5fbbc8e
--- /dev/null
+++ b/arch/arm/mach-omap2/smartreflex_v2.c
@@ -0,0 +1,186 @@
+/*
+ * Device driver for the SmartReflex IP block v2
+ *
+ * Author: Thara Gopinath	<thara@xxxxxx>
+ *
+ * Copyright (C) 2007,2010 Texas Instruments, Inc.
+ * Lesly A M <x0080970@xxxxxx>
+ * Thara Gopinath <thara@xxxxxx>
+ *
+ * Copyright (C) 2008,2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * 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/module.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <plat/common.h>
+#include <plat/smartreflex.h>
+
+#include "smartreflex.h"
+
+static irqreturn_t _interrupt(int irq, void *data)
+{
+	struct smartreflex *sr = (struct smartreflex *)data;
+	u32 status = 0;
+
+	/* Read the status bits */
+	sr_read_reg(sr, IRQSTATUS);
+
+	/* Clear them by writing back */
+	sr_write_reg(sr, IRQSTATUS, status);
+
+	/*
+	 * XXX If the class driver needs to be notified here, it should
+	 * use an atomic notifier
+	 */
+
+	return IRQ_HANDLED;
+}
+
+static void _disable(struct smartreflex *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);
+}
+
+static int _configure_minmax(struct smartreflex *sr)
+{
+	/*
+	 * Enabling the interrupts if MINMAXAVG module is used.
+	 * TODO: check if all the interrupts are mandatory
+	 */
+	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;
+}
+
+static int __init sr_probe(struct platform_device *pdev)
+{
+	struct smartreflex *sr = kzalloc(sizeof(struct smartreflex), GFP_KERNEL);
+	struct smartreflex_platform_data *pdata = pdev->dev.platform_data;
+	u32 srclklength;
+	u8 senn_shift, senp_shift;
+	int ret = 0;
+
+	if (!sr) {
+		dev_err(&pdev->dev, "%s: unable to allocate sr\n", __func__);
+		return -ENOMEM;
+	}
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+		ret = -EINVAL;
+		goto err_free_devinfo;
+	}
+
+	srclklength = sr_calculate_clk_length(sr);
+
+	sr->proto_sr_config = (srclklength << SRCONFIG_SRCLKLENGTH_SHIFT) |
+		SRCONFIG_SENENABLE;
+
+	senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
+	senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
+	sr->errconfig_offs = ERRCONFIG_V2;
+	sr->errconfig_mask = ERRCONFIG_VPBOUNDINTST_V2;
+	sr->vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
+	sr->vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
+
+	sr->proto_sr_config |= ((pdata->senn_mod << senn_shift) |
+				(pdata->senp_mod << senp_shift));
+
+	sr->isr = _interrupt;
+	sr->disable = _disable;
+	sr->configure_minmax = _configure_minmax;
+
+	ret = sr_common_probe(pdev, sr);
+
+	return ret;
+
+err_free_devinfo:
+	kfree(sr);
+
+	return ret;
+}
+
+static struct platform_driver smartreflex_driver = {
+	.remove		= sr_remove,
+	.driver		= {
+		.name	= "smartreflex-v2",
+	},
+};
+
+/*
+ * SmartReflex IP v2 is the update from v1 for the 45nm version of the IP
+ * used in OMAP3630 and OMAP4430
+ */
+static int __init sr_init(void)
+{
+	int ret = 0;
+
+	if (!(cpu_is_omap3630() || cpu_is_omap44xx()))
+		return -ENODEV;
+
+	ret = platform_driver_probe(&smartreflex_driver, sr_probe);
+	if (ret) {
+		pr_err("%s: platform driver register failed for SR\n",
+			__func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __exit sr_exit(void)
+{
+	platform_driver_unregister(&smartreflex_driver);
+}
+late_initcall(sr_init);
+module_exit(sr_exit);
+
+MODULE_DESCRIPTION("SmartReflex v2 device driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index 2fefbb5..b177aab 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -24,8 +24,8 @@
 #include <linux/io.h>
 
 #include <plat/omap_device.h>
+#include <plat/smartreflex.h>
 
-#include "smartreflex.h"
 #include "voltage.h"
 #include "control.h"
 #include "pm.h"
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index aa59f42..1451088 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -41,37 +41,6 @@ config OMAP_DEBUG_LEDS
 	depends on OMAP_DEBUG_DEVICES
 	default y if LEDS_CLASS
 
-config OMAP_SMARTREFLEX
-	bool "SmartReflex support"
-	depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM
-	help
-	  Say Y if you want to enable SmartReflex.
-
-	  SmartReflex can perform continuous dynamic voltage
-	  scaling around the nominal operating point voltage
-	  according to silicon characteristics and operating
-	  conditions. Enabling SmartReflex reduces power
-	  consumption.
-
-	  Please note, that by default SmartReflex is only
-	  initialized. To enable the automatic voltage
-	  compensation for vdd mpu  and vdd core from user space,
-	  user must write 1 to
-		/debug/voltage/vdd_<X>/smartreflex/autocomp,
-	  where X is mpu or core for OMAP3.
-	  Optionally autocompensation can be enabled in the kernel
-	  by default during system init via the enable_on_init flag
-	  which an be passed as platform data to the smartreflex driver.
-
-config OMAP_SMARTREFLEX_CLASS3
-	bool "Class 3 mode of Smartreflex Implementation"
-	depends on OMAP_SMARTREFLEX && TWL4030_CORE
-	help
-	  Say Y to enable Class 3 implementation of Smartreflex
-
-	  Class 3 implementation of Smartreflex employs continuous hardware
-	  voltage calibration.
-
 config OMAP_RESET_CLOCKS
 	bool "Reset unused clocks during boot"
 	depends on ARCH_OMAP
diff --git a/arch/arm/plat-omap/include/plat/smartreflex.h b/arch/arm/plat-omap/include/plat/smartreflex.h
new file mode 100644
index 0000000..3ebadb7
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/smartreflex.h
@@ -0,0 +1,106 @@
+/*
+ * OMAP Smartreflex Defines and Routines
+ *
+ * Author: Thara Gopinath	<thara@xxxxxx>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@xxxxxx>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <x0080970@xxxxxx>
+ *
+ * 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_PLATOMAP_SMARTREFLEX_H
+#define __ASM_ARM_PLATOMAP_SMARTREFLEX_H
+
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+
+#include "voltage.h"
+
+/*
+ * 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
+#define OMAP3430_SR_ERRMAXLIMIT		0x02
+
+/**
+ * struct omap_sr_data_table	- Smartreflex n-target value info
+ *
+ * @efuse_offs:	The offset of the efuse where n-target values are stored.
+ * @nvalue:	The n-target value.
+ * @errminlimit: The value of the ERRMINLIMIT bitfield for this n-target
+ * @volt_nominal: microvolts DC that the VDD is initially programmed to
+ */
+struct omap_sr_data_table {
+	u32 efuse_offs;
+	u32 nvalue;
+	u32 errminlimit;
+	unsigned long volt_nominal;
+};
+
+/* XXX Kerneldoc documentation needed */
+struct omap_sr_dev_attr {
+	char *sensor_voltdm_name; /* XXX should be const */
+	u32 errweight;
+	u32 errmaxlimit;
+	u32 accumdata;
+	u32 senn_avgweight;
+	u32 senp_avgweight;
+	u8 pdev_inst_id;
+};
+
+/**
+ * struct smartreflex_platform_data - Smartreflex platform data.
+ *
+ * @name: XXX
+ * @ip_type:		Smartreflex IP type.
+ * @err_weight: XXX
+ * @err_maxlimit: XXX
+ * @accum_data: XXX
+ * @senp_mod:		SENPENABLE value for the sr
+ * @senn_mod:		SENNENABLE value for sr
+ * @senn_avgweight: XXX
+ * @senp_avgweight: XXX
+ * @data_count:	Number of rows in @data_table
+ * @enable_on_init:	whether this sr module needs to enabled at
+ *			boot up or not.
+ * @data_table:	table containing SR parameters for each valid voltage
+ * @voltdm:		Pointer to the voltage domain associated with the SR
+ * @sr: struct smartreflex:
+ *			associated with this SR device (allocated in *_probe())
+ */
+struct smartreflex_platform_data {
+	const char			*name;
+	int				ip_type;
+	u32				err_weight;
+	u32				err_maxlimit;
+	u32				accum_data;
+	u32				senp_mod;
+	u32				senn_mod;
+	u32				senn_avgweight;
+	u32				senp_avgweight;
+	int				data_count;
+	bool				enable_on_init;
+	struct omap_sr_data_table	*data_table;
+	struct voltagedomain		*voltdm;
+	struct smartreflex		*sr;
+};
+
+#endif
-- 
1.7.5.4

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


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux