* [RFC/PATCH 00/26] PM: Create the AVS class of drivers
@ 2011-11-22 15:05 jean.pihet
2011-11-22 15:05 ` [PATCH 01/26] OMAP2+: smartreflex: use sane default values jean.pihet
` (27 more replies)
0 siblings, 28 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
The following patches are in RFC state; the code is still WIP and has been
compile tested only. Feedback on the code organization is welcome!
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.
To that end, create the AVS framework in drivers/power/avs and
move the OMAP SmartReflex code to the new directory.
In preparation to the move of the OMAP code the following changes have been
made:
- split into common code (not semiconductor specific), a v1 IP driver,
a v2 IP driver and a 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,
- removal of unused code in SmartReflex: notification machanism, PMIC
specific code.
The following features are supported:
- read the SmartReflex values from the e-fuses and allow the board file code
to override the values,
- platform integration data for SmartReflex is passed to the driver using
pdata.
ToDo:
- integration with the platform code,
- kerneldoc should be added to the new structs and functions,
- use correct device attribute data for OMAP4,
- test on board (OMAP3/4),
- integrate latest SmartReflex fixes [1]
The code is based on Paul's original version of the SmartReflex driver conversion
[2].
Compile tested only using omap2plus_defconfig with the CONFIG_POWER_AVS* options set.
Based on latest master branch of the l-o git tree (3.2.0-rc2) [3].
[1] http://marc.info/?l=linux-omap&m=132134699423547&w=2
[2] smartreflex_cleanup_3.1 branch of git://git.pwsan.com/linux-2.6
[3] git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
Jean Pihet (14):
OMAP3/4: SmartReflex: class drivers should use struct omap_sr *
OMAP3/4: SmartReflex: API should use struct omap_sr *, not struct
voltagedomain *
OMAP: SmartReflex: drop _sr_lookup()
OMAP3+: Pass SmartReflex instance-specific data via hwmod dev_attr
OMAP3+: hwmod: get rid of vdd_name field
OMAP2+: rename struct omap_sr_class_data to smartreflex_class_data
OMAP2+: Use the names from the SmartReflex data instead of voltage
domains.
OMAP2+: SmartReflex: make driver generic
OMAP2+: SmartReflex: get rid of superfluous data that is duplicated
between platform_data and the struct omap_sr
OMAP2+: SmartReflex: remove OMAP specific code
OMAP2+: SmartReflex: conversion into generic driver
OMAP3+: voltage: export functions to plat/voltage.h
OMAP: PM: convert the SmartReflex code into the AVS driver framework
PM: Create the AVS class of drivers
Paul Walmsley (12):
OMAP2+: smartreflex: use sane default values
OMAP: hwmod/SmartReflex: remove IP block instance-specific data from
the driver code
OMAP: SmartReflex: make pdata distinct from other data
OMAP: SmartReflex: Use 'sr' for struct smartreflex
OMAP3+: SmartReflex: remove unused PMIC code
OMAP: SmartReflex: remove some SoC-specific implementation details
from driver
OMAP: SmartReflex driver interface: allow core to override eFuse data
OMAP2+: SmartReflex: rename nvalue table
OMAP2+: SmartReflex: cosmetic changes
OMAP3+: Add SmartReflex clocks
OMAP2+: Use the TRM formula to calculate the SmartReflex clock rate
OMAP2+: SmartReflex: Remove the notifier handler
arch/arm/mach-omap2/Makefile | 4 +-
arch/arm/mach-omap2/clock3xxx_data.c | 6 +
arch/arm/mach-omap2/clock44xx_data.c | 3 +
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 37 +-
arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 40 +-
arch/arm/mach-omap2/pm.h | 2 +-
arch/arm/mach-omap2/smartreflex-class3.c | 59 --
arch/arm/mach-omap2/smartreflex.c | 1056 -------------------------
arch/arm/mach-omap2/smartreflex.h | 246 ------
arch/arm/mach-omap2/sr_device.c | 129 ++--
arch/arm/mach-omap2/voltage.h | 3 +-
arch/arm/mach-omap2/vp.h | 2 -
arch/arm/plat-omap/Kconfig | 31 -
arch/arm/plat-omap/include/plat/omap_hwmod.h | 3 -
arch/arm/plat-omap/include/plat/smartreflex.h | 106 +++
arch/arm/plat-omap/include/plat/voltage.h | 3 +
drivers/power/Kconfig | 2 +
drivers/power/Makefile | 2 +
drivers/power/avs/Kconfig | 56 ++
drivers/power/avs/Makefile | 4 +
drivers/power/avs/smartreflex-class3.c | 64 ++
drivers/power/avs/smartreflex-common.c | 543 +++++++++++++
drivers/power/avs/smartreflex.h | 231 ++++++
drivers/power/avs/smartreflex_v1.c | 183 +++++
drivers/power/avs/smartreflex_v2.c | 186 +++++
25 files changed, 1544 insertions(+), 1457 deletions(-)
delete mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
delete mode 100644 arch/arm/mach-omap2/smartreflex.c
delete mode 100644 arch/arm/mach-omap2/smartreflex.h
create mode 100644 arch/arm/plat-omap/include/plat/smartreflex.h
create mode 100644 drivers/power/avs/Kconfig
create mode 100644 drivers/power/avs/Makefile
create mode 100644 drivers/power/avs/smartreflex-class3.c
create mode 100644 drivers/power/avs/smartreflex-common.c
create mode 100644 drivers/power/avs/smartreflex.h
create mode 100644 drivers/power/avs/smartreflex_v1.c
create mode 100644 drivers/power/avs/smartreflex_v2.c
--
1.7.5.4
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 01/26] OMAP2+: smartreflex: use sane default values
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 02/26] OMAP3/4: SmartReflex: class drivers should use struct omap_sr * jean.pihet
` (26 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Paul Walmsley <paul@pwsan.com>
Use sane values for the smartreflex data from the e-fuses.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/sr_device.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index 9f43fcc..221407a 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -38,11 +38,18 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
struct omap_sr_nvalue_table *nvalue_table;
int i, count = 0;
+ sr_data->nvalue_count = 0;
+ sr_data->nvalue_table = NULL;
+
while (volt_data[count].volt_nominal)
count++;
nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count,
GFP_KERNEL);
+ if (!nvalue_table) {
+ pr_err("OMAP: SmartReflex: cannot allocate memory for n-value table\n");
+ return;
+ }
for (i = 0; i < count; i++) {
u32 v;
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 02/26] OMAP3/4: SmartReflex: class drivers should use struct omap_sr *
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
2011-11-22 15:05 ` [PATCH 01/26] OMAP2+: smartreflex: use sane default values jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 03/26] OMAP3/4: SmartReflex: API should use struct omap_sr *, not struct voltagedomain * jean.pihet
` (25 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw
Cc: Jean Pihet, Thara Gopinath, Nishanth Menon
From: Jean Pihet <j-pihet@ti.com>
Convert SmartReflex "class" functions to take a struct omap_sr *, rather than
a struct voltagedomain *. SmartReflex code should be driver code and not
tightly coupled to OMAP subarchitecture-specific structures.
Based on Paul's original code for the SmartReflex driver conversion.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Nishanth Menon <nm@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/smartreflex-class3.c | 22 +++++++++---------
arch/arm/mach-omap2/smartreflex.c | 37 +++++------------------------
arch/arm/mach-omap2/smartreflex.h | 32 ++++++++++++++++++++++---
3 files changed, 46 insertions(+), 45 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index 53d9d0a..97bdb0b 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -13,33 +13,33 @@
#include "smartreflex.h"
-static int sr_class3_enable(struct voltagedomain *voltdm)
+static int sr_class3_enable(struct omap_sr *sr)
{
- unsigned long volt = voltdm_get_voltage(voltdm);
+ unsigned long volt = voltdm_get_voltage(sr->voltdm);
if (!volt) {
pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
- __func__, voltdm->name);
+ __func__, sr->voltdm->name);
return -ENODATA;
}
- omap_vp_enable(voltdm);
- return sr_enable(voltdm, volt);
+ omap_vp_enable(sr->voltdm);
+ return sr_enable(sr->voltdm, volt);
}
-static int sr_class3_disable(struct voltagedomain *voltdm, int is_volt_reset)
+static int sr_class3_disable(struct omap_sr *sr, int is_volt_reset)
{
- omap_vp_disable(voltdm);
- sr_disable(voltdm);
+ omap_vp_disable(sr->voltdm);
+ sr_disable(sr->voltdm);
if (is_volt_reset)
- voltdm_reset(voltdm);
+ voltdm_reset(sr->voltdm);
return 0;
}
-static int sr_class3_configure(struct voltagedomain *voltdm)
+static int sr_class3_configure(struct omap_sr *sr)
{
- return sr_configure_errgen(voltdm);
+ return sr_configure_errgen(sr->voltdm);
}
/* SR class3 structure */
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index cf246b3..01ff78a 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -35,29 +35,6 @@
#define NVALUE_NAME_LEN 40
#define SR_DISABLE_TIMEOUT 200
-struct omap_sr {
- int srid;
- int ip_type;
- int nvalue_count;
- bool autocomp_active;
- u32 clk_length;
- u32 err_weight;
- u32 err_minlimit;
- u32 err_maxlimit;
- u32 accum_data;
- u32 senn_avgweight;
- u32 senp_avgweight;
- u32 senp_mod;
- u32 senn_mod;
- unsigned int irq;
- void __iomem *base;
- struct platform_device *pdev;
- struct list_head node;
- struct omap_sr_nvalue_table *nvalue_table;
- struct voltagedomain *voltdm;
- struct dentry *dbg_dir;
-};
-
/* sr_list contains all the instances of smartreflex module */
static LIST_HEAD(sr_list);
@@ -146,7 +123,7 @@ static irqreturn_t sr_interrupt(int irq, void *data)
}
if (sr_class->notify)
- sr_class->notify(sr_info->voltdm, status);
+ sr_class->notify(sr_info, status);
return IRQ_HANDLED;
}
@@ -223,7 +200,7 @@ static void sr_start_vddautocomp(struct omap_sr *sr)
return;
}
- if (!sr_class->enable(sr->voltdm))
+ if (!sr_class->enable(sr))
sr->autocomp_active = true;
}
@@ -237,7 +214,7 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)
}
if (sr->autocomp_active) {
- sr_class->disable(sr->voltdm, 1);
+ sr_class->disable(sr, 1);
sr->autocomp_active = false;
}
}
@@ -580,7 +557,7 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
return 0;
/* Configure SR */
- ret = sr_class->configure(voltdm);
+ ret = sr_class->configure(sr);
if (ret)
return ret;
@@ -691,7 +668,7 @@ void omap_sr_enable(struct voltagedomain *voltdm)
return;
}
- sr_class->enable(voltdm);
+ sr_class->enable(sr);
}
/**
@@ -724,7 +701,7 @@ void omap_sr_disable(struct voltagedomain *voltdm)
return;
}
- sr_class->disable(voltdm, 0);
+ sr_class->disable(sr, 0);
}
/**
@@ -757,7 +734,7 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
return;
}
- sr_class->disable(voltdm, 1);
+ sr_class->disable(sr, 1);
}
/**
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 5f35b9e..f435972 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -142,6 +142,30 @@
#define OMAP3430_SR_ERRWEIGHT 0x04
#define OMAP3430_SR_ERRMAXLIMIT 0x02
+/* XXX kerneldoc documentation needed */
+struct omap_sr {
+ int srid;
+ int ip_type;
+ int nvalue_count;
+ bool autocomp_active;
+ u32 clk_length;
+ u32 err_weight;
+ u32 err_minlimit;
+ u32 err_maxlimit;
+ u32 accum_data;
+ u32 senn_avgweight;
+ u32 senp_avgweight;
+ u32 senp_mod;
+ u32 senn_mod;
+ unsigned int irq;
+ void __iomem *base;
+ struct platform_device *pdev;
+ struct list_head node;
+ struct omap_sr_nvalue_table *nvalue_table;
+ struct voltagedomain *voltdm;
+ struct dentry *dbg_dir;
+};
+
/**
* struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
* pmic specific info to smartreflex driver
@@ -177,10 +201,10 @@ struct omap_sr_pmic_data {
* based decisions.
*/
struct omap_sr_class_data {
- 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);
+ int (*enable)(struct omap_sr *sr);
+ int (*disable)(struct omap_sr *sr, int is_volt_reset);
+ int (*configure)(struct omap_sr *sr);
+ int (*notify)(struct omap_sr *sr, u32 status);
u8 notify_flags;
u8 class_type;
};
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 03/26] OMAP3/4: SmartReflex: API should use struct omap_sr *, not struct voltagedomain *
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
2011-11-22 15:05 ` [PATCH 01/26] OMAP2+: smartreflex: use sane default values jean.pihet
2011-11-22 15:05 ` [PATCH 02/26] OMAP3/4: SmartReflex: class drivers should use struct omap_sr * jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 04/26] OMAP: SmartReflex: drop _sr_lookup() jean.pihet
` (24 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw
Cc: Jean Pihet, Thara Gopinath, Nishanth Menon
From: Jean Pihet <j-pihet@ti.com>
The SmartReflex API should take pointers to a SmartReflex instance-specific
structure record, not pointers to a OMAP subarchitecture-specific struct
voltagedomain *. The SmartReflex drivers should not be tightly coupled
to the SoC subarchitecture; these IP blocks could appear on different
subarchitectures.
Based on Paul's original code for the SmartReflex driver conversion.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Nishanth Menon <nm@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/smartreflex-class3.c | 6 +-
arch/arm/mach-omap2/smartreflex.c | 68 ++++++++----------------------
arch/arm/mach-omap2/smartreflex.h | 20 ++++----
3 files changed, 31 insertions(+), 63 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index 97bdb0b..0205f17 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -24,13 +24,13 @@ static int sr_class3_enable(struct omap_sr *sr)
}
omap_vp_enable(sr->voltdm);
- return sr_enable(sr->voltdm, volt);
+ return sr_enable(sr, volt);
}
static int sr_class3_disable(struct omap_sr *sr, int is_volt_reset)
{
omap_vp_disable(sr->voltdm);
- sr_disable(sr->voltdm);
+ sr_disable(sr);
if (is_volt_reset)
voltdm_reset(sr->voltdm);
@@ -39,7 +39,7 @@ static int sr_class3_disable(struct omap_sr *sr, int is_volt_reset)
static int sr_class3_configure(struct omap_sr *sr)
{
- return sr_configure_errgen(sr->voltdm);
+ return sr_configure_errgen(sr);
}
/* SR class3 structure */
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 01ff78a..55966bc 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -364,7 +364,7 @@ static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)
/**
* 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.
+ * @sr: struct omap_sr *
*
* This API is to be called from the smartreflex class driver to
* configure the error generator module inside the smartreflex module.
@@ -373,18 +373,14 @@ static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)
* 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)
+int sr_configure_errgen(struct omap_sr *sr)
{
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);
- if (IS_ERR(sr)) {
- pr_warning("%s: omap_sr struct for sr_%s not found\n",
- __func__, voltdm->name);
+ if (IS_ERR_OR_NULL(sr))
return -EINVAL;
- }
if (!sr->clk_length)
sr_set_clk_length(sr);
@@ -433,7 +429,7 @@ int sr_configure_errgen(struct voltagedomain *voltdm)
/**
* 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.
+ * @sr: struct omap_sr *
*
* This API is to be called from the smartreflex class driver to
* configure the minmaxavg module inside the smartreflex module.
@@ -442,18 +438,14 @@ int sr_configure_errgen(struct voltagedomain *voltdm)
* 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)
+int sr_configure_minmax(struct omap_sr *sr)
{
u32 sr_config, sr_avgwt;
u32 senp_en = 0, senn_en = 0;
u8 senp_shift, senn_shift;
- 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);
+ if (IS_ERR_OR_NULL(sr))
return -EINVAL;
- }
if (!sr->clk_length)
sr_set_clk_length(sr);
@@ -509,7 +501,7 @@ int sr_configure_minmax(struct voltagedomain *voltdm)
/**
* sr_enable() - Enables the smartreflex module.
- * @voltdm: VDD pointer to which the SR module to be configured belongs to.
+ * @sr: struct omap_sr *
* @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.
@@ -518,18 +510,14 @@ int sr_configure_minmax(struct voltagedomain *voltdm)
* 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)
+int sr_enable(struct omap_sr *sr, 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);
+ if (IS_ERR_OR_NULL(sr))
return -EINVAL;
- }
volt_data = omap_voltage_get_voltdata(sr->voltdm, volt);
@@ -575,15 +563,10 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
* This API is to be called from the smartreflex class driver to
* disable a smartreflex module.
*/
-void sr_disable(struct voltagedomain *voltdm)
+void sr_disable(struct omap_sr *sr)
{
- 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);
+ 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))
@@ -649,15 +632,10 @@ int sr_register_class(struct omap_sr_class_data *class_data)
* 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)
+void omap_sr_enable(struct omap_sr *sr)
{
- 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);
+ if (IS_ERR_OR_NULL(sr))
return;
- }
if (!sr->autocomp_active)
return;
@@ -682,15 +660,10 @@ void omap_sr_enable(struct voltagedomain *voltdm)
* the smartreflex class disable not to reset the VP voltage after
* disabling smartreflex.
*/
-void omap_sr_disable(struct voltagedomain *voltdm)
+void omap_sr_disable(struct omap_sr *sr)
{
- 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);
+ if (IS_ERR_OR_NULL(sr))
return;
- }
if (!sr->autocomp_active)
return;
@@ -707,7 +680,7 @@ void omap_sr_disable(struct voltagedomain *voltdm)
/**
* 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.
+ * @sr: struct omap_sr *
*
* This API is to be called from the kernel in order to disable
* a particular smartreflex module. This API will in turn call
@@ -715,15 +688,10 @@ void omap_sr_disable(struct voltagedomain *voltdm)
* the smartreflex class disable to reset the VP voltage after
* disabling smartreflex.
*/
-void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
+void omap_sr_disable_reset_volt(struct omap_sr *sr)
{
- 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);
+ if (IS_ERR_OR_NULL(sr))
return;
- }
if (!sr->autocomp_active)
return;
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index f435972..305776f 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -244,26 +244,26 @@ struct omap_sr_data {
};
/* Smartreflex module enable/disable interface */
-void omap_sr_enable(struct voltagedomain *voltdm);
-void omap_sr_disable(struct voltagedomain *voltdm);
-void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
+void omap_sr_enable(struct omap_sr *sr);
+void omap_sr_disable(struct omap_sr *sr);
+void omap_sr_disable_reset_volt(struct omap_sr *sr);
/* API to register the pmic specific data with the smartreflex driver. */
void omap_sr_register_pmic(struct omap_sr_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);
+int sr_enable(struct omap_sr *sr, unsigned long volt);
+void sr_disable(struct omap_sr *sr);
+int sr_configure_errgen(struct omap_sr *sr);
+int sr_configure_minmax(struct omap_sr *sr);
/* API to register the smartreflex class driver with the smartreflex driver */
int sr_register_class(struct omap_sr_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_enable(struct omap_sr *sr) {}
+static inline void omap_sr_disable(struct omap_sr *sr) {}
static inline void omap_sr_disable_reset_volt(
- struct voltagedomain *voltdm) {}
+ struct omap_sr *sr) {}
static inline void omap_sr_register_pmic(
struct omap_sr_pmic_data *pmic_data) {}
#endif
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 04/26] OMAP: SmartReflex: drop _sr_lookup()
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (2 preceding siblings ...)
2011-11-22 15:05 ` [PATCH 03/26] OMAP3/4: SmartReflex: API should use struct omap_sr *, not struct voltagedomain * jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 05/26] OMAP: hwmod/SmartReflex: remove IP block instance-specific data from the driver code jean.pihet
` (23 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw
Cc: Jean Pihet, Thara Gopinath, Nishanth Menon
From: Jean Pihet <j-pihet@ti.com>
Drop the _sr_lookup() function that returns a struct omap_sr from a
struct voltagedomain. Instead, retain a pointer to the struct omap_sr
* in the driver platform data. This removes another struct
voltagedomain * dependency in the SmartReflex driver code.
Based on Paul's original code for the SmartReflex driver conversion.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Nishanth Menon <nm@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 28 +++++++---------------------
arch/arm/mach-omap2/smartreflex.h | 2 ++
2 files changed, 9 insertions(+), 21 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 55966bc..c03eb4e 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -86,23 +86,6 @@ 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);
-}
-
static irqreturn_t sr_interrupt(int irq, void *data)
{
struct omap_sr *sr_info = (struct omap_sr *)data;
@@ -558,7 +541,7 @@ int sr_enable(struct omap_sr *sr, unsigned long volt)
/**
* sr_disable() - Disables the smartreflex module.
- * @voltdm: VDD pointer to which the SR module to be configured belongs to.
+ * @sr: struct omap_sr *
*
* This API is to be called from the smartreflex class driver to
* disable a smartreflex module.
@@ -625,7 +608,7 @@ int sr_register_class(struct omap_sr_class_data *class_data)
/**
* 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.
+ * @sr: struct omap_sr *
*
* This API is to be called from the kernel in order to enable
* a particular smartreflex module. This API will do the initial
@@ -652,7 +635,7 @@ void omap_sr_enable(struct omap_sr *sr)
/**
* 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.
+ * @sr: struct omap_sr *
*
* This API is to be called from the kernel in order to disable
* a particular smartreflex module. This API will in turn call
@@ -810,6 +793,8 @@ static int __init omap_sr_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
pm_runtime_irq_safe(&pdev->dev);
+ pdata->sr = sr_info;
+
sr_info->pdev = pdev;
sr_info->srid = pdev->id;
sr_info->voltdm = pdata->voltdm;
@@ -935,7 +920,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
return -EINVAL;
}
- sr_info = _sr_lookup(pdata->voltdm);
+ sr_info = pdata->sr;
if (IS_ERR(sr_info)) {
dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
__func__);
@@ -950,6 +935,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
list_del(&sr_info->node);
iounmap(sr_info->base);
kfree(sr_info);
+ pdata->sr = NULL;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(mem->start, resource_size(mem));
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 305776f..d7e8d90 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -232,6 +232,7 @@ struct omap_sr_nvalue_table {
* @nvalue_table: table containing the efuse offsets and nvalues
* corresponding to them.
* @voltdm: Pointer to the voltage domain associated with the SR
+ * @sr: struct omap_sr * associated with this SR device (allocated in *_probe())
*/
struct omap_sr_data {
int ip_type;
@@ -241,6 +242,7 @@ struct omap_sr_data {
bool enable_on_init;
struct omap_sr_nvalue_table *nvalue_table;
struct voltagedomain *voltdm;
+ struct omap_sr *sr;
};
/* Smartreflex module enable/disable interface */
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 05/26] OMAP: hwmod/SmartReflex: remove IP block instance-specific data from the driver code
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (3 preceding siblings ...)
2011-11-22 15:05 ` [PATCH 04/26] OMAP: SmartReflex: drop _sr_lookup() jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 06/26] OMAP3+: Pass SmartReflex instance-specific data via hwmod dev_attr jean.pihet
` (22 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Paul Walmsley <paul@pwsan.com>
Add SmartReflex IP instance-specific data (dev_attr data) to the hwmod
data. This data is IP block instance-specific and may even be
semiconductor process-specific; it definitely should not be hardcoded
in the driver.
The pdev_inst_id field is only needed until the clkdev entries for
SmartReflex can be removed.
ToDo:
. this patch needs to be reviewed to determine the correct SmartReflex
omap_sr_dev_attr values for OMAP4.
. kerneldoc needed in smartreflex.h
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 33 ++++++++++++++++++++++---
arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 37 ++++++++++++++++++++++++++++
arch/arm/mach-omap2/smartreflex.h | 11 ++++++++
3 files changed, 77 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 7f8915a..403421a 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -32,6 +32,7 @@
#include "prm-regbits-34xx.h"
#include "cm-regbits-34xx.h"
#include "wd_timer.h"
+#include "smartreflex.h"
#include <mach/am35xx.h>
/*
@@ -2592,8 +2593,18 @@ static struct omap_hwmod_ocp_if *omap3_sr1_slaves[] = {
&omap3_l4_core__sr1,
};
+static struct omap_sr_dev_attr omap3xxx_sr1_dev_attr = {
+ .pdev_inst_id = 0,
+ .sensor_voltdm_name = "mpu",
+ .errweight = OMAP3430_SR_ERRWEIGHT,
+ .errmaxlimit = OMAP3430_SR_ERRMAXLIMIT,
+ .accumdata = OMAP3430_SR_ACCUMDATA,
+ .senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT,
+ .senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT,
+};
+
static struct omap_hwmod omap34xx_sr1_hwmod = {
- .name = "sr1_hwmod",
+ .name = "sr1",
.class = &omap34xx_smartreflex_hwmod_class,
.main_clk = "sr1_fck",
.vdd_name = "mpu_iva",
@@ -2608,11 +2619,12 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
},
.slaves = omap3_sr1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves),
+ .dev_attr = &omap3xxx_sr1_dev_attr,
.flags = HWMOD_SET_DEFAULT_CLOCKACT,
};
static struct omap_hwmod omap36xx_sr1_hwmod = {
- .name = "sr1_hwmod",
+ .name = "sr1",
.class = &omap36xx_smartreflex_hwmod_class,
.main_clk = "sr1_fck",
.vdd_name = "mpu_iva",
@@ -2627,6 +2639,7 @@ static struct omap_hwmod omap36xx_sr1_hwmod = {
},
.slaves = omap3_sr1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves),
+ .dev_attr = &omap3xxx_sr1_dev_attr,
};
/* SR2 */
@@ -2634,8 +2647,18 @@ static struct omap_hwmod_ocp_if *omap3_sr2_slaves[] = {
&omap3_l4_core__sr2,
};
+static struct omap_sr_dev_attr omap3xxx_sr2_dev_attr = {
+ .pdev_inst_id = 1,
+ .sensor_voltdm_name = "core",
+ .errweight = OMAP3430_SR_ERRWEIGHT,
+ .errmaxlimit = OMAP3430_SR_ERRMAXLIMIT,
+ .accumdata = OMAP3430_SR_ACCUMDATA,
+ .senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT,
+ .senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT,
+};
+
static struct omap_hwmod omap34xx_sr2_hwmod = {
- .name = "sr2_hwmod",
+ .name = "sr2",
.class = &omap34xx_smartreflex_hwmod_class,
.main_clk = "sr2_fck",
.vdd_name = "core",
@@ -2650,11 +2673,12 @@ static struct omap_hwmod omap34xx_sr2_hwmod = {
},
.slaves = omap3_sr2_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves),
+ .dev_attr = &omap3xxx_sr2_dev_attr,
.flags = HWMOD_SET_DEFAULT_CLOCKACT,
};
static struct omap_hwmod omap36xx_sr2_hwmod = {
- .name = "sr2_hwmod",
+ .name = "sr2",
.class = &omap36xx_smartreflex_hwmod_class,
.main_clk = "sr2_fck",
.vdd_name = "core",
@@ -2669,6 +2693,7 @@ static struct omap_hwmod omap36xx_sr2_hwmod = {
},
.slaves = omap3_sr2_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves),
+ .dev_attr = &omap3xxx_sr2_dev_attr,
};
/*
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index daaf165..3fbeadc 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -39,6 +39,7 @@
#include "prm44xx.h"
#include "prm-regbits-44xx.h"
#include "wd_timer.h"
+#include "smartreflex.h"
/* Base offset for all OMAP4 interrupts external to MPUSS */
#define OMAP44XX_IRQ_GIC_START 32
@@ -3987,6 +3988,17 @@ static struct omap_hwmod_ocp_if *omap44xx_smartreflex_core_slaves[] = {
&omap44xx_l4_cfg__smartreflex_core,
};
+#warning omap44xx_sr_core_dev_attr values are likely wrong
+static struct omap_sr_dev_attr omap44xx_sr_core_dev_attr = {
+ .pdev_inst_id = 0,
+ .sensor_voltdm_name = "core",
+ .errweight = OMAP3430_SR_ERRWEIGHT,
+ .errmaxlimit = OMAP3430_SR_ERRMAXLIMIT,
+ .accumdata = OMAP3430_SR_ACCUMDATA,
+ .senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT,
+ .senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT,
+};
+
static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
.name = "smartreflex_core",
.class = &omap44xx_smartreflex_hwmod_class,
@@ -4004,6 +4016,7 @@ static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
},
.slaves = omap44xx_smartreflex_core_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_core_slaves),
+ .dev_attr = &omap44xx_sr_core_dev_attr,
};
/* smartreflex_iva */
@@ -4036,6 +4049,17 @@ static struct omap_hwmod_ocp_if *omap44xx_smartreflex_iva_slaves[] = {
&omap44xx_l4_cfg__smartreflex_iva,
};
+#warning omap44xx_sr_iva_dev_attr values are likely wrong
+static struct omap_sr_dev_attr omap44xx_sr_iva_dev_attr = {
+ .pdev_inst_id = 1,
+ .sensor_voltdm_name = "iva",
+ .errweight = OMAP3430_SR_ERRWEIGHT,
+ .errmaxlimit = OMAP3430_SR_ERRMAXLIMIT,
+ .accumdata = OMAP3430_SR_ACCUMDATA,
+ .senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT,
+ .senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT,
+};
+
static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
.name = "smartreflex_iva",
.class = &omap44xx_smartreflex_hwmod_class,
@@ -4052,6 +4076,7 @@ static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
},
.slaves = omap44xx_smartreflex_iva_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_iva_slaves),
+ .dev_attr = &omap44xx_sr_iva_dev_attr,
};
/* smartreflex_mpu */
@@ -4084,6 +4109,17 @@ static struct omap_hwmod_ocp_if *omap44xx_smartreflex_mpu_slaves[] = {
&omap44xx_l4_cfg__smartreflex_mpu,
};
+#warning omap44xx_sr_mpu_dev_attr values are likely wrong
+static struct omap_sr_dev_attr omap44xx_sr_mpu_dev_attr = {
+ .pdev_inst_id = 2,
+ .sensor_voltdm_name = "mpu",
+ .errweight = OMAP3430_SR_ERRWEIGHT,
+ .errmaxlimit = OMAP3430_SR_ERRMAXLIMIT,
+ .accumdata = OMAP3430_SR_ACCUMDATA,
+ .senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT,
+ .senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT,
+};
+
static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
.name = "smartreflex_mpu",
.class = &omap44xx_smartreflex_hwmod_class,
@@ -4100,6 +4136,7 @@ static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
},
.slaves = omap44xx_smartreflex_mpu_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_smartreflex_mpu_slaves),
+ .dev_attr = &omap44xx_sr_mpu_dev_attr,
};
/*
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index d7e8d90..deed861 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -176,6 +176,17 @@ struct omap_sr_pmic_data {
void (*sr_pmic_init) (void);
};
+/* 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;
+};
+
#ifdef CONFIG_OMAP_SMARTREFLEX
/*
* The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 06/26] OMAP3+: Pass SmartReflex instance-specific data via hwmod dev_attr
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (4 preceding siblings ...)
2011-11-22 15:05 ` [PATCH 05/26] OMAP: hwmod/SmartReflex: remove IP block instance-specific data from the driver code jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 07/26] OMAP3+: hwmod: get rid of vdd_name field jean.pihet
` (21 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
Based on Paul's original code for the SmartReflex driver conversion.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 28 +++++-----------------------
arch/arm/mach-omap2/smartreflex.h | 10 ++++++++++
arch/arm/mach-omap2/sr_device.c | 30 +++++++++++++++++++-----------
3 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index c03eb4e..ca3987a 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -152,28 +152,6 @@ static void sr_set_clk_length(struct omap_sr *sr)
}
}
-static void sr_set_regfields(struct omap_sr *sr)
-{
- /*
- * For time being these values are defined in smartreflex.h
- * and populated during init. May be they can be moved to board
- * file or pmic specific data structure. In that case these structure
- * fields will have to be populated using the pdata or pmic structure.
- */
- if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
- 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;
- }
- }
-}
-
static void sr_start_vddautocomp(struct omap_sr *sr)
{
if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
@@ -800,8 +778,13 @@ static int __init omap_sr_probe(struct platform_device *pdev)
sr_info->voltdm = pdata->voltdm;
sr_info->nvalue_table = pdata->nvalue_table;
sr_info->nvalue_count = pdata->nvalue_count;
+ sr_info->err_weight = pdata->err_weight;
+ sr_info->err_maxlimit = pdata->err_maxlimit;
+ sr_info->accum_data = pdata->accum_data;
sr_info->senn_mod = pdata->senn_mod;
+ sr_info->senn_avgweight = pdata->senn_avgweight;
sr_info->senp_mod = pdata->senp_mod;
+ sr_info->senp_avgweight = pdata->senp_avgweight;
sr_info->autocomp_active = false;
sr_info->ip_type = pdata->ip_type;
sr_info->base = ioremap(mem->start, resource_size(mem));
@@ -815,7 +798,6 @@ static int __init omap_sr_probe(struct platform_device *pdev)
sr_info->irq = irq->start;
sr_set_clk_length(sr_info);
- sr_set_regfields(sr_info);
list_add(&sr_info->node, &sr_list);
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index deed861..6cf9e96 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -235,8 +235,13 @@ struct omap_sr_nvalue_table {
* struct omap_sr_data - Smartreflex platform data.
*
* @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
* @nvalue_count: Number of distinct nvalues in the nvalue table
* @enable_on_init: whether this sr module needs to enabled at
* boot up or not.
@@ -247,8 +252,13 @@ struct omap_sr_nvalue_table {
*/
struct omap_sr_data {
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 nvalue_count;
bool enable_on_init;
struct omap_sr_nvalue_table *nvalue_table;
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index 221407a..77442bb 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -81,8 +81,8 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
struct omap_sr_data *sr_data;
struct platform_device *pdev;
struct omap_volt_data *volt_data;
+ struct omap_sr_dev_attr *da;
char *name = "smartreflex";
- static int i;
sr_data = kzalloc(sizeof(struct omap_sr_data), GFP_KERNEL);
if (!sr_data) {
@@ -91,9 +91,9 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
return -ENOMEM;
}
- if (!oh->vdd_name) {
- pr_err("%s: No voltage domain specified for %s."
- "Cannot initialize\n", __func__, oh->name);
+ if (!oh->dev_attr) {
+ pr_err("%s: No dev_attr specified for %s. Cannot initialize\n",
+ __func__, oh->name);
goto exit;
}
@@ -101,17 +101,26 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
sr_data->senn_mod = 0x1;
sr_data->senp_mod = 0x1;
- sr_data->voltdm = voltdm_lookup(oh->vdd_name);
+ da = (struct omap_sr_dev_attr *)oh->dev_attr;
+
+ sr_data->err_weight = da->errweight;
+ sr_data->err_maxlimit = da->errmaxlimit;
+ sr_data->accum_data = da->accumdata;
+ sr_data->senn_avgweight = da->senn_avgweight;
+ sr_data->senp_avgweight = da->senp_avgweight;
+
+ sr_data->voltdm = voltdm_lookup(da->sensor_voltdm_name);
if (IS_ERR(sr_data->voltdm)) {
pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
- __func__, oh->vdd_name);
+ __func__, da->sensor_voltdm_name);
goto exit;
}
omap_voltage_get_volttable(sr_data->voltdm, &volt_data);
if (!volt_data) {
- pr_warning("%s: No Voltage table registerd fo VDD%d."
- "Something really wrong\n\n", __func__, i + 1);
+ pr_warning("%s: No Voltage table registerd fo VDD %s."
+ "Something really wrong\n\n", __func__,
+ da->sensor_voltdm_name);
goto exit;
}
@@ -119,13 +128,12 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
sr_data->enable_on_init = sr_enable_on_init;
- pdev = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
- NULL, 0, 0);
+ pdev = omap_device_build(name, da->pdev_inst_id, oh, sr_data,
+ sizeof(*sr_data), NULL, 0, 0);
if (IS_ERR(pdev))
pr_warning("%s: Could not build omap_device for %s: %s.\n\n",
__func__, name, oh->name);
exit:
- i++;
kfree(sr_data);
return 0;
}
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 07/26] OMAP3+: hwmod: get rid of vdd_name field
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (5 preceding siblings ...)
2011-11-22 15:05 ` [PATCH 06/26] OMAP3+: Pass SmartReflex instance-specific data via hwmod dev_attr jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 08/26] OMAP: SmartReflex: make pdata distinct from other data jean.pihet
` (20 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
Remove the vdd_name field from hwmod, which was only used by the SmartReflex
code and has been removed. SmartReflex will use a name field in its internal
structures instead.
Based on Paul's original code for the SmartReflex driver conversion.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 4 ----
arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 3 ---
arch/arm/plat-omap/include/plat/omap_hwmod.h | 3 ---
3 files changed, 0 insertions(+), 10 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 403421a..cb8e78c 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -2607,7 +2607,6 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
.name = "sr1",
.class = &omap34xx_smartreflex_hwmod_class,
.main_clk = "sr1_fck",
- .vdd_name = "mpu_iva",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
@@ -2627,7 +2626,6 @@ static struct omap_hwmod omap36xx_sr1_hwmod = {
.name = "sr1",
.class = &omap36xx_smartreflex_hwmod_class,
.main_clk = "sr1_fck",
- .vdd_name = "mpu_iva",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
@@ -2661,7 +2659,6 @@ static struct omap_hwmod omap34xx_sr2_hwmod = {
.name = "sr2",
.class = &omap34xx_smartreflex_hwmod_class,
.main_clk = "sr2_fck",
- .vdd_name = "core",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
@@ -2681,7 +2678,6 @@ static struct omap_hwmod omap36xx_sr2_hwmod = {
.name = "sr2",
.class = &omap36xx_smartreflex_hwmod_class,
.main_clk = "sr2_fck",
- .vdd_name = "core",
.prcm = {
.omap2 = {
.prcm_reg_id = 1,
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 3fbeadc..1b43ff1 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -4006,7 +4006,6 @@ static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
.mpu_irqs = omap44xx_smartreflex_core_irqs,
.main_clk = "smartreflex_core_fck",
- .vdd_name = "core",
.prcm = {
.omap4 = {
.clkctrl_offs = OMAP4_CM_ALWON_SR_CORE_CLKCTRL_OFFSET,
@@ -4066,7 +4065,6 @@ static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
.clkdm_name = "l4_ao_clkdm",
.mpu_irqs = omap44xx_smartreflex_iva_irqs,
.main_clk = "smartreflex_iva_fck",
- .vdd_name = "iva",
.prcm = {
.omap4 = {
.clkctrl_offs = OMAP4_CM_ALWON_SR_IVA_CLKCTRL_OFFSET,
@@ -4126,7 +4124,6 @@ static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
.clkdm_name = "l4_ao_clkdm",
.mpu_irqs = omap44xx_smartreflex_mpu_irqs,
.main_clk = "smartreflex_mpu_fck",
- .vdd_name = "mpu",
.prcm = {
.omap4 = {
.clkctrl_offs = OMAP4_CM_ALWON_SR_MPU_CLKCTRL_OFFSET,
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 8b372ed..bdc6ee4 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -480,8 +480,6 @@ struct omap_hwmod_class {
* @main_clk: main clock: OMAP clock name
* @_clk: pointer to the main struct clk (filled in at runtime)
* @opt_clks: other device clocks that drivers can request (0..*)
- * @vdd_name: voltage domain name
- * @voltdm: pointer to voltage domain (filled in at runtime)
* @masters: ptr to array of OCP ifs that this hwmod can initiate on
* @slaves: ptr to array of OCP ifs that this hwmod can respond on
* @dev_attr: arbitrary device attributes that can be passed to the driver
@@ -524,7 +522,6 @@ struct omap_hwmod {
struct omap_hwmod_opt_clk *opt_clks;
char *clkdm_name;
struct clockdomain *clkdm;
- char *vdd_name;
struct omap_hwmod_ocp_if **masters; /* connect to *_IA */
struct omap_hwmod_ocp_if **slaves; /* connect to *_TA */
void *dev_attr;
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 08/26] OMAP: SmartReflex: make pdata distinct from other data
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (6 preceding siblings ...)
2011-11-22 15:05 ` [PATCH 07/26] OMAP3+: hwmod: get rid of vdd_name field jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 09/26] OMAP: SmartReflex: Use 'sr' for struct smartreflex jean.pihet
` (19 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Paul Walmsley <paul@pwsan.com>
Rename "struct omap_sr_data" to "struct smartreflex_platform_data" to
highlight that this structure contains platform_data. Rename the
sr_data variable in arch/arm/mach-omap2/sr_device.c to pdata to
indicate that this data is platform_data. This patch should result in
no functional change.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 7 +++--
arch/arm/mach-omap2/smartreflex.h | 4 +-
arch/arm/mach-omap2/sr_device.c | 50 ++++++++++++++++++------------------
3 files changed, 31 insertions(+), 30 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index ca3987a..4b0dafc 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -194,7 +194,8 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)
static int sr_late_init(struct omap_sr *sr_info)
{
char *name;
- struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data;
+ struct smartreflex_platform_data *pdata =
+ sr_info->pdev->dev.platform_data;
struct resource *mem;
int ret = 0;
@@ -732,7 +733,7 @@ DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
static int __init omap_sr_probe(struct platform_device *pdev)
{
struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
- struct omap_sr_data *pdata = pdev->dev.platform_data;
+ struct smartreflex_platform_data *pdata = pdev->dev.platform_data;
struct resource *mem, *irq;
struct dentry *nvalue_dir;
struct omap_volt_data *volt_data;
@@ -893,7 +894,7 @@ err_free_devinfo:
static int __devexit omap_sr_remove(struct platform_device *pdev)
{
- struct omap_sr_data *pdata = pdev->dev.platform_data;
+ struct smartreflex_platform_data *pdata = pdev->dev.platform_data;
struct omap_sr *sr_info;
struct resource *mem;
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 6cf9e96..e4930be 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -232,7 +232,7 @@ struct omap_sr_nvalue_table {
};
/**
- * struct omap_sr_data - Smartreflex platform data.
+ * struct smartreflex_platform_data - Smartreflex platform data.
*
* @ip_type: Smartreflex IP type.
* @err_weight: XXX
@@ -250,7 +250,7 @@ struct omap_sr_nvalue_table {
* @voltdm: Pointer to the voltage domain associated with the SR
* @sr: struct omap_sr * associated with this SR device (allocated in *_probe())
*/
-struct omap_sr_data {
+struct smartreflex_platform_data {
int ip_type;
u32 err_weight;
u32 err_maxlimit;
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index 77442bb..f464d6a2 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -33,13 +33,13 @@ static bool sr_enable_on_init;
/* Read EFUSE values from control registers for OMAP3430 */
static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
- struct omap_sr_data *sr_data)
+ struct smartreflex_platform_data *pdata)
{
struct omap_sr_nvalue_table *nvalue_table;
int i, count = 0;
- sr_data->nvalue_count = 0;
- sr_data->nvalue_table = NULL;
+ pdata->nvalue_count = 0;
+ pdata->nvalue_table = NULL;
while (volt_data[count].volt_nominal)
count++;
@@ -72,21 +72,21 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
nvalue_table[i].nvalue = v;
}
- sr_data->nvalue_table = nvalue_table;
- sr_data->nvalue_count = count;
+ pdata->nvalue_table = nvalue_table;
+ pdata->nvalue_count = count;
}
static int sr_dev_init(struct omap_hwmod *oh, void *user)
{
- struct omap_sr_data *sr_data;
+ struct smartreflex_platform_data *pdata;
struct platform_device *pdev;
struct omap_volt_data *volt_data;
struct omap_sr_dev_attr *da;
char *name = "smartreflex";
- 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",
+ pdata = kzalloc(sizeof(struct smartreflex_platform_data), GFP_KERNEL);
+ if (!pdata) {
+ pr_err("%s: Unable to allocate memory for %s pdata.Error!\n",
__func__, oh->name);
return -ENOMEM;
}
@@ -97,26 +97,26 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
goto exit;
}
- sr_data->ip_type = oh->class->rev;
- sr_data->senn_mod = 0x1;
- sr_data->senp_mod = 0x1;
+ pdata->ip_type = oh->class->rev;
+ pdata->senn_mod = 0x1;
+ pdata->senp_mod = 0x1;
da = (struct omap_sr_dev_attr *)oh->dev_attr;
- sr_data->err_weight = da->errweight;
- sr_data->err_maxlimit = da->errmaxlimit;
- sr_data->accum_data = da->accumdata;
- sr_data->senn_avgweight = da->senn_avgweight;
- sr_data->senp_avgweight = da->senp_avgweight;
+ pdata->err_weight = da->errweight;
+ pdata->err_maxlimit = da->errmaxlimit;
+ pdata->accum_data = da->accumdata;
+ pdata->senn_avgweight = da->senn_avgweight;
+ pdata->senp_avgweight = da->senp_avgweight;
- sr_data->voltdm = voltdm_lookup(da->sensor_voltdm_name);
- if (IS_ERR(sr_data->voltdm)) {
+ pdata->voltdm = voltdm_lookup(da->sensor_voltdm_name);
+ if (IS_ERR(pdata->voltdm)) {
pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
__func__, da->sensor_voltdm_name);
goto exit;
}
- omap_voltage_get_volttable(sr_data->voltdm, &volt_data);
+ omap_voltage_get_volttable(pdata->voltdm, &volt_data);
if (!volt_data) {
pr_warning("%s: No Voltage table registerd fo VDD %s."
"Something really wrong\n\n", __func__,
@@ -124,17 +124,17 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
goto exit;
}
- sr_set_nvalues(volt_data, sr_data);
+ sr_set_nvalues(volt_data, pdata);
- sr_data->enable_on_init = sr_enable_on_init;
+ pdata->enable_on_init = sr_enable_on_init;
- pdev = omap_device_build(name, da->pdev_inst_id, oh, sr_data,
- sizeof(*sr_data), NULL, 0, 0);
+ pdev = omap_device_build(name, da->pdev_inst_id, oh, pdata,
+ sizeof(*pdata), NULL, 0, 0);
if (IS_ERR(pdev))
pr_warning("%s: Could not build omap_device for %s: %s.\n\n",
__func__, name, oh->name);
exit:
- kfree(sr_data);
+ kfree(pdata);
return 0;
}
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 09/26] OMAP: SmartReflex: Use 'sr' for struct smartreflex
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (7 preceding siblings ...)
2011-11-22 15:05 ` [PATCH 08/26] OMAP: SmartReflex: make pdata distinct from other data jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 10/26] OMAP2+: rename struct omap_sr_class_data to smartreflex_class_data jean.pihet
` (18 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/smartreflex-class3.c | 6 +-
arch/arm/mach-omap2/smartreflex.c | 233 +++++++++++++++---------------
arch/arm/mach-omap2/smartreflex.h | 35 +++---
3 files changed, 136 insertions(+), 138 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index 0205f17..190f330 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -13,7 +13,7 @@
#include "smartreflex.h"
-static int sr_class3_enable(struct omap_sr *sr)
+static int sr_class3_enable(struct smartreflex *sr)
{
unsigned long volt = voltdm_get_voltage(sr->voltdm);
@@ -27,7 +27,7 @@ static int sr_class3_enable(struct omap_sr *sr)
return sr_enable(sr, volt);
}
-static int sr_class3_disable(struct omap_sr *sr, int is_volt_reset)
+static int sr_class3_disable(struct smartreflex *sr, int is_volt_reset)
{
omap_vp_disable(sr->voltdm);
sr_disable(sr);
@@ -37,7 +37,7 @@ static int sr_class3_disable(struct omap_sr *sr, int is_volt_reset)
return 0;
}
-static int sr_class3_configure(struct omap_sr *sr)
+static int sr_class3_configure(struct smartreflex *sr)
{
return sr_configure_errgen(sr);
}
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 4b0dafc..e856d9f 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -31,7 +31,6 @@
#include "pm.h"
#include "smartreflex.h"
-#define SMARTREFLEX_NAME_LEN 16
#define NVALUE_NAME_LEN 40
#define SR_DISABLE_TIMEOUT 200
@@ -42,12 +41,12 @@ static struct omap_sr_class_data *sr_class;
static struct omap_sr_pmic_data *sr_pmic_data;
static struct dentry *sr_dbg_dir;
-static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
+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 omap_sr *sr, unsigned offset, u32 mask,
+static inline void sr_modify_reg(struct smartreflex *sr, unsigned offset, u32 mask,
u32 value)
{
u32 reg_val;
@@ -81,37 +80,37 @@ static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
__raw_writel(reg_val, (sr->base + offset));
}
-static inline u32 sr_read_reg(struct omap_sr *sr, unsigned 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 omap_sr *sr_info = (struct omap_sr *)data;
+ struct smartreflex *sr = (struct smartreflex *)data;
u32 status = 0;
- if (sr_info->ip_type == SR_TYPE_V1) {
+ if (sr->ip_type == SR_TYPE_V1) {
/* Read the status bits */
- status = sr_read_reg(sr_info, ERRCONFIG_V1);
+ status = sr_read_reg(sr, ERRCONFIG_V1);
/* Clear them by writing back */
- sr_write_reg(sr_info, ERRCONFIG_V1, status);
- } else if (sr_info->ip_type == SR_TYPE_V2) {
+ sr_write_reg(sr, ERRCONFIG_V1, status);
+ } else if (sr->ip_type == SR_TYPE_V2) {
/* Read the status bits */
- status = sr_read_reg(sr_info, IRQSTATUS);
+ status = sr_read_reg(sr, IRQSTATUS);
/* Clear them by writing back */
- sr_write_reg(sr_info, IRQSTATUS, status);
+ sr_write_reg(sr, IRQSTATUS, status);
}
if (sr_class->notify)
- sr_class->notify(sr_info, status);
+ sr_class->notify(sr, status);
return IRQ_HANDLED;
}
-static void sr_set_clk_length(struct omap_sr *sr)
+static void sr_set_clk_length(struct smartreflex *sr)
{
struct clk *sys_ck;
u32 sys_clk_speed;
@@ -152,7 +151,7 @@ static void sr_set_clk_length(struct omap_sr *sr)
}
}
-static void sr_start_vddautocomp(struct omap_sr *sr)
+static void sr_start_vddautocomp(struct smartreflex *sr)
{
if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
dev_warn(&sr->pdev->dev,
@@ -165,7 +164,7 @@ static void sr_start_vddautocomp(struct omap_sr *sr)
sr->autocomp_active = true;
}
-static void sr_stop_vddautocomp(struct omap_sr *sr)
+static void sr_stop_vddautocomp(struct smartreflex *sr)
{
if (!sr_class || !(sr_class->disable)) {
dev_warn(&sr->pdev->dev,
@@ -191,46 +190,45 @@ static void sr_stop_vddautocomp(struct omap_sr *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)
+static int sr_late_init(struct smartreflex *sr)
{
char *name;
- struct smartreflex_platform_data *pdata =
- sr_info->pdev->dev.platform_data;
+ struct smartreflex_platform_data *pdata = sr->pdev->dev.platform_data;
struct resource *mem;
int ret = 0;
- if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
- name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
+ if (sr_class->notify && sr_class->notify_flags && sr->irq) {
+ name = kasprintf(GFP_KERNEL, "sr_%s", sr->voltdm->name);
if (name == NULL) {
ret = -ENOMEM;
goto error;
}
- ret = request_irq(sr_info->irq, sr_interrupt,
- 0, name, (void *)sr_info);
+ ret = request_irq(sr->irq, sr_interrupt,
+ 0, name, (void *)sr);
if (ret)
goto error;
- disable_irq(sr_info->irq);
+ disable_irq(sr->irq);
}
if (pdata && pdata->enable_on_init)
- sr_start_vddautocomp(sr_info);
+ sr_start_vddautocomp(sr);
return ret;
error:
- iounmap(sr_info->base);
- mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
+ iounmap(sr->base);
+ mem = platform_get_resource(sr->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"
+ list_del(&sr->node);
+ dev_err(&sr->pdev->dev, "%s: ERROR in registering"
"interrupt handler. Smartreflex will"
"not function as desired\n", __func__);
kfree(name);
- kfree(sr_info);
+ kfree(sr);
return ret;
}
-static void sr_v1_disable(struct omap_sr *sr)
+static void sr_v1_disable(struct smartreflex *sr)
{
int timeout = 0;
@@ -266,7 +264,7 @@ static void sr_v1_disable(struct omap_sr *sr)
ERRCONFIG_MCUDISACKINTST);
}
-static void sr_v2_disable(struct omap_sr *sr)
+static void sr_v2_disable(struct smartreflex *sr)
{
int timeout = 0;
@@ -303,7 +301,7 @@ static void sr_v2_disable(struct omap_sr *sr)
sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
}
-static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)
+static u32 sr_retrieve_nvalue(struct smartreflex *sr, u32 efuse_offs)
{
int i;
@@ -326,7 +324,7 @@ static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)
/**
* sr_configure_errgen() - Configures the smrtreflex to perform AVS using the
* error generator module.
- * @sr: struct omap_sr *
+ * @sr: struct smartreflex *
*
* This API is to be called from the smartreflex class driver to
* configure the error generator module inside the smartreflex module.
@@ -335,7 +333,7 @@ static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)
* 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 omap_sr *sr)
+int sr_configure_errgen(struct smartreflex *sr)
{
u32 sr_config, sr_errconfig, errconfig_offs, vpboundint_en;
u32 vpboundint_st, senp_en = 0, senn_en = 0;
@@ -391,7 +389,7 @@ int sr_configure_errgen(struct omap_sr *sr)
/**
* sr_configure_minmax() - Configures the smrtreflex to perform AVS using the
* minmaxavg module.
- * @sr: struct omap_sr *
+ * @sr: struct smartreflex *
*
* This API is to be called from the smartreflex class driver to
* configure the minmaxavg module inside the smartreflex module.
@@ -400,7 +398,7 @@ int sr_configure_errgen(struct omap_sr *sr)
* 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 omap_sr *sr)
+int sr_configure_minmax(struct smartreflex *sr)
{
u32 sr_config, sr_avgwt;
u32 senp_en = 0, senn_en = 0;
@@ -463,7 +461,7 @@ int sr_configure_minmax(struct omap_sr *sr)
/**
* sr_enable() - Enables the smartreflex module.
- * @sr: struct omap_sr *
+ * @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.
@@ -472,7 +470,7 @@ int sr_configure_minmax(struct omap_sr *sr)
* 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 omap_sr *sr, unsigned long volt)
+int sr_enable(struct smartreflex *sr, unsigned long volt)
{
u32 nvalue_reciprocal;
struct omap_volt_data *volt_data;
@@ -520,12 +518,12 @@ int sr_enable(struct omap_sr *sr, unsigned long volt)
/**
* sr_disable() - Disables the smartreflex module.
- * @sr: struct omap_sr *
+ * @sr: struct smartreflex *
*
* This API is to be called from the smartreflex class driver to
* disable a smartreflex module.
*/
-void sr_disable(struct omap_sr *sr)
+void sr_disable(struct smartreflex *sr)
{
if (IS_ERR_OR_NULL(sr))
return;
@@ -558,7 +556,7 @@ void sr_disable(struct omap_sr *sr)
*/
int sr_register_class(struct omap_sr_class_data *class_data)
{
- struct omap_sr *sr_info;
+ struct smartreflex *sr;
if (!class_data) {
pr_warning("%s:, Smartreflex class data passed is NULL\n",
@@ -578,8 +576,8 @@ int sr_register_class(struct omap_sr_class_data *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);
+ list_for_each_entry(sr, &sr_list, node)
+ sr_late_init(sr);
return 0;
}
@@ -587,14 +585,14 @@ int sr_register_class(struct omap_sr_class_data *class_data)
/**
* omap_sr_enable() - API to enable SR clocks and to call into the
* registered smartreflex class enable API.
- * @sr: struct omap_sr *
+ * @sr: struct smartreflex *
*
* 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 omap_sr *sr)
+void omap_sr_enable(struct smartreflex *sr)
{
if (IS_ERR_OR_NULL(sr))
return;
@@ -614,7 +612,7 @@ void omap_sr_enable(struct omap_sr *sr)
/**
* omap_sr_disable() - API to disable SR without resetting the voltage
* processor voltage
- * @sr: struct omap_sr *
+ * @sr: struct smartreflex *
*
* This API is to be called from the kernel in order to disable
* a particular smartreflex module. This API will in turn call
@@ -622,7 +620,7 @@ void omap_sr_enable(struct omap_sr *sr)
* the smartreflex class disable not to reset the VP voltage after
* disabling smartreflex.
*/
-void omap_sr_disable(struct omap_sr *sr)
+void omap_sr_disable(struct smartreflex *sr)
{
if (IS_ERR_OR_NULL(sr))
return;
@@ -642,7 +640,7 @@ void omap_sr_disable(struct omap_sr *sr)
/**
* omap_sr_disable_reset_volt() - API to disable SR and reset the
* voltage processor voltage
- * @sr: struct omap_sr *
+ * @sr: struct smartreflex *
*
* This API is to be called from the kernel in order to disable
* a particular smartreflex module. This API will in turn call
@@ -650,7 +648,7 @@ void omap_sr_disable(struct omap_sr *sr)
* the smartreflex class disable to reset the VP voltage after
* disabling smartreflex.
*/
-void omap_sr_disable_reset_volt(struct omap_sr *sr)
+void omap_sr_disable_reset_volt(struct smartreflex *sr)
{
if (IS_ERR_OR_NULL(sr))
return;
@@ -689,24 +687,24 @@ void omap_sr_register_pmic(struct omap_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;
+ struct smartreflex *sr = (struct smartreflex *) data;
- if (!sr_info) {
- pr_warning("%s: omap_sr struct not found\n", __func__);
+ if (!sr) {
+ pr_warning("%s: smartreflex struct not found\n", __func__);
return -EINVAL;
}
- *val = sr_info->autocomp_active;
+ *val = sr->autocomp_active;
return 0;
}
static int omap_sr_autocomp_store(void *data, u64 val)
{
- struct omap_sr *sr_info = (struct omap_sr *) data;
+ struct smartreflex *sr = (struct smartreflex *) data;
- if (!sr_info) {
- pr_warning("%s: omap_sr struct not found\n", __func__);
+ if (!sr) {
+ pr_warning("%s: smartreflex struct not found\n", __func__);
return -EINVAL;
}
@@ -717,11 +715,11 @@ static int omap_sr_autocomp_store(void *data, u64 val)
}
/* control enable/disable only if there is a delta in value */
- if (sr_info->autocomp_active != val) {
+ if (sr->autocomp_active != val) {
if (!val)
- sr_stop_vddautocomp(sr_info);
+ sr_stop_vddautocomp(sr);
else
- sr_start_vddautocomp(sr_info);
+ sr_start_vddautocomp(sr);
}
return 0;
@@ -732,7 +730,7 @@ DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
static int __init omap_sr_probe(struct platform_device *pdev)
{
- struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
+ 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;
@@ -740,9 +738,8 @@ static int __init omap_sr_probe(struct platform_device *pdev)
int i, ret = 0;
char *name;
- if (!sr_info) {
- dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
- __func__);
+ if (!sr) {
+ dev_err(&pdev->dev, "%s: unable to allocate sr\n", __func__);
return -ENOMEM;
}
@@ -772,42 +769,41 @@ static int __init omap_sr_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
pm_runtime_irq_safe(&pdev->dev);
- pdata->sr = sr_info;
-
- sr_info->pdev = pdev;
- sr_info->srid = pdev->id;
- sr_info->voltdm = pdata->voltdm;
- sr_info->nvalue_table = pdata->nvalue_table;
- sr_info->nvalue_count = pdata->nvalue_count;
- sr_info->err_weight = pdata->err_weight;
- sr_info->err_maxlimit = pdata->err_maxlimit;
- sr_info->accum_data = pdata->accum_data;
- sr_info->senn_mod = pdata->senn_mod;
- sr_info->senn_avgweight = pdata->senn_avgweight;
- sr_info->senp_mod = pdata->senp_mod;
- sr_info->senp_avgweight = pdata->senp_avgweight;
- sr_info->autocomp_active = false;
- sr_info->ip_type = pdata->ip_type;
- sr_info->base = ioremap(mem->start, resource_size(mem));
- if (!sr_info->base) {
+ pdata->sr = sr;
+
+ sr->pdev = pdev;
+ sr->srid = pdev->id;
+ sr->voltdm = pdata->voltdm;
+ sr->nvalue_count = pdata->nvalue_count;
+ sr->err_weight = pdata->err_weight;
+ sr->err_maxlimit = pdata->err_maxlimit;
+ sr->accum_data = pdata->accum_data;
+ sr->senn_mod = pdata->senn_mod;
+ sr->senn_avgweight = pdata->senn_avgweight;
+ sr->senp_mod = pdata->senp_mod;
+ sr->senp_avgweight = pdata->senp_avgweight;
+ sr->autocomp_active = false;
+ sr->ip_type = pdata->ip_type;
+ 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_info->irq = irq->start;
+ sr->irq = irq->start;
- sr_set_clk_length(sr_info);
+ sr_set_clk_length(sr);
- list_add(&sr_info->node, &sr_list);
+ list_add(&sr->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);
+ ret = sr_late_init(sr);
if (ret) {
pr_warning("%s: Error in SR late init\n", __func__);
return ret;
@@ -825,32 +821,32 @@ static int __init omap_sr_probe(struct platform_device *pdev)
}
}
- name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
+ name = kasprintf(GFP_KERNEL, "sr_%s", sr->voltdm->name);
if (!name) {
dev_err(&pdev->dev, "%s: Unable to alloc debugfs name\n",
__func__);
ret = -ENOMEM;
goto err_iounmap;
}
- sr_info->dbg_dir = debugfs_create_dir(name, sr_dbg_dir);
+ sr->dbg_dir = debugfs_create_dir(name, sr_dbg_dir);
kfree(name);
- if (IS_ERR(sr_info->dbg_dir)) {
+ if (IS_ERR(sr->dbg_dir)) {
dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
__func__);
- ret = PTR_ERR(sr_info->dbg_dir);
+ ret = PTR_ERR(sr->dbg_dir);
goto err_iounmap;
}
(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR,
- sr_info->dbg_dir, (void *)sr_info, &pm_sr_fops);
- (void) debugfs_create_x32("errweight", S_IRUGO, sr_info->dbg_dir,
- &sr_info->err_weight);
- (void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr_info->dbg_dir,
- &sr_info->err_maxlimit);
- (void) debugfs_create_x32("errminlimit", S_IRUGO, sr_info->dbg_dir,
- &sr_info->err_minlimit);
-
- nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir);
+ sr->dbg_dir, (void *)sr, &pm_sr_fops);
+ (void) debugfs_create_x32("errweight", S_IRUGO, sr->dbg_dir,
+ &sr->err_weight);
+ (void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr->dbg_dir,
+ &sr->err_maxlimit);
+ (void) debugfs_create_x32("errminlimit", S_IRUGO, sr->dbg_dir,
+ &sr->err_minlimit);
+
+ 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__);
@@ -858,36 +854,37 @@ static int __init omap_sr_probe(struct platform_device *pdev)
goto err_debugfs;
}
- omap_voltage_get_volttable(sr_info->voltdm, &volt_data);
+ omap_voltage_get_volttable(sr->voltdm, &volt_data);
if (!volt_data) {
dev_warn(&pdev->dev, "%s: No Voltage table for the"
" corresponding vdd vdd_%s. Cannot create debugfs"
"entries for n-values\n",
- __func__, sr_info->voltdm->name);
+ __func__, sr->voltdm->name);
ret = -ENODATA;
goto err_debugfs;
}
- for (i = 0; i < sr_info->nvalue_count; i++) {
+ for (i = 0; i < sr->nvalue_count; i++) {
char name[NVALUE_NAME_LEN + 1];
- snprintf(name, sizeof(name), "volt_%d",
+ /* XXX Also needs to include errminlimit! */
+ snprintf(name, sizeof(name), "volt_%u",
volt_data[i].volt_nominal);
(void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
- &(sr_info->nvalue_table[i].nvalue));
+ &(sr->nvalue_table[i].nvalue));
}
return ret;
err_debugfs:
- debugfs_remove_recursive(sr_info->dbg_dir);
+ debugfs_remove_recursive(sr->dbg_dir);
err_iounmap:
- list_del(&sr_info->node);
- iounmap(sr_info->base);
+ list_del(&sr->node);
+ iounmap(sr->base);
err_release_region:
release_mem_region(mem->start, resource_size(mem));
err_free_devinfo:
- kfree(sr_info);
+ kfree(sr);
return ret;
}
@@ -895,7 +892,7 @@ err_free_devinfo:
static int __devexit omap_sr_remove(struct platform_device *pdev)
{
struct smartreflex_platform_data *pdata = pdev->dev.platform_data;
- struct omap_sr *sr_info;
+ struct smartreflex *sr;
struct resource *mem;
if (!pdata) {
@@ -903,21 +900,21 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
return -EINVAL;
}
- sr_info = pdata->sr;
- if (IS_ERR(sr_info)) {
- dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
+ sr = pdata->sr;
+ if (IS_ERR(sr)) {
+ dev_warn(&pdev->dev, "%s: smartreflex struct not found\n",
__func__);
return -EINVAL;
}
- if (sr_info->autocomp_active)
- sr_stop_vddautocomp(sr_info);
- if (sr_info->dbg_dir)
- debugfs_remove_recursive(sr_info->dbg_dir);
+ if (sr->autocomp_active)
+ sr_stop_vddautocomp(sr);
+ if (sr->dbg_dir)
+ debugfs_remove_recursive(sr->dbg_dir);
- list_del(&sr_info->node);
- iounmap(sr_info->base);
- kfree(sr_info);
+ list_del(&sr->node);
+ iounmap(sr->base);
+ kfree(sr);
pdata->sr = NULL;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(mem->start, resource_size(mem));
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index e4930be..3341584 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -143,7 +143,7 @@
#define OMAP3430_SR_ERRMAXLIMIT 0x02
/* XXX kerneldoc documentation needed */
-struct omap_sr {
+struct smartreflex {
int srid;
int ip_type;
int nvalue_count;
@@ -212,10 +212,10 @@ struct omap_sr_dev_attr {
* based decisions.
*/
struct omap_sr_class_data {
- int (*enable)(struct omap_sr *sr);
- int (*disable)(struct omap_sr *sr, int is_volt_reset);
- int (*configure)(struct omap_sr *sr);
- int (*notify)(struct omap_sr *sr, u32 status);
+ int (*enable)(struct smartreflex *sr);
+ int (*disable)(struct smartreflex *sr, int is_volt_reset);
+ int (*configure)(struct smartreflex *sr);
+ int (*notify)(struct smartreflex *sr, u32 status);
u8 notify_flags;
u8 class_type;
};
@@ -248,7 +248,8 @@ struct omap_sr_nvalue_table {
* @nvalue_table: table containing the efuse offsets and nvalues
* corresponding to them.
* @voltdm: Pointer to the voltage domain associated with the SR
- * @sr: struct omap_sr * associated with this SR device (allocated in *_probe())
+ * @sr: struct smartreflex:
+ * associated with this SR device (allocated in *_probe())
*/
struct smartreflex_platform_data {
int ip_type;
@@ -263,30 +264,30 @@ struct smartreflex_platform_data {
bool enable_on_init;
struct omap_sr_nvalue_table *nvalue_table;
struct voltagedomain *voltdm;
- struct omap_sr *sr;
+ struct smartreflex *sr;
};
/* Smartreflex module enable/disable interface */
-void omap_sr_enable(struct omap_sr *sr);
-void omap_sr_disable(struct omap_sr *sr);
-void omap_sr_disable_reset_volt(struct omap_sr *sr);
+void omap_sr_enable(struct smartreflex *sr);
+void omap_sr_disable(struct smartreflex *sr);
+void omap_sr_disable_reset_volt(struct smartreflex *sr);
/* API to register the pmic specific data with the smartreflex driver. */
void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
/* Smartreflex driver hooks to be called from Smartreflex class driver */
-int sr_enable(struct omap_sr *sr, unsigned long volt);
-void sr_disable(struct omap_sr *sr);
-int sr_configure_errgen(struct omap_sr *sr);
-int sr_configure_minmax(struct omap_sr *sr);
+int sr_enable(struct smartreflex *sr, unsigned long volt);
+void sr_disable(struct smartreflex *sr);
+int sr_configure_errgen(struct smartreflex *sr);
+int sr_configure_minmax(struct smartreflex *sr);
/* API to register the smartreflex class driver with the smartreflex driver */
int sr_register_class(struct omap_sr_class_data *class_data);
#else
-static inline void omap_sr_enable(struct omap_sr *sr) {}
-static inline void omap_sr_disable(struct omap_sr *sr) {}
+static inline void omap_sr_enable(struct smartreflex *sr) {}
+static inline void omap_sr_disable(struct smartreflex *sr) {}
static inline void omap_sr_disable_reset_volt(
- struct omap_sr *sr) {}
+ struct smartreflex *sr) {}
static inline void omap_sr_register_pmic(
struct omap_sr_pmic_data *pmic_data) {}
#endif
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 10/26] OMAP2+: rename struct omap_sr_class_data to smartreflex_class_data
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (8 preceding siblings ...)
2011-11-22 15:05 ` [PATCH 09/26] OMAP: SmartReflex: Use 'sr' for struct smartreflex jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 11/26] OMAP3+: SmartReflex: remove unused PMIC code jean.pihet
` (17 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
Makes the code non-OMAP specific.
Based on Paul's original code for the SmartReflex driver conversion.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/smartreflex-class3.c | 2 +-
arch/arm/mach-omap2/smartreflex.c | 4 ++--
arch/arm/mach-omap2/smartreflex.h | 6 +++---
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index 190f330..c9ea22f 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -43,7 +43,7 @@ static int sr_class3_configure(struct smartreflex *sr)
}
/* SR class3 structure */
-static struct omap_sr_class_data class3_data = {
+static struct smartreflex_class_data class3_data = {
.enable = sr_class3_enable,
.disable = sr_class3_disable,
.configure = sr_class3_configure,
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index e856d9f..3b10245 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -37,7 +37,7 @@
/* sr_list contains all the instances of smartreflex module */
static LIST_HEAD(sr_list);
-static struct omap_sr_class_data *sr_class;
+static struct smartreflex_class_data *sr_class;
static struct omap_sr_pmic_data *sr_pmic_data;
static struct dentry *sr_dbg_dir;
@@ -554,7 +554,7 @@ void sr_disable(struct smartreflex *sr)
* with the smartreflex driver during init. Returns 0 on success else the
* error value.
*/
-int sr_register_class(struct omap_sr_class_data *class_data)
+int sr_register_class(struct smartreflex_class_data *class_data)
{
struct smartreflex *sr;
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 3341584..0573995 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -199,7 +199,7 @@ struct omap_sr_dev_attr {
#define SR_CLASS3 0x3
/**
- * struct omap_sr_class_data - Smartreflex class driver info
+ * struct smartreflex_class_data - Smartreflex class driver info
*
* @enable: API to enable a particular class smaartreflex.
* @disable: API to disable a particular class smartreflex.
@@ -211,7 +211,7 @@ struct omap_sr_dev_attr {
* Can be used by the SR driver to take any class
* based decisions.
*/
-struct omap_sr_class_data {
+struct smartreflex_class_data {
int (*enable)(struct smartreflex *sr);
int (*disable)(struct smartreflex *sr, int is_volt_reset);
int (*configure)(struct smartreflex *sr);
@@ -282,7 +282,7 @@ int sr_configure_errgen(struct smartreflex *sr);
int sr_configure_minmax(struct smartreflex *sr);
/* API to register the smartreflex class driver with the smartreflex driver */
-int sr_register_class(struct omap_sr_class_data *class_data);
+int sr_register_class(struct smartreflex_class_data *class_data);
#else
static inline void omap_sr_enable(struct smartreflex *sr) {}
static inline void omap_sr_disable(struct smartreflex *sr) {}
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 11/26] OMAP3+: SmartReflex: remove unused PMIC code
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (9 preceding siblings ...)
2011-11-22 15:05 ` [PATCH 10/26] OMAP2+: rename struct omap_sr_class_data to smartreflex_class_data jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 12/26] OMAP: SmartReflex: remove some SoC-specific implementation details from driver jean.pihet
` (16 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Paul Walmsley <paul@pwsan.com>
The code can be added it back in when it actually does something.
Based on Paul's original code for the SmartReflex driver conversion.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 31 -------------------------------
arch/arm/mach-omap2/smartreflex.h | 15 ---------------
2 files changed, 0 insertions(+), 46 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 3b10245..86f2bf2 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -38,7 +38,6 @@
static LIST_HEAD(sr_list);
static struct smartreflex_class_data *sr_class;
-static struct omap_sr_pmic_data *sr_pmic_data;
static struct dentry *sr_dbg_dir;
static inline void sr_write_reg(struct smartreflex *sr, unsigned offset, u32 value)
@@ -665,25 +664,6 @@ void omap_sr_disable_reset_volt(struct smartreflex *sr)
sr_class->disable(sr, 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_sr_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)
{
@@ -933,17 +913,6 @@ 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__);
-
ret = platform_driver_probe(&smartreflex_driver, omap_sr_probe);
if (ret) {
pr_err("%s: platform driver register failed for SR\n",
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 0573995..0ebcec0 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -166,16 +166,6 @@ struct smartreflex {
struct dentry *dbg_dir;
};
-/**
- * struct omap_sr_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_sr_pmic_data {
- void (*sr_pmic_init) (void);
-};
-
/* XXX Kerneldoc documentation needed */
struct omap_sr_dev_attr {
char *sensor_voltdm_name; /* XXX should be const */
@@ -272,9 +262,6 @@ void omap_sr_enable(struct smartreflex *sr);
void omap_sr_disable(struct smartreflex *sr);
void omap_sr_disable_reset_volt(struct smartreflex *sr);
-/* API to register the pmic specific data with the smartreflex driver. */
-void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
-
/* Smartreflex driver hooks to be called from Smartreflex class driver */
int sr_enable(struct smartreflex *sr, unsigned long volt);
void sr_disable(struct smartreflex *sr);
@@ -288,7 +275,5 @@ static inline void omap_sr_enable(struct smartreflex *sr) {}
static inline void omap_sr_disable(struct smartreflex *sr) {}
static inline void omap_sr_disable_reset_volt(
struct smartreflex *sr) {}
-static inline void omap_sr_register_pmic(
- struct omap_sr_pmic_data *pmic_data) {}
#endif
#endif
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 12/26] OMAP: SmartReflex: remove some SoC-specific implementation details from driver
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (10 preceding siblings ...)
2011-11-22 15:05 ` [PATCH 11/26] OMAP3+: SmartReflex: remove unused PMIC code jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 13/26] OMAP: SmartReflex driver interface: allow core to override eFuse data jean.pihet
` (15 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw
Cc: Jean Pihet, Thara Gopinath, Nishanth Menon
From: Paul Walmsley <paul@pwsan.com>
The SmartReflex driver incorrectly treats some per-OPP data as data
common to all OPPs (e.g., ERRMINLIMIT). Move this data into a per-OPP
data structure.
The SmartReflex driver should not be dependent on whether the host SoC
uses eFuses to store SmartReflex parameters or not. (Even SoCs that
do store SR data in eFuses often need to override that data with
software-defined values.) So, convert sr_retrieve_nvalue() to look up
per-OPP data by the OPP's nominal voltage, rather than by the eFuse
offset.
Based on Paul's original code for the SmartReflex driver conversion.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Nishanth Menon <nm@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 53 ++++++++++++++-----------------------
arch/arm/mach-omap2/smartreflex.h | 4 +++
arch/arm/mach-omap2/sr_device.c | 27 ++++++++++++++----
3 files changed, 45 insertions(+), 39 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 86f2bf2..66c6f6b 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -300,22 +300,24 @@ static void sr_v2_disable(struct smartreflex *sr)
sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
}
-static u32 sr_retrieve_nvalue(struct smartreflex *sr, u32 efuse_offs)
+static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
+ struct smartreflex *sr,
+ unsigned long volt_nominal)
{
int i;
if (!sr->nvalue_table) {
dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
__func__);
- return 0;
+ return NULL;
}
for (i = 0; i < sr->nvalue_count; i++) {
- if (sr->nvalue_table[i].efuse_offs == efuse_offs)
- return sr->nvalue_table[i].nvalue;
+ if (sr->nvalue_table[i].volt_nominal == volt_nominal)
+ return &sr->nvalue_table[i];
}
- return 0;
+ return NULL;
}
/* Public Functions */
@@ -471,31 +473,21 @@ int sr_configure_minmax(struct smartreflex *sr)
*/
int sr_enable(struct smartreflex *sr, unsigned long volt)
{
- u32 nvalue_reciprocal;
- struct omap_volt_data *volt_data;
+ struct omap_sr_nvalue_table *nvalue_row;
int ret;
if (IS_ERR_OR_NULL(sr))
return -EINVAL;
- volt_data = omap_voltage_get_voltdata(sr->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 = sr_retrieve_nvalue(sr, volt_data->sr_efuse_offs);
-
- if (!nvalue_reciprocal) {
- dev_warn(&sr->pdev->dev, "%s: NVALUE = 0 at voltage %ld\n",
- __func__, volt);
+ 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 = volt_data->sr_errminlimit;
+ sr->err_minlimit = nvalue_row->errminlimit;
pm_runtime_get_sync(&sr->pdev->dev);
@@ -508,7 +500,7 @@ int sr_enable(struct smartreflex *sr, unsigned long volt)
if (ret)
return ret;
- sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
+ sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue);
/* SRCONFIG - enable SR */
sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
@@ -714,7 +706,6 @@ static int __init omap_sr_probe(struct platform_device *pdev)
struct smartreflex_platform_data *pdata = pdev->dev.platform_data;
struct resource *mem, *irq;
struct dentry *nvalue_dir;
- struct omap_volt_data *volt_data;
int i, ret = 0;
char *name;
@@ -823,8 +814,6 @@ static int __init omap_sr_probe(struct platform_device *pdev)
&sr->err_weight);
(void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr->dbg_dir,
&sr->err_maxlimit);
- (void) debugfs_create_x32("errminlimit", S_IRUGO, sr->dbg_dir,
- &sr->err_minlimit);
nvalue_dir = debugfs_create_dir("nvalue", sr->dbg_dir);
if (IS_ERR(nvalue_dir)) {
@@ -834,12 +823,10 @@ static int __init omap_sr_probe(struct platform_device *pdev)
goto err_debugfs;
}
- omap_voltage_get_volttable(sr->voltdm, &volt_data);
- if (!volt_data) {
- dev_warn(&pdev->dev, "%s: No Voltage table for the"
- " corresponding vdd vdd_%s. Cannot create debugfs"
- "entries for n-values\n",
- __func__, sr->voltdm->name);
+ if (sr->nvalue_count == 0 || !sr->nvalue_table) {
+ dev_warn(&pdev->dev, "%s: No Voltage table for the "
+ "corresponding vdd vdd_%s. Cannot create debugfs "
+ "entries for n-values\n", __func__, sr->voltdm->name);
ret = -ENODATA;
goto err_debugfs;
}
@@ -848,8 +835,8 @@ static int __init omap_sr_probe(struct platform_device *pdev)
char name[NVALUE_NAME_LEN + 1];
/* XXX Also needs to include errminlimit! */
- snprintf(name, sizeof(name), "volt_%u",
- volt_data[i].volt_nominal);
+ snprintf(name, sizeof(name), "volt_%lu",
+ sr->nvalue_table[i].volt_nominal);
(void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
&(sr->nvalue_table[i].nvalue));
}
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 0ebcec0..ca70a90 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -215,10 +215,14 @@ struct smartreflex_class_data {
*
* @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_nvalue_table {
u32 efuse_offs;
u32 nvalue;
+ u32 errminlimit;
+ unsigned long volt_nominal;
};
/**
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index f464d6a2..8fe836f 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -36,7 +36,7 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
struct smartreflex_platform_data *pdata)
{
struct omap_sr_nvalue_table *nvalue_table;
- int i, count = 0;
+ int i, j, count = 0;
pdata->nvalue_count = 0;
pdata->nvalue_table = NULL;
@@ -51,8 +51,9 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
return;
}
- for (i = 0; i < count; i++) {
+ for (i = 0, j = 0; i < count; i++) {
u32 v;
+
/*
* In OMAP4 the efuse registers are 24 bit aligned.
* A __raw_readl will fail for non-32 bit aligned address
@@ -65,15 +66,29 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
omap_ctrl_readb(offset + 1) << 8 |
omap_ctrl_readb(offset + 2) << 16;
} else {
- v = omap_ctrl_readl(volt_data[i].sr_efuse_offs);
+ v = omap_ctrl_readl(volt_data[i].sr_efuse_offs);
}
- nvalue_table[i].efuse_offs = volt_data[i].sr_efuse_offs;
- nvalue_table[i].nvalue = v;
+ /*
+ * Many OMAP SoCs don't have the eFuse values set.
+ * For example, pretty much all OMAP3xxx before
+ * ES3.something.
+ *
+ * XXX There needs to be some way for board files or
+ * userspace to add these in.
+ */
+ if (v == 0)
+ continue;
+
+ nvalue_table[j].nvalue = v;
+ nvalue_table[j].errminlimit = volt_data[i].sr_errminlimit;
+ nvalue_table[j].volt_nominal = volt_data[i].volt_nominal;
+
+ j++;
}
pdata->nvalue_table = nvalue_table;
- pdata->nvalue_count = count;
+ pdata->nvalue_count = j;
}
static int sr_dev_init(struct omap_hwmod *oh, void *user)
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 13/26] OMAP: SmartReflex driver interface: allow core to override eFuse data
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (11 preceding siblings ...)
2011-11-22 15:05 ` [PATCH 12/26] OMAP: SmartReflex: remove some SoC-specific implementation details from driver jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 14/26] OMAP2+: Use the names from the SmartReflex data instead of voltage domains jean.pihet
` (14 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw
Cc: Jean Pihet, Thara Gopinath, Nishanth Menon
From: Paul Walmsley <paul@pwsan.com>
Sometimes, the automatic voltage scaling control loop parameters in
the SoC eFuse data are not present or are incorrect. Nevertheless,
some boards may wish to use SmartReflex anyway, with conservative
values provided by the SoC manufacturer. This patch adds code to
allow board files to specify or override the SmartReflex eFuse data.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
Cc: Thara Gopinath <thara@ti.com>
Cc: Nishanth Menon <nm@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/sr_device.c | 40 ++++++++++++++++++++++----------------
arch/arm/mach-omap2/voltage.h | 2 +
2 files changed, 25 insertions(+), 17 deletions(-)
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index 8fe836f..2dec827 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -7,8 +7,9 @@
* Copyright (C) 2010 Texas Instruments, Inc.
* Thara Gopinath <thara@ti.com>
*
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2008, 2011 Nokia Corporation
* Kalle Jokiniemi
+ * Paul Walmsley
*
* Copyright (C) 2007 Texas Instruments, Inc.
* Lesly A M <x0080970@ti.com>
@@ -54,31 +55,36 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
for (i = 0, j = 0; i < count; i++) {
u32 v;
- /*
- * In OMAP4 the efuse registers are 24 bit aligned.
- * A __raw_readl will fail for non-32 bit aligned address
- * and hence the 8-bit read and shift.
- */
- if (cpu_is_omap44xx()) {
- u16 offset = volt_data[i].sr_efuse_offs;
-
- v = omap_ctrl_readb(offset) |
- omap_ctrl_readb(offset + 1) << 8 |
- omap_ctrl_readb(offset + 2) << 16;
+ if (volt_data[i].sr_nvalue != 0) {
+ v = volt_data[i].sr_nvalue;
} else {
- v = omap_ctrl_readl(volt_data[i].sr_efuse_offs);
+ /*
+ * In OMAP4 the efuse registers are 24 bit
+ * aligned. A __raw_readl will fail for
+ * non-32 bit aligned address and hence the
+ * 8-bit read and shift.
+ */
+ if (cpu_is_omap44xx()) {
+ u16 offset = volt_data[i].sr_efuse_offs;
+
+ v = omap_ctrl_readb(offset) |
+ omap_ctrl_readb(offset + 1) << 8 |
+ omap_ctrl_readb(offset + 2) << 16;
+ } else {
+ v = omap_ctrl_readl(volt_data[i].sr_efuse_offs);
+ }
}
/*
* Many OMAP SoCs don't have the eFuse values set.
* For example, pretty much all OMAP3xxx before
* ES3.something.
- *
- * XXX There needs to be some way for board files or
- * userspace to add these in.
*/
- if (v == 0)
+ if (v == 0) {
+ pr_debug("SR: %s: voltage %d: no N value; skipping\n",
+ sr_data->voltdm->name, volt_data[i].volt_nominal);
continue;
+ }
nvalue_table[j].nvalue = v;
nvalue_table[j].errminlimit = volt_data[i].sr_errminlimit;
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index 16a1b09..ebd8899 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -96,6 +96,7 @@ struct voltagedomain {
* @sr_efuse_offs: The offset of the efuse register(from system
* control module base address) from where to read
* the n-target value for the smartreflex module.
+ * @sr_nvalue: the SR N value for this OPP. Use to override bogus eFuse vals
* @sr_errminlimit: Error min limit value for smartreflex. This value
* differs at differnet opp and thus is linked
* with voltage.
@@ -105,6 +106,7 @@ struct voltagedomain {
struct omap_volt_data {
u32 volt_nominal;
u32 sr_efuse_offs;
+ u32 sr_nvalue;
u8 sr_errminlimit;
u8 vp_errgain;
};
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 14/26] OMAP2+: Use the names from the SmartReflex data instead of voltage domains.
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (12 preceding siblings ...)
2011-11-22 15:05 ` [PATCH 13/26] OMAP: SmartReflex driver interface: allow core to override eFuse data jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:05 ` [PATCH 15/26] OMAP2+: SmartReflex: rename nvalue table jean.pihet
` (13 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
Associate a name with each SmartReflex instance, rather than
attempting to reuse the name of a voltage domain. This helps remove
any dependencies on SoC-specific structures.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/smartreflex-class3.c | 2 +-
arch/arm/mach-omap2/smartreflex.c | 23 ++++++-----------------
arch/arm/mach-omap2/smartreflex.h | 3 +++
arch/arm/mach-omap2/sr_device.c | 10 ++++++----
4 files changed, 16 insertions(+), 22 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index c9ea22f..f741193 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -19,7 +19,7 @@ static int sr_class3_enable(struct smartreflex *sr)
if (!volt) {
pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
- __func__, sr->voltdm->name);
+ __func__, sr->name);
return -ENODATA;
}
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 66c6f6b..5a72c87 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -191,19 +191,13 @@ static void sr_stop_vddautocomp(struct smartreflex *sr)
*/
static int sr_late_init(struct smartreflex *sr)
{
- char *name;
struct smartreflex_platform_data *pdata = sr->pdev->dev.platform_data;
struct resource *mem;
int ret = 0;
if (sr_class->notify && sr_class->notify_flags && sr->irq) {
- name = kasprintf(GFP_KERNEL, "sr_%s", sr->voltdm->name);
- if (name == NULL) {
- ret = -ENOMEM;
- goto error;
- }
- ret = request_irq(sr->irq, sr_interrupt,
- 0, name, (void *)sr);
+ ret = request_irq(sr->irq, sr_interrupt, 0, sr->name,
+ (void *)sr);
if (ret)
goto error;
disable_irq(sr->irq);
@@ -222,7 +216,6 @@ error:
dev_err(&sr->pdev->dev, "%s: ERROR in registering"
"interrupt handler. Smartreflex will"
"not function as desired\n", __func__);
- kfree(name);
kfree(sr);
return ret;
}
@@ -707,7 +700,6 @@ static int __init omap_sr_probe(struct platform_device *pdev)
struct resource *mem, *irq;
struct dentry *nvalue_dir;
int i, ret = 0;
- char *name;
if (!sr) {
dev_err(&pdev->dev, "%s: unable to allocate sr\n", __func__);
@@ -792,15 +784,14 @@ static int __init omap_sr_probe(struct platform_device *pdev)
}
}
- name = kasprintf(GFP_KERNEL, "sr_%s", sr->voltdm->name);
- if (!name) {
+ 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(name, sr_dbg_dir);
- kfree(name);
+ 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__);
@@ -824,9 +815,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
}
if (sr->nvalue_count == 0 || !sr->nvalue_table) {
- dev_warn(&pdev->dev, "%s: No Voltage table for the "
- "corresponding vdd vdd_%s. Cannot create debugfs "
- "entries for n-values\n", __func__, sr->voltdm->name);
+ dev_warn(&pdev->dev, "%s: no SR data table\n", __func__);
ret = -ENODATA;
goto err_debugfs;
}
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index ca70a90..7b0304a 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -144,6 +144,7 @@
/* XXX kerneldoc documentation needed */
struct smartreflex {
+ char *name;
int srid;
int ip_type;
int nvalue_count;
@@ -228,6 +229,7 @@ struct omap_sr_nvalue_table {
/**
* struct smartreflex_platform_data - Smartreflex platform data.
*
+ * @name: XXX
* @ip_type: Smartreflex IP type.
* @err_weight: XXX
* @err_maxlimit: XXX
@@ -246,6 +248,7 @@ struct omap_sr_nvalue_table {
* associated with this SR device (allocated in *_probe())
*/
struct smartreflex_platform_data {
+ const char *name;
int ip_type;
u32 err_weight;
u32 err_maxlimit;
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index 2dec827..aece907 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -82,7 +82,7 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
*/
if (v == 0) {
pr_debug("SR: %s: voltage %d: no N value; skipping\n",
- sr_data->voltdm->name, volt_data[i].volt_nominal);
+ pdata->name, volt_data[i].volt_nominal);
continue;
}
@@ -103,6 +103,7 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
struct platform_device *pdev;
struct omap_volt_data *volt_data;
struct omap_sr_dev_attr *da;
+ struct voltagedomain *voltdm;
char *name = "smartreflex";
pdata = kzalloc(sizeof(struct smartreflex_platform_data), GFP_KERNEL);
@@ -118,6 +119,7 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
goto exit;
}
+ pdata->name = oh->name;
pdata->ip_type = oh->class->rev;
pdata->senn_mod = 0x1;
pdata->senp_mod = 0x1;
@@ -130,14 +132,14 @@ static int sr_dev_init(struct omap_hwmod *oh, void *user)
pdata->senn_avgweight = da->senn_avgweight;
pdata->senp_avgweight = da->senp_avgweight;
- pdata->voltdm = voltdm_lookup(da->sensor_voltdm_name);
- if (IS_ERR(pdata->voltdm)) {
+ voltdm = voltdm_lookup(da->sensor_voltdm_name);
+ if (IS_ERR(voltdm)) {
pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
__func__, da->sensor_voltdm_name);
goto exit;
}
- omap_voltage_get_volttable(pdata->voltdm, &volt_data);
+ omap_voltage_get_volttable(voltdm, &volt_data);
if (!volt_data) {
pr_warning("%s: No Voltage table registerd fo VDD %s."
"Something really wrong\n\n", __func__,
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 15/26] OMAP2+: SmartReflex: rename nvalue table
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (13 preceding siblings ...)
2011-11-22 15:05 ` [PATCH 14/26] OMAP2+: Use the names from the SmartReflex data instead of voltage domains jean.pihet
@ 2011-11-22 15:05 ` jean.pihet
2011-11-22 15:06 ` [PATCH 16/26] OMAP2+: SmartReflex: cosmetic changes jean.pihet
` (12 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:05 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Paul Walmsley <paul@pwsan.com>
struct omap_sr_nvalue_table now contains more than simply n-values, so
rename it accordingly to omap_sr_data_table.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 29 ++++++++++++++---------------
arch/arm/mach-omap2/smartreflex.h | 17 ++++++++---------
arch/arm/mach-omap2/sr_device.c | 23 ++++++++++++-----------
3 files changed, 34 insertions(+), 35 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 5a72c87..41c4d2a 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -3,14 +3,13 @@
*
* Author: Thara Gopinath <thara@ti.com>
*
- * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2007,2010 Texas Instruments, Inc.
+ * Lesly A M <x0080970@ti.com>
* Thara Gopinath <thara@ti.com>
*
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2008,2011 Nokia Corporation
* Kalle Jokiniemi
- *
- * Copyright (C) 2007 Texas Instruments, Inc.
- * Lesly A M <x0080970@ti.com>
+ * 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
@@ -299,15 +298,15 @@ static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
{
int i;
- if (!sr->nvalue_table) {
+ if (!sr->data_table) {
dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
__func__);
return NULL;
}
- for (i = 0; i < sr->nvalue_count; i++) {
- if (sr->nvalue_table[i].volt_nominal == volt_nominal)
- return &sr->nvalue_table[i];
+ for (i = 0; i < sr->data_count; i++) {
+ if (sr->data_table[i].volt_nominal == volt_nominal)
+ return &sr->data_table[i];
}
return NULL;
@@ -466,7 +465,7 @@ int sr_configure_minmax(struct smartreflex *sr)
*/
int sr_enable(struct smartreflex *sr, unsigned long volt)
{
- struct omap_sr_nvalue_table *nvalue_row;
+ struct omap_sr_data_table *nvalue_row;
int ret;
if (IS_ERR_OR_NULL(sr))
@@ -737,7 +736,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
sr->pdev = pdev;
sr->srid = pdev->id;
sr->voltdm = pdata->voltdm;
- sr->nvalue_count = pdata->nvalue_count;
+ sr->data_count = pdata->data_count;
sr->err_weight = pdata->err_weight;
sr->err_maxlimit = pdata->err_maxlimit;
sr->accum_data = pdata->accum_data;
@@ -814,20 +813,20 @@ static int __init omap_sr_probe(struct platform_device *pdev)
goto err_debugfs;
}
- if (sr->nvalue_count == 0 || !sr->nvalue_table) {
+ if (sr->data_count == 0 || !sr->data_table) {
dev_warn(&pdev->dev, "%s: no SR data table\n", __func__);
ret = -ENODATA;
goto err_debugfs;
}
- for (i = 0; i < sr->nvalue_count; i++) {
+ for (i = 0; i < sr->data_count; i++) {
char name[NVALUE_NAME_LEN + 1];
/* XXX Also needs to include errminlimit! */
snprintf(name, sizeof(name), "volt_%lu",
- sr->nvalue_table[i].volt_nominal);
+ sr->data_table[i].volt_nominal);
(void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
- &(sr->nvalue_table[i].nvalue));
+ &(sr->data_table[i].nvalue));
}
return ret;
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 7b0304a..e7ed7a1 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -147,7 +147,7 @@ struct smartreflex {
char *name;
int srid;
int ip_type;
- int nvalue_count;
+ int data_count;
bool autocomp_active;
u32 clk_length;
u32 err_weight;
@@ -162,7 +162,7 @@ struct smartreflex {
void __iomem *base;
struct platform_device *pdev;
struct list_head node;
- struct omap_sr_nvalue_table *nvalue_table;
+ struct omap_sr_data_table *data_table;
struct voltagedomain *voltdm;
struct dentry *dbg_dir;
};
@@ -212,14 +212,14 @@ struct smartreflex_class_data {
};
/**
- * struct omap_sr_nvalue_table - Smartreflex n-target value info
+ * 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_nvalue_table {
+struct omap_sr_data_table {
u32 efuse_offs;
u32 nvalue;
u32 errminlimit;
@@ -238,11 +238,10 @@ struct omap_sr_nvalue_table {
* @senn_mod: SENNENABLE value for sr
* @senn_avgweight: XXX
* @senp_avgweight: XXX
- * @nvalue_count: Number of distinct nvalues in the nvalue table
+ * @data_count: Number of rows in @data_table
* @enable_on_init: whether this sr module needs to enabled at
* boot up or not.
- * @nvalue_table: table containing the efuse offsets and nvalues
- * corresponding to them.
+ * @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())
@@ -257,9 +256,9 @@ struct smartreflex_platform_data {
u32 senn_mod;
u32 senn_avgweight;
u32 senp_avgweight;
- int nvalue_count;
+ int data_count;
bool enable_on_init;
- struct omap_sr_nvalue_table *nvalue_table;
+ struct omap_sr_data_table *data_table;
struct voltagedomain *voltdm;
struct smartreflex *sr;
};
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index aece907..2fefbb5 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -36,19 +36,20 @@ static bool sr_enable_on_init;
static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
struct smartreflex_platform_data *pdata)
{
- struct omap_sr_nvalue_table *nvalue_table;
+ struct omap_sr_data_table *data_table;
int i, j, count = 0;
- pdata->nvalue_count = 0;
- pdata->nvalue_table = NULL;
+ pdata->data_count = 0;
+ pdata->data_table = NULL;
while (volt_data[count].volt_nominal)
count++;
- nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count,
+ data_table = kzalloc(sizeof(struct omap_sr_data_table)*count,
GFP_KERNEL);
- if (!nvalue_table) {
- pr_err("OMAP: SmartReflex: cannot allocate memory for n-value table\n");
+ if (!data_table) {
+ pr_err("OMAP: SmartReflex: cannot allocate memory for n-value "
+ "table\n");
return;
}
@@ -86,15 +87,15 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
continue;
}
- nvalue_table[j].nvalue = v;
- nvalue_table[j].errminlimit = volt_data[i].sr_errminlimit;
- nvalue_table[j].volt_nominal = volt_data[i].volt_nominal;
+ data_table[j].nvalue = v;
+ data_table[j].errminlimit = volt_data[i].sr_errminlimit;
+ data_table[j].volt_nominal = volt_data[i].volt_nominal;
j++;
}
- pdata->nvalue_table = nvalue_table;
- pdata->nvalue_count = j;
+ pdata->data_table = data_table;
+ pdata->data_count = j;
}
static int sr_dev_init(struct omap_hwmod *oh, void *user)
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 16/26] OMAP2+: SmartReflex: cosmetic changes
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (14 preceding siblings ...)
2011-11-22 15:05 ` [PATCH 15/26] OMAP2+: SmartReflex: rename nvalue table jean.pihet
@ 2011-11-22 15:06 ` jean.pihet
2011-11-22 15:06 ` [PATCH 17/26] OMAP3+: Add SmartReflex clocks jean.pihet
` (11 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:06 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Paul Walmsley <paul@pwsan.com>
Concatenate error message strings; fix some indenting.
Kevin mentioned some time ago that the lkml consensus was to not break
error messages up into partial strings to fit within 80 columns, but
rather to make it one big line; so, do so in the SmartReflex driver
code.
Also, while here, fix some obviously incorrect indentation and whitespace,
and remove some of the obvious references to "OMAP", since we're trying
to convert this into an SoC-independent driver.
This patch shouldn't result in any functional changes.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 35 ++++++++++++++---------------------
1 files changed, 14 insertions(+), 21 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 41c4d2a..154a98b 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -1,5 +1,5 @@
/*
- * OMAP SmartReflex Voltage Control
+ * SmartReflex Voltage Control
*
* Author: Thara Gopinath <thara@ti.com>
*
@@ -39,13 +39,14 @@ static LIST_HEAD(sr_list);
static struct smartreflex_class_data *sr_class;
static struct dentry *sr_dbg_dir;
-static inline void sr_write_reg(struct smartreflex *sr, unsigned offset, u32 value)
+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)
+static inline void sr_modify_reg(struct smartreflex *sr, unsigned offset,
+ u32 mask, u32 value)
{
u32 reg_val;
u32 errconfig_offs = 0, errconfig_mask = 0;
@@ -212,9 +213,7 @@ error:
mem = platform_get_resource(sr->pdev, IORESOURCE_MEM, 0);
release_mem_region(mem->start, resource_size(mem));
list_del(&sr->node);
- dev_err(&sr->pdev->dev, "%s: ERROR in registering"
- "interrupt handler. Smartreflex will"
- "not function as desired\n", __func__);
+ dev_err(&sr->pdev->dev, "%s: ERROR in registering interrupt handler. Smartreflex will not function as desired\n", __func__);
kfree(sr);
return ret;
}
@@ -358,8 +357,7 @@ int sr_configure_errgen(struct smartreflex *sr)
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__);
+ dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex module without specifying the ip\n", __func__);
return -EINVAL;
}
@@ -418,8 +416,7 @@ int sr_configure_minmax(struct smartreflex *sr)
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__);
+ dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex module without specifying the ip\n", __func__);
return -EINVAL;
}
@@ -584,8 +581,7 @@ void omap_sr_enable(struct smartreflex *sr)
return;
if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
- dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
- "registered\n", __func__);
+ dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not registered\n", __func__);
return;
}
@@ -612,8 +608,7 @@ void omap_sr_disable(struct smartreflex *sr)
return;
if (!sr_class || !(sr_class->disable)) {
- dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
- "registered\n", __func__);
+ dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not registered\n", __func__);
return;
}
@@ -640,8 +635,7 @@ void omap_sr_disable_reset_volt(struct smartreflex *sr)
return;
if (!sr_class || !(sr_class->disable)) {
- dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
- "registered\n", __func__);
+ dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not registered\n", __func__);
return;
}
@@ -807,8 +801,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
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__);
+ dev_err(&pdev->dev, "%s: Unable to create debugfs directory for n-values\n", __func__);
ret = PTR_ERR(nvalue_dir);
goto err_debugfs;
}
@@ -878,7 +871,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
}
static struct platform_driver smartreflex_driver = {
- .remove = omap_sr_remove,
+ .remove = omap_sr_remove,
.driver = {
.name = "smartreflex",
},
@@ -905,7 +898,7 @@ static void __exit sr_exit(void)
late_initcall(sr_init);
module_exit(sr_exit);
-MODULE_DESCRIPTION("OMAP Smartreflex Driver");
+MODULE_DESCRIPTION("SmartReflex device driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRIVER_NAME);
MODULE_AUTHOR("Texas Instruments Inc");
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 17/26] OMAP3+: Add SmartReflex clocks
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (15 preceding siblings ...)
2011-11-22 15:06 ` [PATCH 16/26] OMAP2+: SmartReflex: cosmetic changes jean.pihet
@ 2011-11-22 15:06 ` jean.pihet
2011-11-22 15:06 ` [PATCH 18/26] OMAP2+: Use the TRM formula to calculate the SmartReflex clock rate jean.pihet
` (10 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:06 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Paul Walmsley <paul@pwsan.com>
Add functional clocks for OMAP3 SmartReflex 1&2 and for OMAP4 SmartReflex 1,2&3
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/clock3xxx_data.c | 6 ++++++
arch/arm/mach-omap2/clock44xx_data.c | 3 +++
2 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 5d0064a..d653005 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -3448,7 +3448,13 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "traceclk_src_fck", &traceclk_src_fck, CK_3XXX),
CLK(NULL, "traceclk_fck", &traceclk_fck, CK_3XXX),
CLK(NULL, "sr1_fck", &sr1_fck, CK_34XX | CK_36XX),
+ /*
+ * These smartreflex alias lines should be removable after
+ * the omap_device code adds clkdev aliases to "main"
+ */
+ CLK("smartreflex.0", "fck", &sr1_fck, CK_34XX | CK_36XX),
CLK(NULL, "sr2_fck", &sr2_fck, CK_34XX | CK_36XX),
+ CLK("smartreflex.1", "fck", &sr2_fck, CK_34XX | CK_36XX),
CLK(NULL, "sr_l4_ick", &sr_l4_ick, CK_34XX | CK_36XX),
CLK(NULL, "secure_32k_fck", &secure_32k_fck, CK_3XXX),
CLK(NULL, "gpt12_fck", &gpt12_fck, CK_3XXX),
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 0798a80..1988fa2 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -3278,8 +3278,11 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "slimbus2_slimbus_clk", &slimbus2_slimbus_clk, CK_443X),
CLK(NULL, "slimbus2_fck", &slimbus2_fck, CK_443X),
CLK(NULL, "smartreflex_core_fck", &smartreflex_core_fck, CK_443X),
+ CLK("smartreflex.0", "fck", &smartreflex_core_fck, CK_443X),
CLK(NULL, "smartreflex_iva_fck", &smartreflex_iva_fck, CK_443X),
+ CLK("smartreflex.1", "fck", &smartreflex_iva_fck, CK_443X),
CLK(NULL, "smartreflex_mpu_fck", &smartreflex_mpu_fck, CK_443X),
+ CLK("smartreflex.2", "fck", &smartreflex_mpu_fck, CK_443X),
CLK(NULL, "gpt1_fck", &timer1_fck, CK_443X),
CLK(NULL, "gpt10_fck", &timer10_fck, CK_443X),
CLK(NULL, "gpt11_fck", &timer11_fck, CK_443X),
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 18/26] OMAP2+: Use the TRM formula to calculate the SmartReflex clock rate
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (16 preceding siblings ...)
2011-11-22 15:06 ` [PATCH 17/26] OMAP3+: Add SmartReflex clocks jean.pihet
@ 2011-11-22 15:06 ` jean.pihet
2011-11-22 15:06 ` [PATCH 19/26] OMAP2+: SmartReflex: Remove the notifier handler jean.pihet
` (9 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:06 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 53 ++++++++++++++----------------------
arch/arm/mach-omap2/smartreflex.h | 8 -----
2 files changed, 21 insertions(+), 40 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 154a98b..882f1d5 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -33,6 +33,13 @@
#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 */
+
/* sr_list contains all the instances of smartreflex module */
static LIST_HEAD(sr_list);
@@ -111,43 +118,25 @@ static irqreturn_t sr_interrupt(int irq, void *data)
static void sr_set_clk_length(struct smartreflex *sr)
{
- struct clk *sys_ck;
- u32 sys_clk_speed;
+ struct clk *fck;
+ int fck_rate;
- if (cpu_is_omap34xx())
- sys_ck = clk_get(NULL, "sys_ck");
- else
- sys_ck = clk_get(NULL, "sys_clkin_ck");
-
- if (IS_ERR(sys_ck)) {
+ 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;
}
- 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;
- }
+ 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"
+ */
+ sr->clk_length = fck_rate / (2 * SR_CLK);
+
+ dev_dbg(&sr->pdev->dev, "%s: SRCLKLENGTH = %03x\n", sr->clk_length);
}
static void sr_start_vddautocomp(struct smartreflex *sr)
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index e7ed7a1..59fff8a 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -119,14 +119,6 @@
#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.
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 19/26] OMAP2+: SmartReflex: Remove the notifier handler
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (17 preceding siblings ...)
2011-11-22 15:06 ` [PATCH 18/26] OMAP2+: Use the TRM formula to calculate the SmartReflex clock rate jean.pihet
@ 2011-11-22 15:06 ` jean.pihet
2011-11-22 15:06 ` [PATCH 20/26] OMAP2+: SmartReflex: make driver generic jean.pihet
` (8 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:06 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Paul Walmsley <paul@pwsan.com>
If needed should be handled by an atomic notifier. Currently no
code needs this.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 8 +++++---
arch/arm/mach-omap2/smartreflex.h | 5 -----
2 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 882f1d5..e57263a 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -110,8 +110,10 @@ static irqreturn_t sr_interrupt(int irq, void *data)
sr_write_reg(sr, IRQSTATUS, status);
}
- if (sr_class->notify)
- sr_class->notify(sr, status);
+ /*
+ * XXX If the class driver needs to be notified here, it should
+ * use an atomic notifier
+ */
return IRQ_HANDLED;
}
@@ -184,7 +186,7 @@ static int sr_late_init(struct smartreflex *sr)
struct resource *mem;
int ret = 0;
- if (sr_class->notify && sr_class->notify_flags && sr->irq) {
+ if (sr->irq) {
ret = request_irq(sr->irq, sr_interrupt, 0, sr->name,
(void *)sr);
if (ret)
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 59fff8a..e0e8ee3 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -187,9 +187,6 @@ struct omap_sr_dev_attr {
* @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.
@@ -198,8 +195,6 @@ struct smartreflex_class_data {
int (*enable)(struct smartreflex *sr);
int (*disable)(struct smartreflex *sr, int is_volt_reset);
int (*configure)(struct smartreflex *sr);
- int (*notify)(struct smartreflex *sr, u32 status);
- u8 notify_flags;
u8 class_type;
};
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 20/26] OMAP2+: SmartReflex: make driver generic
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (18 preceding siblings ...)
2011-11-22 15:06 ` [PATCH 19/26] OMAP2+: SmartReflex: Remove the notifier handler jean.pihet
@ 2011-11-22 15:06 ` jean.pihet
2011-11-22 15:06 ` [PATCH 21/26] OMAP2+: SmartReflex: get rid of superfluous data that is duplicated between platform_data and the struct omap_sr jean.pihet
` (7 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:06 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
Use the data from the SmartReflex data struct; make the driver
OMAP independent.
Based on Paul's original code for the SmartReflex driver conversion.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
---
arch/arm/mach-omap2/smartreflex.c | 129 ++++++++++++++----------------------
arch/arm/mach-omap2/smartreflex.h | 9 ++-
2 files changed, 55 insertions(+), 83 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index e57263a..2e37915 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -56,7 +56,6 @@ static inline void sr_modify_reg(struct smartreflex *sr, unsigned offset,
u32 mask, u32 value)
{
u32 reg_val;
- u32 errconfig_offs = 0, errconfig_mask = 0;
reg_val = __raw_readl(sr->base + offset);
reg_val &= ~mask;
@@ -70,16 +69,8 @@ static inline void sr_modify_reg(struct smartreflex *sr, unsigned offset,
* if they are currently set, but does allow the caller to write
* those bits.
*/
- 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;
+ if (offset == sr->errconfig_offs)
+ reg_val &= ~sr->errconfig_mask;
reg_val |= value;
@@ -118,16 +109,16 @@ static irqreturn_t sr_interrupt(int irq, void *data)
return IRQ_HANDLED;
}
-static void sr_set_clk_length(struct smartreflex *sr)
+static int sr_calculate_clk_length(struct smartreflex *sr)
{
struct clk *fck;
- int fck_rate;
+ int fck_rate, clk_length;
- fck = clk_get(sr->pdev->dev, "fck");
+ 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;
+ return 0;
}
fck_rate = clk_get_rate(fck);
clk_put(fck);
@@ -136,9 +127,12 @@ static void sr_set_clk_length(struct smartreflex *sr)
* This formula is from OMAP34xx TRM Rev ZH Section 4.10.5.4.3
* "SmartReflex Submodules"
*/
- sr->clk_length = fck_rate / (2 * SR_CLK);
+ clk_length = fck_rate / (2 * SR_CLK);
+
+ dev_dbg(&sr->pdev->dev, "%s: SRCLKLENGTH = %03x\n",
+ __func__, clk_length);
- dev_dbg(&sr->pdev->dev, "%s: SRCLKLENGTH = %03x\n", sr->clk_length);
+ return clk_length;
}
static void sr_start_vddautocomp(struct smartreflex *sr)
@@ -318,52 +312,28 @@ static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
*/
int sr_configure_errgen(struct smartreflex *sr)
{
- u32 sr_config, sr_errconfig, errconfig_offs, vpboundint_en;
- u32 vpboundint_st, senp_en = 0, senn_en = 0;
- u8 senp_shift, senn_shift;
+ u32 sr_config, sr_errconfig;
if (IS_ERR_OR_NULL(sr))
return -EINVAL;
- if (!sr->clk_length)
- sr_set_clk_length(sr);
-
- senp_en = sr->senp_mod;
- senn_en = sr->senn_mod;
-
- 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__);
+ if (!sr_calculate_clk_length(sr))
return -EINVAL;
- }
-
- sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
+
+ sr_config = sr->proto_sr_config;
+ sr_config |= SRCONFIG_ERRGEN_EN;
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_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, errconfig_offs,
- vpboundint_en, (vpboundint_en | vpboundint_st));
+ sr_modify_reg(sr, sr->errconfig_offs,
+ sr->vpboundint_en, (sr->vpboundint_en | sr->vpboundint_st));
return 0;
}
@@ -383,36 +353,14 @@ int sr_configure_errgen(struct smartreflex *sr)
int sr_configure_minmax(struct smartreflex *sr)
{
u32 sr_config, sr_avgwt;
- u32 senp_en = 0, senn_en = 0;
- u8 senp_shift, senn_shift;
if (IS_ERR_OR_NULL(sr))
return -EINVAL;
- if (!sr->clk_length)
- sr_set_clk_length(sr);
-
- senp_en = sr->senp_mod;
- senn_en = sr->senn_mod;
-
- 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_config = sr->proto_sr_config;
+ sr_config |= (sr->accum_data << SRCONFIG_ACCUMDATA_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);
@@ -719,15 +667,12 @@ static int __init omap_sr_probe(struct platform_device *pdev)
pdata->sr = sr;
sr->pdev = pdev;
- sr->srid = pdev->id;
sr->voltdm = pdata->voltdm;
sr->data_count = pdata->data_count;
sr->err_weight = pdata->err_weight;
sr->err_maxlimit = pdata->err_maxlimit;
sr->accum_data = pdata->accum_data;
- sr->senn_mod = pdata->senn_mod;
sr->senn_avgweight = pdata->senn_avgweight;
- sr->senp_mod = pdata->senp_mod;
sr->senp_avgweight = pdata->senp_avgweight;
sr->autocomp_active = false;
sr->ip_type = pdata->ip_type;
@@ -741,7 +686,33 @@ static int __init omap_sr_probe(struct platform_device *pdev)
if (irq)
sr->irq = irq->start;
- sr_set_clk_length(sr);
+ srclklength = sr_calculate_clk_length(sr);
+
+ sr->proto_sr_config = (srclklength << SRCONFIG_SRCLKLENGTH_SHIFT) |
+ SRCONFIG_SENENABLE;
+
+ if (sr->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 (sr->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));
list_add(&sr->node, &sr_list);
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index e0e8ee3..6ed1381 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -137,19 +137,19 @@
/* XXX kerneldoc documentation needed */
struct smartreflex {
char *name;
- int srid;
int ip_type;
int data_count;
bool autocomp_active;
- u32 clk_length;
u32 err_weight;
u32 err_minlimit;
u32 err_maxlimit;
u32 accum_data;
u32 senn_avgweight;
u32 senp_avgweight;
- u32 senp_mod;
- u32 senn_mod;
+ u32 errconfig_mask;
+ u32 vpboundint_en;
+ u32 vpboundint_st;
+ u32 proto_sr_config;
unsigned int irq;
void __iomem *base;
struct platform_device *pdev;
@@ -157,6 +157,7 @@ struct smartreflex {
struct omap_sr_data_table *data_table;
struct voltagedomain *voltdm;
struct dentry *dbg_dir;
+ u8 errconfig_offs;
};
/* XXX Kerneldoc documentation needed */
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 21/26] OMAP2+: SmartReflex: get rid of superfluous data that is duplicated between platform_data and the struct omap_sr
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (19 preceding siblings ...)
2011-11-22 15:06 ` [PATCH 20/26] OMAP2+: SmartReflex: make driver generic jean.pihet
@ 2011-11-22 15:06 ` jean.pihet
2011-11-22 15:06 ` [PATCH 22/26] OMAP2+: SmartReflex: remove OMAP specific code jean.pihet
` (6 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:06 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
Based on Paul's original code for the SmartReflex driver conversion.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
---
arch/arm/mach-omap2/smartreflex.c | 51 +++++++++++++++++++------------------
arch/arm/mach-omap2/smartreflex.h | 6 ----
2 files changed, 26 insertions(+), 31 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 2e37915..0f03d80 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -85,15 +85,16 @@ static inline u32 sr_read_reg(struct smartreflex *sr, unsigned 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 (sr->ip_type == SR_TYPE_V1) {
+ 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 (sr->ip_type == SR_TYPE_V2) {
+ } else if (pdata->ip_type == SR_TYPE_V2) {
/* Read the status bits */
status = sr_read_reg(sr, IRQSTATUS);
@@ -280,6 +281,7 @@ 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) {
@@ -288,7 +290,7 @@ static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
return NULL;
}
- for (i = 0; i < sr->data_count; i++) {
+ for (i = 0; i < pdata->data_count; i++) {
if (sr->data_table[i].volt_nominal == volt_nominal)
return &sr->data_table[i];
}
@@ -312,6 +314,7 @@ static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
*/
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))
@@ -324,8 +327,8 @@ int sr_configure_errgen(struct smartreflex *sr)
sr_config |= SRCONFIG_ERRGEN_EN;
sr_write_reg(sr, SRCONFIG, sr_config);
- sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
- (sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
+ 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),
@@ -352,31 +355,32 @@ int sr_configure_errgen(struct smartreflex *sr)
*/
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 |= (sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
+ sr_config |= (pdata->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
sr_write_reg(sr, SRCONFIG, sr_config);
- sr_avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
- (sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT);
+ 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 (sr->ip_type == SR_TYPE_V1) {
+ 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 (sr->ip_type == SR_TYPE_V2) {
+ } else if (pdata->ip_type == SR_TYPE_V2) {
sr_write_reg(sr, IRQSTATUS,
IRQSTATUS_MCUACCUMINT | IRQSTATUS_MCVALIDINT |
IRQSTATUS_MCBOUNDSINT | IRQSTATUS_MCUDISABLEACKINT);
@@ -444,6 +448,8 @@ int sr_enable(struct smartreflex *sr, unsigned long volt)
*/
void sr_disable(struct smartreflex *sr)
{
+ struct smartreflex_platform_data *pdata = sr->pdev->dev.platform_data;
+
if (IS_ERR_OR_NULL(sr))
return;
@@ -456,9 +462,9 @@ void sr_disable(struct smartreflex *sr)
* disable the clocks.
*/
if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) {
- if (sr->ip_type == SR_TYPE_V1)
+ if (pdata->ip_type == SR_TYPE_V1)
sr_v1_disable(sr);
- else if (sr->ip_type == SR_TYPE_V2)
+ else if (pdata->ip_type == SR_TYPE_V2)
sr_v2_disable(sr);
}
@@ -631,6 +637,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
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) {
@@ -668,14 +675,8 @@ static int __init omap_sr_probe(struct platform_device *pdev)
sr->pdev = pdev;
sr->voltdm = pdata->voltdm;
- sr->data_count = pdata->data_count;
- sr->err_weight = pdata->err_weight;
- sr->err_maxlimit = pdata->err_maxlimit;
- sr->accum_data = pdata->accum_data;
- sr->senn_avgweight = pdata->senn_avgweight;
- sr->senp_avgweight = pdata->senp_avgweight;
+
sr->autocomp_active = false;
- sr->ip_type = pdata->ip_type;
sr->base = ioremap(mem->start, resource_size(mem));
if (!sr->base) {
dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
@@ -691,7 +692,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
sr->proto_sr_config = (srclklength << SRCONFIG_SRCLKLENGTH_SHIFT) |
SRCONFIG_SENENABLE;
- if (sr->ip_type == SR_TYPE_V1) {
+ 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;
@@ -699,7 +700,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
sr->errconfig_mask = ERRCONFIG_STATUS_V1_MASK;
sr->vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
sr->vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
- } else if (sr->ip_type == SR_TYPE_V2) {
+ } 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;
@@ -757,9 +758,9 @@ static int __init omap_sr_probe(struct platform_device *pdev)
(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,
- &sr->err_weight);
+ &pdata->err_weight);
(void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr->dbg_dir,
- &sr->err_maxlimit);
+ &pdata->err_maxlimit);
nvalue_dir = debugfs_create_dir("nvalue", sr->dbg_dir);
if (IS_ERR(nvalue_dir)) {
@@ -768,13 +769,13 @@ static int __init omap_sr_probe(struct platform_device *pdev)
goto err_debugfs;
}
- if (sr->data_count == 0 || !sr->data_table) {
+ 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 < sr->data_count; i++) {
+ for (i = 0; i < pdata->data_count; i++) {
char name[NVALUE_NAME_LEN + 1];
/* XXX Also needs to include errminlimit! */
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 6ed1381..7cd7f84 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -138,14 +138,8 @@
struct smartreflex {
char *name;
int ip_type;
- int data_count;
bool autocomp_active;
- u32 err_weight;
u32 err_minlimit;
- u32 err_maxlimit;
- u32 accum_data;
- u32 senn_avgweight;
- u32 senp_avgweight;
u32 errconfig_mask;
u32 vpboundint_en;
u32 vpboundint_st;
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 22/26] OMAP2+: SmartReflex: remove OMAP specific code
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (20 preceding siblings ...)
2011-11-22 15:06 ` [PATCH 21/26] OMAP2+: SmartReflex: get rid of superfluous data that is duplicated between platform_data and the struct omap_sr jean.pihet
@ 2011-11-22 15:06 ` jean.pihet
2011-11-22 15:06 ` [PATCH 23/26] OMAP2+: SmartReflex: conversion into generic driver jean.pihet
` (5 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:06 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
In preparation for the generic driver implementation
Based on Paul's original code for the SmartReflex driver conversion.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
---
arch/arm/mach-omap2/smartreflex.c | 80 -------------------------------------
arch/arm/mach-omap2/smartreflex.h | 10 -----
2 files changed, 0 insertions(+), 90 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 0f03d80..947446f 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -507,86 +507,6 @@ int sr_register_class(struct smartreflex_class_data *class_data)
return 0;
}
-/**
- * omap_sr_enable() - API to enable SR clocks and to call into the
- * registered smartreflex class enable API.
- * @sr: struct smartreflex *
- *
- * 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 smartreflex *sr)
-{
- if (IS_ERR_OR_NULL(sr))
- 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(sr);
-}
-
-/**
- * omap_sr_disable() - API to disable SR without resetting the voltage
- * processor voltage
- * @sr: struct smartreflex *
- *
- * 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 smartreflex *sr)
-{
- if (IS_ERR_OR_NULL(sr))
- 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(sr, 0);
-}
-
-/**
- * omap_sr_disable_reset_volt() - API to disable SR and reset the
- * voltage processor voltage
- * @sr: struct smartreflex *
- *
- * 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 smartreflex *sr)
-{
- if (IS_ERR_OR_NULL(sr))
- 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(sr, 1);
-}
-
/* PM Debug Fs enteries to enable disable smartreflex. */
static int omap_sr_autocomp_show(void *data, u64 *val)
{
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 7cd7f84..5c641a8 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -245,11 +245,6 @@ struct smartreflex_platform_data {
struct smartreflex *sr;
};
-/* Smartreflex module enable/disable interface */
-void omap_sr_enable(struct smartreflex *sr);
-void omap_sr_disable(struct smartreflex *sr);
-void omap_sr_disable_reset_volt(struct smartreflex *sr);
-
/* Smartreflex driver hooks to be called from Smartreflex class driver */
int sr_enable(struct smartreflex *sr, unsigned long volt);
void sr_disable(struct smartreflex *sr);
@@ -258,10 +253,5 @@ int sr_configure_minmax(struct smartreflex *sr);
/* API to register the smartreflex class driver with the smartreflex driver */
int sr_register_class(struct smartreflex_class_data *class_data);
-#else
-static inline void omap_sr_enable(struct smartreflex *sr) {}
-static inline void omap_sr_disable(struct smartreflex *sr) {}
-static inline void omap_sr_disable_reset_volt(
- struct smartreflex *sr) {}
#endif
#endif
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 23/26] OMAP2+: SmartReflex: conversion into generic driver
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (21 preceding siblings ...)
2011-11-22 15:06 ` [PATCH 22/26] OMAP2+: SmartReflex: remove OMAP specific code jean.pihet
@ 2011-11-22 15:06 ` jean.pihet
2011-11-22 15:06 ` [PATCH 24/26] OMAP3+: voltage: export functions to plat/voltage.h jean.pihet
` (4 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:06 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
Use pdev and pdata to register the driver and pass data to it from the
platform code.
Based on Paul's original code for the SmartReflex driver conversion.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
---
arch/arm/mach-omap2/smartreflex-class3.c | 5 +-
arch/arm/mach-omap2/smartreflex.c | 120 ++++++++++--------------------
arch/arm/mach-omap2/smartreflex.h | 52 +++++++------
3 files changed, 69 insertions(+), 108 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index f741193..2d37f76 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -53,7 +53,10 @@ 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;
+
pr_info("SmartReflex Class3 initialized\n");
- return sr_register_class(&class3_data);
+ return sr_register_class(pdev, &class3_data);
}
late_initcall(sr_class3_init);
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 947446f..f7d305d 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -1,5 +1,5 @@
/*
- * SmartReflex Voltage Control
+ * Device driver for the SmartReflex IP block
*
* Author: Thara Gopinath <thara@ti.com>
*
@@ -40,10 +40,6 @@
*/
#define SR_CLK 100000 /* Hz */
-/* sr_list contains all the instances of smartreflex module */
-static LIST_HEAD(sr_list);
-
-static struct smartreflex_class_data *sr_class;
static struct dentry *sr_dbg_dir;
static inline void sr_write_reg(struct smartreflex *sr, unsigned offset,
@@ -138,20 +134,21 @@ static int sr_calculate_clk_length(struct smartreflex *sr)
static void sr_start_vddautocomp(struct smartreflex *sr)
{
- if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
+ 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_class->enable(sr))
+ if (!sr->sr_class->enable(sr))
sr->autocomp_active = true;
}
static void sr_stop_vddautocomp(struct smartreflex *sr)
{
- if (!sr_class || !(sr_class->disable)) {
+ if (!sr->sr_class || !sr->sr_class->disable) {
dev_warn(&sr->pdev->dev,
"%s: smartreflex class driver not registered\n",
__func__);
@@ -159,51 +156,11 @@ static void sr_stop_vddautocomp(struct smartreflex *sr)
}
if (sr->autocomp_active) {
- sr_class->disable(sr, 1);
+ sr->sr_class->disable(sr, 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.
- *
- * Currently this function registers interrupt 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 smartreflex *sr)
-{
- struct smartreflex_platform_data *pdata = sr->pdev->dev.platform_data;
- struct resource *mem;
- int ret = 0;
-
- if (sr->irq) {
- ret = request_irq(sr->irq, sr_interrupt, 0, sr->name,
- (void *)sr);
- if (ret)
- goto error;
- disable_irq(sr->irq);
- }
-
- if (pdata && pdata->enable_on_init)
- sr_start_vddautocomp(sr);
-
- return ret;
-
-error:
- iounmap(sr->base);
- mem = platform_get_resource(sr->pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, resource_size(mem));
- list_del(&sr->node);
- dev_err(&sr->pdev->dev, "%s: ERROR in registering interrupt handler. Smartreflex will not function as desired\n", __func__);
- kfree(sr);
- return ret;
-}
-
static void sr_v1_disable(struct smartreflex *sr)
{
int timeout = 0;
@@ -428,7 +385,7 @@ int sr_enable(struct smartreflex *sr, unsigned long volt)
return 0;
/* Configure SR */
- ret = sr_class->configure(sr);
+ ret = sr->sr_class->configure(sr);
if (ret)
return ret;
@@ -475,36 +432,51 @@ void sr_disable(struct smartreflex *sr)
* 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 smartreflex_class_data *class_data)
+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 (!class_data) {
- pr_warning("%s:, Smartreflex class data passed is NULL\n",
- __func__);
+ 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_class) {
- pr_warning("%s: Smartreflex class driver already registered\n",
- __func__);
- return -EBUSY;
+ 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_class = class_data;
+ sr->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, &sr_list, node)
- sr_late_init(sr);
+ if (pdata->enable_on_init)
+ sr_start_vddautocomp(sr);
- return 0;
+src_err:
+ return ret;
}
/* PM Debug Fs enteries to enable disable smartreflex. */
@@ -635,20 +607,6 @@ static int __init omap_sr_probe(struct platform_device *pdev)
sr->proto_sr_config |= ((pdata->senn_mod << senn_shift) |
(pdata->senp_mod << senp_shift));
- list_add(&sr->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);
- 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 (!sr_dbg_dir) {
sr_dbg_dir = debugfs_create_dir("smartreflex", NULL);
@@ -710,7 +668,6 @@ static int __init omap_sr_probe(struct platform_device *pdev)
err_debugfs:
debugfs_remove_recursive(sr->dbg_dir);
err_iounmap:
- list_del(&sr->node);
iounmap(sr->base);
err_release_region:
release_mem_region(mem->start, resource_size(mem));
@@ -743,7 +700,6 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
if (sr->dbg_dir)
debugfs_remove_recursive(sr->dbg_dir);
- list_del(&sr->node);
iounmap(sr->base);
kfree(sr);
pdata->sr = NULL;
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
index 5c641a8..30b7179 100644
--- a/arch/arm/mach-omap2/smartreflex.h
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -21,6 +21,7 @@
#define __ASM_ARM_OMAP_SMARTREFLEX_H
#include <linux/platform_device.h>
+#include <linux/interrupt.h>
#include "voltage.h"
@@ -134,6 +135,16 @@
#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;
@@ -149,35 +160,14 @@ struct smartreflex {
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;
};
-/* 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;
-};
-
-#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.
- */
-#define SR_CLASS1 0x1
-#define SR_CLASS2 0x2
-#define SR_CLASS3 0x3
-
/**
- * struct smartreflex_class_data - Smartreflex class driver info
+ * struct omap_sr_class_data - Smartreflex class driver info
*
* @enable: API to enable a particular class smaartreflex.
* @disable: API to disable a particular class smartreflex.
@@ -190,9 +180,21 @@ 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
*
@@ -252,6 +254,6 @@ int sr_configure_errgen(struct smartreflex *sr);
int sr_configure_minmax(struct smartreflex *sr);
/* API to register the smartreflex class driver with the smartreflex driver */
-int sr_register_class(struct smartreflex_class_data *class_data);
-#endif
+int sr_register_class(struct platform_device *pdev,
+ struct smartreflex_class_data *class_data);
#endif
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 24/26] OMAP3+: voltage: export functions to plat/voltage.h
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (22 preceding siblings ...)
2011-11-22 15:06 ` [PATCH 23/26] OMAP2+: SmartReflex: conversion into generic driver jean.pihet
@ 2011-11-22 15:06 ` jean.pihet
2011-11-22 15:06 ` [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework jean.pihet
` (3 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:06 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
Move some functions from mach-omap2/ dir to the plat/ dir.
The SmartReflex class driver is a user of the basic voltage domains
functions (enable, disable, reset).
Signed-off-by: Jean Pihet <j-pihet@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/voltage.h | 1 -
arch/arm/mach-omap2/vp.h | 2 --
arch/arm/plat-omap/include/plat/voltage.h | 3 +++
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index ebd8899..c2b7339 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -169,6 +169,5 @@ int voltdm_for_each_pwrdm(struct voltagedomain *voltdm,
int (*fn)(struct voltagedomain *voltdm,
struct powerdomain *pwrdm));
int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
-void voltdm_reset(struct voltagedomain *voltdm);
unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
#endif
diff --git a/arch/arm/mach-omap2/vp.h b/arch/arm/mach-omap2/vp.h
index 7c155d2..837cb8d 100644
--- a/arch/arm/mach-omap2/vp.h
+++ b/arch/arm/mach-omap2/vp.h
@@ -118,8 +118,6 @@ extern struct omap_vp_instance omap4_vp_iva;
extern struct omap_vp_instance omap4_vp_core;
void omap_vp_init(struct voltagedomain *voltdm);
-void omap_vp_enable(struct voltagedomain *voltdm);
-void omap_vp_disable(struct voltagedomain *voltdm);
int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
unsigned long target_volt);
int omap_vp_update_errorgain(struct voltagedomain *voltdm,
diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
index 0a6a482..1842709 100644
--- a/arch/arm/plat-omap/include/plat/voltage.h
+++ b/arch/arm/plat-omap/include/plat/voltage.h
@@ -16,5 +16,8 @@ struct voltagedomain;
struct voltagedomain *voltdm_lookup(const char *name);
int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
+void voltdm_reset(struct voltagedomain *voltdm);
+void omap_vp_enable(struct voltagedomain *voltdm);
+void omap_vp_disable(struct voltagedomain *voltdm);
#endif
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (23 preceding siblings ...)
2011-11-22 15:06 ` [PATCH 24/26] OMAP3+: voltage: export functions to plat/voltage.h jean.pihet
@ 2011-11-22 15:06 ` jean.pihet
2011-11-23 9:51 ` Felipe Balbi
2011-11-23 23:34 ` Todd Poynor
2011-11-22 15:06 ` [PATCH 26/26] PM: Create the AVS class of drivers jean.pihet
` (2 subsequent siblings)
27 siblings, 2 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:06 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
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@ti.com>
---
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@ti.com>
+ *
+ * Copyright (C) 2007,2010 Texas Instruments, Inc.
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * 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@ti.com>
- *
- * Copyright (C) 2007,2010 Texas Instruments, Inc.
- * Lesly A M <x0080970@ti.com>
- * Thara Gopinath <thara@ti.com>
- *
- * 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@ti.com>
+ *
+ * Copyright (C) 2007,2010 Texas Instruments, Inc.
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * 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@ti.com>
+ *
+ * Copyright (C) 2007,2010 Texas Instruments, Inc.
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * 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@ti.com>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <x0080970@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#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
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 26/26] PM: Create the AVS class of drivers
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (24 preceding siblings ...)
2011-11-22 15:06 ` [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework jean.pihet
@ 2011-11-22 15:06 ` jean.pihet
2011-11-22 16:43 ` [RFC/PATCH 00/26] " Mark Brown
[not found] ` <87mx9tu3x5.fsf@ti.com>
27 siblings, 0 replies; 43+ messages in thread
From: jean.pihet @ 2011-11-22 15:06 UTC (permalink / raw)
To: Linux OMAP Mailing List, paul, khilman, balbi, rjw; +Cc: Jean Pihet
From: Jean Pihet <j-pihet@ti.com>
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.
To that end, create the AVS framework in drivers/power/avs and
move the OMAP SmartReflex code to the new directory.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
arch/arm/mach-omap2/Kconfig | 57 ---
arch/arm/mach-omap2/Makefile | 3 -
arch/arm/mach-omap2/smartreflex-class3.c | 64 ----
arch/arm/mach-omap2/smartreflex-common.c | 543 ------------------------------
arch/arm/mach-omap2/smartreflex.h | 231 -------------
arch/arm/mach-omap2/smartreflex_v1.c | 183 ----------
arch/arm/mach-omap2/smartreflex_v2.c | 186 ----------
drivers/power/Kconfig | 2 +
drivers/power/Makefile | 2 +
drivers/power/avs/Kconfig | 56 +++
drivers/power/avs/Makefile | 4 +
drivers/power/avs/smartreflex-class3.c | 64 ++++
drivers/power/avs/smartreflex-common.c | 543 ++++++++++++++++++++++++++++++
drivers/power/avs/smartreflex.h | 231 +++++++++++++
drivers/power/avs/smartreflex_v1.c | 183 ++++++++++
drivers/power/avs/smartreflex_v2.c | 186 ++++++++++
16 files changed, 1271 insertions(+), 1267 deletions(-)
delete mode 100644 arch/arm/mach-omap2/smartreflex-class3.c
delete mode 100644 arch/arm/mach-omap2/smartreflex-common.c
delete mode 100644 arch/arm/mach-omap2/smartreflex.h
delete mode 100644 arch/arm/mach-omap2/smartreflex_v1.c
delete mode 100644 arch/arm/mach-omap2/smartreflex_v2.c
create mode 100644 drivers/power/avs/Kconfig
create mode 100644 drivers/power/avs/Makefile
create mode 100644 drivers/power/avs/smartreflex-class3.c
create mode 100644 drivers/power/avs/smartreflex-common.c
create mode 100644 drivers/power/avs/smartreflex.h
create mode 100644 drivers/power/avs/smartreflex_v1.c
create mode 100644 drivers/power/avs/smartreflex_v2.c
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 3faf921..09ea525 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -370,61 +370,4 @@ 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 6673ec5..74b4782 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -66,9 +66,6 @@ obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o
obj-$(CONFIG_PM_DEBUG) += pm-debug.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/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
deleted file mode 100644
index 516901b..0000000
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Smart reflex Class 3 specific implementations
- *
- * Author: Thara Gopinath <thara@ti.com>
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Thara Gopinath <thara@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "smartreflex.h"
-
-static int sr_class3_enable(struct smartreflex *sr)
-{
- unsigned long volt = voltdm_get_voltage(sr->voltdm);
-
- if (!volt) {
- pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
- __func__, sr->name);
- return -ENODATA;
- }
-
- omap_vp_enable(sr->voltdm);
- return sr_enable(sr, volt);
-}
-
-static int sr_class3_disable(struct smartreflex *sr, int is_volt_reset)
-{
- omap_vp_disable(sr->voltdm);
- sr_disable(sr);
- if (is_volt_reset)
- voltdm_reset(sr->voltdm);
-
- return 0;
-}
-
-static int sr_class3_configure(struct smartreflex *sr)
-{
- return sr_configure_errgen(sr);
-}
-
-/* SR class3 structure */
-static struct 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 */
-static int __init sr_class3_init(void)
-{
- struct platform_device *pdev = NULL;
- int ret = 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
deleted file mode 100644
index d693195..0000000
--- a/arch/arm/mach-omap2/smartreflex-common.c
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
- * Device driver for the SmartReflex IP blocks, common code
- *
- * Author: Thara Gopinath <thara@ti.com>
- *
- * Copyright (C) 2007,2010 Texas Instruments, Inc.
- * Lesly A M <x0080970@ti.com>
- * Thara Gopinath <thara@ti.com>
- *
- * 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.h b/arch/arm/mach-omap2/smartreflex.h
deleted file mode 100644
index 3395a48..0000000
--- a/arch/arm/mach-omap2/smartreflex.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * OMAP Smartreflex Defines and Routines
- *
- * Author: Thara Gopinath <thara@ti.com>
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Thara Gopinath <thara@ti.com>
- *
- * Copyright (C) 2008 Nokia Corporation
- * Kalle Jokiniemi
- *
- * Copyright (C) 2007 Texas Instruments, Inc.
- * Lesly A M <x0080970@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __DRIVERS_POWER_AVS_SMARTREFLEX_H
-#define __DRIVERS_POWER_AVS_SMARTREFLEX_H
-
-#include <linux/interrupt.h>
-#include <linux/io.h>
-
-#include <plat/smartreflex.h>
-#include <plat/voltage.h>
-
-#include "smartreflex.h"
-
-/*
- * 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
-
-/*
- * 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
-#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)
-
-/* 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;
- 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;
- unsigned int irq;
- irqreturn_t (*isr)(int irq, void *data);
- void (*disable)(struct smartreflex *sr);
- int (*configure_minmax)(struct smartreflex *sr);
-};
-
-/**
- * struct omap_sr_class_data - Smartreflex class driver info
- *
- * @enable: API to enable a particular class smaartreflex.
- * @disable: API to disable a particular class smartreflex.
- * @configure: API to configure a particular class smartreflex.
- * @class_type: specify which smartreflex class.
- * Can be used by the SR driver to take any class
- * based decisions.
- */
-struct smartreflex_class_data {
- int (*enable)(struct smartreflex *sr);
- int (*disable)(struct smartreflex *sr, int is_volt_reset);
- int (*configure)(struct smartreflex *sr);
- u8 class_type;
-};
-
-/* 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);
-void sr_disable(struct smartreflex *sr);
-int sr_configure_errgen(struct smartreflex *sr);
-int sr_configure_minmax(struct smartreflex *sr);
-
-/* API to register the smartreflex class driver with the smartreflex driver */
-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
deleted file mode 100644
index 5629632..0000000
--- a/arch/arm/mach-omap2/smartreflex_v1.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Device driver for the SmartReflex IP block v1
- *
- * Author: Thara Gopinath <thara@ti.com>
- *
- * Copyright (C) 2007,2010 Texas Instruments, Inc.
- * Lesly A M <x0080970@ti.com>
- * Thara Gopinath <thara@ti.com>
- *
- * 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
deleted file mode 100644
index 5fbbc8e..0000000
--- a/arch/arm/mach-omap2/smartreflex_v2.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Device driver for the SmartReflex IP block v2
- *
- * Author: Thara Gopinath <thara@ti.com>
- *
- * Copyright (C) 2007,2010 Texas Instruments, Inc.
- * Lesly A M <x0080970@ti.com>
- * Thara Gopinath <thara@ti.com>
- *
- * 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/drivers/power/Kconfig b/drivers/power/Kconfig
index 9f88641..945b427 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -251,3 +251,5 @@ config CHARGER_MAX8998
platform data of MAX8998/LP3974 PMICs.
endif # POWER_SUPPLY
+
+source "drivers/power/avs/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b4af13d..2bd3d16 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -38,3 +38,5 @@ obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
+
+obj-$(CONFIG_POWER_AVS) += avs/
diff --git a/drivers/power/avs/Kconfig b/drivers/power/avs/Kconfig
new file mode 100644
index 0000000..900a239
--- /dev/null
+++ b/drivers/power/avs/Kconfig
@@ -0,0 +1,56 @@
+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
diff --git a/drivers/power/avs/Makefile b/drivers/power/avs/Makefile
new file mode 100644
index 0000000..e263ab4
--- /dev/null
+++ b/drivers/power/avs/Makefile
@@ -0,0 +1,4 @@
+omap-3-4-common = smartreflex-common.o
+obj-$(CONFIG_POWER_AVS_OMAP_V1) += $(omap-3-4-common) smartreflex_v1.o
+obj-$(CONFIG_POWER_AVS_OMAP_V2) += $(omap-3-4-common) smartreflex_v2.o
+obj-$(CONFIG_POWER_AVS_OMAP_CLASS3) += smartreflex-class3.o
diff --git a/drivers/power/avs/smartreflex-class3.c b/drivers/power/avs/smartreflex-class3.c
new file mode 100644
index 0000000..516901b
--- /dev/null
+++ b/drivers/power/avs/smartreflex-class3.c
@@ -0,0 +1,64 @@
+/*
+ * Smart reflex Class 3 specific implementations
+ *
+ * Author: Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "smartreflex.h"
+
+static int sr_class3_enable(struct smartreflex *sr)
+{
+ unsigned long volt = voltdm_get_voltage(sr->voltdm);
+
+ if (!volt) {
+ pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
+ __func__, sr->name);
+ return -ENODATA;
+ }
+
+ omap_vp_enable(sr->voltdm);
+ return sr_enable(sr, volt);
+}
+
+static int sr_class3_disable(struct smartreflex *sr, int is_volt_reset)
+{
+ omap_vp_disable(sr->voltdm);
+ sr_disable(sr);
+ if (is_volt_reset)
+ voltdm_reset(sr->voltdm);
+
+ return 0;
+}
+
+static int sr_class3_configure(struct smartreflex *sr)
+{
+ return sr_configure_errgen(sr);
+}
+
+/* SR class3 structure */
+static struct 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 */
+static int __init sr_class3_init(void)
+{
+ struct platform_device *pdev = NULL;
+ int ret = sr_register_class(pdev, &class3_data);
+
+ if (!ret)
+ pr_info("SmartReflex Class3 initialized\n");
+
+ return ret;
+}
+late_initcall(sr_class3_init);
diff --git a/drivers/power/avs/smartreflex-common.c b/drivers/power/avs/smartreflex-common.c
new file mode 100644
index 0000000..d693195
--- /dev/null
+++ b/drivers/power/avs/smartreflex-common.c
@@ -0,0 +1,543 @@
+/*
+ * Device driver for the SmartReflex IP blocks, common code
+ *
+ * Author: Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2007,2010 Texas Instruments, Inc.
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * 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/drivers/power/avs/smartreflex.h b/drivers/power/avs/smartreflex.h
new file mode 100644
index 0000000..3395a48
--- /dev/null
+++ b/drivers/power/avs/smartreflex.h
@@ -0,0 +1,231 @@
+/*
+ * OMAP Smartreflex Defines and Routines
+ *
+ * Author: Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <x0080970@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DRIVERS_POWER_AVS_SMARTREFLEX_H
+#define __DRIVERS_POWER_AVS_SMARTREFLEX_H
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <plat/smartreflex.h>
+#include <plat/voltage.h>
+
+#include "smartreflex.h"
+
+/*
+ * 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
+
+/*
+ * 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
+#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)
+
+/* 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;
+ 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;
+ unsigned int irq;
+ irqreturn_t (*isr)(int irq, void *data);
+ void (*disable)(struct smartreflex *sr);
+ int (*configure_minmax)(struct smartreflex *sr);
+};
+
+/**
+ * struct omap_sr_class_data - Smartreflex class driver info
+ *
+ * @enable: API to enable a particular class smaartreflex.
+ * @disable: API to disable a particular class smartreflex.
+ * @configure: API to configure a particular class smartreflex.
+ * @class_type: specify which smartreflex class.
+ * Can be used by the SR driver to take any class
+ * based decisions.
+ */
+struct smartreflex_class_data {
+ int (*enable)(struct smartreflex *sr);
+ int (*disable)(struct smartreflex *sr, int is_volt_reset);
+ int (*configure)(struct smartreflex *sr);
+ u8 class_type;
+};
+
+/* 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);
+void sr_disable(struct smartreflex *sr);
+int sr_configure_errgen(struct smartreflex *sr);
+int sr_configure_minmax(struct smartreflex *sr);
+
+/* API to register the smartreflex class driver with the smartreflex driver */
+int sr_register_class(struct platform_device *pdev,
+ struct smartreflex_class_data *class_data);
+#endif
+
diff --git a/drivers/power/avs/smartreflex_v1.c b/drivers/power/avs/smartreflex_v1.c
new file mode 100644
index 0000000..5629632
--- /dev/null
+++ b/drivers/power/avs/smartreflex_v1.c
@@ -0,0 +1,183 @@
+/*
+ * Device driver for the SmartReflex IP block v1
+ *
+ * Author: Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2007,2010 Texas Instruments, Inc.
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * 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/drivers/power/avs/smartreflex_v2.c b/drivers/power/avs/smartreflex_v2.c
new file mode 100644
index 0000000..5fbbc8e
--- /dev/null
+++ b/drivers/power/avs/smartreflex_v2.c
@@ -0,0 +1,186 @@
+/*
+ * Device driver for the SmartReflex IP block v2
+ *
+ * Author: Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2007,2010 Texas Instruments, Inc.
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * 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");
--
1.7.5.4
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [RFC/PATCH 00/26] PM: Create the AVS class of drivers
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
` (25 preceding siblings ...)
2011-11-22 15:06 ` [PATCH 26/26] PM: Create the AVS class of drivers jean.pihet
@ 2011-11-22 16:43 ` Mark Brown
2011-11-22 17:40 ` Cousson, Benoit
[not found] ` <87mx9tu3x5.fsf@ti.com>
27 siblings, 1 reply; 43+ messages in thread
From: Mark Brown @ 2011-11-22 16:43 UTC (permalink / raw)
To: jean.pihet; +Cc: Linux OMAP Mailing List, paul, khilman, balbi, rjw, Jean Pihet
On Tue, Nov 22, 2011 at 04:05:44PM +0100, jean.pihet@newoldbits.com wrote:
> 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.
This sounds a lot like what devfreq (which was recently merged) is
supposed to do. Have you looked at the overlap there?
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [RFC/PATCH 00/26] PM: Create the AVS class of drivers
2011-11-22 16:43 ` [RFC/PATCH 00/26] " Mark Brown
@ 2011-11-22 17:40 ` Cousson, Benoit
2011-11-22 17:47 ` Mark Brown
0 siblings, 1 reply; 43+ messages in thread
From: Cousson, Benoit @ 2011-11-22 17:40 UTC (permalink / raw)
To: Mark Brown
Cc: jean.pihet, Linux OMAP Mailing List, paul, khilman, balbi, rjw,
Jean Pihet
Hi Mark,
On 11/22/2011 5:43 PM, Mark Brown wrote:
> On Tue, Nov 22, 2011 at 04:05:44PM +0100, jean.pihet@newoldbits.com wrote:
>
>> 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.
>
> This sounds a lot like what devfreq (which was recently merged) is
> supposed to do. Have you looked at the overlap there?
devfreq is a fmwk for DVFS governors at device level, whereas AVS stands
for Adaptive Voltage Scaling. This technique does not involve any
frequency change, and does a fine voltage adjustment to adapt to silicon
process / aging / thermal variation based on a HW closed loop.
Both DVFS and AVS can be used independently.
I think that AVS does belong to the voltage control infrastructure more
than the DVFS/freq one.
But that just my .2 cents
Regards,
Benoit
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [RFC/PATCH 00/26] PM: Create the AVS class of drivers
2011-11-22 17:40 ` Cousson, Benoit
@ 2011-11-22 17:47 ` Mark Brown
2011-11-22 20:01 ` Jean Pihet
0 siblings, 1 reply; 43+ messages in thread
From: Mark Brown @ 2011-11-22 17:47 UTC (permalink / raw)
To: Cousson, Benoit
Cc: jean.pihet, Linux OMAP Mailing List, paul, khilman, balbi, rjw,
Jean Pihet
On Tue, Nov 22, 2011 at 06:40:07PM +0100, Cousson, Benoit wrote:
> On 11/22/2011 5:43 PM, Mark Brown wrote:
> >This sounds a lot like what devfreq (which was recently merged) is
> >supposed to do. Have you looked at the overlap there?
> devfreq is a fmwk for DVFS governors at device level, whereas AVS
> stands for Adaptive Voltage Scaling. This technique does not involve
> any frequency change, and does a fine voltage adjustment to adapt to
> silicon process / aging / thermal variation based on a HW closed
> loop.
Ah, I see. It wasn't clear from the changelog that this was about fine
adjustmnets rather than operating point selection.
> Both DVFS and AVS can be used independently.
> I think that AVS does belong to the voltage control infrastructure
> more than the DVFS/freq one.
This does sound like the two may need to understand each other at some
point - if you want to do AVS on things that can vary their operating
point to fine tune the voltages that get set then you'll need to be able
to interface the two.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [RFC/PATCH 00/26] PM: Create the AVS class of drivers
2011-11-22 17:47 ` Mark Brown
@ 2011-11-22 20:01 ` Jean Pihet
0 siblings, 0 replies; 43+ messages in thread
From: Jean Pihet @ 2011-11-22 20:01 UTC (permalink / raw)
To: Mark Brown, Cousson, Benoit
Cc: Linux OMAP Mailing List, paul, khilman, balbi, rjw, Jean Pihet
Hi Mark, Benoit,
On Tue, Nov 22, 2011 at 6:47 PM, Mark Brown
<broonie@opensource.wolfsonmicro.com> wrote:
> On Tue, Nov 22, 2011 at 06:40:07PM +0100, Cousson, Benoit wrote:
>> On 11/22/2011 5:43 PM, Mark Brown wrote:
>
>> >This sounds a lot like what devfreq (which was recently merged) is
>> >supposed to do. Have you looked at the overlap there?
>
>> devfreq is a fmwk for DVFS governors at device level, whereas AVS
>> stands for Adaptive Voltage Scaling. This technique does not involve
>> any frequency change, and does a fine voltage adjustment to adapt to
>> silicon process / aging / thermal variation based on a HW closed
>> loop.
>
> Ah, I see. It wasn't clear from the changelog that this was about fine
> adjustmnets rather than operating point selection.
Ok I will update the commit description as well as the Kconfig description.
>
>> Both DVFS and AVS can be used independently.
>
>> I think that AVS does belong to the voltage control infrastructure
>> more than the DVFS/freq one.
>
> This does sound like the two may need to understand each other at some
> point - if you want to do AVS on things that can vary their operating
> point to fine tune the voltages that get set then you'll need to be able
> to interface the two.
Sure it is needed to notify the AVS code when the OPP changes, in
order to update the adjustment parameters of the SmartReflex IP.
I need to update my ToDo list with this point.
Thanks,
Jean
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework
2011-11-22 15:06 ` [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework jean.pihet
@ 2011-11-23 9:51 ` Felipe Balbi
2011-11-23 10:22 ` Jean Pihet
2011-11-23 23:34 ` Todd Poynor
1 sibling, 1 reply; 43+ messages in thread
From: Felipe Balbi @ 2011-11-23 9:51 UTC (permalink / raw)
To: jean.pihet; +Cc: Linux OMAP Mailing List, paul, khilman, balbi, rjw, Jean Pihet
[-- Attachment #1: Type: text/plain, Size: 1263 bytes --]
On Tue, Nov 22, 2011 at 04:06:09PM +0100, jean.pihet@newoldbits.com wrote:
> +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
can't you read the revision register and decide this in runtime ?
--
balbi
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework
2011-11-23 9:51 ` Felipe Balbi
@ 2011-11-23 10:22 ` Jean Pihet
2011-11-23 11:04 ` Felipe Balbi
0 siblings, 1 reply; 43+ messages in thread
From: Jean Pihet @ 2011-11-23 10:22 UTC (permalink / raw)
To: balbi; +Cc: Linux OMAP Mailing List, paul, khilman, rjw, Jean Pihet
Hi Felipe,
On Wed, Nov 23, 2011 at 10:51 AM, Felipe Balbi <balbi@ti.com> wrote:
> On Tue, Nov 22, 2011 at 04:06:09PM +0100, jean.pihet@newoldbits.com wrote:
>> +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
>
> can't you read the revision register and decide this in runtime ?
Those Kconfig options are used to compile the v1 and/or v2 drivers.
The init of v1 or v2 is decided at runtime, cf. the sr_init functions
where the cpu revision is checked. Is this the correct check?
>
> --
> balbi
>
Thanks,
Jean
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework
2011-11-23 10:22 ` Jean Pihet
@ 2011-11-23 11:04 ` Felipe Balbi
2011-11-23 11:30 ` Jean Pihet
0 siblings, 1 reply; 43+ messages in thread
From: Felipe Balbi @ 2011-11-23 11:04 UTC (permalink / raw)
To: Jean Pihet; +Cc: balbi, Linux OMAP Mailing List, paul, khilman, rjw, Jean Pihet
[-- Attachment #1: Type: text/plain, Size: 1981 bytes --]
On Wed, Nov 23, 2011 at 11:22:42AM +0100, Jean Pihet wrote:
> Hi Felipe,
>
> On Wed, Nov 23, 2011 at 10:51 AM, Felipe Balbi <balbi@ti.com> wrote:
> > On Tue, Nov 22, 2011 at 04:06:09PM +0100, jean.pihet@newoldbits.com wrote:
> >> +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
> >
> > can't you read the revision register and decide this in runtime ?
> Those Kconfig options are used to compile the v1 and/or v2 drivers.
> The init of v1 or v2 is decided at runtime, cf. the sr_init functions
> where the cpu revision is checked. Is this the correct check?
if you already decide in runtime the correct initialization to call, why
do you add ifdefs ? It's not like you're adding that huge amount of code
for v1 and v2, right ?
--
balbi
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework
2011-11-23 11:04 ` Felipe Balbi
@ 2011-11-23 11:30 ` Jean Pihet
2011-11-23 11:38 ` Felipe Balbi
2012-01-12 0:52 ` Kevin Hilman
0 siblings, 2 replies; 43+ messages in thread
From: Jean Pihet @ 2011-11-23 11:30 UTC (permalink / raw)
To: balbi; +Cc: Linux OMAP Mailing List, paul, khilman, rjw, Jean Pihet
Felipe,
On Wed, Nov 23, 2011 at 12:04 PM, Felipe Balbi <balbi@ti.com> wrote:
> On Wed, Nov 23, 2011 at 11:22:42AM +0100, Jean Pihet wrote:
>> Hi Felipe,
>>
>> On Wed, Nov 23, 2011 at 10:51 AM, Felipe Balbi <balbi@ti.com> wrote:
>> > On Tue, Nov 22, 2011 at 04:06:09PM +0100, jean.pihet@newoldbits.com wrote:
>> >> +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
>> >
>> > can't you read the revision register and decide this in runtime ?
>> Those Kconfig options are used to compile the v1 and/or v2 drivers.
>> The init of v1 or v2 is decided at runtime, cf. the sr_init functions
>> where the cpu revision is checked. Is this the correct check?
>
> if you already decide in runtime the correct initialization to call, why
> do you add ifdefs ?
There is no #ifdef with CONFIG_POWER_AVS_OMAP_V[12], those options are
used to compile or not the respective modules, cf.
driver/power/avs/Makefile.
> It's not like you're adding that huge amount of code
> for v1 and v2, right ?
That is correct, so both modules could be always compiled and init'ed
at runtime depending on the chip revision.
I am OK to change the code, please let me know what you think.
>
> --
> balbi
>
Thanks,
Jean
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework
2011-11-23 11:30 ` Jean Pihet
@ 2011-11-23 11:38 ` Felipe Balbi
2012-01-12 0:52 ` Kevin Hilman
1 sibling, 0 replies; 43+ messages in thread
From: Felipe Balbi @ 2011-11-23 11:38 UTC (permalink / raw)
To: Jean Pihet; +Cc: balbi, Linux OMAP Mailing List, paul, khilman, rjw, Jean Pihet
[-- Attachment #1: Type: text/plain, Size: 2229 bytes --]
Hi,
On Wed, Nov 23, 2011 at 12:30:54PM +0100, Jean Pihet wrote:
> >> On Wed, Nov 23, 2011 at 10:51 AM, Felipe Balbi <balbi@ti.com> wrote:
> >> > On Tue, Nov 22, 2011 at 04:06:09PM +0100, jean.pihet@newoldbits.com wrote:
> >> >> +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
> >> >
> >> > can't you read the revision register and decide this in runtime ?
> >> Those Kconfig options are used to compile the v1 and/or v2 drivers.
> >> The init of v1 or v2 is decided at runtime, cf. the sr_init functions
> >> where the cpu revision is checked. Is this the correct check?
> >
> > if you already decide in runtime the correct initialization to call, why
> > do you add ifdefs ?
> There is no #ifdef with CONFIG_POWER_AVS_OMAP_V[12], those options are
> used to compile or not the respective modules, cf.
> driver/power/avs/Makefile.
separate modules ? Can't that be combined into one driver only ?
--
balbi
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework
2011-11-22 15:06 ` [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework jean.pihet
2011-11-23 9:51 ` Felipe Balbi
@ 2011-11-23 23:34 ` Todd Poynor
2012-01-12 0:55 ` Kevin Hilman
1 sibling, 1 reply; 43+ messages in thread
From: Todd Poynor @ 2011-11-23 23:34 UTC (permalink / raw)
To: jean.pihet
Cc: Linux OMAP Mailing List, paul, khilman, balbi, rjw, Jean Pihet,
nm
...
> +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));
Nishanth Menon has a patch for the reversed order of parameters for
mask and bits to set in the above.
> +
> + return 0;
> +}
...
> +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;
Need free(sr->name) ?
> + }
> +
> + 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)) {
Sometimes set to NULL, use IS_ERR_OR_NULL ?
> + 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);
Need free(sr->name) ?
> + kfree(sr);
> + pdata->sr = NULL;
> + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + release_mem_region(mem->start, resource_size(mem));
> +
> + return 0;
> +}
...
> +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);
Felipe Balbi sent a patch to the list fixing the write of zero,
failing to clear the interrupts, to the list recently.
Todd
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework
2011-11-23 11:30 ` Jean Pihet
2011-11-23 11:38 ` Felipe Balbi
@ 2012-01-12 0:52 ` Kevin Hilman
2012-01-12 11:13 ` Jean Pihet
1 sibling, 1 reply; 43+ messages in thread
From: Kevin Hilman @ 2012-01-12 0:52 UTC (permalink / raw)
To: Jean Pihet; +Cc: balbi, Linux OMAP Mailing List, paul, rjw, Jean Pihet
Jean Pihet <jean.pihet@newoldbits.com> writes:
>> if you already decide in runtime the correct initialization to call, why
>> do you add ifdefs ?
>
> There is no #ifdef with CONFIG_POWER_AVS_OMAP_V[12], those options are
> used to compile or not the respective modules, cf.
> driver/power/avs/Makefile.
I'd suggest not even having user-selectable Kconfig for this.
Just have a single Kconfig for POWER_AVS, then have
config POWER_AVS_OMAP
default PM && (ARCH_OMAP3 || ARCH_OMAP4)
which compiles both versions of the OMAP IP.
Kevin
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework
2011-11-23 23:34 ` Todd Poynor
@ 2012-01-12 0:55 ` Kevin Hilman
2012-01-12 11:12 ` Jean Pihet
0 siblings, 1 reply; 43+ messages in thread
From: Kevin Hilman @ 2012-01-12 0:55 UTC (permalink / raw)
To: Todd Poynor
Cc: jean.pihet, Linux OMAP Mailing List, paul, balbi, rjw, Jean Pihet,
nm
Todd Poynor <toddpoynor@google.com> writes:
>> +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);
>
> Felipe Balbi sent a patch to the list fixing the write of zero,
> failing to clear the interrupts, to the list recently.
Right, this patch is in mainline now[1], so rebasing this series should
pick up this change.
Kevin
[1]
commit 5a4f1844c2ba21f804d7729306d9b16eaeb724a8
Author: Felipe Balbi <balbi@ti.com>
Date: Wed Nov 23 14:43:37 2011 -0800
ARM: OMAP: smartreflex: fix IRQ handling bug
Fix a bug which has been on this driver since
it was added by the original commit 984aa6db
which would never clear IRQSTATUS bits.
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
Cc: stable@vger.kernel.org
Signed-off-by: Tony Lindgren <tony@atomide.com>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [RFC/PATCH 00/26] PM: Create the AVS class of drivers
[not found] ` <87mx9tu3x5.fsf@ti.com>
@ 2012-01-12 1:06 ` Kevin Hilman
2012-01-12 11:17 ` Jean Pihet
1 sibling, 0 replies; 43+ messages in thread
From: Kevin Hilman @ 2012-01-12 1:06 UTC (permalink / raw)
To: jean.pihet, rjw; +Cc: Linux OMAP Mailing List, paul, balbi, Jean Pihet
On 01/11/2012 05:04 PM, Kevin Hilman wrote:
> This series looks like a good cleanup to me.
>
> Could you update this against current Linus tree which should now have
> all the OMAP stuff merged in and so we can get some broader testing here.
Oh, and when reposting, please also Cc linux-arm-kernel.
Thanks,
Kevin
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework
2012-01-12 0:55 ` Kevin Hilman
@ 2012-01-12 11:12 ` Jean Pihet
0 siblings, 0 replies; 43+ messages in thread
From: Jean Pihet @ 2012-01-12 11:12 UTC (permalink / raw)
To: Kevin Hilman, Todd Poynor
Cc: Linux OMAP Mailing List, paul, balbi, rjw, Jean Pihet, nm
Kevin, Todd,
On Thu, Jan 12, 2012 at 1:55 AM, Kevin Hilman <khilman@ti.com> wrote:
> Todd Poynor <toddpoynor@google.com> writes:
>
>>> +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);
>>
>> Felipe Balbi sent a patch to the list fixing the write of zero,
>> failing to clear the interrupts, to the list recently.
>
> Right, this patch is in mainline now[1], so rebasing this series should
> pick up this change.
I did include all the latest fixes from Felipe and Nishant in the
latest version. More details to come in the chang e logs.
Jean
>
> Kevin
>
> [1]
> commit 5a4f1844c2ba21f804d7729306d9b16eaeb724a8
> Author: Felipe Balbi <balbi@ti.com>
> Date: Wed Nov 23 14:43:37 2011 -0800
>
> ARM: OMAP: smartreflex: fix IRQ handling bug
>
> Fix a bug which has been on this driver since
> it was added by the original commit 984aa6db
> which would never clear IRQSTATUS bits.
>
> Signed-off-by: Felipe Balbi <balbi@ti.com>
> Signed-off-by: Kevin Hilman <khilman@ti.com>
> Cc: stable@vger.kernel.org
> Signed-off-by: Tony Lindgren <tony@atomide.com>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework
2012-01-12 0:52 ` Kevin Hilman
@ 2012-01-12 11:13 ` Jean Pihet
0 siblings, 0 replies; 43+ messages in thread
From: Jean Pihet @ 2012-01-12 11:13 UTC (permalink / raw)
To: Kevin Hilman; +Cc: balbi, Linux OMAP Mailing List, paul, rjw, Jean Pihet
Kevin,
On Thu, Jan 12, 2012 at 1:52 AM, Kevin Hilman <khilman@ti.com> wrote:
> Jean Pihet <jean.pihet@newoldbits.com> writes:
>
>>> if you already decide in runtime the correct initialization to call, why
>>> do you add ifdefs ?
>>
>> There is no #ifdef with CONFIG_POWER_AVS_OMAP_V[12], those options are
>> used to compile or not the respective modules, cf.
>> driver/power/avs/Makefile.
>
> I'd suggest not even having user-selectable Kconfig for this.
>
> Just have a single Kconfig for POWER_AVS, then have
>
> config POWER_AVS_OMAP
> default PM && (ARCH_OMAP3 || ARCH_OMAP4)
>
> which compiles both versions of the OMAP IP.
Ok will do that.
Regards,
Jean
>
> Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [RFC/PATCH 00/26] PM: Create the AVS class of drivers
[not found] ` <87mx9tu3x5.fsf@ti.com>
2012-01-12 1:06 ` Kevin Hilman
@ 2012-01-12 11:17 ` Jean Pihet
1 sibling, 0 replies; 43+ messages in thread
From: Jean Pihet @ 2012-01-12 11:17 UTC (permalink / raw)
To: Kevin Hilman; +Cc: rjw, Linux OMAP Mailing List, paul, balbi, Jean Pihet
Hi Kevin,
On Thu, Jan 12, 2012 at 2:04 AM, Kevin Hilman <khilman@ti.com> wrote:
> Hi Jean,
>
> jean.pihet@newoldbits.com writes:
>
>> From: Jean Pihet <j-pihet@ti.com>
>>
>> The following patches are in RFC state; the code is still WIP and has been
>> compile tested only. Feedback on the code organization is welcome!
>
> This series looks like a good cleanup to me.
>
> Could you update this against current Linus tree which should now have
> all the OMAP stuff merged in and so we can get some broader testing here.
Ok
>
> Rafael, are you OK with this as a new driver under drivers/power/avs?
> It's only the last patch that moves the cleaned up driver under
> drivers/power/avs.
>
> Maybe we should take this in two phases. For the v3.4 merge window, do
> the cleanup (patches 1-25), and for the following merge window, move it
> under drivers/power/avs and post it to a broader audience for
> discussion.
Doing it that way helps to identify the dependencies with other OMAP
specific code.
Let me refresh this patch series and re-send.
>
> Kevin
Regards,
Jean
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 43+ messages in thread
end of thread, other threads:[~2012-01-12 11:17 UTC | newest]
Thread overview: 43+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-22 15:05 [RFC/PATCH 00/26] PM: Create the AVS class of drivers jean.pihet
2011-11-22 15:05 ` [PATCH 01/26] OMAP2+: smartreflex: use sane default values jean.pihet
2011-11-22 15:05 ` [PATCH 02/26] OMAP3/4: SmartReflex: class drivers should use struct omap_sr * jean.pihet
2011-11-22 15:05 ` [PATCH 03/26] OMAP3/4: SmartReflex: API should use struct omap_sr *, not struct voltagedomain * jean.pihet
2011-11-22 15:05 ` [PATCH 04/26] OMAP: SmartReflex: drop _sr_lookup() jean.pihet
2011-11-22 15:05 ` [PATCH 05/26] OMAP: hwmod/SmartReflex: remove IP block instance-specific data from the driver code jean.pihet
2011-11-22 15:05 ` [PATCH 06/26] OMAP3+: Pass SmartReflex instance-specific data via hwmod dev_attr jean.pihet
2011-11-22 15:05 ` [PATCH 07/26] OMAP3+: hwmod: get rid of vdd_name field jean.pihet
2011-11-22 15:05 ` [PATCH 08/26] OMAP: SmartReflex: make pdata distinct from other data jean.pihet
2011-11-22 15:05 ` [PATCH 09/26] OMAP: SmartReflex: Use 'sr' for struct smartreflex jean.pihet
2011-11-22 15:05 ` [PATCH 10/26] OMAP2+: rename struct omap_sr_class_data to smartreflex_class_data jean.pihet
2011-11-22 15:05 ` [PATCH 11/26] OMAP3+: SmartReflex: remove unused PMIC code jean.pihet
2011-11-22 15:05 ` [PATCH 12/26] OMAP: SmartReflex: remove some SoC-specific implementation details from driver jean.pihet
2011-11-22 15:05 ` [PATCH 13/26] OMAP: SmartReflex driver interface: allow core to override eFuse data jean.pihet
2011-11-22 15:05 ` [PATCH 14/26] OMAP2+: Use the names from the SmartReflex data instead of voltage domains jean.pihet
2011-11-22 15:05 ` [PATCH 15/26] OMAP2+: SmartReflex: rename nvalue table jean.pihet
2011-11-22 15:06 ` [PATCH 16/26] OMAP2+: SmartReflex: cosmetic changes jean.pihet
2011-11-22 15:06 ` [PATCH 17/26] OMAP3+: Add SmartReflex clocks jean.pihet
2011-11-22 15:06 ` [PATCH 18/26] OMAP2+: Use the TRM formula to calculate the SmartReflex clock rate jean.pihet
2011-11-22 15:06 ` [PATCH 19/26] OMAP2+: SmartReflex: Remove the notifier handler jean.pihet
2011-11-22 15:06 ` [PATCH 20/26] OMAP2+: SmartReflex: make driver generic jean.pihet
2011-11-22 15:06 ` [PATCH 21/26] OMAP2+: SmartReflex: get rid of superfluous data that is duplicated between platform_data and the struct omap_sr jean.pihet
2011-11-22 15:06 ` [PATCH 22/26] OMAP2+: SmartReflex: remove OMAP specific code jean.pihet
2011-11-22 15:06 ` [PATCH 23/26] OMAP2+: SmartReflex: conversion into generic driver jean.pihet
2011-11-22 15:06 ` [PATCH 24/26] OMAP3+: voltage: export functions to plat/voltage.h jean.pihet
2011-11-22 15:06 ` [PATCH 25/26] OMAP: PM: convert the SmartReflex code into the AVS driver framework jean.pihet
2011-11-23 9:51 ` Felipe Balbi
2011-11-23 10:22 ` Jean Pihet
2011-11-23 11:04 ` Felipe Balbi
2011-11-23 11:30 ` Jean Pihet
2011-11-23 11:38 ` Felipe Balbi
2012-01-12 0:52 ` Kevin Hilman
2012-01-12 11:13 ` Jean Pihet
2011-11-23 23:34 ` Todd Poynor
2012-01-12 0:55 ` Kevin Hilman
2012-01-12 11:12 ` Jean Pihet
2011-11-22 15:06 ` [PATCH 26/26] PM: Create the AVS class of drivers jean.pihet
2011-11-22 16:43 ` [RFC/PATCH 00/26] " Mark Brown
2011-11-22 17:40 ` Cousson, Benoit
2011-11-22 17:47 ` Mark Brown
2011-11-22 20:01 ` Jean Pihet
[not found] ` <87mx9tu3x5.fsf@ti.com>
2012-01-12 1:06 ` Kevin Hilman
2012-01-12 11:17 ` Jean Pihet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).