+diff -urN kernel-power-2.6.28/arch/arm/mach-omap2/omap3-opp.h kernel-power-2.6.28.SR/arch/arm/mach-omap2/omap3-opp.h
+--- kernel-power-2.6.28/arch/arm/mach-omap2/omap3-opp.h 2011-10-11 13:51:21.441301622 +0100
++++ kernel-power-2.6.28.SR/arch/arm/mach-omap2/omap3-opp.h 2011-10-22 16:31:45.291911000 +0100
+@@ -11,8 +11,7 @@
+ #define S900M 900000000
+ #define S850M 850000000
+ #define S805M 805000000
+-#define S750M 750000000
+-#define S700M 700000000
++#define S720M 720000000
+ #define S600M 600000000
+ #define S550M 550000000
+ #define S500M 500000000
+diff -urN kernel-power-2.6.28/arch/arm/mach-omap2/pm34xx.c kernel-power-2.6.28.SR/arch/arm/mach-omap2/pm34xx.c
+--- kernel-power-2.6.28/arch/arm/mach-omap2/pm34xx.c 2011-10-11 13:51:19.475662264 +0100
++++ kernel-power-2.6.28.SR/arch/arm/mach-omap2/pm34xx.c 2011-11-14 17:06:15.733128000 +0000
+@@ -629,9 +629,9 @@
+ * Only needed if we are going to enter retention.
+ */
+ if (mpu_next_state < PWRDM_POWER_ON)
+- disable_smartreflex(SR1);
++ disable_smartreflex(SR1,0);
+ if (core_next_state < PWRDM_POWER_ON)
+- disable_smartreflex(SR2);
++ disable_smartreflex(SR2,0);
+
+ /* CORE */
+ if (core_next_state < PWRDM_POWER_ON) {
+diff -urN kernel-power-2.6.28/arch/arm/mach-omap2/pm.c kernel-power-2.6.28.SR/arch/arm/mach-omap2/pm.c
+--- kernel-power-2.6.28/arch/arm/mach-omap2/pm.c 2011-10-11 13:51:21.444897248 +0100
++++ kernel-power-2.6.28.SR/arch/arm/mach-omap2/pm.c 2011-11-12 13:33:08.600565000 +0000
+@@ -44,25 +44,23 @@
+
+ struct omap_opp omap3_mpu_rate_table[] = {
+ {0, 0, 0},
+- {0, 1, 0x1E},
+- /*underclocking*/
+- {S125M, 2, 0x1E},
+ /*default*/
+- {S250M, 3, 0x26},
+- {S500M, 4, 0x30},
+- {S550M, 5, 0x36},
+- {S600M, 6, 0x3C},
++ {S125M, VDD1_OPP1, 0x1E},
++ {S250M, VDD1_OPP2, 0x26},
++ {S500M, VDD1_OPP3, 0x30},
++ {S550M, VDD1_OPP4, 0x36},
++ {S600M, VDD1_OPP5, 0x3C},
+ /*overclocking*/
+- {S700M, 7, 0x3C},
+- {S750M, 8, 0x3C},
+- {S805M, 9, 0x3C},
+- {S850M, 10, 0x3C},
+- {S900M, 11, 0x3C},
+- {S950M, 12, 0x3C},
+- {S1000M, 13, 0x3C},
+- {S1100M, 14, 0x48},
+- {S1150M, 15, 0x48},
++ {S720M, VDD1_OPP6, 0x3C},
++ {S805M, VDD1_OPP7, 0x3C},
++ {S850M, VDD1_OPP8, 0x3C},
++ {S900M, VDD1_OPP9, 0x3C},
++ {S950M, VDD1_OPP10, 0x3C},
++ {S1000M,VDD1_OPP11, 0x3C},
++ {S1100M,VDD1_OPP12, 0x48},
++ {S1150M,VDD1_OPP13, 0x48},
+ };
++EXPORT_SYMBOL(omap3_mpu_rate_table);
+
+ struct omap_opp omap3_l3_rate_table[] = {
+ {0, 0, 0},
+@@ -76,25 +74,23 @@
+
+ struct omap_opp omap3_dsp_rate_table[] = {
+ {0, 0, 0},
+- /*underclocking*/
+- {S90M, 1, 0x1E},
+ /*default*/
+- {S90M, 2, 0x1E},
+- {S180M, 3, 0x26},
+- {S360M, 4, 0x30},
+- {S400M, 5, 0x36},
+- {S430M, 6, 0x3C},
++ {S90M, VDD1_OPP1, 0x1E},
++ {S180M, VDD1_OPP2, 0x26},
++ {S360M, VDD1_OPP3, 0x30},
++ {S400M, VDD1_OPP4, 0x36},
++ {S430M, VDD1_OPP5, 0x3C},
+ /*overclocking*/
+- {S430M, 7, 0x3C},
+- {S430M, 8, 0x3C},
+- {S430M, 9, 0x3C},/*800MHz*/
+- {S500M, 10, 0x3C},
+- {S500M, 11, 0x3C},
+- {S500M, 12, 0x3C},
+- {S500M, 13, 0x3C},
+- {S520M, 14, 0x48},
+- {S520M, 15, 0x48},
++ {S520M, VDD1_OPP6, 0x3C},
++ {S520M, VDD1_OPP7, 0x3C},
++ {S520M, VDD1_OPP8, 0x3C},
++ {S520M, VDD1_OPP9, 0x3C},
++ {S520M, VDD1_OPP10, 0x3C},
++ {S520M, VDD1_OPP11, 0x3C},
++ {S520M, VDD1_OPP12, 0x48},
++ {S520M, VDD1_OPP13, 0x48},
+ };
++EXPORT_SYMBOL(omap3_dsp_rate_table);
+
+ unsigned short enable_dyn_sleep;
+ unsigned short clocks_off_while_idle;
+@@ -342,13 +338,13 @@
+ }
+
+ if (attr == &vdd1_opp_attr) {
+- if (value < 1 || value > 5) {
++ if (value < MIN_VDD1_OPP || value > MAX_VDD1_OPP) {
+ printk(KERN_ERR "vdd_opp_store: Invalid value\n");
+ return -EINVAL;
+ }
+ resource_set_opp_level(PRCM_VDD1, value, flags);
+ } else if (attr == &vdd2_opp_attr) {
+- if (value < 1 || value > 3) {
++ if (value < MIN_VDD2_OPP || value > MAX_VDD2_OPP) {
+ printk(KERN_ERR "vdd_opp_store: Invalid value\n");
+ return -EINVAL;
+ }
+diff -urN kernel-power-2.6.28/arch/arm/mach-omap2/resource34xx.c kernel-power-2.6.28.SR/arch/arm/mach-omap2/resource34xx.c
+--- kernel-power-2.6.28/arch/arm/mach-omap2/resource34xx.c 2011-10-11 13:50:56.787174344 +0100
++++ kernel-power-2.6.28.SR/arch/arm/mach-omap2/resource34xx.c 2011-11-15 10:50:41.556771000 +0000
+@@ -279,7 +279,7 @@
+
+ #ifdef CONFIG_OMAP_SMARTREFLEX
+ sr_status = sr_stop_vddautocomap((get_vdd(t_opp) == PRCM_VDD1) ?
+- SR1 : SR2);
++ SR1 : SR2,opp[current_level].opp_id);
+ #endif
+ for (i = 0; i < 2; i++) {
+ if (i == raise)
+diff -urN kernel-power-2.6.28/arch/arm/mach-omap2/smartreflex.c kernel-power-2.6.28.SR/arch/arm/mach-omap2/smartreflex.c
+--- kernel-power-2.6.28/arch/arm/mach-omap2/smartreflex.c 2011-10-11 13:51:21.441301622 +0100
++++ kernel-power-2.6.28.SR/arch/arm/mach-omap2/smartreflex.c 2011-11-15 10:54:13.761220000 +0000
+@@ -37,6 +37,7 @@
+ #include "prm.h"
+ #include "smartreflex.h"
+ #include "prm-regbits-34xx.h"
++#include "omap3-opp.h"
+
+ /*
+ * VP_TRANXDONE_TIMEOUT: maximum microseconds to wait for the VP to
+@@ -73,6 +74,12 @@
+ */
+ #define SR_DISABLE_MAX_ATTEMPTS 4
+
++#define ACCURACY 100
++#define NDELTA_3430 (3.0 * ACCURACY)
++#define PDELTA_3430 (2.6 * ACCURACY)
++#define SR_NVALUE_ADJUST -150000
++#define SR_NVALUE_DSP_ADJUST 12500
++
+ struct omap_sr {
+ int srid;
+ int is_sr_reset;
+@@ -82,6 +89,7 @@
+ u32 req_opp_no;
+ u32 opp1_nvalue, opp2_nvalue, opp3_nvalue, opp4_nvalue;
+ u32 opp5_nvalue;
++ u32 opp6_nvalue, opp7_nvalue, opp8_nvalue, opp9_nvalue;
+ u32 senp_mod, senn_mod;
+ void __iomem *srbase_addr;
+ void __iomem *vpbase_addr;
+@@ -101,6 +109,7 @@
+
+ reg_val = __raw_readl(SR_REGADDR(offset));
+ reg_val &= ~mask;
++
+ reg_val |= value;
+
+ __raw_writel(reg_val, SR_REGADDR(offset));
+@@ -211,6 +220,147 @@
+ }
+ }
+
++static u32 calculate_opp_nadj(u32 opp_value, u32 delta_n)
++{
++ u32 sen_ngain_fuse, sen_nrn_fuse;
++
++ sen_ngain_fuse = (opp_value & 0x000F0000) >> 0x10;
++ sen_nrn_fuse = (opp_value & 0x000000FF);
++
++ return ((1 << (sen_ngain_fuse + 8)) / sen_nrn_fuse) + delta_n;
++}
++
++static u32 calculate_opp_padj(u32 opp_value, u32 delta_p)
++{
++ u32 sen_pgain_fuse, sen_prn_fuse;
++
++ sen_pgain_fuse = (opp_value & 0x000F00000) >> 0x14;
++ sen_prn_fuse = (opp_value & 0x0000FF00) >> 8;
++
++ return ((1 << (sen_pgain_fuse + 8)) / sen_prn_fuse) + delta_p;
++}
++
++static u32 get_padj_for_freq(u32 opp0fuse,u32 opp1fuse, u32 freq)
++{
++ u32 padj_0=calculate_opp_padj(opp0fuse,0);
++ u32 padj_1=calculate_opp_padj(opp1fuse,0);
++ u32 p_slope_a=(1000*(padj_1-padj_0))/(250-125);
++ u32 p_slope_b=1000*(padj_1-p_slope_a*250/1000);
++
++ return (u32)(p_slope_a*freq+p_slope_b)/1000;
++}
++
++static u32 get_nadj_for_freq(u32 opp0fuse,u32 opp1fuse, u32 freq)
++{
++ u32 nadj_0=calculate_opp_nadj(opp0fuse,0);
++ u32 nadj_1=calculate_opp_nadj(opp1fuse,0);
++ u32 n_slope_a=(1000*(nadj_1-nadj_0))/(250-125);
++ u32 n_slope_b=1000*(nadj_1-n_slope_a*250/1000);
++
++ return (u32)(n_slope_a*freq+n_slope_b)/1000;
++}
++
++static u32 calculate_freq_efuse_value(u32 opp0fuse,u32 opp1fuse,u32 freq)
++{
++ u32 sen_nrn, sen_ngain, sen_prn, sen_pgain;
++ u32 padj,nadj;
++ cal_reciprocal(padj=get_padj_for_freq(opp0fuse,opp1fuse,freq), &sen_pgain, &sen_prn);
++ cal_reciprocal(nadj=get_nadj_for_freq(opp0fuse,opp1fuse,freq), &sen_ngain, &sen_nrn);
++
++ return (sen_pgain << 0x14) | (sen_ngain << 0x10)
++ | (sen_prn << 0x08) | (sen_nrn);
++}
++
++/**
++ * recalc_with_margin() - helper to add margin to reciprocal and gain
++ * @uv: voltage in uVolts to add.
++ * @soc_delta: SoC specific delta base
++ * @reci: Reciprocal for the sensor
++ * @gain: Gain for the sensor
++ *
++ * The algorithm computes an adjustment required to meet the delta voltage
++ * to be added to a given sensor's reciprocal and gain. It then does a
++ * search for maximum gain for valid reciprocal value. This forms the
++ * new reciprocal and gain which incorporates the additional voltage
++ * requested.
++ *
++ * IMPORTANT: since it is not possible to ascertain the actual voltage from
++ * ntarget value, the additional voltage will be accurate upto 1 additional
++ * pmic step. The algorithm is optimized to adjust to higher end rather than
++ * less than requested additional voltage as it could be unsafe to run at
++ * voltage lower than requested level.
++ *
++ * Example: if the PMIC step size is 12.5 and requested margin in 25mV(2 PMIC
++ * steps). the actual voltage achieved can be original V achieved + 25mV upto
++ * original V + 37.5mV(3 steps) - depending on where V was achieved.
++ */
++static __init int recalc_with_margin(long uv, int soc_delta, unsigned int *reci,
++ unsigned int *gain)
++{
++ int r = 0, g = 0;
++ int nadj = 0;
++
++ nadj = ((1 << (*gain + 8)) * ACCURACY) / (*reci) +
++ soc_delta * uv / 1000;
++
++ /* Linear search for the best reciprocal */
++ for (g = 15; g >= 0; g--) {
++ r = ((1 << (g + 8)) * ACCURACY) / nadj;
++ if (r < 256) {
++ *reci = r;
++ *gain = g;
++ return 0;
++ }
++ }
++ /* Dont modify the input, just return error */
++ return -EINVAL;
++}
++
++/**
++ * sr_ntarget_add_margin() - Modify h/w ntarget to add a s/w margin
++ * @vdata: voltage data for the OPP to be modified with ntarget populated
++ * @add_uv: voltate to add to nTarget in uVolts
++ *
++ * Once the sr_device_init is complete and nTargets are populated, using this
++ * function nTarget read from h/w efuse and stored in vdata is modified to add
++ * a platform(board) specific additional voltage margin. Based on analysis,
++ * we might need different margins to be added per vdata.
++ */
++int __init sr_ntarget_add_margin(u32 old_ntarget, ulong add_uv)
++{
++ u32 temp_senp_gain, temp_senp_reciprocal;
++ u32 temp_senn_gain, temp_senn_reciprocal;
++ int soc_p_delta, soc_n_delta;
++ int r;
++
++ temp_senp_gain = (old_ntarget & 0x00F00000) >> 20;
++ temp_senn_gain = (old_ntarget & 0x000F0000) >> 16;
++ temp_senp_reciprocal = (old_ntarget & 0x0000FF00) >> 8;
++ temp_senn_reciprocal = old_ntarget & 0x000000FF;
++
++ soc_p_delta = PDELTA_3430;
++ soc_n_delta = NDELTA_3430;
++
++ r = recalc_with_margin(add_uv, soc_n_delta,
++ &temp_senn_reciprocal, &temp_senn_gain);
++ if (r) {
++ pr_err("%s: unable to add %ld uV to ntarget 0x%08x\n",
++ __func__, add_uv, old_ntarget);
++ return r;
++ }
++ r = recalc_with_margin(add_uv, soc_p_delta,
++ &temp_senp_reciprocal, &temp_senp_gain);
++ if (r) {
++ pr_err("%s: unable to add %ld uV to ntarget 0x%08x\n",
++ __func__, add_uv, old_ntarget);
++ return r;
++ }
++
++ /* Populate the new modified nTarget */
++ return (temp_senp_gain << 20) | (temp_senn_gain << 16) |
++ (temp_senp_reciprocal << 8) | temp_senn_reciprocal;
++
++}
+ static void sr_set_efuse_nvalues(struct omap_sr *sr)
+ {
+ if (sr->srid == SR1) {
+@@ -220,17 +370,24 @@
+ sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
+ OMAP343X_SR1_SENPENABLE_MASK) >>
+ OMAP343X_SR1_SENPENABLE_SHIFT;
+-
+- sr->opp5_nvalue = omap_ctrl_readl(
+- OMAP343X_CONTROL_FUSE_OPP5_VDD1);
+- sr->opp4_nvalue = omap_ctrl_readl(
+- OMAP343X_CONTROL_FUSE_OPP4_VDD1);
+- sr->opp3_nvalue = omap_ctrl_readl(
+- OMAP343X_CONTROL_FUSE_OPP3_VDD1);
+- sr->opp2_nvalue = omap_ctrl_readl(
+- OMAP343X_CONTROL_FUSE_OPP2_VDD1);
+- sr->opp1_nvalue = omap_ctrl_readl(
+- OMAP343X_CONTROL_FUSE_OPP1_VDD1);
++ sr->opp1_nvalue = sr_ntarget_add_margin(omap_ctrl_readl(
++ OMAP343X_CONTROL_FUSE_OPP1_VDD1),SR_NVALUE_ADJUST);
++ sr->opp2_nvalue = sr_ntarget_add_margin(omap_ctrl_readl(
++ OMAP343X_CONTROL_FUSE_OPP2_VDD1),SR_NVALUE_ADJUST);
++ /* 500 */
++ sr->opp3_nvalue = sr_ntarget_add_margin(sr->opp2_nvalue,212500);
++ /* 550 */
++ sr->opp4_nvalue = sr_ntarget_add_margin(sr->opp3_nvalue,50000);
++ /* 600 */
++ sr->opp5_nvalue = sr_ntarget_add_margin(sr->opp4_nvalue,50000);
++ /* 720 */
++ sr->opp6_nvalue = sr_ntarget_add_margin(sr->opp5_nvalue,100000);
++ /* 805 */
++ sr->opp7_nvalue = sr_ntarget_add_margin(sr->opp6_nvalue,75000);
++ /* 850 */
++ sr->opp8_nvalue = sr_ntarget_add_margin(sr->opp7_nvalue,50000);
++ /* 900 */
++ sr->opp9_nvalue = sr_ntarget_add_margin(sr->opp8_nvalue,55000);
+ } else if (sr->srid == SR2) {
+ sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
+ OMAP343X_SR2_SENNENABLE_MASK) >>
+@@ -262,6 +419,14 @@
+ sr->opp3_nvalue = cal_test_nvalue(0x85b + 0x200, 0x655 + 0x200);
+ sr->opp2_nvalue = cal_test_nvalue(0x506 + 0x1a0, 0x3be + 0x1a0);
+ sr->opp1_nvalue = cal_test_nvalue(0x373 + 0x100, 0x28c + 0x100);
++ sr->opp6_nvalue = calculate_freq_efuse_value(sr->opp1_nvalue,sr->opp2_nvalue,
++ mpu_opps[VDD1_OPP6].rate/1000000);
++ sr->opp7_nvalue = calculate_freq_efuse_value(sr->opp1_nvalue,sr->opp2_nvalue,
++ mpu_opps[VDD1_OPP7].rate/1000000);
++ sr->opp8_nvalue = calculate_freq_efuse_value(sr->opp1_nvalue,sr->opp2_nvalue,
++ mpu_opps[VDD1_OPP8].rate/1000000);
++ sr->opp9_nvalue = calculate_freq_efuse_value(sr->opp1_nvalue,sr->opp2_nvalue,
++ mpu_opps[VDD1_OPP9].rate/1000000);
+ } else if (sr->srid == SR2) {
+ sr->senp_mod = 0x03;
+ sr->senn_mod = 0x03;
+@@ -426,7 +591,7 @@
+ sr->is_sr_reset = 0;
+ }
+
+-static int sr_reset_voltage(int srid)
++static int sr_reset_voltage(int srid,u32 curr_opp_no)
+ {
+ u32 target_opp_no, vsel = 0;
+ u32 reg_addr = 0;
+@@ -443,6 +608,14 @@
+ reg_addr = R_VDD1_SR_CONTROL;
+ prm_vp1_voltage = prm_read_mod_reg(OMAP3430_GR_MOD,
+ OMAP3_PRM_VP1_VOLTAGE_OFFSET);
++ /* Store current calibrated voltage to be used next time preventing
++ * overvoltage when calibration cycle starts. if cur_opp_no is 0 don't
++ * store current voltage, we've been called from sram_idle().
++ * Just in case add 1 to it, so we can start a little higher next time
++ */
++ if(curr_opp_no)
++ mpu_opps[curr_opp_no].vsel = min((u32)mpu_opps[curr_opp_no].vsel,
++ prm_vp1_voltage+1);
+ t2_smps_steps = abs(vsel - prm_vp1_voltage);
+ errorgain = (target_opp_no > SR_MAX_LOW_OPP) ?
+ PRM_VP1_CONFIG_ERRORGAIN_HIGHOPP :
+@@ -513,7 +686,19 @@
+ sr->req_opp_no = target_opp_no;
+
+ if (sr->srid == SR1) {
+- switch (min(target_opp_no-1,5)) {
++ switch (min(target_opp_no,(u32)PRCM_NO_VDD1_OPPS)) {
++ case 9:
++ nvalue_reciprocal = sr->opp9_nvalue;
++ break;
++ case 8:
++ nvalue_reciprocal = sr->opp8_nvalue;
++ break;
++ case 7:
++ nvalue_reciprocal = sr->opp7_nvalue;
++ break;
++ case 6:
++ nvalue_reciprocal = sr->opp6_nvalue;
++ break;
+ case 5:
+ nvalue_reciprocal = sr->opp5_nvalue;
+ break;
+@@ -534,6 +719,11 @@
+ nvalue_reciprocal = sr->opp3_nvalue;
+ break;
+ }
++ /* give a little more just when DSP is overclocked */
++ if(dsp_opps[target_opp_no].rate > S430M)
++ nvalue_reciprocal = sr_ntarget_add_margin(nvalue_reciprocal,SR_NVALUE_DSP_ADJUST);
++ if(dsp_opps[target_opp_no].rate > S520M)
++ nvalue_reciprocal = sr_ntarget_add_margin(nvalue_reciprocal,SR_NVALUE_DSP_ADJUST);
+ } else {
+ switch (target_opp_no) {
+ case 3:
+@@ -556,7 +746,6 @@
+ target_opp_no);
+ return SR_FALSE;
+ }
+-
+ sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
+
+ /* Enable the interrupt */
+@@ -772,7 +961,7 @@
+ }
+ EXPORT_SYMBOL(sr_start_vddautocomap);
+
+-int sr_stop_vddautocomap(int srid)
++int sr_stop_vddautocomap(int srid,u32 cur_opp_no)
+ {
+ struct omap_sr *sr = NULL;
+
+@@ -789,7 +978,7 @@
+ sr_clk_disable(sr);
+ sr->is_autocomp_active = 0;
+ /* Reset the volatage for current OPP */
+- sr_reset_voltage(srid);
++ sr_reset_voltage(srid,cur_opp_no);
+ return SR_TRUE;
+ } else
+ return SR_FALSE;
+@@ -823,7 +1012,7 @@
+ }
+ }
+
+-void disable_smartreflex(int srid)
++void disable_smartreflex(int srid,u32 cur_opp_no)
+ {
+ struct omap_sr *sr = NULL;
+
+@@ -843,7 +1032,7 @@
+ /* Disable SR clk */
+ sr_clk_disable(sr);
+ /* Reset the volatage for current OPP */
+- sr_reset_voltage(srid);
++ sr_reset_voltage(srid,cur_opp_no);
+ }
+ }
+ }
+@@ -953,22 +1142,22 @@
+ const char *buf, size_t n)
+ {
+ unsigned short value;
+-
++ u32 current_vdd1opp_no;
+ if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
+ printk(KERN_ERR "sr_vdd1_autocomp: Invalid value\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&dvfs_mutex);
++ current_vdd1opp_no = resource_get_level("vdd1_opp");
++ if (IS_ERR_VALUE(current_vdd1opp_no)) {
++ mutex_unlock(&dvfs_mutex);
++ return -ENODEV;
++ }
+
+ if (value == 0) {
+- sr_stop_vddautocomap(SR1);
++ sr_stop_vddautocomap(SR1,current_vdd1opp_no);
+ } else {
+- u32 current_vdd1opp_no = resource_get_level("vdd1_opp");
+- if (IS_ERR_VALUE(current_vdd1opp_no)) {
+- mutex_unlock(&dvfs_mutex);
+- return -ENODEV;
+- }
+ sr_start_vddautocomap(SR1, current_vdd1opp_no);
+ }
+
+@@ -1008,9 +1197,13 @@
+ mutex_lock(&dvfs_mutex);
+
+ current_vdd2opp_no = resource_get_level("vdd2_opp");
++ if (IS_ERR_VALUE(current_vdd2opp_no)) {
++ mutex_unlock(&dvfs_mutex);
++ return -ENODEV;
++ }
+
+ if (value == 0)
+- sr_stop_vddautocomap(SR2);
++ sr_stop_vddautocomap(SR2, current_vdd2opp_no);
+ else
+ sr_start_vddautocomap(SR2, current_vdd2opp_no);
+
+@@ -1028,23 +1221,87 @@
+ .store = omap_sr_vdd2_autocomp_store,
+ };
+
+-static ssize_t omap_sr_opp1_efuse_show(struct kobject *kobj,
++static ssize_t omap_sr_efuse_vdd1_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+ {
+- return sprintf(buf, "%08x\n%08x\n%08x\n%08x\n%08x\n", sr1.opp1_nvalue,
++ return sprintf(buf, "%08x\n%08x\n%08x\n%08x\n%08x\n%08x\n%08x\n%08x\n%08x\n",
++ sr1.opp1_nvalue,
+ sr1.opp2_nvalue,
+ sr1.opp3_nvalue,
+ sr1.opp4_nvalue,
+- sr1.opp5_nvalue);
++ sr1.opp5_nvalue,
++ sr1.opp6_nvalue,
++ sr1.opp7_nvalue,
++ sr1.opp8_nvalue,
++ sr1.opp9_nvalue
++ );
++}
++
++static struct kobj_attribute sr_efuse_vdd1 = {
++ .attr = {
++ .name = "efuse_vdd1",
++ .mode = 0444,
++ },
++ .show = omap_sr_efuse_vdd1_show,
++};
++
++static ssize_t omap_sr_vdd1_voltage_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf)
++{
++ u32 prm_vp1_voltage;
++ mutex_lock(&dvfs_mutex);
++ prm_vp1_voltage = prm_read_mod_reg(OMAP3430_GR_MOD,
++ OMAP3_PRM_VP1_VOLTAGE_OFFSET);
++ mutex_unlock(&dvfs_mutex);
++ return sprintf(buf,"%u\n",prm_vp1_voltage);
++}
++
++static struct kobj_attribute sr_vdd1_voltage = {
++ .attr = {
++ .name = "sr_vdd1_voltage",
++ .mode = 0444,
++ },
++ .show = omap_sr_vdd1_voltage_show,
++};
++
++static ssize_t omap_sr_efuse_vdd2_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf)
++{
++ return sprintf(buf, "%08x\n%08x\n%08x\n", sr2.opp1_nvalue,
++ sr2.opp2_nvalue,
++ sr2.opp3_nvalue
++ );
++}
++
++static struct kobj_attribute sr_efuse_vdd2 = {
++ .attr = {
++ .name = "efuse_vdd2",
++ .mode = 0444,
++ },
++ .show = omap_sr_efuse_vdd2_show,
++};
++
++static ssize_t omap_sr_vdd2_voltage_show(struct kobject *kobj,
++ struct kobj_attribute *attr,
++ char *buf)
++{
++ u32 prm_vp2_voltage;
++ mutex_lock(&dvfs_mutex);
++ prm_vp2_voltage = prm_read_mod_reg(OMAP3430_GR_MOD,
++ OMAP3_PRM_VP2_VOLTAGE_OFFSET);
++ mutex_unlock(&dvfs_mutex);
++ return sprintf(buf,"%u\n",prm_vp2_voltage);
+ }
+
+-static struct kobj_attribute sr_efuse = {
++static struct kobj_attribute sr_vdd2_voltage = {
+ .attr = {
+- .name = "Efuse",
++ .name = "sr_vdd2_voltage",
+ .mode = 0444,
+ },
+- .show = omap_sr_opp1_efuse_show,
++ .show = omap_sr_vdd2_voltage_show,
+ };
+
+ static int __init omap3_sr_init(void)
+@@ -1084,10 +1341,21 @@
+ if (ret)
+ printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
+
+- ret = sysfs_create_file(power_kobj, &sr_efuse.attr);
++ ret = sysfs_create_file(power_kobj, &sr_efuse_vdd1.attr);
+ if (ret)
+- printk(KERN_ERR "sysfs_create_file failed for OPP data: %d\n", ret);
++ printk(KERN_ERR "sysfs_create_file failed for VDD1 efuse data: %d\n", ret);
+
++ ret = sysfs_create_file(power_kobj, &sr_vdd1_voltage.attr);
++ if (ret)
++ printk(KERN_ERR "sysfs_create_file failed for VDD1 voltage data: %d\n", ret);
++
++ ret = sysfs_create_file(power_kobj, &sr_efuse_vdd2.attr);
++ if (ret)
++ printk(KERN_ERR "sysfs_create_file failed for VDD2 efuse data: %d\n", ret);
++
++ ret = sysfs_create_file(power_kobj, &sr_vdd2_voltage.attr);
++ if (ret)
++ printk(KERN_ERR "sysfs_create_file failed for VDD2 voltage data: %d\n", ret);
+ return 0;
+ }
+
+diff -urN kernel-power-2.6.28/arch/arm/mach-omap2/smartreflex.h kernel-power-2.6.28.SR/arch/arm/mach-omap2/smartreflex.h
+--- kernel-power-2.6.28/arch/arm/mach-omap2/smartreflex.h 2011-10-11 13:51:21.441301622 +0100
++++ kernel-power-2.6.28.SR/arch/arm/mach-omap2/smartreflex.h 2011-11-14 21:08:28.136636000 +0000
+@@ -63,7 +63,7 @@
+
+ /* PRM_VP1_VSTEPMAX */
+ #define PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX (0x01F4 << 8)
+-#define PRM_VP1_VSTEPMAX_VSTEPMAX (0x04 << 0)
++#define PRM_VP1_VSTEPMAX_VSTEPMAX (0x01 << 0)
+
+ /* PRM_VP1_VLIMITTO */
+ #define PRM_VP1_VLIMITTO_VDDMAX (0x3C << 24)
+@@ -240,7 +240,15 @@
+ ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x4))
+ #define PRCM_VDD1_OPP5 (OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
+ ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x5))
+-#define PRCM_NO_VDD1_OPPS 5
++#define PRCM_VDD1_OPP6 (OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
++ ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x6))
++#define PRCM_VDD1_OPP7 (OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
++ ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x7))
++#define PRCM_VDD1_OPP8 (OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
++ ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x8))
++#define PRCM_VDD1_OPP9 (OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
++ ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x9))
++#define PRCM_NO_VDD1_OPPS VDD1_OPP9
+
+
+ /* VDD2 OPPs */
+@@ -254,7 +262,7 @@
+ /* XXX: end remove/move */
+
+ /* SR_MAX_LOW_OPP: the highest of the "low OPPs", 1 and 2. */
+-#define SR_MAX_LOW_OPP 3
++#define SR_MAX_LOW_OPP VDD1_OPP2
+
+ /* XXX: find more appropriate place for these once DVFS is in place */
+ extern u32 current_vdd1_opp;
+@@ -273,10 +281,10 @@
+ */
+ #ifdef CONFIG_OMAP_SMARTREFLEX
+ void enable_smartreflex(int srid);
+-void disable_smartreflex(int srid);
++void disable_smartreflex(int srid,u32 cur_opp_no);
+ int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel);
+ void sr_start_vddautocomap(int srid, u32 target_opp_no);
+-int sr_stop_vddautocomap(int srid);
++int sr_stop_vddautocomap(int srid,u32 cur_opp_no);
+ #else
+ static inline void enable_smartreflex(int srid) {}
+ static inline void disable_smartreflex(int srid) {}
+diff -urN kernel-power-2.6.28/arch/arm/plat-omap/include/mach/omap34xx.h kernel-power-2.6.28.SR/arch/arm/plat-omap/include/mach/omap34xx.h
+--- kernel-power-2.6.28/arch/arm/plat-omap/include/mach/omap34xx.h 2011-10-11 13:51:21.441301622 +0100
++++ kernel-power-2.6.28.SR/arch/arm/plat-omap/include/mach/omap34xx.h 2011-10-22 15:52:18.063235000 +0100
+@@ -107,6 +107,14 @@
+ #define VDD1_OPP3 0x3
+ #define VDD1_OPP4 0x4
+ #define VDD1_OPP5 0x5
++#define VDD1_OPP6 0x6\r
++#define VDD1_OPP7 0x7\r
++#define VDD1_OPP8 0x8\r
++#define VDD1_OPP9 0x9\r
++#define VDD1_OPP10 0xA\r
++#define VDD1_OPP11 0xB\r
++#define VDD1_OPP12 0xC\r
++#define VDD1_OPP13 0xD\r
+
+ /* VDD2 OPPS */
+ #define VDD2_OPP1 0x1
+@@ -114,8 +122,7 @@
+ #define VDD2_OPP3 0x3
+
+ #define MIN_VDD1_OPP VDD1_OPP1
+-/*#define MAX_VDD1_OPP VDD1_OPP5*/
+-#define MAX_VDD1_OPP 15
++#define MAX_VDD1_OPP VDD1_OPP13
+ #define MIN_VDD2_OPP VDD2_OPP1
+ #define MAX_VDD2_OPP VDD2_OPP3
+