Merge branch 'for_3.6/pm/sr-move' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into devel-driver
This commit is contained in:
@@ -70,8 +70,9 @@ obj-$(CONFIG_ARCH_OMAP3) += cpuidle34xx.o
|
|||||||
obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o
|
obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o
|
||||||
obj-$(CONFIG_ARCH_OMAP4) += cpuidle44xx.o
|
obj-$(CONFIG_ARCH_OMAP4) += cpuidle44xx.o
|
||||||
obj-$(CONFIG_PM_DEBUG) += pm-debug.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_OMAP) += sr_device.o
|
||||||
|
obj-$(CONFIG_POWER_AVS_OMAP_CLASS3) += smartreflex-class3.o
|
||||||
|
|
||||||
AFLAGS_sleep24xx.o :=-Wa,-march=armv6
|
AFLAGS_sleep24xx.o :=-Wa,-march=armv6
|
||||||
AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a$(plus_sec)
|
AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a$(plus_sec)
|
||||||
|
@@ -14,6 +14,8 @@
|
|||||||
*
|
*
|
||||||
* XXX these should be marked initdata for multi-OMAP kernels
|
* XXX these should be marked initdata for multi-OMAP kernels
|
||||||
*/
|
*/
|
||||||
|
#include <linux/power/smartreflex.h>
|
||||||
|
|
||||||
#include <plat/omap_hwmod.h>
|
#include <plat/omap_hwmod.h>
|
||||||
#include <mach/irqs.h>
|
#include <mach/irqs.h>
|
||||||
#include <plat/cpu.h>
|
#include <plat/cpu.h>
|
||||||
@@ -29,8 +31,6 @@
|
|||||||
#include <plat/dmtimer.h>
|
#include <plat/dmtimer.h>
|
||||||
|
|
||||||
#include "omap_hwmod_common_data.h"
|
#include "omap_hwmod_common_data.h"
|
||||||
|
|
||||||
#include "smartreflex.h"
|
|
||||||
#include "prm-regbits-34xx.h"
|
#include "prm-regbits-34xx.h"
|
||||||
#include "cm-regbits-34xx.h"
|
#include "cm-regbits-34xx.h"
|
||||||
#include "wd_timer.h"
|
#include "wd_timer.h"
|
||||||
@@ -1325,7 +1325,7 @@ static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct omap_hwmod omap34xx_sr1_hwmod = {
|
static struct omap_hwmod omap34xx_sr1_hwmod = {
|
||||||
.name = "sr1",
|
.name = "smartreflex_mpu_iva",
|
||||||
.class = &omap34xx_smartreflex_hwmod_class,
|
.class = &omap34xx_smartreflex_hwmod_class,
|
||||||
.main_clk = "sr1_fck",
|
.main_clk = "sr1_fck",
|
||||||
.prcm = {
|
.prcm = {
|
||||||
@@ -1343,7 +1343,7 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct omap_hwmod omap36xx_sr1_hwmod = {
|
static struct omap_hwmod omap36xx_sr1_hwmod = {
|
||||||
.name = "sr1",
|
.name = "smartreflex_mpu_iva",
|
||||||
.class = &omap36xx_smartreflex_hwmod_class,
|
.class = &omap36xx_smartreflex_hwmod_class,
|
||||||
.main_clk = "sr1_fck",
|
.main_clk = "sr1_fck",
|
||||||
.prcm = {
|
.prcm = {
|
||||||
@@ -1370,7 +1370,7 @@ static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct omap_hwmod omap34xx_sr2_hwmod = {
|
static struct omap_hwmod omap34xx_sr2_hwmod = {
|
||||||
.name = "sr2",
|
.name = "smartreflex_core",
|
||||||
.class = &omap34xx_smartreflex_hwmod_class,
|
.class = &omap34xx_smartreflex_hwmod_class,
|
||||||
.main_clk = "sr2_fck",
|
.main_clk = "sr2_fck",
|
||||||
.prcm = {
|
.prcm = {
|
||||||
@@ -1388,7 +1388,7 @@ static struct omap_hwmod omap34xx_sr2_hwmod = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct omap_hwmod omap36xx_sr2_hwmod = {
|
static struct omap_hwmod omap36xx_sr2_hwmod = {
|
||||||
.name = "sr2",
|
.name = "smartreflex_core",
|
||||||
.class = &omap36xx_smartreflex_hwmod_class,
|
.class = &omap36xx_smartreflex_hwmod_class,
|
||||||
.main_clk = "sr2_fck",
|
.main_clk = "sr2_fck",
|
||||||
.prcm = {
|
.prcm = {
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <linux/power/smartreflex.h>
|
||||||
|
|
||||||
#include <plat/omap_hwmod.h>
|
#include <plat/omap_hwmod.h>
|
||||||
#include <plat/cpu.h>
|
#include <plat/cpu.h>
|
||||||
@@ -32,8 +33,6 @@
|
|||||||
#include <plat/common.h>
|
#include <plat/common.h>
|
||||||
|
|
||||||
#include "omap_hwmod_common_data.h"
|
#include "omap_hwmod_common_data.h"
|
||||||
|
|
||||||
#include "smartreflex.h"
|
|
||||||
#include "cm1_44xx.h"
|
#include "cm1_44xx.h"
|
||||||
#include "cm2_44xx.h"
|
#include "cm2_44xx.h"
|
||||||
#include "prm44xx.h"
|
#include "prm44xx.h"
|
||||||
|
@@ -88,7 +88,7 @@ extern void enable_omap3630_toggle_l2_on_restore(void);
|
|||||||
static inline 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) */
|
#endif /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
|
||||||
|
|
||||||
#ifdef CONFIG_OMAP_SMARTREFLEX
|
#ifdef CONFIG_POWER_AVS_OMAP
|
||||||
extern int omap_devinit_smartreflex(void);
|
extern int omap_devinit_smartreflex(void);
|
||||||
extern void omap_enable_smartreflex_on_init(void);
|
extern void omap_enable_smartreflex_on_init(void);
|
||||||
#else
|
#else
|
||||||
|
@@ -11,36 +11,37 @@
|
|||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "smartreflex.h"
|
#include <linux/power/smartreflex.h>
|
||||||
|
#include "voltage.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) {
|
if (!volt) {
|
||||||
pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
|
pr_warning("%s: Curr voltage unknown. Cannot enable %s\n",
|
||||||
__func__, voltdm->name);
|
__func__, sr->name);
|
||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
omap_vp_enable(voltdm);
|
omap_vp_enable(sr->voltdm);
|
||||||
return sr_enable(voltdm, volt);
|
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)
|
||||||
{
|
{
|
||||||
sr_disable_errgen(voltdm);
|
sr_disable_errgen(sr->voltdm);
|
||||||
omap_vp_disable(voltdm);
|
omap_vp_disable(sr->voltdm);
|
||||||
sr_disable(voltdm);
|
sr_disable(sr->voltdm);
|
||||||
if (is_volt_reset)
|
if (is_volt_reset)
|
||||||
voltdm_reset(voltdm);
|
voltdm_reset(sr->voltdm);
|
||||||
|
|
||||||
return 0;
|
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 */
|
/* SR class3 structure */
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
#include <linux/power/smartreflex.h>
|
||||||
|
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
@@ -24,7 +25,6 @@
|
|||||||
|
|
||||||
#include <plat/omap_device.h>
|
#include <plat/omap_device.h>
|
||||||
|
|
||||||
#include "smartreflex.h"
|
|
||||||
#include "voltage.h"
|
#include "voltage.h"
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "pm.h"
|
#include "pm.h"
|
||||||
@@ -36,7 +36,10 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
|
|||||||
struct omap_sr_data *sr_data)
|
struct omap_sr_data *sr_data)
|
||||||
{
|
{
|
||||||
struct omap_sr_nvalue_table *nvalue_table;
|
struct omap_sr_nvalue_table *nvalue_table;
|
||||||
int i, count = 0;
|
int i, j, count = 0;
|
||||||
|
|
||||||
|
sr_data->nvalue_count = 0;
|
||||||
|
sr_data->nvalue_table = NULL;
|
||||||
|
|
||||||
while (volt_data[count].volt_nominal)
|
while (volt_data[count].volt_nominal)
|
||||||
count++;
|
count++;
|
||||||
@@ -44,8 +47,14 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
|
|||||||
nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count,
|
nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
if (!nvalue_table) {
|
||||||
|
pr_err("OMAP: SmartReflex: cannot allocate memory for n-value table\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, j = 0; i < count; i++) {
|
||||||
u32 v;
|
u32 v;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In OMAP4 the efuse registers are 24 bit aligned.
|
* In OMAP4 the efuse registers are 24 bit aligned.
|
||||||
* A __raw_readl will fail for non-32 bit aligned address
|
* A __raw_readl will fail for non-32 bit aligned address
|
||||||
@@ -61,12 +70,27 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
|
|||||||
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].efuse_offs = volt_data[i].sr_efuse_offs;
|
||||||
|
nvalue_table[j].errminlimit = volt_data[i].sr_errminlimit;
|
||||||
|
nvalue_table[j].volt_nominal = volt_data[i].volt_nominal;
|
||||||
|
|
||||||
|
j++;
|
||||||
}
|
}
|
||||||
|
|
||||||
sr_data->nvalue_table = nvalue_table;
|
sr_data->nvalue_table = nvalue_table;
|
||||||
sr_data->nvalue_count = count;
|
sr_data->nvalue_count = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
|
static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
|
||||||
@@ -93,6 +117,7 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sr_data->name = oh->name;
|
||||||
sr_data->ip_type = oh->class->rev;
|
sr_data->ip_type = oh->class->rev;
|
||||||
sr_data->senn_mod = 0x1;
|
sr_data->senn_mod = 0x1;
|
||||||
sr_data->senp_mod = 0x1;
|
sr_data->senp_mod = 0x1;
|
||||||
|
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
|
||||||
|
#include <plat/voltage.h>
|
||||||
|
|
||||||
#include "vc.h"
|
#include "vc.h"
|
||||||
#include "vp.h"
|
#include "vp.h"
|
||||||
|
|
||||||
@@ -90,25 +92,6 @@ struct voltagedomain {
|
|||||||
struct omap_volt_data *volt_data;
|
struct omap_volt_data *volt_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* struct omap_volt_data - Omap voltage specific data.
|
|
||||||
* @voltage_nominal: The possible voltage value in uV
|
|
||||||
* @sr_efuse_offs: The offset of the efuse register(from system
|
|
||||||
* control module base address) from where to read
|
|
||||||
* the n-target value for the smartreflex module.
|
|
||||||
* @sr_errminlimit: Error min limit value for smartreflex. This value
|
|
||||||
* differs at differnet opp and thus is linked
|
|
||||||
* with voltage.
|
|
||||||
* @vp_errorgain: Error gain value for the voltage processor. This
|
|
||||||
* field also differs according to the voltage/opp.
|
|
||||||
*/
|
|
||||||
struct omap_volt_data {
|
|
||||||
u32 volt_nominal;
|
|
||||||
u32 sr_efuse_offs;
|
|
||||||
u8 sr_errminlimit;
|
|
||||||
u8 vp_errgain;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
|
* struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
|
||||||
* @slew_rate: PMIC slew rate (in uv/us)
|
* @slew_rate: PMIC slew rate (in uv/us)
|
||||||
|
@@ -45,31 +45,30 @@ config OMAP_DEBUG_LEDS
|
|||||||
depends on OMAP_DEBUG_DEVICES
|
depends on OMAP_DEBUG_DEVICES
|
||||||
default y if LEDS_CLASS
|
default y if LEDS_CLASS
|
||||||
|
|
||||||
config OMAP_SMARTREFLEX
|
config POWER_AVS_OMAP
|
||||||
bool "SmartReflex support"
|
bool "AVS(Adaptive Voltage Scaling) support for OMAP IP versions 1&2"
|
||||||
depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM
|
depends on POWER_AVS && (ARCH_OMAP3 || ARCH_OMAP4) && PM
|
||||||
help
|
help
|
||||||
Say Y if you want to enable SmartReflex.
|
Say Y to enable AVS(Adaptive Voltage Scaling)
|
||||||
|
support on OMAP containing the version 1 or
|
||||||
SmartReflex can perform continuous dynamic voltage
|
version 2 of the SmartReflex IP.
|
||||||
scaling around the nominal operating point voltage
|
V1 is the 65nm version used in OMAP3430.
|
||||||
according to silicon characteristics and operating
|
V2 is the update for the 45nm version of the IP used in OMAP3630
|
||||||
conditions. Enabling SmartReflex reduces power
|
and OMAP4430
|
||||||
consumption.
|
|
||||||
|
|
||||||
Please note, that by default SmartReflex is only
|
Please note, that by default SmartReflex is only
|
||||||
initialized. To enable the automatic voltage
|
initialized and not enabled. To enable the automatic voltage
|
||||||
compensation for vdd mpu and vdd core from user space,
|
compensation for vdd mpu and vdd core from user space,
|
||||||
user must write 1 to
|
user must write 1 to
|
||||||
/debug/voltage/vdd_<X>/smartreflex/autocomp,
|
/debug/smartreflex/sr_<X>/autocomp,
|
||||||
where X is mpu or core for OMAP3.
|
where X is mpu_iva or core for OMAP3.
|
||||||
Optionally autocompensation can be enabled in the kernel
|
Optionally autocompensation can be enabled in the kernel
|
||||||
by default during system init via the enable_on_init flag
|
by default during system init via the enable_on_init flag
|
||||||
which an be passed as platform data to the smartreflex driver.
|
which an be passed as platform data to the smartreflex driver.
|
||||||
|
|
||||||
config OMAP_SMARTREFLEX_CLASS3
|
config POWER_AVS_OMAP_CLASS3
|
||||||
bool "Class 3 mode of Smartreflex Implementation"
|
bool "Class 3 mode of Smartreflex Implementation"
|
||||||
depends on OMAP_SMARTREFLEX && TWL4030_CORE
|
depends on POWER_AVS_OMAP && TWL4030_CORE
|
||||||
help
|
help
|
||||||
Say Y to enable Class 3 implementation of Smartreflex
|
Say Y to enable Class 3 implementation of Smartreflex
|
||||||
|
|
||||||
|
@@ -11,10 +11,29 @@
|
|||||||
#ifndef __ARCH_ARM_OMAP_VOLTAGE_H
|
#ifndef __ARCH_ARM_OMAP_VOLTAGE_H
|
||||||
#define __ARCH_ARM_OMAP_VOLTAGE_H
|
#define __ARCH_ARM_OMAP_VOLTAGE_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct omap_volt_data - Omap voltage specific data.
|
||||||
|
* @voltage_nominal: The possible voltage value in uV
|
||||||
|
* @sr_efuse_offs: The offset of the efuse register(from system
|
||||||
|
* control module base address) from where to read
|
||||||
|
* the n-target value for the smartreflex module.
|
||||||
|
* @sr_errminlimit: Error min limit value for smartreflex. This value
|
||||||
|
* differs at differnet opp and thus is linked
|
||||||
|
* with voltage.
|
||||||
|
* @vp_errorgain: Error gain value for the voltage processor. This
|
||||||
|
* field also differs according to the voltage/opp.
|
||||||
|
*/
|
||||||
|
struct omap_volt_data {
|
||||||
|
u32 volt_nominal;
|
||||||
|
u32 sr_efuse_offs;
|
||||||
|
u8 sr_errminlimit;
|
||||||
|
u8 vp_errgain;
|
||||||
|
};
|
||||||
struct voltagedomain;
|
struct voltagedomain;
|
||||||
|
|
||||||
struct voltagedomain *voltdm_lookup(const char *name);
|
struct voltagedomain *voltdm_lookup(const char *name);
|
||||||
int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
|
int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
|
||||||
unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
|
unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
|
||||||
|
struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
|
||||||
|
unsigned long volt);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -310,3 +310,5 @@ config AB8500_BATTERY_THERM_ON_BATCTRL
|
|||||||
Say Y to enable battery temperature measurements using
|
Say Y to enable battery temperature measurements using
|
||||||
thermistor connected on BATCTRL ADC.
|
thermistor connected on BATCTRL ADC.
|
||||||
endif # POWER_SUPPLY
|
endif # POWER_SUPPLY
|
||||||
|
|
||||||
|
source "drivers/power/avs/Kconfig"
|
||||||
|
@@ -43,4 +43,5 @@ obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
|
|||||||
obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o
|
obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o
|
||||||
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
|
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
|
||||||
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
|
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
|
||||||
|
obj-$(CONFIG_POWER_AVS) += avs/
|
||||||
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
|
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
|
||||||
|
12
drivers/power/avs/Kconfig
Normal file
12
drivers/power/avs/Kconfig
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
menuconfig POWER_AVS
|
||||||
|
tristate "Adaptive Voltage Scaling class support"
|
||||||
|
help
|
||||||
|
AVS is a power management technique which finely controls the
|
||||||
|
operating voltage of a device in order to optimize (i.e. reduce)
|
||||||
|
its power consumption.
|
||||||
|
At a given operating point 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.
|
1
drivers/power/avs/Makefile
Normal file
1
drivers/power/avs/Makefile
Normal file
@@ -0,0 +1 @@
|
|||||||
|
obj-$(CONFIG_POWER_AVS_OMAP) += smartreflex.o
|
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Author: Thara Gopinath <thara@ti.com>
|
* Author: Thara Gopinath <thara@ti.com>
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 Texas Instruments, Inc.
|
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||||
* Thara Gopinath <thara@ti.com>
|
* Thara Gopinath <thara@ti.com>
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008 Nokia Corporation
|
* Copyright (C) 2008 Nokia Corporation
|
||||||
@@ -25,39 +25,12 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/power/smartreflex.h>
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#include "pm.h"
|
|
||||||
#include "smartreflex.h"
|
|
||||||
|
|
||||||
#define SMARTREFLEX_NAME_LEN 16
|
#define SMARTREFLEX_NAME_LEN 16
|
||||||
#define NVALUE_NAME_LEN 40
|
#define NVALUE_NAME_LEN 40
|
||||||
#define SR_DISABLE_TIMEOUT 200
|
#define SR_DISABLE_TIMEOUT 200
|
||||||
|
|
||||||
struct omap_sr {
|
|
||||||
struct list_head node;
|
|
||||||
struct platform_device *pdev;
|
|
||||||
struct omap_sr_nvalue_table *nvalue_table;
|
|
||||||
struct voltagedomain *voltdm;
|
|
||||||
struct dentry *dbg_dir;
|
|
||||||
unsigned int irq;
|
|
||||||
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;
|
|
||||||
void __iomem *base;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* sr_list contains all the instances of smartreflex module */
|
/* sr_list contains all the instances of smartreflex module */
|
||||||
static LIST_HEAD(sr_list);
|
static LIST_HEAD(sr_list);
|
||||||
|
|
||||||
@@ -148,7 +121,7 @@ static irqreturn_t sr_interrupt(int irq, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sr_class->notify)
|
if (sr_class->notify)
|
||||||
sr_class->notify(sr_info->voltdm, status);
|
sr_class->notify(sr_info, status);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
@@ -207,7 +180,7 @@ static void sr_set_regfields(struct omap_sr *sr)
|
|||||||
sr->err_weight = OMAP3430_SR_ERRWEIGHT;
|
sr->err_weight = OMAP3430_SR_ERRWEIGHT;
|
||||||
sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
|
sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
|
||||||
sr->accum_data = OMAP3430_SR_ACCUMDATA;
|
sr->accum_data = OMAP3430_SR_ACCUMDATA;
|
||||||
if (!(strcmp(sr->voltdm->name, "mpu"))) {
|
if (!(strcmp(sr->name, "smartreflex_mpu_iva"))) {
|
||||||
sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
|
sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
|
||||||
sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
|
sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
|
||||||
} else {
|
} else {
|
||||||
@@ -226,7 +199,7 @@ static void sr_start_vddautocomp(struct omap_sr *sr)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sr_class->enable(sr->voltdm))
|
if (!sr_class->enable(sr))
|
||||||
sr->autocomp_active = true;
|
sr->autocomp_active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +213,7 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sr->autocomp_active) {
|
if (sr->autocomp_active) {
|
||||||
sr_class->disable(sr->voltdm, 1);
|
sr_class->disable(sr, 1);
|
||||||
sr->autocomp_active = false;
|
sr->autocomp_active = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,19 +231,13 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)
|
|||||||
*/
|
*/
|
||||||
static int sr_late_init(struct omap_sr *sr_info)
|
static int sr_late_init(struct omap_sr *sr_info)
|
||||||
{
|
{
|
||||||
char *name;
|
|
||||||
struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data;
|
struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data;
|
||||||
struct resource *mem;
|
struct resource *mem;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
|
if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
|
||||||
name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
|
|
||||||
if (name == NULL) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
ret = request_irq(sr_info->irq, sr_interrupt,
|
ret = request_irq(sr_info->irq, sr_interrupt,
|
||||||
0, name, sr_info);
|
0, sr_info->name, sr_info);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
disable_irq(sr_info->irq);
|
disable_irq(sr_info->irq);
|
||||||
@@ -289,7 +256,6 @@ error:
|
|||||||
dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
|
dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
|
||||||
"interrupt handler. Smartreflex will"
|
"interrupt handler. Smartreflex will"
|
||||||
"not function as desired\n", __func__);
|
"not function as desired\n", __func__);
|
||||||
kfree(name);
|
|
||||||
kfree(sr_info);
|
kfree(sr_info);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -320,7 +286,7 @@ static void sr_v1_disable(struct omap_sr *sr)
|
|||||||
* Wait for SR to be disabled.
|
* Wait for SR to be disabled.
|
||||||
* wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us.
|
* wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us.
|
||||||
*/
|
*/
|
||||||
omap_test_timeout((sr_read_reg(sr, ERRCONFIG_V1) &
|
sr_test_cond_timeout((sr_read_reg(sr, ERRCONFIG_V1) &
|
||||||
ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT,
|
ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT,
|
||||||
timeout);
|
timeout);
|
||||||
|
|
||||||
@@ -365,7 +331,7 @@ static void sr_v2_disable(struct omap_sr *sr)
|
|||||||
* Wait for SR to be disabled.
|
* Wait for SR to be disabled.
|
||||||
* wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us.
|
* wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us.
|
||||||
*/
|
*/
|
||||||
omap_test_timeout((sr_read_reg(sr, IRQSTATUS) &
|
sr_test_cond_timeout((sr_read_reg(sr, IRQSTATUS) &
|
||||||
IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT,
|
IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT,
|
||||||
timeout);
|
timeout);
|
||||||
|
|
||||||
@@ -378,22 +344,23 @@ static void sr_v2_disable(struct omap_sr *sr)
|
|||||||
sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
|
sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)
|
static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
|
||||||
|
struct omap_sr *sr, u32 efuse_offs)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!sr->nvalue_table) {
|
if (!sr->nvalue_table) {
|
||||||
dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
|
dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
|
||||||
__func__);
|
__func__);
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < sr->nvalue_count; i++) {
|
for (i = 0; i < sr->nvalue_count; i++) {
|
||||||
if (sr->nvalue_table[i].efuse_offs == efuse_offs)
|
if (sr->nvalue_table[i].efuse_offs == efuse_offs)
|
||||||
return sr->nvalue_table[i].nvalue;
|
return &sr->nvalue_table[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Public Functions */
|
/* Public Functions */
|
||||||
@@ -419,8 +386,7 @@ int sr_configure_errgen(struct voltagedomain *voltdm)
|
|||||||
struct omap_sr *sr = _sr_lookup(voltdm);
|
struct omap_sr *sr = _sr_lookup(voltdm);
|
||||||
|
|
||||||
if (IS_ERR(sr)) {
|
if (IS_ERR(sr)) {
|
||||||
pr_warning("%s: omap_sr struct for sr_%s not found\n",
|
pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
|
||||||
__func__, voltdm->name);
|
|
||||||
return PTR_ERR(sr);
|
return PTR_ERR(sr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,8 +453,7 @@ int sr_disable_errgen(struct voltagedomain *voltdm)
|
|||||||
struct omap_sr *sr = _sr_lookup(voltdm);
|
struct omap_sr *sr = _sr_lookup(voltdm);
|
||||||
|
|
||||||
if (IS_ERR(sr)) {
|
if (IS_ERR(sr)) {
|
||||||
pr_warning("%s: omap_sr struct for sr_%s not found\n",
|
pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
|
||||||
__func__, voltdm->name);
|
|
||||||
return PTR_ERR(sr);
|
return PTR_ERR(sr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,8 +503,7 @@ int sr_configure_minmax(struct voltagedomain *voltdm)
|
|||||||
struct omap_sr *sr = _sr_lookup(voltdm);
|
struct omap_sr *sr = _sr_lookup(voltdm);
|
||||||
|
|
||||||
if (IS_ERR(sr)) {
|
if (IS_ERR(sr)) {
|
||||||
pr_warning("%s: omap_sr struct for sr_%s not found\n",
|
pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
|
||||||
__func__, voltdm->name);
|
|
||||||
return PTR_ERR(sr);
|
return PTR_ERR(sr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -620,12 +584,11 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
|
|||||||
{
|
{
|
||||||
struct omap_volt_data *volt_data;
|
struct omap_volt_data *volt_data;
|
||||||
struct omap_sr *sr = _sr_lookup(voltdm);
|
struct omap_sr *sr = _sr_lookup(voltdm);
|
||||||
u32 nvalue_reciprocal;
|
struct omap_sr_nvalue_table *nvalue_row;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (IS_ERR(sr)) {
|
if (IS_ERR(sr)) {
|
||||||
pr_warning("%s: omap_sr struct for sr_%s not found\n",
|
pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
|
||||||
__func__, voltdm->name);
|
|
||||||
return PTR_ERR(sr);
|
return PTR_ERR(sr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,16 +600,16 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
|
|||||||
return PTR_ERR(volt_data);
|
return PTR_ERR(volt_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
nvalue_reciprocal = sr_retrieve_nvalue(sr, volt_data->sr_efuse_offs);
|
nvalue_row = sr_retrieve_nvalue_row(sr, volt_data->sr_efuse_offs);
|
||||||
|
|
||||||
if (!nvalue_reciprocal) {
|
if (!nvalue_row) {
|
||||||
dev_warn(&sr->pdev->dev, "%s: NVALUE = 0 at voltage %ld\n",
|
dev_warn(&sr->pdev->dev, "%s: failure getting SR data for this voltage %ld\n",
|
||||||
__func__, volt);
|
__func__, volt);
|
||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* errminlimit is opp dependent and hence linked to voltage */
|
/* 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);
|
pm_runtime_get_sync(&sr->pdev->dev);
|
||||||
|
|
||||||
@@ -655,11 +618,11 @@ int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Configure SR */
|
/* Configure SR */
|
||||||
ret = sr_class->configure(voltdm);
|
ret = sr_class->configure(sr);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
|
sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue);
|
||||||
|
|
||||||
/* SRCONFIG - enable SR */
|
/* SRCONFIG - enable SR */
|
||||||
sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
|
sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
|
||||||
@@ -678,8 +641,7 @@ void sr_disable(struct voltagedomain *voltdm)
|
|||||||
struct omap_sr *sr = _sr_lookup(voltdm);
|
struct omap_sr *sr = _sr_lookup(voltdm);
|
||||||
|
|
||||||
if (IS_ERR(sr)) {
|
if (IS_ERR(sr)) {
|
||||||
pr_warning("%s: omap_sr struct for sr_%s not found\n",
|
pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
|
||||||
__func__, voltdm->name);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -759,8 +721,7 @@ void omap_sr_enable(struct voltagedomain *voltdm)
|
|||||||
struct omap_sr *sr = _sr_lookup(voltdm);
|
struct omap_sr *sr = _sr_lookup(voltdm);
|
||||||
|
|
||||||
if (IS_ERR(sr)) {
|
if (IS_ERR(sr)) {
|
||||||
pr_warning("%s: omap_sr struct for sr_%s not found\n",
|
pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
|
||||||
__func__, voltdm->name);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -773,7 +734,7 @@ void omap_sr_enable(struct voltagedomain *voltdm)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sr_class->enable(voltdm);
|
sr_class->enable(sr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -792,8 +753,7 @@ void omap_sr_disable(struct voltagedomain *voltdm)
|
|||||||
struct omap_sr *sr = _sr_lookup(voltdm);
|
struct omap_sr *sr = _sr_lookup(voltdm);
|
||||||
|
|
||||||
if (IS_ERR(sr)) {
|
if (IS_ERR(sr)) {
|
||||||
pr_warning("%s: omap_sr struct for sr_%s not found\n",
|
pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
|
||||||
__func__, voltdm->name);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -806,7 +766,7 @@ void omap_sr_disable(struct voltagedomain *voltdm)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sr_class->disable(voltdm, 0);
|
sr_class->disable(sr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -825,8 +785,7 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
|
|||||||
struct omap_sr *sr = _sr_lookup(voltdm);
|
struct omap_sr *sr = _sr_lookup(voltdm);
|
||||||
|
|
||||||
if (IS_ERR(sr)) {
|
if (IS_ERR(sr)) {
|
||||||
pr_warning("%s: omap_sr struct for sr_%s not found\n",
|
pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
|
||||||
__func__, voltdm->name);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -839,7 +798,7 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sr_class->disable(voltdm, 1);
|
sr_class->disable(sr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -911,9 +870,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
|||||||
struct omap_sr_data *pdata = pdev->dev.platform_data;
|
struct omap_sr_data *pdata = pdev->dev.platform_data;
|
||||||
struct resource *mem, *irq;
|
struct resource *mem, *irq;
|
||||||
struct dentry *nvalue_dir;
|
struct dentry *nvalue_dir;
|
||||||
struct omap_volt_data *volt_data;
|
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
char *name;
|
|
||||||
|
|
||||||
sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
|
sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
|
||||||
if (!sr_info) {
|
if (!sr_info) {
|
||||||
@@ -950,6 +907,14 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
|||||||
pm_runtime_enable(&pdev->dev);
|
pm_runtime_enable(&pdev->dev);
|
||||||
pm_runtime_irq_safe(&pdev->dev);
|
pm_runtime_irq_safe(&pdev->dev);
|
||||||
|
|
||||||
|
sr_info->name = kasprintf(GFP_KERNEL, "%s", pdata->name);
|
||||||
|
if (!sr_info->name) {
|
||||||
|
dev_err(&pdev->dev, "%s: Unable to alloc SR instance name\n",
|
||||||
|
__func__);
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err_release_region;
|
||||||
|
}
|
||||||
|
|
||||||
sr_info->pdev = pdev;
|
sr_info->pdev = pdev;
|
||||||
sr_info->srid = pdev->id;
|
sr_info->srid = pdev->id;
|
||||||
sr_info->voltdm = pdata->voltdm;
|
sr_info->voltdm = pdata->voltdm;
|
||||||
@@ -997,20 +962,12 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
|
sr_info->dbg_dir = debugfs_create_dir(sr_info->name, sr_dbg_dir);
|
||||||
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);
|
|
||||||
kfree(name);
|
|
||||||
if (IS_ERR_OR_NULL(sr_info->dbg_dir)) {
|
if (IS_ERR_OR_NULL(sr_info->dbg_dir)) {
|
||||||
dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
|
dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
|
||||||
__func__);
|
__func__);
|
||||||
ret = PTR_ERR(sr_info->dbg_dir);
|
ret = PTR_ERR(sr_info->dbg_dir);
|
||||||
goto err_iounmap;
|
goto err_free_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR,
|
(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR,
|
||||||
@@ -1019,8 +976,6 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
|||||||
&sr_info->err_weight);
|
&sr_info->err_weight);
|
||||||
(void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr_info->dbg_dir,
|
(void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr_info->dbg_dir,
|
||||||
&sr_info->err_maxlimit);
|
&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);
|
nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir);
|
||||||
if (IS_ERR_OR_NULL(nvalue_dir)) {
|
if (IS_ERR_OR_NULL(nvalue_dir)) {
|
||||||
@@ -1030,12 +985,10 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
|||||||
goto err_debugfs;
|
goto err_debugfs;
|
||||||
}
|
}
|
||||||
|
|
||||||
omap_voltage_get_volttable(sr_info->voltdm, &volt_data);
|
if (sr_info->nvalue_count == 0 || !sr_info->nvalue_table) {
|
||||||
if (!volt_data) {
|
dev_warn(&pdev->dev, "%s: %s: No Voltage table for the corresponding vdd. Cannot create debugfs entries for n-values\n",
|
||||||
dev_warn(&pdev->dev, "%s: No Voltage table for the"
|
__func__, sr_info->name);
|
||||||
" corresponding vdd vdd_%s. Cannot create debugfs"
|
|
||||||
"entries for n-values\n",
|
|
||||||
__func__, sr_info->voltdm->name);
|
|
||||||
ret = -ENODATA;
|
ret = -ENODATA;
|
||||||
goto err_debugfs;
|
goto err_debugfs;
|
||||||
}
|
}
|
||||||
@@ -1043,16 +996,23 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
|||||||
for (i = 0; i < sr_info->nvalue_count; i++) {
|
for (i = 0; i < sr_info->nvalue_count; i++) {
|
||||||
char name[NVALUE_NAME_LEN + 1];
|
char name[NVALUE_NAME_LEN + 1];
|
||||||
|
|
||||||
snprintf(name, sizeof(name), "volt_%d",
|
snprintf(name, sizeof(name), "volt_%lu",
|
||||||
volt_data[i].volt_nominal);
|
sr_info->nvalue_table[i].volt_nominal);
|
||||||
(void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
|
(void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
|
||||||
&(sr_info->nvalue_table[i].nvalue));
|
&(sr_info->nvalue_table[i].nvalue));
|
||||||
|
snprintf(name, sizeof(name), "errminlimit_%lu",
|
||||||
|
sr_info->nvalue_table[i].volt_nominal);
|
||||||
|
(void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
|
||||||
|
&(sr_info->nvalue_table[i].errminlimit));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err_debugfs:
|
err_debugfs:
|
||||||
debugfs_remove_recursive(sr_info->dbg_dir);
|
debugfs_remove_recursive(sr_info->dbg_dir);
|
||||||
|
err_free_name:
|
||||||
|
kfree(sr_info->name);
|
||||||
err_iounmap:
|
err_iounmap:
|
||||||
list_del(&sr_info->node);
|
list_del(&sr_info->node);
|
||||||
iounmap(sr_info->base);
|
iounmap(sr_info->base);
|
||||||
@@ -1089,6 +1049,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
list_del(&sr_info->node);
|
list_del(&sr_info->node);
|
||||||
iounmap(sr_info->base);
|
iounmap(sr_info->base);
|
||||||
|
kfree(sr_info->name);
|
||||||
kfree(sr_info);
|
kfree(sr_info);
|
||||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
release_mem_region(mem->start, resource_size(mem));
|
release_mem_region(mem->start, resource_size(mem));
|
@@ -17,12 +17,13 @@
|
|||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ASM_ARM_OMAP_SMARTREFLEX_H
|
#ifndef __POWER_SMARTREFLEX_H
|
||||||
#define __ASM_ARM_OMAP_SMARTREFLEX_H
|
#define __POWER_SMARTREFLEX_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
#include "voltage.h"
|
#include <plat/voltage.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Different Smartreflex IPs version. The v1 is the 65nm version used in
|
* Different Smartreflex IPs version. The v1 is the 65nm version used in
|
||||||
@@ -142,6 +143,51 @@
|
|||||||
#define OMAP3430_SR_ERRWEIGHT 0x04
|
#define OMAP3430_SR_ERRWEIGHT 0x04
|
||||||
#define OMAP3430_SR_ERRMAXLIMIT 0x02
|
#define OMAP3430_SR_ERRMAXLIMIT 0x02
|
||||||
|
|
||||||
|
struct omap_sr {
|
||||||
|
char *name;
|
||||||
|
struct list_head node;
|
||||||
|
struct platform_device *pdev;
|
||||||
|
struct omap_sr_nvalue_table *nvalue_table;
|
||||||
|
struct voltagedomain *voltdm;
|
||||||
|
struct dentry *dbg_dir;
|
||||||
|
unsigned int irq;
|
||||||
|
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;
|
||||||
|
void __iomem *base;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test_cond_timeout - busy-loop, testing a condition
|
||||||
|
* @cond: condition to test until it evaluates to true
|
||||||
|
* @timeout: maximum number of microseconds in the timeout
|
||||||
|
* @index: loop index (integer)
|
||||||
|
*
|
||||||
|
* Loop waiting for @cond to become true or until at least @timeout
|
||||||
|
* microseconds have passed. To use, define some integer @index in the
|
||||||
|
* calling code. After running, if @index == @timeout, then the loop has
|
||||||
|
* timed out.
|
||||||
|
*
|
||||||
|
* Copied from omap_test_timeout */
|
||||||
|
#define sr_test_cond_timeout(cond, timeout, index) \
|
||||||
|
({ \
|
||||||
|
for (index = 0; index < timeout; index++) { \
|
||||||
|
if (cond) \
|
||||||
|
break; \
|
||||||
|
udelay(1); \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
|
* struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
|
||||||
* pmic specific info to smartreflex driver
|
* pmic specific info to smartreflex driver
|
||||||
@@ -161,7 +207,7 @@ struct omap_smartreflex_dev_attr {
|
|||||||
const char *sensor_voltdm_name;
|
const char *sensor_voltdm_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_OMAP_SMARTREFLEX
|
#ifdef CONFIG_POWER_AVS_OMAP
|
||||||
/*
|
/*
|
||||||
* The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
|
* The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
|
||||||
* The smartreflex class driver should pass the class type.
|
* The smartreflex class driver should pass the class type.
|
||||||
@@ -186,10 +232,10 @@ struct omap_smartreflex_dev_attr {
|
|||||||
* based decisions.
|
* based decisions.
|
||||||
*/
|
*/
|
||||||
struct omap_sr_class_data {
|
struct omap_sr_class_data {
|
||||||
int (*enable)(struct voltagedomain *voltdm);
|
int (*enable)(struct omap_sr *sr);
|
||||||
int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
|
int (*disable)(struct omap_sr *sr, int is_volt_reset);
|
||||||
int (*configure)(struct voltagedomain *voltdm);
|
int (*configure)(struct omap_sr *sr);
|
||||||
int (*notify)(struct voltagedomain *voltdm, u32 status);
|
int (*notify)(struct omap_sr *sr, u32 status);
|
||||||
u8 notify_flags;
|
u8 notify_flags;
|
||||||
u8 class_type;
|
u8 class_type;
|
||||||
};
|
};
|
||||||
@@ -199,15 +245,20 @@ struct omap_sr_class_data {
|
|||||||
*
|
*
|
||||||
* @efuse_offs: The offset of the efuse where n-target values are stored.
|
* @efuse_offs: The offset of the efuse where n-target values are stored.
|
||||||
* @nvalue: The n-target value.
|
* @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_nvalue_table {
|
||||||
u32 efuse_offs;
|
u32 efuse_offs;
|
||||||
u32 nvalue;
|
u32 nvalue;
|
||||||
|
u32 errminlimit;
|
||||||
|
unsigned long volt_nominal;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct omap_sr_data - Smartreflex platform data.
|
* struct omap_sr_data - Smartreflex platform data.
|
||||||
*
|
*
|
||||||
|
* @name: instance name
|
||||||
* @ip_type: Smartreflex IP type.
|
* @ip_type: Smartreflex IP type.
|
||||||
* @senp_mod: SENPENABLE value for the sr
|
* @senp_mod: SENPENABLE value for the sr
|
||||||
* @senn_mod: SENNENABLE value for sr
|
* @senn_mod: SENNENABLE value for sr
|
||||||
@@ -219,6 +270,7 @@ struct omap_sr_nvalue_table {
|
|||||||
* @voltdm: Pointer to the voltage domain associated with the SR
|
* @voltdm: Pointer to the voltage domain associated with the SR
|
||||||
*/
|
*/
|
||||||
struct omap_sr_data {
|
struct omap_sr_data {
|
||||||
|
const char *name;
|
||||||
int ip_type;
|
int ip_type;
|
||||||
u32 senp_mod;
|
u32 senp_mod;
|
||||||
u32 senn_mod;
|
u32 senn_mod;
|
Reference in New Issue
Block a user