Re: [RFC][PATCH 2/2] OMAP3:PM:SR: SmartReflex Refactor Rev2.0

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

 



Nishanth Menon <nm@xxxxxx> writes:

> Refactor the smart reflex implementation.

Unless there are major objections, I'd like to put Nishanth's SR
rework/refactor into the PM branch for broader testing and review.
This will likely happen early next week.

Kevin

> Original implementation summary:
> Kalle Jokiniemi (1):
>       OMAP3: PM: SmartReflex driver integration
>
> Phil Carmody (2):
>       OMAP3: PM: Don't do unnecessary searches in omap_sr_vdd*_autocomp_store
>       OMAP3: PM: Early exit on invalid parameters
>
> Rajendra Nayak (10):
>       OMAP3: SR: Fix init voltage on OPP change
>       OMAP3: SR: Update VDD1/2 voltages at boot
>       OMAP3: SR: Use sysclk for SR CLKLENGTH calc
>       OMAP3: SR: Reset voltage level on SR disable
>       OMAP3: SR: Replace printk's with pr_* calls
>       OMAP3: SR: Remove redundant defines
>       OMAP3: SR: Replace (0x1 << n) with BIT(n)
>       OMAP3: SR: Fix SR driver to check for omap-pm return values
>       OMAP3: PM: Put optimal SMPS stabilization delay
>       OMAP3: SR: Wait for VP idle before a VP disable
>
> Roger Quadros (4):
>       OMAP3: PM: Fix Smartreflex when used with PM_NOOP layer
>       OMAP3: PM: Make Smartreflex driver independent of SRF
>       OMAP3: PM: Do not Enable SmartReflex if OPP tables not defined
>       OMAP3: PM: Smartreflex: Fix VDD2 OPP determining logic
>
> Teerth Reddy (1):
>       OMAP3: SR: Replace SR_PASS/FAIL,SR_TRUE/FALSE
>
> This patch introduces the following changes in addition to refactoring
> the implementation:
> a) changes the DVFS transition sequences from:
>     freq, voltage(SR+vp) and viceversa
>     TO:
>     disable_vp,SR; freq, voltage(SR+vp) and viceversa; enable_vp,SR
> 	[NOTE: sequence change for disable path - was sr_dis,vp_dis]
>     This change prevents spikes and unexpected voltage changes
>     as a result of SR being left enabled at wrong times
> b) Major rewrite of smartreflex.c to do the following:
>
>  1) Support VCbypass style of voltage configuration as optional
>    introduce and support forceupdate  default as recommended by
>    OMAP3430 TRM.
>  2) Centralize operations to allow for simpler and predictable code
>    flows
>  3) Modification to SR configured values to be inline with
>    silicon characterization results
>  4) cleanup of header
>  5) Introduce a few omap_pmic weak functions which can be overridden
>   by platforms implementing PMICs which are different from TWL4030
>   derivatives
>
> c) Fix ERRCONFIG access to prevent unplanned cleanup of interrupt
>   status registers - this is done using a interrupt status mask
> d) Test nvalues reduced to few lines of code with preconfigured values
>   as well as added multiple levels of warning to keep user informed
> e) Use a singular mutex lock at smartreflex level to isolate access b/w
>   dvfs access/cpu_idle or userspace control
> f) Setup h/w timeout based on cpu sysclk and not hardcoded values
>
> Tested on:
> 	SDP3430 with test N values and with ES3.1 silicon
>
> TODO:
> a) Handle scenarios for multiple OMAP variants with differing
>    SR capabilities (e.g. varying OPP levels - e.g. 3630, 4430 etc..)
> b) Handling OMAP variants with different tuning values
> c) Handling different SR capable PMIC with different tuning values
> d) A proper handling of locking mechanism b/w dvfs and userspace access of
>    sr[x]_vddautocomp
> e) A more robust error handling 
> f) using SR on larger number of boards and any tuning parameters
>    which may be needed additionally (HS/FS I2C4 ops etc..)
> g) Wider testing and and bug fixes
>
> This also incorporates some of the ideas from discussions with Guilhem
>
> Signed-off-by: Nishanth Menon <nm@xxxxxx>
> Cc: Rajendra Nayak <rnayak@xxxxxx>
> Cc: Roger Quadros <ext-roger.quadros@xxxxxxxxx>
> Cc: Kalle Jokiniemi <ext-kalle.jokiniemi@xxxxxxxxx>
> Cc: Teerth Reddy <teerth@xxxxxx>
> Cc: Kevin Hilman <khilman@xxxxxxxxxxxxxxxxxxx>
> Cc: Paul Walmsley <paul@xxxxxxxxx>
> Cc: Högander Jouni <jouni.hogander@xxxxxxxxx>
> Cc: Imberton Guilhem <guilhem.imberton@xxxxxxxxxxxx>
> Cc: Mike Chan <mikechan@xxxxxxxxxx>
> ---
>  arch/arm/mach-omap2/resource34xx.c |    8 +-
>  arch/arm/mach-omap2/smartreflex.c  | 1346 ++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/smartreflex.h  |  249 +++++++
>  arch/arm/plat-omap/Kconfig         |   18 +-
>  4 files changed, 1617 insertions(+), 4 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/smartreflex.c
>  create mode 100644 arch/arm/mach-omap2/smartreflex.h
>
> diff --git a/arch/arm/mach-omap2/resource34xx.c b/arch/arm/mach-omap2/resource34xx.c
> index 1693e9b..6710c86 100644
> --- a/arch/arm/mach-omap2/resource34xx.c
> +++ b/arch/arm/mach-omap2/resource34xx.c
> @@ -287,17 +287,23 @@ static int program_opp(int res, struct omap_opp *opp, int target_level,
>  	else
>  		raise = 0;
>  
> +#ifdef CONFIG_OMAP_SMARTREFLEX
> +	sr_vp_disable_both(t_opp, c_opp);
> +#endif
>  	for (i = 0; i < 2; i++) {
>  		if (i == raise)
>  			ret = program_opp_freq(res, target_level,
>  					current_level);
>  #ifdef CONFIG_OMAP_SMARTREFLEX
>  		else
> -			sr_voltagescale_vcbypass(t_opp, c_opp,
> +			sr_voltage_set(t_opp, c_opp,
>  				opp[target_level].vsel,
>  				opp[current_level].vsel);
>  #endif
>  	}
> +#ifdef CONFIG_OMAP_SMARTREFLEX
> +	sr_vp_enable_both(t_opp, c_opp);
> +#endif
>  
>  	return ret;
>  }
> diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
> new file mode 100644
> index 0000000..d881e8e
> --- /dev/null
> +++ b/arch/arm/mach-omap2/smartreflex.c
> @@ -0,0 +1,1346 @@
> +/*
> + * linux/arch/arm/mach-omap3/smartreflex.c
> + *
> + * OMAP34XX SmartReflex Voltage Control
> + *
> + * Copyright (C) 2009 Texas Instruments, Inc.
> + * Nishanth Menon
> + *
> + * Copyright (C) 2008 Nokia Corporation
> + * Kalle Jokiniemi
> + *
> + * Copyright (C) 2007 Texas Instruments, Inc.
> + * Lesly A M <x0080970@xxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/clk.h>
> +#include <linux/sysfs.h>
> +#include <linux/kobject.h>
> +#include <linux/i2c/twl4030.h>
> +#include <linux/io.h>
> +
> +#include <mach/omap34xx.h>
> +#include <mach/control.h>
> +#include <mach/clock.h>
> +#include <mach/omap-pm.h>
> +#include <mach/resource.h>
> +#include <mach/powerdomain.h>
> +
> +#include "prm.h"
> +#include "smartreflex.h"
> +#include "prm-regbits-34xx.h"
> +
> +/* MCUDISACK is expected to happen within 1uSec. */
> +#define COUNT_TIMEOUT_MCUDISACK		50
> +
> +/* VPINIDLE is expected to happen within 100uSec. Typical is 2uSec */
> +#define COUNT_TIMEOUT_VPINIDLE		200
> +
> +/* Time taken for setting the device - worst case as FS I2C
> + * Depends on SMPSWAITIME MIN/MAX Typical is 200uSec
> + */
> +#define COUNT_TIMEOUT_TRANSDONE_SET	400
> +
> +/* Time to clear out multiple transdone events typical is 3uSec */
> +#define COUNT_TIMEOUT_TRANSDONE_CLR	50
> +
> +/* Time For VCBypass mode for TWL4030 derivative chip. */
> +#define COUNT_TIMEOUT_TWL4030_VCBYPASS	500
> +
> +/* How many retries to do for I2C errors seen on bus for Forceupdate? */
> +#define COUNT_RETRY_SMPSNOACK		4
> +
> +#define SR_REGADDR(offset)	(sr->srbase_addr + (offset))
> +
> +/* Which function to use for setting voltage */
> +#ifdef CONFIG_OMAP_VC_BYPASS_UPDATE
> +#define SR_CHOSEN_VOLTAGE_UPDATE_MECH  sr_vc_bypass
> +#else
> +#define SR_CHOSEN_VOLTAGE_UPDATE_MECH  sr_vp_forceupdate
> +#endif
> +
> +/* Using SMART REFLEX TEST nVALUES - for devices without EFUSE */
> +#ifdef CONFIG_OMAP_SMARTREFLEX_TESTING_NVALUES
> +#warning "SR TESTING NVALUES BUILD- Hope you know what you are doing!!!!!"
> +
> +/* 5 values each for the valid OPP please.. */
> +static u32 __initdata sr1_test_nvalues[] = {
> +	/* *INDENT-OFF* */
> +	0x00000000,	0x00000000,
> +	0x00AAB48A,	0x00ABA2E6,
> +	0x00AB90D3
> +	/* *INDENT-ON* */
> +};
> +#define SR1_N_MOD 0x3
> +#define SR1_P_MOD 0x3
> +
> +/* 3 values each for the valid OPP please.. */
> +static u32 __initdata sr2_test_nvalues[] = {
> +	/* *INDENT-OFF* */
> +	0x00000000,	0x00000000,
> +	0x00AAC695
> +	/* *INDENT-ON* */
> +};
> +#define SR2_N_MOD 0x3
> +#define SR2_P_MOD 0x3
> +
> +#endif			/* CONFIG_OMAP_SMARTREFLEX_TESTING_NVALUES */
> +
> +/* Structure for Voltage processor */
> +struct omap_sr_vp {
> +	/* Store the commonly used register offsets.
> +	 * this saves a if condition decision
> +	 */
> +	u16 prm_vpx_status_offset;
> +	u16 prm_vpx_config_offset;
> +	u16 prm_vpx_stepmin_offset;
> +	u16 prm_vpx_stepmax_offset;
> +	u16 prm_vpx_limito_offset;
> +	/* Store the defaults
> +	 * allowing us to save OCP read
> +	 * operation
> +	 */
> +	u32 vpconfig_value;
> +	u32 vpstepmin_value;
> +	u32 vpstepmax_value;
> +	u32 vplimito_value;
> +	u32 vpenable_mask;
> +	u32 irqmask_trans_done;
> +	u32 irqmask_smps_noack;
> +};
> +
> +/* Structure for Smart Reflex */
> +struct omap_sr {
> +	int srid;
> +	/* SR activity marker */
> +	u8 is_sr_reset;
> +	u8 is_autocomp_active;
> +	u32 req_opp_no;
> +	u32 opp_nvalue[5];
> +	u32 sr_config_value;
> +	u32 sr_errconfig_value;
> +	struct clk *fclk;
> +	struct clk *iclk;
> +	void __iomem *srbase_addr;
> +	void __iomem *vpbase_addr;
> +	/* Lock for maintaining SR+VP programming sequence atomicity */
> +	/* Voltage processor for the specific SR module */
> +	struct omap_sr_vp vp;
> +};
> +
> +/* Smart Reflex 1 structure */
> +static struct omap_sr sr1 = {
> +	/* *INDENT-OFF* */
> +	.srid			= SR1,
> +	.is_sr_reset		= 1,
> +	.is_autocomp_active	= 0,
> +	.srbase_addr		= OMAP2_IO_ADDRESS(OMAP34XX_SR1_BASE),
> +	.vp = {
> +		.prm_vpx_status_offset	= OMAP3_PRM_VP1_STATUS_OFFSET,
> +		.prm_vpx_config_offset	= OMAP3_PRM_VP1_CONFIG_OFFSET,
> +		.prm_vpx_stepmin_offset	= OMAP3_PRM_VP1_VSTEPMIN_OFFSET,
> +		.prm_vpx_stepmax_offset	= OMAP3_PRM_VP1_VSTEPMAX_OFFSET,
> +		.prm_vpx_limito_offset	= OMAP3_PRM_VP1_VLIMITTO_OFFSET,
> +		.vpconfig_value		= PRM_VP1_CONFIG_ERROROFFSET |
> +			PRM_VP1_CONFIG_TIMEOUTEN,
> +		.vpstepmin_value	= PRM_VP1_VSTEPMIN_SMPSWAITTIMEMIN |
> +			PRM_VP1_VSTEPMIN_VSTEPMIN,
> +		.vpstepmax_value	= PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX |
> +			PRM_VP1_VSTEPMAX_VSTEPMAX,
> +		.vplimito_value		= PRM_VP1_VLIMITTO_VDDMAX |
> +			PRM_VP1_VLIMITTO_VDDMIN,
> +		.vpenable_mask		= PRM_VP1_CONFIG_VPENABLE,
> +		.irqmask_trans_done	= VP1_IRQMASK_TRANSDONE,
> +		.irqmask_smps_noack	= OMAP3430_VP1_NOSMPSACK_ST,
> +	},
> +	/* *INDENT-ON* */
> +};
> +
> +/* Smart Reflex 2 structure */
> +static struct omap_sr sr2 = {
> +	/* *INDENT-OFF* */
> +	.srid			= SR2,
> +	.is_sr_reset		= 1,
> +	.is_autocomp_active	= 0,
> +	.srbase_addr		= OMAP2_IO_ADDRESS(OMAP34XX_SR2_BASE),
> +	.vp = {
> +		.prm_vpx_status_offset	= OMAP3_PRM_VP2_STATUS_OFFSET,
> +		.prm_vpx_config_offset	= OMAP3_PRM_VP2_CONFIG_OFFSET,
> +		.prm_vpx_stepmin_offset	= OMAP3_PRM_VP2_VSTEPMIN_OFFSET,
> +		.prm_vpx_stepmax_offset	= OMAP3_PRM_VP2_VSTEPMAX_OFFSET,
> +		.prm_vpx_limito_offset	= OMAP3_PRM_VP2_VLIMITTO_OFFSET,
> +		.vpconfig_value		= PRM_VP2_CONFIG_ERROROFFSET |
> +			PRM_VP2_CONFIG_TIMEOUTEN,
> +		.vpstepmin_value	= PRM_VP2_VSTEPMIN_SMPSWAITTIMEMIN |
> +			PRM_VP2_VSTEPMIN_VSTEPMIN,
> +		.vpstepmax_value	= PRM_VP2_VSTEPMAX_SMPSWAITTIMEMAX |
> +			PRM_VP2_VSTEPMAX_VSTEPMAX,
> +		.vplimito_value		= PRM_VP2_VLIMITTO_VDDMAX |
> +			PRM_VP2_VLIMITTO_VDDMIN,
> +		.vpenable_mask		= PRM_VP2_CONFIG_VPENABLE,
> +		.irqmask_trans_done	= VP2_IRQMASK_TRANSDONE,
> +		.irqmask_smps_noack	= OMAP3430_VP1_NOSMPSACK_ST,
> +	},
> +	/* *INDENT-ON* */
> +};
> +
> +/****************** PMIC WEAK FUNCTIONS FOR TWL4030 derivatives **********/
> +
> +/**
> + * @brief pmic_srinit - Power management IC initialization
> + * for smart reflex. The current code is written for TWL4030
> + * derivatives, replace in board file if PMIC requires
> + * a different sequence
> + *
> + * @return result of operation
> + */
> +int __weak __init omap_pmic_srinit(void)
> +{
> +	int ret = -ENODEV;
> +#ifdef CONFIG_TWL4030_CORE
> +	u8 reg;
> +	/* Enable SR on T2 */
> +	ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &reg,
> +				  R_DCDC_GLOBAL_CFG);
> +
> +	reg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
> +	ret |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, reg,
> +				    R_DCDC_GLOBAL_CFG);
> +#endif		/* End of CONFIG_TWL4030_CORE */
> +	return ret;
> +}
> +
> +/**
> + * @brief omap_pmic_voltage_ramp_delay - how much should this pmic ramp delay
> + * Various PMICs have different ramp up and down delays. choose to implement
> + * in required pmic file to override this function.
> + * On TWL4030 derivatives:
> + *  T2 SMPS slew rate (min) 4mV/uS, step size 12.5mV,
> + *  2us added as buffer.
> + *
> + * @param target_vsel - targetted voltage selction
> + * @param current_vsel - current voltage selection
> + *
> + * @return delay in uSeconds
> + */
> +u32 __weak omap_pmic_voltage_ramp_delay(u8 target_vsel, u8 current_vsel)
> +{
> +	u32 t2_smps_steps = abs(target_vsel - current_vsel);
> +	u32 t2_smps_delay = ((t2_smps_steps * 125) / 40) + 2;
> +	return t2_smps_delay;
> +}
> +
> +#ifdef CONFIG_OMAP_VC_BYPASS_UPDATE
> +/**
> + * @brief omap_pmic_voltage_cmds - hook for pmic command sequence
> + * to be send out which are specific to pmic to set a specific voltage.
> + * this should inturn call vc_send_command with the required sequence
> + * The current implementation is for TWL4030 derivatives
> + *
> + * @param srid - which SR is this for?
> + * @param target_vsel - what voltage is desired to be set?
> + *
> + * @return specific value to set.
> + */
> +int __weak omap_pmic_voltage_cmds(u8 srid, u8 target_vsel)
> +{
> +	u8 reg_addr = (srid == SR1) ? R_VDD1_SR_CONTROL : R_VDD2_SR_CONTROL;
> +	return vc_send_command(R_SRI2C_SLAVE_ADDR, reg_addr, target_vsel,
> +			COUNT_TIMEOUT_TWL4030_VCBYPASS);
> +}
> +#endif			/* ifdef CONFIG_OMAP_VC_BYPASS_UPDATE */
> +
> +/*********************** Voltage Controller functions *************************/
> +
> +/**
> + * @brief vc_send_command - The actual command transmission using
> + * Voltage controller on I2C4
> + *
> + * @param slave_addr - what is the PMIC slave address
> + * @param reg_addr  - what is the register address I should be using?
> + * @param data - what value do you want to write here?
> + * @param timeout_us timeout in uSeconds.
> + *
> + * @return 0 if all ok, else error value
> + */
> +int vc_send_command(u8 slave_addr, u8 reg_addr, u8 data, u16 timeout_us)
> +{
> +	u32 value;
> +	/* time to wait =
> +	 * timeout_us/10 -> each udelay event
> +	 * 1 udelay event every 50 iteration, assuming
> +	 * each iteration is instaneous,
> +	 * count = (timeout_us/10) * 50 or timeout_us * 5
> +	 */
> +	u32 count = timeout_us * 5;
> +
> +	value = (data << OMAP3430_DATA_SHIFT) |
> +	    (reg_addr << OMAP3430_REGADDR_SHIFT) |
> +	    (slave_addr << OMAP3430_SLAVEADDR_SHIFT);
> +
> +	prm_write_mod_reg(value, OMAP3430_GR_MOD,
> +			  OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
> +
> +	value = prm_set_mod_reg_bits(OMAP3430_VALID, OMAP3430_GR_MOD,
> +				     OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
> +	/*
> +	 * Do continous 50 checks then follow with a 10usec delay,
> +	 * then check again
> +	 */
> +	do {
> +		value = prm_read_mod_reg(OMAP3430_GR_MOD,
> +					 OMAP3_PRM_VC_BYPASS_VAL_OFFSET)
> +		    & OMAP3430_VALID;
> +		/* should i wait? */
> +		if (value && (count % 50))
> +			udelay(10);
> +		count--;
> +	} while (value && count);
> +	if (!count) {
> +		pr_err("VC:Command Timedout! slave_addr=0x%02X,"
> +		       "reg=0x%02X, value=0x%02X", slave_addr, reg_addr, data);
> +		return -ETIMEDOUT;
> +	}
> +	return 0;
> +}
> +EXPORT_SYMBOL(vc_send_command);
> +
> +/**
> + * @brief sr_vc_bypass - setup voltage using VC Bypass technique
> + *
> + * @param target_opp - target opp to go to
> + * @param current_opp  - current opp
> + * @param target_vsel  - which voltage to go to?
> + * @param current_vsel  - current voltage
> + *
> + * @return -success or failure
> + */
> +#ifdef CONFIG_OMAP_VC_BYPASS_UPDATE
> +static int sr_vc_bypass(struct omap_sr *sr,
> +			u32 target_opp_no, u8 target_vsel, u8 current_vsel)
> +{
> +	int ret = 0;
> +	struct omap_sr_vp *vp = &sr->vp;
> +	u32 vc_cmd_val_offs;
> +	u32 vpconfig_value;
> +
> +	vc_cmd_val_offs =
> +	    (sr->srid ==
> +	     SR1) ? OMAP3_PRM_VC_CMD_VAL_0_OFFSET :
> +	    OMAP3_PRM_VC_CMD_VAL_1_OFFSET;
> +
> +	vpconfig_value = vp->vpconfig_value;
> +	vpconfig_value |= ((target_opp_no < 3) ? SR_ERRGAIN_LOWOP :
> +			   SR_ERRGAIN_HIGHOPP) << OMAP3430_ERRORGAIN_SHIFT;
> +	vpconfig_value |= target_vsel << OMAP3430_INITVOLTAGE_SHIFT;
> +	prm_write_mod_reg(vpconfig_value, OMAP3430_GR_MOD,
> +			  vp->prm_vpx_config_offset);
> +
> +	prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
> +			     (target_vsel << OMAP3430_VC_CMD_ON_SHIFT),
> +			     OMAP3430_GR_MOD, vc_cmd_val_offs);
> +
> +	/*
> +	 * Various PMIC might need a set of commands
> +	 * provide hooks for specific PMICs to implement
> +	 */
> +	ret = omap_pmic_voltage_cmds(sr->srid, target_vsel);
> +
> +	/* delay based on pmic */
> +	if (!ret)
> +		udelay(omap_pmic_voltage_ramp_delay(target_vsel, current_vsel));
> +
> +	WARN_ON(ret);
> +
> +	return ret;
> +}
> +#endif			/* ifdef CONFIG_OMAP_VC_BYPASS_UPDATE */
> +
> +/********************* SR Private functions ***************************/
> +
> +/**
> + * @brief sr_write_reg - write to Smart Reflex Register
> + *
> + * @param sr  - pointer to SR structure
> + * @param offset - SR reg offset to write to
> + * @param value - value to write with
> + */
> +static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
> +{
> +	__raw_writel(value, SR_REGADDR(offset));
> +}
> +
> +/**
> + * @brief sr_modify_reg - Modify a register and write a new value to a field
> + *
> + * @param sr -pointer to SR structure
> + * @param offset -register offset
> + * @param mask -mask to clear out
> + * @param value -value to write there
> + */
> +static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
> +				 u32 value)
> +{
> +	u32 reg_val;
> +
> +	reg_val = __raw_readl(SR_REGADDR(offset));
> +	reg_val &= ~mask;
> +	reg_val |= value;
> +
> +	__raw_writel(reg_val, SR_REGADDR(offset));
> +}
> +
> +/**
> + * @brief sr_read_reg - read a SR register
> + *
> + * @param sr - pointer to SR structure
> + * @param offset - register offset
> + *
> + * @return value in that register
> + */
> +static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
> +{
> +	return __raw_readl(SR_REGADDR(offset));
> +}
> +
> +/**
> + * @brief sr_vplimito_value -return the timeout value based on sysclk
> + *		and desired timeout uSec
> + *
> + * @param sys_clk_speed - internal sysclk freq in hz
> + * @param timeout_us - timeout in uSec
> + *
> + * @return timeout value to use in VPLIMITTO:TIMEOUT reg
> + */
> +static inline u32 sr_vplimito_value(u32 sys_clk_speed, u16 timeout_us)
> +{
> +	u32 timeout_val;
> +	/* prevent round off errors, we will divide by 10 later */
> +	timeout_val = (sys_clk_speed / 100000);
> +	timeout_val *= timeout_us;
> +	timeout_val /= 10;
> +	return timeout_val;
> +}
> +
> +/**
> + * @brief sr_clk_enable - SR clock enable
> + *
> + * @param sr - Structure to SR structure
> + *
> + * @return - result
> + */
> +static int sr_clk_enable(struct omap_sr *sr)
> +{
> +	if (clk_enable(sr->iclk) != 0) {
> +		pr_crit("SR:Could not enable %s for [%d]\n",
> +		       sr->iclk->name, sr->srid);
> +		return -EINVAL;
> +	}
> +	if (clk_enable(sr->fclk) != 0) {
> +		pr_crit("SR:Could not enable %s for [%d]\n",
> +		       sr->fclk->name, sr->srid);
> +		clk_disable(sr->iclk);
> +		return -EINVAL;
> +	}
> +	sr_modify_reg(sr, ERRCONFIG,
> +		      SR_CLKACTIVITY_MASK | ERRCONFIG_INTERRUPT_STATUS_MASK,
> +		      SR_CLKACTIVITY_IOFF_FON);
> +	sr->is_sr_reset = 0;
> +
> +	return 0;
> +}
> +
> +/**
> + * @brief sr_clk_disable - SR func clock disable
> + *
> + * @param sr - pointer to SR structure
> + */
> +static void sr_clk_disable(struct omap_sr *sr)
> +{
> +	/* set fclk, iclk- idle */
> +	sr_modify_reg(sr, ERRCONFIG,
> +		      SR_CLKACTIVITY_MASK | ERRCONFIG_INTERRUPT_STATUS_MASK,
> +		      SR_CLKACTIVITY_IOFF_FOFF);
> +
> +	clk_disable(sr->fclk);
> +	clk_disable(sr->iclk);
> +	sr->is_sr_reset = 1;
> +}
> +
> +/****************** Voltage processor functions ***************************/
> +
> +/**
> + * @brief sr_vp_clear_vptransdone - clear vptrans_done event
> + *
> + * @param sr - sr pointer
> + *
> + * @return 0 if cleared ok, else 1 if timedout!
> + */
> +static int sr_vp_clear_vptransdone(struct omap_sr *sr)
> +{
> +	struct omap_sr_vp *vp = &sr->vp;
> +	u32 irqstat;
> +	u32 count = COUNT_TIMEOUT_TRANSDONE_CLR;
> +	do {
> +		prm_write_mod_reg(vp->irqmask_trans_done, OCP_MOD,
> +				  OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
> +		irqstat = prm_read_mod_reg(OCP_MOD,
> +					   OMAP3_PRM_IRQSTATUS_MPU_OFFSET) &
> +		    vp->irqmask_trans_done;
> +		if (irqstat)
> +			udelay(1);
> +		count--;
> +	} while (count && irqstat);
> +	if (!count) {
> +		pr_crit("SR:VPTransdone[%d]:Timedout\n", sr->srid);
> +		return -ETIMEDOUT;
> +	}
> +	return 0;
> +}
> +
> +/**
> + * @brief sr_vp_forceupdate - do a forceupdate method
> + *		to update the voltage level
> + *
> + * @param sr - pointer to sr structure
> + * @param target_opp_no - targetted opp number
> + * @param target_vsel - targetted voltage level
> + * @param current_vsel - current voltage level
> + *
> + * @return 0 if all worked out, else 1
> + */
> +#ifndef CONFIG_OMAP_VC_BYPASS_UPDATE
> +static int sr_vp_forceupdate(struct omap_sr *sr, u32 target_opp_no,
> +			     u8 target_vsel, u8 current_vsel)
> +{
> +	u32 count;
> +	u32 irqstat;
> +	u32 vpconfig_value;
> +	u32 retry_counter = COUNT_RETRY_SMPSNOACK;
> +
> +	struct omap_sr_vp *vp = &sr->vp;
> +
> +retry_forceupdate:
> +	/* First clear any pending events in the system */
> +	if (sr_vp_clear_vptransdone(sr)) {
> +		pr_crit("SR:forceupdate-transdone1[%d]:timedout\n", sr->srid);
> +		return -ETIMEDOUT;
> +	}
> +
> +	vpconfig_value = vp->vpconfig_value;
> +	vpconfig_value |= ((target_opp_no < 3) ? SR_ERRGAIN_LOWOP :
> +			   SR_ERRGAIN_HIGHOPP) << OMAP3430_ERRORGAIN_SHIFT;
> +	vpconfig_value |= target_vsel << OMAP3430_INITVOLTAGE_SHIFT;
> +
> +	prm_write_mod_reg(vpconfig_value, OMAP3430_GR_MOD,
> +			  vp->prm_vpx_config_offset);
> +
> +	/* Trigger initVDD value copy to voltage processor */
> +	prm_set_mod_reg_bits(OMAP3430_INITVDD, OMAP3430_GR_MOD,
> +			     vp->prm_vpx_config_offset);
> +
> +	/* Force update of voltage */
> +	prm_set_mod_reg_bits(OMAP3430_FORCEUPDATE, OMAP3430_GR_MOD,
> +			     vp->prm_vpx_config_offset);
> +
> +	/* Clear initVDD copy trigger bit */
> +	prm_clear_mod_reg_bits(OMAP3430_INITVDD, OMAP3430_GR_MOD,
> +			       vp->prm_vpx_config_offset);
> +	/* Clear force bit */
> +	prm_clear_mod_reg_bits(OMAP3430_FORCEUPDATE, OMAP3430_GR_MOD,
> +			       vp->prm_vpx_config_offset);
> +
> +	/* Now wait for the i2c transactions to complete */
> +	count = COUNT_TIMEOUT_TRANSDONE_SET;
> +	irqstat = 0;
> +	do {
> +		irqstat = prm_read_mod_reg(OCP_MOD,
> +					   OMAP3_PRM_IRQSTATUS_MPU_OFFSET) &
> +		    vp->irqmask_trans_done;
> +		if (!irqstat)
> +			udelay(1);
> +		count--;
> +	} while (count && !irqstat);
> +	if (!count) {
> +		irqstat = prm_read_mod_reg(OCP_MOD,
> +					   OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
> +		if (irqstat & vp->irqmask_smps_noack) {
> +			WARN(irqstat, "SMPS NO ACK DETECTED[0x%08X]!!"
> +					"ATTEMPTING RECOVERY [%d left]\n",
> +					irqstat, retry_counter);
> +			prm_write_mod_reg(irqstat, OCP_MOD,
> +					   OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
> +			retry_counter--;
> +			if (retry_counter)
> +				goto retry_forceupdate;
> +		}
> +		pr_crit("SR:forceupdate-transdone[%d]:timedout-"
> +		       "irqstat=0x%08X\n", sr->srid, irqstat);
> +		BUG();
> +		return -ETIMEDOUT;
> +	}
> +
> +	/*
> +	 * Now we wait for voltage to rise on PMIC
> +	 */
> +	udelay(omap_pmic_voltage_ramp_delay(target_vsel, current_vsel));
> +
> +	/* clear that event */
> +	if (sr_vp_clear_vptransdone(sr)) {
> +		pr_crit("SR:forceupdate-transdone2[%d]:timedout\n", sr->srid);
> +		BUG();
> +		return -ETIMEDOUT;
> +	}
> +	return 0;
> +}
> +#endif		/* ifndef CONFIG_OMAP_VC_BYPASS_UPDATE */
> +
> +/**
> + * @brief sr_vp_enable - enable VP enable code
> + *
> + * @param sr
> + */
> +static int sr_vp_enable(struct omap_sr *sr, u32 target_opp_no)
> +{
> +	u32 vpconfig_value;
> +	struct omap_sr_vp *vp = &sr->vp;
> +
> +	/* Disable VP */
> +	prm_clear_mod_reg_bits(vp->vpenable_mask, OMAP3430_GR_MOD,
> +			       vp->prm_vpx_config_offset);
> +	/* Clear INITVDD */
> +	prm_clear_mod_reg_bits(OMAP3430_INITVDD, OMAP3430_GR_MOD,
> +			       vp->prm_vpx_config_offset);
> +
> +	vpconfig_value = vp->vpconfig_value;
> +	vpconfig_value |= ((sr->srid == SR1) ? mpu_opps[target_opp_no].vsel :
> +			   l3_opps[target_opp_no].vsel) <<
> +	    OMAP3430_INITVOLTAGE_SHIFT;
> +	vpconfig_value |=
> +	    ((target_opp_no < 3) ? SR_ERRGAIN_LOWOP : SR_ERRGAIN_HIGHOPP) <<
> +	    OMAP3430_ERRORGAIN_SHIFT;
> +
> +	prm_write_mod_reg(vpconfig_value, OMAP3430_GR_MOD,
> +			  vp->prm_vpx_config_offset);
> +
> +	prm_write_mod_reg(vp->vpstepmin_value, OMAP3430_GR_MOD,
> +			  vp->prm_vpx_stepmin_offset);
> +	prm_write_mod_reg(vp->vpstepmax_value, OMAP3430_GR_MOD,
> +			  vp->prm_vpx_stepmax_offset);
> +	prm_write_mod_reg(vp->vplimito_value, OMAP3430_GR_MOD,
> +			  vp->prm_vpx_limito_offset);
> +
> +	/* write1 to latch */
> +	prm_set_mod_reg_bits(OMAP3430_INITVDD, OMAP3430_GR_MOD,
> +			     vp->prm_vpx_config_offset);
> +	/* write2 clear */
> +	prm_clear_mod_reg_bits(OMAP3430_INITVDD, OMAP3430_GR_MOD,
> +			       vp->prm_vpx_config_offset);
> +	/* Enable VP */
> +	prm_set_mod_reg_bits(vp->vpenable_mask, OMAP3430_GR_MOD,
> +			     vp->prm_vpx_config_offset);
> +	return 0;
> +}
> +
> +/**
> + * @brief sr_vp_disable - disbale Voltage processor
> + *
> + * @param sr - sr structure
> + *
> + * @return 0 if all ok, else return -ETIMEDOUT
> + */
> +static int sr_vp_disable(struct omap_sr *sr)
> +{
> +	int count;
> +	u32 v;
> +	struct omap_sr_vp *vp = &sr->vp;
> +
> +	v = prm_read_mod_reg(OMAP3430_GR_MOD,
> +			     vp->prm_vpx_config_offset) & vp->vpenable_mask;
> +	/* Am i already disabled? */
> +	if (!v) {
> +		pr_info("SR[%d] attempt to disable VP when already disabled!\n",
> +			sr->srid);
> +		return 0;
> +	}
> +
> +	/* Disable VP */
> +	prm_clear_mod_reg_bits(vp->vpenable_mask, OMAP3430_GR_MOD,
> +			       vp->prm_vpx_config_offset);
> +
> +	/* Wait for vp to get idle - clear any events pending */
> +	count = COUNT_TIMEOUT_MCUDISACK;
> +	do {
> +		v = prm_read_mod_reg(OMAP3430_GR_MOD,
> +				     vp->prm_vpx_status_offset) &
> +		    PRM_VP_STATUS_VPINIDLE;
> +		if (!v)
> +			udelay(1);
> +		count--;
> +	} while (count && !v);
> +	if (unlikely(!count)) {
> +		v = prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
> +		pr_warning("SR:vpdisable-vpinidle[%d][opp=%d]:timedout-"
> +				"irqstat=0x%08X\n", sr->srid,
> +				sr->req_opp_no, v);
> +		return -ETIMEDOUT;
> +	}
> +	return 0;
> +}
> +
> +/**
> + * @brief sr_vp_configure - configure the basic SR structure
> + *
> + * @param sr - pointer to SR structure
> + */
> +static void sr_vp_configure(struct omap_sr *sr)
> +{
> +	u32 target_opp_no;
> +	u32 target_vsel;
> +	u32 prm_vpx_voltage;
> +
> +	if (sr->srid == SR1) {
> +		target_opp_no = mpu_opps[resource_get_level("vdd1_opp")].opp_id;
> +		target_vsel = mpu_opps[resource_get_level("vdd1_opp")].vsel;
> +		prm_vpx_voltage = prm_read_mod_reg(OMAP3430_GR_MOD,
> +					   OMAP3_PRM_VP1_VOLTAGE_OFFSET);
> +	} else {
> +		target_opp_no = l3_opps[resource_get_level("vdd2_opp")].opp_id;
> +		target_vsel = l3_opps[resource_get_level("vdd2_opp")].vsel;
> +		prm_vpx_voltage = prm_read_mod_reg(OMAP3430_GR_MOD,
> +					   OMAP3_PRM_VP2_VOLTAGE_OFFSET);
> +	}
> +
> +	sr_vp_enable(sr, target_opp_no);
> +	if (SR_CHOSEN_VOLTAGE_UPDATE_MECH
> +	    (sr, target_opp_no, target_vsel, prm_vpx_voltage))
> +		pr_crit("SR[%d] CONFIGURE VP failed!!\n", sr->srid);
> +}
> +
> +/**
> + * @brief sr_vp_reset_voltage - reset the voltages back to DVFS values
> + *
> + * @param srid -SRID
> + *
> + * @return 0 if ok, else result
> + */
> +static int sr_vp_reset_voltage(int srid)
> +{
> +	u32 target_opp_no;
> +	u32 target_vsel;
> +	u32 prm_vpx_voltage;
> +	struct omap_sr *sr;
> +	if (srid == SR1) {
> +		sr = &sr1;
> +		target_opp_no = sr1.req_opp_no;
> +		target_vsel = mpu_opps[target_opp_no].vsel;
> +		prm_vpx_voltage = prm_read_mod_reg(OMAP3430_GR_MOD,
> +					   OMAP3_PRM_VP1_VOLTAGE_OFFSET);
> +	} else {
> +		sr = &sr2;
> +		target_opp_no = sr2.req_opp_no;
> +		target_vsel = l3_opps[target_opp_no].vsel;
> +		prm_vpx_voltage = prm_read_mod_reg(OMAP3430_GR_MOD,
> +					   OMAP3_PRM_VP2_VOLTAGE_OFFSET);
> +	}
> +	return SR_CHOSEN_VOLTAGE_UPDATE_MECH(sr, target_opp_no,
> +					     target_vsel, prm_vpx_voltage);
> +
> +}
> +
> +/*********************** SR functions *************************/
> +
> +/**
> + * @brief sr_enable - enable smart reflex
> + *
> + * @param sr - smartreflex structure we are interest
> + * @param target_opp_no - target opp we want to switch to
> + *
> + * @return 0 if all went right, else return err val
> + */
> +static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
> +{
> +	u32 value;
> +
> +	if (!sr->is_sr_reset) {
> +		pr_info("SR[%d]already enabled\n", sr->srid);
> +		return -EINVAL;
> +	}
> +
> +	sr->req_opp_no = target_opp_no;
> +
> +	value = sr->opp_nvalue[target_opp_no - 1];
> +	if (value == 0) {
> +		pr_info("SR[%d]:OPP%d doesn't support SmartReflex\n",
> +		       sr->srid, target_opp_no);
> +		return -EINVAL;
> +	}
> +
> +	sr_clk_enable(sr);
> +	/* Start with setting SREnable as 0 */
> +	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0);
> +
> +	sr_write_reg(sr, SRCONFIG, sr->sr_config_value);
> +
> +	sr_write_reg(sr, NVALUERECIPROCAL, value);
> +
> +	value = sr->sr_errconfig_value |
> +	    ((target_opp_no < 3) ? SR_ERRMINLIMIT_LOWOPP :
> +	     SR_ERRMINLIMIT_HIGHOPP);
> +
> +	sr_write_reg(sr, ERRCONFIG, value);
> +
> +	/* SRCONFIG - enable SR */
> +	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
> +
> +	return 0;
> +}
> +
> +/**
> + * @brief sr_disable - disable Smart Reflex
> + *
> + * @param sr -  pointer to sr structure of interest
> + *
> + * @return 0 if all went right, else return INVAL/TIMEDOUT
> + */
> +int sr_disable(struct omap_sr *sr)
> +{
> +	int count;
> +	u32 stat;
> +	u32 value;
> +
> +	if (sr->is_sr_reset) {
> +		pr_info("SR[%d]-disable:already Disabled\n", sr->srid);
> +		return -EINVAL;
> +	}
> +	value = sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE;
> +	if (!value) {
> +		pr_info("SR[%d] attempt to disable SR when already disabled!\n",
> +			sr->srid);
> +		return 0;
> +	}
> +	value = sr->opp_nvalue[sr->req_opp_no - 1];
> +	if (value == 0) {
> +		pr_info("SR[%d]-disable:"
> +		       "OPP%d doesn't support SmartReflex\n",
> +		       sr->srid, sr->req_opp_no);
> +		return -EINVAL;
> +	}
> +	/* Enable the MCUDISACKINST */
> +	sr_modify_reg(sr, ERRCONFIG, ERRCONFIG_MCUDISACKINTEN |
> +		      ERRCONFIG_INTERRUPT_STATUS_MASK,
> +		      ERRCONFIG_MCUDISACKINTEN);
> +
> +	/* SRCONFIG - disable SR */
> +	sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0);
> +
> +	/* Disable VPBOUND interrupt and clear any status
> +	 * before actually waiting for disack
> +	 * should be done after sr is disabled
> +	 */
> +	sr_modify_reg(sr, ERRCONFIG, ERRCONFIG_VPBOUNDINTEN |
> +		      ERRCONFIG_INTERRUPT_STATUS_MASK, ERRCONFIG_VPBOUNDINTST);
> +
> +	/* Wait for MCUDISACKINTST to be set */
> +	count = COUNT_TIMEOUT_MCUDISACK;
> +	do {
> +		stat = sr_read_reg(sr, ERRCONFIG) & ERRCONFIG_MCUDISACKINTST;
> +		if (!stat)
> +			udelay(1);
> +		count--;
> +	} while (count && !stat);
> +	/* Clear the event and disable MCUDISACKINST */
> +	sr_modify_reg(sr, ERRCONFIG, ERRCONFIG_MCUDISACKINTEN |
> +		      ERRCONFIG_INTERRUPT_STATUS_MASK,
> +		      ERRCONFIG_MCUDISACKINTST);
> +
> +	if (!count) {
> +		pr_crit("SR[%d]-disable:MCUDIS timedout\n", sr->srid);
> +		return -ETIMEDOUT;
> +	}
> +	sr_clk_disable(sr);
> +	return 0;
> +}
> +
> +/**************** Common enable/disable functionality *********************/
> +
> +/**
> + * @brief srvp_disable - disable SR and VP
> + * These functions are based on h/w timeouts and should ideally not fail.
> + *
> + * @param sr -sr struct
> + *
> + * @return  result
> + */
> +static int srvp_disable(struct omap_sr *sr)
> +{
> +	int ret;
> +	/* If we dont have an nvalue, dont bother.. */
> +	if (!sr->opp_nvalue[sr->req_opp_no - 1]) {
> +		pr_warning("SR[%d]: OPP%d does not support SR to disable\n",
> +				sr->srid, sr->req_opp_no);
> +		return -EINVAL;
> +	}
> +	ret = sr_vp_disable(sr);
> +	if (unlikely(ret)) {
> +		pr_err("SR[%d]: failed to disable vp:%d\n", sr->srid, ret);
> +	} else {
> +		ret = sr_disable(sr);
> +		if (unlikely(ret))
> +			pr_err("SR[%d]: failed to disable sr:%d\n",
> +			       sr->srid, ret);
> +	}
> +	/*
> +	 * Does not make much sense renabling SR as
> +	 * system is going to be in an invalid state
> +	 */
> +	WARN_ON(ret);
> +	return ret;
> +}
> +
> +/**
> + * @brief srvp_enable - enable SR and VP
> + * These functions are based on h/w timeouts and should ideally not fail.
> + *
> + * @param sr -sr struct
> + * @param target_opp -opp to go to
> + *
> + * @return result
> + */
> +static int srvp_enable(struct omap_sr *sr, u32 target_opp)
> +{
> +	int ret;
> +	/* If we dont have an nvalue, dont bother.. */
> +	if (!sr->opp_nvalue[target_opp - 1]) {
> +		pr_warning("SR[%d]: OPP%d does not support SR to enable\n",
> +				sr->srid, target_opp);
> +		return -EINVAL;
> +	}
> +	ret = sr_vp_enable(sr, target_opp);
> +	if (unlikely(ret)) {
> +		pr_err("SR[%d]: failed to enable vp:%d\n", sr->srid, ret);
> +	} else {
> +		ret = sr_enable(sr, target_opp);
> +		/* Attempt to recover */
> +		if (unlikely(ret)) {
> +			pr_err("SR[%d]: failed to enable sr:%d\n", sr->srid,
> +			       ret);
> +			/* nothing we can do if vp_disable fails */
> +			(void)sr_vp_disable(sr);
> +		}
> +	}
> +	/*
> +	 * potentially system in an invalid state - warn..
> +	 */
> +	WARN_ON(ret);
> +	return ret;
> +}
> +
> +/*********************** DVFS Entry POINTS **********************************/
> +
> +/**
> + * @brief sr_vp_enable_both - enable both vp and sr
> + *
> + * @param target_opp - targetted op
> + * @param current_opp - current opp
> + *
> + * @return 0 if ok, 1 if not ok
> + */
> +int sr_vp_enable_both(u32 target_opp, u32 current_opp)
> +{
> +	struct omap_sr *sr;
> +	u32 vdd, target_opp_no;
> +	int ret = 0;
> +
> +	vdd = get_vdd(target_opp);
> +	target_opp_no = get_opp_no(target_opp);
> +	sr = (vdd == PRCM_VDD1) ? &sr1 : &sr2;
> +
> +	if (sr->is_autocomp_active && sr->is_sr_reset) {
> +		ret = srvp_enable(sr, target_opp_no);
> +		if (ret) {
> +			pr_err("SR[%d]:enableboth:"
> +			       "failed enable SR\n", sr->srid);
> +		}
> +	}
> +	return 0;
> +}
> +EXPORT_SYMBOL(sr_vp_enable_both);
> +
> +/**
> + * @brief sr_vp_disable_both - disable both vp and sr
> + *
> + * @param target_opp - targetted opp
> + * @param current_opp - current opp
> + *
> + * @return 0 if ok, 1 if not ok
> + */
> +int sr_vp_disable_both(u32 target_opp, u32 current_opp)
> +{
> +	struct omap_sr *sr;
> +	u32 vdd;
> +	int ret = 0;
> +
> +	vdd = get_vdd(target_opp);
> +	sr = (vdd == PRCM_VDD1) ? &sr1 : &sr2;
> +
> +	if (sr->is_autocomp_active && !sr->is_sr_reset) {
> +		ret = srvp_disable(sr);
> +		if (ret) {
> +			pr_err("SR[%d]:disableboth:"
> +			       "failed disable SR\n", sr->srid);
> +		}
> +	}
> +
> +	return 0;
> +
> +}
> +EXPORT_SYMBOL(sr_vp_disable_both);
> +
> +/**
> + * @brief sr_voltage_set - setup a voltage requested
> + *
> + * @param target_opp - targetted opp
> + * @param current_opp  - current opp
> + * @param target_vsel - targeted voltage
> + * @param current_vsel - current voltage
> + *
> + * @return  - result of op -0 if ok, else value
> + */
> +int sr_voltage_set(u32 target_opp, u32 current_opp,
> +		   u8 target_vsel, u8 current_vsel)
> +{
> +	struct omap_sr *sr;
> +	u32 vdd, target_opp_no;
> +	int ret;
> +
> +	vdd = get_vdd(target_opp);
> +	target_opp_no = get_opp_no(target_opp);
> +	sr = (vdd == PRCM_VDD1) ? &sr1 : &sr2;
> +
> +	ret =
> +	    SR_CHOSEN_VOLTAGE_UPDATE_MECH(sr, target_opp_no, target_vsel,
> +					  current_vsel);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(sr_voltage_set);
> +
> +/*********************** CPUIDLE ENTRY POINTS *********************************/
> +
> +/**
> + * @brief disable_smartreflex - disable SmartReflex before WFI
> + *
> + * @param srid SRID
> + */
> +void disable_smartreflex(int srid)
> +{
> +	struct omap_sr *sr = NULL;
> +	int ret;
> +	u32 current_opp_no;
> +
> +	sr = (srid == SR1) ? &sr1 : &sr2;
> +
> +	current_opp_no = (sr->srid == SR1) ?
> +			mpu_opps[resource_get_level("vdd1_opp")].opp_id :
> +			l3_opps[resource_get_level("vdd2_opp")].opp_id;
> +
> +
> +	if (sr->is_autocomp_active && !sr->is_sr_reset) {
> +		sr->req_opp_no = current_opp_no;
> +		ret = srvp_disable(sr);
> +		if (ret)
> +			pr_err("SR[%d]:disable_smartreflex:"
> +			       "failed disable SR\n", sr->srid);
> +	}
> +
> +	/* Reset the voltage for current OPP to nominal if SR was enabled */
> +	if (sr->is_autocomp_active)
> +		sr_vp_reset_voltage(srid);
> +}
> +EXPORT_SYMBOL(disable_smartreflex);
> +
> +/**
> + * @brief enable_smartreflex - enable smart reflex after WFI is hit
> + *
> + * @param srid -SR ID to hit
> + */
> +void enable_smartreflex(int srid)
> +{
> +	struct omap_sr *sr;
> +	int ret;
> +	u32 current_opp_no;
> +
> +	sr = (srid == SR1) ? &sr1 : &sr2;
> +
> +	current_opp_no = (sr->srid == SR1) ?
> +			mpu_opps[resource_get_level("vdd1_opp")].opp_id :
> +			l3_opps[resource_get_level("vdd2_opp")].opp_id;
> +	if (sr->is_autocomp_active && sr->is_sr_reset) {
> +		ret = srvp_enable(sr, current_opp_no);
> +		if (ret)
> +			pr_err("SR[%d]:enable_smartreflex:"
> +			       "failed enable SR\n", sr->srid);
> +	}
> +}
> +EXPORT_SYMBOL(enable_smartreflex);
> +
> +/*********************** SYSFS ENTRY POINTS *********************************/
> +/**
> + * @brief omap_sr_vdd_autocomp_show - Sysfs entry for showing SR status
> + *
> + */
> +static ssize_t omap_sr_vdd_autocomp_show(struct kobject *kobj,
> +					 struct kobj_attribute *attr, char *buf)
> +{
> +	int srid;
> +	struct omap_sr *sr;
> +	srid = (strcmp(attr->attr.name, "sr_vdd1_autocomp") == 0) ? SR1 : SR2;
> +	sr = (srid == SR1) ? &sr1 : &sr2;
> +	return sprintf(buf, "%d\n", sr->is_autocomp_active);
> +}
> +
> +/**
> + * @brief omap_sr_vdd_autocomp_store - enable/disable SR
> + *
> + */
> +static ssize_t omap_sr_vdd_autocomp_store(struct kobject *kobj,
> +					  struct kobj_attribute *attr,
> +					  const char *buf, size_t n)
> +{
> +	unsigned short value;
> +	int srid;
> +	struct omap_sr *sr;
> +	int ret = 0;
> +	u32 current_vddopp_no;
> +	const char *name;
> +
> +	name = attr->attr.name;
> +
> +	srid = (strcmp(name, "sr_vdd1_autocomp") == 0) ? SR1 : SR2;
> +	sr = (srid == SR1) ? &sr1 : &sr2;
> +	current_vddopp_no = (sr->srid == SR1) ?
> +			mpu_opps[resource_get_level("vdd1_opp")].opp_id :
> +			l3_opps[resource_get_level("vdd2_opp")].opp_id;
> +
> +	if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
> +		pr_err("%s: Invalid value[%d]. Use 0 or 1\n", name, value);
> +		return -EINVAL;
> +	}
> +	if (sr->is_autocomp_active == value) {
> +		pr_info("%s: Already set to %d \n", name, value);
> +		return n;
> +	}
> +	/*
> +	 * Sanity check-might happen if SR and dvfs/idle paths collide
> +	 * but unlikely though..
> +	 */
> +	if (unlikely(value ^ sr->is_sr_reset)) {
> +		pr_warning("%s: Is already set %d Vs %d.\n", name, value,
> +				sr->is_sr_reset);
> +		return n;
> +	}
> +
> +	if (value)
> +		ret = srvp_enable(sr, current_vddopp_no);
> +	else {
> +		ret = srvp_disable(sr);
> +		/* reset the voltage back to nominal */
> +		sr_vp_configure(sr);
> +	}
> +	if (!ret) {
> +		sr->is_autocomp_active = value;
> +		ret = n;
> +	}
> +
> +	return ret;
> +}
> +
> +static struct kobj_attribute sr_vdd1_autocomp = {
> +	.attr = {
> +		 .name = __stringify(sr_vdd1_autocomp),
> +		 .mode = 0644,
> +		 },
> +	.show = omap_sr_vdd_autocomp_show,
> +	.store = omap_sr_vdd_autocomp_store,
> +};
> +
> +static struct kobj_attribute sr_vdd2_autocomp = {
> +	.attr = {
> +		 .name = __stringify(sr_vdd2_autocomp),
> +		 .mode = 0644,
> +		 },
> +	.show = omap_sr_vdd_autocomp_show,
> +	.store = omap_sr_vdd_autocomp_store,
> +};
> +
> +/*********************** INIT FUNCTIONS *************************************/
> +
> +/**
> + * @brief srvp_configure - configure smart reflex and VP params
> + *
> + * @param sr  - structure of sr of interest
> + */
> +static void __init srvp_configure(struct omap_sr *sr)
> +{
> +	struct clk *sys_ck;
> +	u32 sys_clk_speed;
> +	u32 clk_len;
> +	u32 senn_mod, senp_mod;
> +
> +	/* Grab the clock speed */
> +	sys_ck = clk_get(NULL, "sys_ck");
> +	sys_clk_speed = clk_get_rate(sys_ck);
> +	clk_put(sys_ck);
> +
> +	switch (sys_clk_speed) {
> +	case 12000000:
> +		clk_len = SRCLKLENGTH_12MHZ_SYSCLK;
> +		break;
> +	case 13000000:
> +		clk_len = SRCLKLENGTH_13MHZ_SYSCLK;
> +		break;
> +	case 19200000:
> +		clk_len = SRCLKLENGTH_19MHZ_SYSCLK;
> +		break;
> +	case 26000000:
> +		clk_len = SRCLKLENGTH_26MHZ_SYSCLK;
> +		break;
> +	case 38400000:
> +		clk_len = SRCLKLENGTH_38MHZ_SYSCLK;
> +		break;
> +	default:
> +		pr_err("SR[%d]:Invalid sysclk value: %d\n", sr->srid,
> +		       sys_clk_speed);
> +		BUG();
> +		return;
> +	}
> +	/* Configure from the nvalues */
> +	if (sr->srid == SR1) {
> +#ifndef CONFIG_OMAP_SMARTREFLEX_TESTING_NVALUES
> +		senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> +			    OMAP343X_SR1_SENNENABLE_MASK) >>
> +		    OMAP343X_SR1_SENNENABLE_SHIFT;
> +		senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> +			    OMAP343X_SR1_SENPENABLE_MASK) >>
> +		    OMAP343X_SR1_SENPENABLE_SHIFT;
> +
> +		sr->opp_nvalue[4] =
> +		    omap_ctrl_readl(OMAP343X_CONTROL_FUSE_OPP5_VDD1);
> +		sr->opp_nvalue[3] =
> +		    omap_ctrl_readl(OMAP343X_CONTROL_FUSE_OPP4_VDD1);
> +		sr->opp_nvalue[2] =
> +		    omap_ctrl_readl(OMAP343X_CONTROL_FUSE_OPP3_VDD1);
> +		sr->opp_nvalue[1] =
> +		    omap_ctrl_readl(OMAP343X_CONTROL_FUSE_OPP2_VDD1);
> +		sr->opp_nvalue[0] =
> +		    omap_ctrl_readl(OMAP343X_CONTROL_FUSE_OPP1_VDD1);
> +#else
> +		memcpy(&sr->opp_nvalue, &sr1_test_nvalues,
> +		       sizeof(sr1_test_nvalues));
> +		senn_mod = SR1_N_MOD;
> +		senp_mod = SR1_P_MOD;
> +#endif			/* ifndef CONFIG_OMAP_SMARTREFLEX_TESTING_NVALUES */
> +		sr->sr_errconfig_value = SR1_ERRWEIGHT | SR1_ERRMAXLIMIT;
> +		sr->vp.vplimito_value |= sr_vplimito_value(sys_clk_speed,
> +				PRM_VP1_VLIMITTO_TIMEOUT_US) <<
> +					PRM_VP1_VLIMITTO_TIMEOUT_SHIFT;
> +
> +	} else {
> +#ifndef CONFIG_OMAP_SMARTREFLEX_TESTING_NVALUES
> +		senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> +			    OMAP343X_SR2_SENNENABLE_MASK) >>
> +		    OMAP343X_SR2_SENNENABLE_SHIFT;
> +
> +		senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
> +			    OMAP343X_SR2_SENPENABLE_MASK) >>
> +		    OMAP343X_SR2_SENPENABLE_SHIFT;
> +
> +		sr->opp_nvalue[2] =
> +		    omap_ctrl_readl(OMAP343X_CONTROL_FUSE_OPP3_VDD2);
> +		sr->opp_nvalue[1] =
> +		    omap_ctrl_readl(OMAP343X_CONTROL_FUSE_OPP2_VDD2);
> +		sr->opp_nvalue[0] =
> +		    omap_ctrl_readl(OMAP343X_CONTROL_FUSE_OPP1_VDD2);
> +		sr->sr_errconfig_value = SR2_ERRWEIGHT | SR2_ERRMAXLIMIT;
> +#else
> +		memcpy(&sr->opp_nvalue, &sr2_test_nvalues,
> +		       sizeof(sr2_test_nvalues));
> +		senn_mod = SR2_N_MOD;
> +		senp_mod = SR2_P_MOD;
> +#endif			/* ifndef CONFIG_OMAP_SMARTREFLEX_TESTING_NVALUES */
> +		sr->vp.vplimito_value |= sr_vplimito_value(sys_clk_speed,
> +				PRM_VP2_VLIMITTO_TIMEOUT_US) <<
> +					PRM_VP2_VLIMITTO_TIMEOUT_SHIFT;
> +	}
> +
> +	sr->sr_errconfig_value |=
> +	    ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST |
> +	    SR_CLKACTIVITY_IOFF_FON;
> +
> +	sr->sr_config_value =
> +	    (clk_len << SRCONFIG_SRCLKLENGTH_SHIFT) | SRCONFIG_ERRGEN_EN
> +	    | SRCONFIG_SENENABLE | (senn_mod <<
> +				    SRCONFIG_SENNENABLE_SHIFT) |
> +	    (senp_mod << SRCONFIG_SENPENABLE_SHIFT) | SRCONFIG_DELAYCTRL;
> +
> +	/* Set up nominal voltage */
> +	sr_vp_configure(sr);
> +}
> +
> +/**
> + * @brief omap_sr_init - SR initialization
> + *
> + * @return  0
> + */
> +static int __init omap_sr_init(void)
> +{
> +	int ret = 0;
> +	ret = omap_pmic_srinit();
> +	if (ret) {
> +		pr_crit("PMIC init failed during SmartReflex initilization."
> +				"connectivity issues?: %d\n", ret);
> +		return ret;
> +	}
> +
> +#ifdef CONFIG_OMAP_SMARTREFLEX_TESTING_NVALUES
> +	pr_err("Warning: This build uses SmartReflex Testing NVALUES!!..\n");
> +#endif
> +	/* TODO: Extend this support for various PMICs */
> +	if (cpu_is_omap34xx()) {
> +		sr1.fclk = clk_get(NULL, "sr1_fck");
> +		sr1.iclk = clk_get(NULL, "sr_l4_ick");
> +		sr2.fclk = clk_get(NULL, "sr2_fck");
> +		sr2.iclk = clk_get(NULL, "sr_l4_ick");
> +
> +		srvp_configure(&sr1);
> +		srvp_configure(&sr2);
> +
> +	} else {
> +		pr_warning("SmartReflex is not supported\n");
> +		return -ENODEV;
> +	}
> +
> +	pr_info("SmartReflex driver initialized\n");
> +
> +	ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
> +	if (ret)
> +		pr_warning("sysfs_create_file failed: %d\n", ret);
> +
> +	ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
> +	if (ret)
> +		pr_warning("sysfs_create_file failed: %d\n", ret);
> +
> +	return 0;
> +}
> +late_initcall(omap_sr_init);
> diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
> new file mode 100644
> index 0000000..8efe2e2
> --- /dev/null
> +++ b/arch/arm/mach-omap2/smartreflex.h
> @@ -0,0 +1,249 @@
> +#ifndef __ARCH_ARM_MACH_OMAP3_SMARTREFLEX_H
> +#define __ARCH_ARM_MACH_OMAP3_SMARTREFLEX_H
> +/*
> + * linux/arch/arm/mach-omap2/smartreflex.h
> + *
> + * Copyright (C) 2008 Nokia Corporation
> + * Kalle Jokiniemi
> + *
> + * Copyright (C) 2007 Texas Instruments, Inc.
> + * Lesly A M <x0080970@xxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +/* 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		0x20
> +#define ERRCONFIG		0x24
> +
> +/* SR Modules */
> +#define SR1			1
> +#define SR2			2
> +
> +#define VP1_IRQMASK_TRANSDONE		(0x1 << 15)
> +#define VP2_IRQMASK_TRANSDONE		(0x1 << 21)
> +
> +/* PRM_VP1_CONFIG */
> +#define PRM_VP1_CONFIG_ERROROFFSET	(0x00 << 24)
> +#define PRM_VP1_CONFIG_ERRORGAIN	(0x18 << 16)
> +#define SR_ERRGAIN_LOWOP		(0x0C)
> +#define SR_ERRGAIN_HIGHOPP		(0x18)
> +#define SR_ERRMINLIMIT_LOWOPP           (0xF4 << 0)
> +#define SR_ERRMINLIMIT_HIGHOPP          (0xF9 << 0)
> +#define PRM_VP_STATUS_VPINIDLE		(0x1 << 0)
> +
> +#define PRM_VP1_CONFIG_INITVOLTAGE	(0x30 << 8) /* 1.2 volt */
> +#define PRM_VP1_CONFIG_TIMEOUTEN	(0x1 << 3)
> +#define PRM_VP1_CONFIG_INITVDD		(0x1 << 2)
> +#define PRM_VP1_CONFIG_FORCEUPDATE	(0x1 << 1)
> +#define PRM_VP1_CONFIG_VPENABLE		(0x1 << 0)
> +
> +/* PRM_VP1_VSTEPMIN */
> +#define PRM_VP1_VSTEPMIN_SMPSWAITTIMEMIN	(0x03C << 8)
> +#define PRM_VP1_VSTEPMIN_VSTEPMIN		(0x01 << 0)
> +
> +/* PRM_VP1_VSTEPMAX */
> +#define PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX	(0x003C << 8)
> +#define PRM_VP1_VSTEPMAX_VSTEPMAX		(0x08 << 0)
> +
> +/* PRM_VP1_VLIMITTO */
> +#define PRM_VP1_VLIMITTO_VDDMAX		(0x44 << 24)
> +#define PRM_VP1_VLIMITTO_VDDMIN		(0x14 << 16)
> +#define PRM_VP1_VLIMITTO_TIMEOUT_US	(200)
> +#define PRM_VP1_VLIMITTO_TIMEOUT_SHIFT	(0)
> +
> +/* PRM_VP2_CONFIG */
> +#define PRM_VP2_CONFIG_ERROROFFSET	(0x00 << 24)
> +#define PRM_VP2_CONFIG_ERRORGAIN	(0x18 << 16)
> +
> +#define PRM_VP2_CONFIG_INITVOLTAGE	(0x30 << 8) /* 1.2 volt */
> +#define PRM_VP2_CONFIG_TIMEOUTEN	(0x1 << 3)
> +#define PRM_VP2_CONFIG_INITVDD		(0x1 << 2)
> +#define PRM_VP2_CONFIG_FORCEUPDATE	(0x1 << 1)
> +#define PRM_VP2_CONFIG_VPENABLE		(0x1 << 0)
> +
> +/* PRM_VP2_VSTEPMIN */
> +#define PRM_VP2_VSTEPMIN_SMPSWAITTIMEMIN	(0x03C << 8)
> +#define PRM_VP2_VSTEPMIN_VSTEPMIN		(0x01 << 0)
> +
> +/* PRM_VP2_VSTEPMAX */
> +#define PRM_VP2_VSTEPMAX_SMPSWAITTIMEMAX	(0x003C << 8)
> +#define PRM_VP2_VSTEPMAX_VSTEPMAX		(0x08 << 0)
> +
> +/* PRM_VP2_VLIMITTO */
> +#define PRM_VP2_VLIMITTO_VDDMAX		(0x42 << 24)
> +#define PRM_VP2_VLIMITTO_VDDMIN		(0x18 << 16)
> +#define PRM_VP2_VLIMITTO_TIMEOUT_US	(200)
> +#define PRM_VP2_VLIMITTO_TIMEOUT_SHIFT	(0)
> +
> +/* SRCONFIG */
> +#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
> +
> +#define SRCONFIG_SRCLKLENGTH_SHIFT	12
> +#define SRCONFIG_SENNENABLE_SHIFT	5
> +#define SRCONFIG_SENPENABLE_SHIFT	3
> +
> +#define SRCONFIG_SRENABLE		(0x01 << 11)
> +#define SRCONFIG_SENENABLE		(0x01 << 10)
> +#define SRCONFIG_ERRGEN_EN		(0x01 << 9)
> +#define SRCONFIG_MINMAXAVG_EN		(0x01 << 8)
> +
> +#define SRCONFIG_DELAYCTRL		(0x01 << 2)
> +#define SRCONFIG_CLKCTRL		(0x00 << 0)
> +
> +/* NVALUERECIPROCAL */
> +#define NVALUERECIPROCAL_SENPGAIN_SHIFT	20
> +#define NVALUERECIPROCAL_SENNGAIN_SHIFT	16
> +#define NVALUERECIPROCAL_RNSENP_SHIFT	8
> +#define NVALUERECIPROCAL_RNSENN_SHIFT	0
> +
> +/* ERRCONFIG */
> +#define SR_CLKACTIVITY_MASK		(0x03 << 20)
> +#define SR_ERRWEIGHT_MASK		(0x07 << 16)
> +#define SR_ERRMAXLIMIT_MASK		(0xFF << 8)
> +#define SR_ERRMINLIMIT_MASK		(0xFF << 0)
> +
> +#define SR_CLKACTIVITY_IOFF_FOFF	(0x00 << 20)
> +#define SR_CLKACTIVITY_IOFF_FON		(0x02 << 20)
> +
> +#define ERRCONFIG_VPBOUNDINTEN		(0x1 << 31)
> +#define ERRCONFIG_MCUDISACKINTEN	(0x1 << 23)
> +
> +/* Status Bits */
> +#define ERRCONFIG_VPBOUNDINTST		(0x1 << 30)
> +#define ERRCONFIG_MCUACCUMINTST		(0x1 << 28)
> +#define ERRCONFIG_MCUVALIDINTST		(0x1 << 26)
> +#define ERRCONFIG_MCUBOUNDINTST		(0x1 << 24)
> +#define ERRCONFIG_MCUDISACKINTST	(0x1 << 22)
> +
> +/* WARNING: Ensure all access to errconfig register skips
> + * clearing intst bits to ensure that we dont clear status
> + * bits unwantedly.. esp vpbound
> + */
> +#define ERRCONFIG_INTERRUPT_STATUS_MASK  (ERRCONFIG_VPBOUNDINTST |\
> +		ERRCONFIG_MCUACCUMINTST |\
> +		ERRCONFIG_MCUVALIDINTST |\
> +		ERRCONFIG_MCUBOUNDINTST |\
> +		ERRCONFIG_MCUDISACKINTST | (0X1<<19))
> +
> +#define SR1_ERRWEIGHT			(0x04 << 16)
> +#define SR1_ERRMAXLIMIT			(0x02 << 8)
> +#define SR1_ERRMINLIMIT			(0xFA << 0)
> +
> +#define SR2_ERRWEIGHT			(0x04 << 16)
> +#define SR2_ERRMAXLIMIT			(0x02 << 8)
> +#define SR2_ERRMINLIMIT			(0xFA << 0)
> +
> +/* T2 SMART REFLEX */
> +#define R_SRI2C_SLAVE_ADDR		0x12
> +#define R_VDD1_SR_CONTROL		0x00
> +#define R_VDD2_SR_CONTROL		0x01
> +
> +/* VDDs*/
> +#define PRCM_VDD1	1
> +#define PRCM_VDD2	2
> +
> +/*
> + * XXX: These should be removed/moved from here once we have a working DVFS
> + * implementation in place
> + */
> +#define PHY_TO_OFF_PM_MASTER(p)		(p - 0x36)
> +#define PHY_TO_OFF_PM_RECIEVER(p)	(p - 0x5b)
> +#define PHY_TO_OFF_PM_INT(p)		(p - 0x2e)
> +
> +/* Vmode control */
> +#define R_DCDC_GLOBAL_CFG		PHY_TO_OFF_PM_RECIEVER(0x61)
> +/* R_DCDC_GLOBAL_CFG register, SMARTREFLEX_ENABLE values */
> +#define DCDC_GLOBAL_CFG_ENABLE_SRFLX	0x08
> +
> +
> +/* DEVICE ID/DPLL ID/CLOCK ID: bits 28-31 for OMAP type */
> +#define OMAP_TYPE_SHIFT		28
> +#define OMAP_TYPE_MASK		0xF
> +/* OPP ID: bits: 0-4 for OPP number */
> +#define OPP_NO_POS		0
> +#define OPP_NO_MASK		0x1F
> +/* OPP ID: bits: 5-6 for VDD */
> +#define VDD_NO_POS		5
> +#define VDD_NO_MASK		0x3
> +/* Other IDs: bits 20-27 for ID type */
> +/* These IDs have bits 25,26,27 as 1 */
> +#define OTHER_ID_TYPE_SHIFT		20
> +#define OTHER_ID_TYPE_MASK		0xFF
> +
> +#define OTHER_ID_TYPE(X) ((X & OTHER_ID_TYPE_MASK) << OTHER_ID_TYPE_SHIFT)
> +#define ID_OPP_NO(X)	 ((X & OPP_NO_MASK) << OPP_NO_POS)
> +#define ID_VDD(X)	 ((X & VDD_NO_MASK) << VDD_NO_POS)
> +#define OMAP(X)		 ((X >> OMAP_TYPE_SHIFT) & OMAP_TYPE_MASK)
> +#define get_opp_no(X)	 ((X >> OPP_NO_POS) & OPP_NO_MASK)
> +#define get_vdd(X)	 ((X >> VDD_NO_POS) & VDD_NO_MASK)
> +
> +/* XXX: end remove/move */
> +
> +/* XXX: find more appropriate place for these once DVFS is in place */
> +extern u32 current_vdd1_opp;
> +extern u32 current_vdd2_opp;
> +
> +/*
> + * Smartreflex module enable/disable interface.
> + * NOTE: if smartreflex is not enabled from sysfs, these functions will not
> + * do anything.
> + */
> +#ifdef CONFIG_OMAP_SMARTREFLEX
> +void enable_smartreflex(int srid);
> +void disable_smartreflex(int srid);
> +int sr_voltage_set(u32 target_opp, u32 current_opp,
> +		   u8 target_vsel, u8 current_vsel);
> +int sr_vp_disable_both(u32 target_opp, u32 current_opp);
> +int sr_vp_enable_both(u32 target_opp, u32 current_opp);
> +int vc_send_command(u8 slave_addr, u8 reg_addr, u8 data, u16 timeout_us);
> +int omap_pmic_srinit(void);
> +u32 omap_pmic_voltage_ramp_delay(u8 target_vsel, u8 current_vsel);
> +#ifdef CONFIG_OMAP_VC_BYPASS_UPDATE
> +int omap_pmic_voltage_cmds(u8 srid, u8 target_vsel);
> +#endif
> +#else
> +static inline void enable_smartreflex(int srid) {}
> +static inline void disable_smartreflex(int srid) {}
> +static inline int sr_voltage_set(u32 target_opp, u32 current_opp,
> +				   u8 target_vsel, u8 current_vsel)
> +{
> +	return -EINVAL;
> +}
> +static inline int sr_vp_disable_both(u32 target_opp, u32 current_opp)
> +{
> +	return -EINVAL;
> +}
> +static inline int sr_vp_enable_both(u32 target_opp, u32 current_opp)
> +{
> +	return -EINVAL;
> +}
> +static inline int vc_send_command(u8 slave_addr, u8 reg_addr, u8 data,
> +		u16 timeout_us)
> +{
> +	return -EINVAL;
> +}
> +#ifdef CONFIG_OMAP_VC_BYPASS_UPDATE
> +static inline int omap_pmic_voltage_cmds(u8 srid, u8 target_vsel)
> +{
> +	return -EINVAL;
> +}
> +};
> +#endif
> +#endif
> +
> +#endif
> diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
> index 2143db5..30c70d3 100644
> --- a/arch/arm/plat-omap/Kconfig
> +++ b/arch/arm/plat-omap/Kconfig
> @@ -81,9 +81,10 @@ config OMAP_SMARTREFLEX
>  	  compensation for VDD1 and VDD2, user must write 1 to
>  	  /sys/power/sr_vddX_autocomp, where X is 1 or 2.
>  
> -config OMAP_SMARTREFLEX_TESTING
> -	bool "Smartreflex testing support"
> +config OMAP_SMARTREFLEX_TESTING_NVALUES
> +	bool "Use SmartReflex Test NVALUES"
>  	depends on OMAP_SMARTREFLEX
> +	depends on EXPERIMENTAL
>  	default n
>  	help
>  	  Say Y if you want to enable SmartReflex testing with SW hardcoded
> @@ -93,7 +94,18 @@ config OMAP_SMARTREFLEX_TESTING
>  	  SmartReflex modules are included. Using these hardcoded values set
>  	  in software, one can test the SmartReflex features without E-fuse.
>  
> -	  WARNING: Enabling this option may cause your device to hang!
> +	  WARNING:
> +	  * Enabling this option may cause your device to hang!
> +	  * If you don't know what you are doing, leave this option as n
> +
> +config OMAP_VC_BYPASS_UPDATE
> +	bool "Use VC Bypass method of updating voltage"
> +	depends on OMAP_SMARTREFLEX
> +	default n
> +	help
> +	  Say Y if you would like to use VC Bypass method of
> +	  update. If this is disabled, the default
> +	  VP forceupdate method is used.
>  
>  config OMAP_RESET_CLOCKS
>  	bool "Reset unused clocks during boot"
> -- 
> 1.6.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

  Powered by Linux