1 diff -urN kernel-power-2.6.28/arch/arm/mach-omap2/omap3-opp.h kernel-power-2.6.28.new/arch/arm/mach-omap2/omap3-opp.h
2 --- kernel-power-2.6.28/arch/arm/mach-omap2/omap3-opp.h 2012-01-07 13:49:16.551071653 +0000
3 +++ kernel-power-2.6.28.new/arch/arm/mach-omap2/omap3-opp.h 2011-12-31 12:54:23.719318887 +0000
5 #define S900M 900000000
6 #define S850M 850000000
7 #define S805M 805000000
8 -#define S750M 750000000
9 -#define S700M 700000000
10 +#define S720M 720000000
11 #define S600M 600000000
12 #define S550M 550000000
13 #define S500M 500000000
14 diff -urN kernel-power-2.6.28/arch/arm/mach-omap2/pm34xx.c kernel-power-2.6.28.new/arch/arm/mach-omap2/pm34xx.c
15 --- kernel-power-2.6.28/arch/arm/mach-omap2/pm34xx.c 2012-01-07 13:49:16.515051220 +0000
16 +++ kernel-power-2.6.28.new/arch/arm/mach-omap2/pm34xx.c 2011-12-31 12:54:23.735963309 +0000
18 * Only needed if we are going to enter retention.
20 if (mpu_next_state < PWRDM_POWER_ON)
21 - disable_smartreflex(SR1);
22 + disable_smartreflex(SR1,0);
23 if (core_next_state < PWRDM_POWER_ON)
24 - disable_smartreflex(SR2);
25 + disable_smartreflex(SR2,0);
28 if (core_next_state < PWRDM_POWER_ON) {
29 diff -urN kernel-power-2.6.28/arch/arm/mach-omap2/pm.c kernel-power-2.6.28.new/arch/arm/mach-omap2/pm.c
30 --- kernel-power-2.6.28/arch/arm/mach-omap2/pm.c 2012-01-07 13:49:16.567287927 +0000
31 +++ kernel-power-2.6.28.new/arch/arm/mach-omap2/pm.c 2011-12-31 12:54:23.772101815 +0000
34 struct omap_opp omap3_mpu_rate_table[] = {
44 + {S125M, VDD1_OPP1, 0x1E},
45 + {S250M, VDD1_OPP2, 0x26},
46 + {S500M, VDD1_OPP3, 0x30},
47 + {S550M, VDD1_OPP4, 0x36},
48 + {S600M, VDD1_OPP5, 0x3C},
59 + {S720M, VDD1_OPP6, 0x3C},
60 + {S805M, VDD1_OPP7, 0x3C},
61 + {S850M, VDD1_OPP8, 0x3C},
62 + {S900M, VDD1_OPP9, 0x3C},
63 + {S950M, VDD1_OPP10, 0x3C},
64 + {S1000M,VDD1_OPP11, 0x3C},
65 + {S1100M,VDD1_OPP12, 0x48},
66 + {S1150M,VDD1_OPP13, 0x48},
68 +EXPORT_SYMBOL(omap3_mpu_rate_table);
70 struct omap_opp omap3_l3_rate_table[] = {
74 struct omap_opp omap3_dsp_rate_table[] = {
84 + {S90M, VDD1_OPP1, 0x1E},
85 + {S180M, VDD1_OPP2, 0x26},
86 + {S360M, VDD1_OPP3, 0x30},
87 + {S400M, VDD1_OPP4, 0x36},
88 + {S430M, VDD1_OPP5, 0x3C},
92 - {S430M, 9, 0x3C},/*800MHz*/
99 + {S520M, VDD1_OPP6, 0x3C},
100 + {S520M, VDD1_OPP7, 0x3C},
101 + {S520M, VDD1_OPP8, 0x3C},
102 + {S520M, VDD1_OPP9, 0x3C},
103 + {S520M, VDD1_OPP10, 0x3C},
104 + {S520M, VDD1_OPP11, 0x3C},
105 + {S520M, VDD1_OPP12, 0x48},
106 + {S520M, VDD1_OPP13, 0x48},
108 +EXPORT_SYMBOL(omap3_dsp_rate_table);
110 unsigned short enable_dyn_sleep;
111 unsigned short clocks_off_while_idle;
112 @@ -342,13 +338,13 @@
115 if (attr == &vdd1_opp_attr) {
116 - if (value < 1 || value > 5) {
117 + if (value < MIN_VDD1_OPP || value > MAX_VDD1_OPP) {
118 printk(KERN_ERR "vdd_opp_store: Invalid value\n");
121 resource_set_opp_level(PRCM_VDD1, value, flags);
122 } else if (attr == &vdd2_opp_attr) {
123 - if (value < 1 || value > 3) {
124 + if (value < MIN_VDD2_OPP || value > MAX_VDD2_OPP) {
125 printk(KERN_ERR "vdd_opp_store: Invalid value\n");
128 diff -urN kernel-power-2.6.28/arch/arm/mach-omap2/resource34xx.c kernel-power-2.6.28.new/arch/arm/mach-omap2/resource34xx.c
129 --- kernel-power-2.6.28/arch/arm/mach-omap2/resource34xx.c 2012-01-07 13:49:16.527031015 +0000
130 +++ kernel-power-2.6.28.new/arch/arm/mach-omap2/resource34xx.c 2011-12-31 12:54:23.772101815 +0000
133 #ifdef CONFIG_OMAP_SMARTREFLEX
134 sr_status = sr_stop_vddautocomap((get_vdd(t_opp) == PRCM_VDD1) ?
136 + SR1 : SR2,opp[current_level].opp_id);
138 for (i = 0; i < 2; i++) {
140 diff -urN kernel-power-2.6.28/arch/arm/mach-omap2/smartreflex.c kernel-power-2.6.28.new/arch/arm/mach-omap2/smartreflex.c
141 --- kernel-power-2.6.28/arch/arm/mach-omap2/smartreflex.c 2012-01-07 13:49:16.583042210 +0000
142 +++ kernel-power-2.6.28.new/arch/arm/mach-omap2/smartreflex.c 2012-01-06 20:56:55.000000000 +0000
145 #include "smartreflex.h"
146 #include "prm-regbits-34xx.h"
147 +#include "omap3-opp.h"
150 * VP_TRANXDONE_TIMEOUT: maximum microseconds to wait for the VP to
153 #define SR_DISABLE_MAX_ATTEMPTS 4
155 +#define ACCURACY 100
156 +#define NDELTA_3430 (3.0 * ACCURACY)
157 +#define PDELTA_3430 (2.6 * ACCURACY)
159 +/* Since factory calibrated Efuse values lead to very high SR calculated voltages
160 + * adjust them with a constant
162 +#define SR_NVALUE_ADJUST_LOWOPP -150000 /* For 125 and 250 MHz */
163 +#define SR_NVALUE_ADJUST_HIGHOPP -125000 /* For 500+ MHz */
165 +/* Boost voltage with the bellow value(in uV) when DSP frequency is >430 MHz and
166 + * twice that value when DSP frequency is > 520 Mhz
168 +#define SR_NVALUE_DSP_MAX_ADJUST 100000
170 +static atomic_t sr_vdd1_dsp_boost_coeff;
177 u32 opp1_nvalue, opp2_nvalue, opp3_nvalue, opp4_nvalue;
179 + u32 opp6_nvalue, opp7_nvalue, opp8_nvalue, opp9_nvalue;
180 u32 senp_mod, senn_mod;
181 void __iomem *srbase_addr;
182 void __iomem *vpbase_addr;
185 reg_val = __raw_readl(SR_REGADDR(offset));
190 __raw_writel(reg_val, SR_REGADDR(offset));
191 @@ -211,26 +231,173 @@
195 +static u32 calculate_opp_nadj(u32 opp_value, u32 delta_n)
197 + u32 sen_ngain_fuse, sen_nrn_fuse;
199 + sen_ngain_fuse = (opp_value & 0x000F0000) >> 0x10;
200 + sen_nrn_fuse = (opp_value & 0x000000FF);
202 + return ((1 << (sen_ngain_fuse + 8)) / sen_nrn_fuse) + delta_n;
205 +static u32 calculate_opp_padj(u32 opp_value, u32 delta_p)
207 + u32 sen_pgain_fuse, sen_prn_fuse;
209 + sen_pgain_fuse = (opp_value & 0x000F00000) >> 0x14;
210 + sen_prn_fuse = (opp_value & 0x0000FF00) >> 8;
212 + return ((1 << (sen_pgain_fuse + 8)) / sen_prn_fuse) + delta_p;
215 +static u32 get_padj_for_freq(u32 opp0fuse,u32 opp1fuse, u32 freq)
217 + u32 padj_0=calculate_opp_padj(opp0fuse,0);
218 + u32 padj_1=calculate_opp_padj(opp1fuse,0);
219 + u32 p_slope_a=(1000*(padj_1-padj_0))/(250-125);
220 + u32 p_slope_b=1000*(padj_1-p_slope_a*250/1000);
222 + return (u32)(p_slope_a*freq+p_slope_b)/1000;
225 +static u32 get_nadj_for_freq(u32 opp0fuse,u32 opp1fuse, u32 freq)
227 + u32 nadj_0=calculate_opp_nadj(opp0fuse,0);
228 + u32 nadj_1=calculate_opp_nadj(opp1fuse,0);
229 + u32 n_slope_a=(1000*(nadj_1-nadj_0))/(250-125);
230 + u32 n_slope_b=1000*(nadj_1-n_slope_a*250/1000);
232 + return (u32)(n_slope_a*freq+n_slope_b)/1000;
236 + * recalc_with_margin() - helper to add margin to reciprocal and gain
237 + * @uv: voltage in uVolts to add.
238 + * @soc_delta: SoC specific delta base
239 + * @reci: Reciprocal for the sensor
240 + * @gain: Gain for the sensor
242 + * The algorithm computes an adjustment required to meet the delta voltage
243 + * to be added to a given sensor's reciprocal and gain. It then does a
244 + * search for maximum gain for valid reciprocal value. This forms the
245 + * new reciprocal and gain which incorporates the additional voltage
248 + * IMPORTANT: since it is not possible to ascertain the actual voltage from
249 + * ntarget value, the additional voltage will be accurate upto 1 additional
250 + * pmic step. The algorithm is optimized to adjust to higher end rather than
251 + * less than requested additional voltage as it could be unsafe to run at
252 + * voltage lower than requested level.
254 + * Example: if the PMIC step size is 12.5 and requested margin in 25mV(2 PMIC
255 + * steps). the actual voltage achieved can be original V achieved + 25mV upto
256 + * original V + 37.5mV(3 steps) - depending on where V was achieved.
258 +static __init int recalc_with_margin(long uv, int soc_delta, unsigned int *reci,
259 + unsigned int *gain)
264 + nadj = ((1 << (*gain + 8)) * ACCURACY) / (*reci) +
265 + soc_delta * uv / 1000;
267 + /* Linear search for the best reciprocal */
268 + for (g = 15; g >= 0; g--) {
269 + r = ((1 << (g + 8)) * ACCURACY) / nadj;
276 + /* Dont modify the input, just return error */
281 + * sr_ntarget_add_margin() - Modify h/w ntarget to add a s/w margin
282 + * @vdata: voltage data for the OPP to be modified with ntarget populated
283 + * @add_uv: voltate to add to nTarget in uVolts
285 + * Once the sr_device_init is complete and nTargets are populated, using this
286 + * function nTarget read from h/w efuse and stored in vdata is modified to add
287 + * a platform(board) specific additional voltage margin. Based on analysis,
288 + * we might need different margins to be added per vdata.
290 +int __init sr_ntarget_add_margin(u32 old_ntarget, ulong add_uv)
292 + u32 temp_senp_gain, temp_senp_reciprocal;
293 + u32 temp_senn_gain, temp_senn_reciprocal;
294 + int soc_p_delta, soc_n_delta;
297 + temp_senp_gain = (old_ntarget & 0x00F00000) >> 20;
298 + temp_senn_gain = (old_ntarget & 0x000F0000) >> 16;
299 + temp_senp_reciprocal = (old_ntarget & 0x0000FF00) >> 8;
300 + temp_senn_reciprocal = old_ntarget & 0x000000FF;
302 + soc_p_delta = PDELTA_3430;
303 + soc_n_delta = NDELTA_3430;
305 + r = recalc_with_margin(add_uv, soc_n_delta,
306 + &temp_senn_reciprocal, &temp_senn_gain);
308 + pr_err("%s: unable to add %ld uV to ntarget 0x%08x\n",
309 + __func__, add_uv, old_ntarget);
312 + r = recalc_with_margin(add_uv, soc_p_delta,
313 + &temp_senp_reciprocal, &temp_senp_gain);
315 + pr_err("%s: unable to add %ld uV to ntarget 0x%08x\n",
316 + __func__, add_uv, old_ntarget);
320 + /* Populate the new modified nTarget */
321 + return (temp_senp_gain << 20) | (temp_senn_gain << 16) |
322 + (temp_senp_reciprocal << 8) | temp_senn_reciprocal;
326 +static u32 calculate_freq_efuse_value(u32 opp0efuse,u32 opp1efuse,u32 freq)
328 + u32 sen_nrn, sen_ngain, sen_prn, sen_pgain;
329 + u32 opp0efuse_adj = sr_ntarget_add_margin(opp0efuse,freq>S250M?SR_NVALUE_ADJUST_HIGHOPP:SR_NVALUE_ADJUST_LOWOPP);
330 + u32 opp1efuse_adj = sr_ntarget_add_margin(opp1efuse,freq>S250M?SR_NVALUE_ADJUST_HIGHOPP:SR_NVALUE_ADJUST_LOWOPP);
333 + cal_reciprocal(get_padj_for_freq(opp0efuse_adj,opp1efuse_adj,freq), &sen_pgain, &sen_prn);
334 + cal_reciprocal(get_nadj_for_freq(opp0efuse_adj,opp1efuse_adj,freq), &sen_ngain, &sen_nrn);
336 + return (sen_pgain << 0x14) | (sen_ngain << 0x10)
337 + | (sen_prn << 0x08) | (sen_nrn);
340 static void sr_set_efuse_nvalues(struct omap_sr *sr)
342 if (sr->srid == SR1) {
343 + u32 opp0efuse = omap_ctrl_readl(OMAP343X_CONTROL_FUSE_OPP1_VDD1);
344 + u32 opp1efuse = omap_ctrl_readl(OMAP343X_CONTROL_FUSE_OPP2_VDD1);
346 sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
347 OMAP343X_SR1_SENNENABLE_MASK) >>
348 OMAP343X_SR1_SENNENABLE_SHIFT;
349 sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
350 OMAP343X_SR1_SENPENABLE_MASK) >>
351 OMAP343X_SR1_SENPENABLE_SHIFT;
353 - sr->opp5_nvalue = omap_ctrl_readl(
354 - OMAP343X_CONTROL_FUSE_OPP5_VDD1);
355 - sr->opp4_nvalue = omap_ctrl_readl(
356 - OMAP343X_CONTROL_FUSE_OPP4_VDD1);
357 - sr->opp3_nvalue = omap_ctrl_readl(
358 - OMAP343X_CONTROL_FUSE_OPP3_VDD1);
359 - sr->opp2_nvalue = omap_ctrl_readl(
360 - OMAP343X_CONTROL_FUSE_OPP2_VDD1);
361 - sr->opp1_nvalue = omap_ctrl_readl(
362 - OMAP343X_CONTROL_FUSE_OPP1_VDD1);
364 + sr->opp1_nvalue = calculate_freq_efuse_value(opp0efuse,opp1efuse,S125M);
365 + sr->opp2_nvalue = calculate_freq_efuse_value(opp0efuse,opp1efuse,S250M);
366 + sr->opp3_nvalue = calculate_freq_efuse_value(opp0efuse,opp1efuse,S500M);
367 + sr->opp4_nvalue = calculate_freq_efuse_value(opp0efuse,opp1efuse,S550M);
368 + sr->opp5_nvalue = calculate_freq_efuse_value(opp0efuse,opp1efuse,S600M);
369 + sr->opp6_nvalue = calculate_freq_efuse_value(opp0efuse,opp1efuse,S720M);
370 + sr->opp7_nvalue = calculate_freq_efuse_value(opp0efuse,opp1efuse,S805M);
371 + sr->opp8_nvalue = calculate_freq_efuse_value(opp0efuse,opp1efuse,S850M);
372 + sr->opp9_nvalue = calculate_freq_efuse_value(opp0efuse,opp1efuse,S900M);
373 } else if (sr->srid == SR2) {
374 sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
375 OMAP343X_SR2_SENNENABLE_MASK) >>
377 sr->opp3_nvalue = cal_test_nvalue(0x85b + 0x200, 0x655 + 0x200);
378 sr->opp2_nvalue = cal_test_nvalue(0x506 + 0x1a0, 0x3be + 0x1a0);
379 sr->opp1_nvalue = cal_test_nvalue(0x373 + 0x100, 0x28c + 0x100);
380 + sr->opp6_nvalue = calculate_freq_efuse_value(sr->opp1_nvalue,sr->opp2_nvalue,
381 + mpu_opps[VDD1_OPP6].rate/1000000);
382 + sr->opp7_nvalue = calculate_freq_efuse_value(sr->opp1_nvalue,sr->opp2_nvalue,
383 + mpu_opps[VDD1_OPP7].rate/1000000);
384 + sr->opp8_nvalue = calculate_freq_efuse_value(sr->opp1_nvalue,sr->opp2_nvalue,
385 + mpu_opps[VDD1_OPP8].rate/1000000);
386 + sr->opp9_nvalue = calculate_freq_efuse_value(sr->opp1_nvalue,sr->opp2_nvalue,
387 + mpu_opps[VDD1_OPP9].rate/1000000);
388 } else if (sr->srid == SR2) {
395 -static int sr_reset_voltage(int srid)
396 +static int sr_reset_voltage(int srid,u32 curr_opp_no)
398 u32 target_opp_no, vsel = 0;
401 reg_addr = R_VDD1_SR_CONTROL;
402 prm_vp1_voltage = prm_read_mod_reg(OMAP3430_GR_MOD,
403 OMAP3_PRM_VP1_VOLTAGE_OFFSET);
404 + /* Store current calibrated voltage to be used next time preventing
405 + * overvoltage when calibration cycle starts. if cur_opp_no is 0 don't
406 + * store current voltage, we've been called from sram_idle().
407 + * Just in case add 2 to it, so we can start a little higher next time
410 + mpu_opps[curr_opp_no].vsel = min((u32)mpu_opps[curr_opp_no].vsel,
411 + prm_vp1_voltage+2);
412 t2_smps_steps = abs(vsel - prm_vp1_voltage);
413 errorgain = (target_opp_no > SR_MAX_LOW_OPP) ?
414 PRM_VP1_CONFIG_ERRORGAIN_HIGHOPP :
415 @@ -507,13 +690,24 @@
417 u32 nvalue_reciprocal, v;
420 BUG_ON(!(mpu_opps && l3_opps));
423 sr->req_opp_no = target_opp_no;
425 if (sr->srid == SR1) {
426 - switch (min(target_opp_no-1,5)) {
427 + switch (min(target_opp_no,(u32)PRCM_NO_VDD1_OPPS)) {
429 + nvalue_reciprocal = sr->opp9_nvalue;
432 + nvalue_reciprocal = sr->opp8_nvalue;
435 + nvalue_reciprocal = sr->opp7_nvalue;
438 + nvalue_reciprocal = sr->opp6_nvalue;
441 nvalue_reciprocal = sr->opp5_nvalue;
444 nvalue_reciprocal = sr->opp1_nvalue;
447 - nvalue_reciprocal = sr->opp3_nvalue;
448 + nvalue_reciprocal = sr->opp9_nvalue;
451 + /* give more juice when DSP is active and overclocked */
452 + if(omap_pm_dsp_get_min_opp() > VDD1_OPP1 && dsp_opps[target_opp_no].rate > S430M)
454 + /* DSP is active and overclocked, boost voltage based on overclocking percent
457 + u32 dsp_volt_boost = ((dsp_opps[target_opp_no].rate-S430M)/1000000) *
458 + atomic_read(&sr_vdd1_dsp_boost_coeff) *
459 + (VDD1_OPP9-target_opp_no);
460 + dsp_volt_boost = dsp_volt_boost > SR_NVALUE_DSP_MAX_ADJUST ? SR_NVALUE_DSP_MAX_ADJUST : dsp_volt_boost;
461 + nvalue_reciprocal = sr_ntarget_add_margin(nvalue_reciprocal,dsp_volt_boost);
462 + mpu_opps[target_opp_no].vsel += (dsp_volt_boost/12500);
463 + mpu_opps[target_opp_no].vsel = mpu_opps[target_opp_no].vsel > (PRM_VP1_VLIMITTO_VDDMAX >> 24) ?
464 + PRM_VP1_VLIMITTO_VDDMAX >> 24 : mpu_opps[target_opp_no].vsel;
467 switch (target_opp_no) {
474 sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
476 /* Enable the interrupt */
479 EXPORT_SYMBOL(sr_start_vddautocomap);
481 -int sr_stop_vddautocomap(int srid)
482 +int sr_stop_vddautocomap(int srid,u32 cur_opp_no)
484 struct omap_sr *sr = NULL;
488 sr->is_autocomp_active = 0;
489 /* Reset the volatage for current OPP */
490 - sr_reset_voltage(srid);
491 + sr_reset_voltage(srid,cur_opp_no);
499 -void disable_smartreflex(int srid)
500 +void disable_smartreflex(int srid,u32 cur_opp_no)
502 struct omap_sr *sr = NULL;
507 /* Reset the volatage for current OPP */
508 - sr_reset_voltage(srid);
509 + sr_reset_voltage(srid,cur_opp_no);
513 @@ -953,22 +1161,22 @@
514 const char *buf, size_t n)
516 unsigned short value;
518 + u32 current_vdd1opp_no;
519 if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
520 printk(KERN_ERR "sr_vdd1_autocomp: Invalid value\n");
524 mutex_lock(&dvfs_mutex);
525 + current_vdd1opp_no = resource_get_level("vdd1_opp");
526 + if (IS_ERR_VALUE(current_vdd1opp_no)) {
527 + mutex_unlock(&dvfs_mutex);
532 - sr_stop_vddautocomap(SR1);
533 + sr_stop_vddautocomap(SR1,current_vdd1opp_no);
535 - u32 current_vdd1opp_no = resource_get_level("vdd1_opp");
536 - if (IS_ERR_VALUE(current_vdd1opp_no)) {
537 - mutex_unlock(&dvfs_mutex);
540 sr_start_vddautocomap(SR1, current_vdd1opp_no);
543 @@ -1008,9 +1216,13 @@
544 mutex_lock(&dvfs_mutex);
546 current_vdd2opp_no = resource_get_level("vdd2_opp");
547 + if (IS_ERR_VALUE(current_vdd2opp_no)) {
548 + mutex_unlock(&dvfs_mutex);
553 - sr_stop_vddautocomap(SR2);
554 + sr_stop_vddautocomap(SR2, current_vdd2opp_no);
556 sr_start_vddautocomap(SR2, current_vdd2opp_no);
558 @@ -1028,30 +1240,128 @@
559 .store = omap_sr_vdd2_autocomp_store,
562 -static ssize_t omap_sr_opp1_efuse_show(struct kobject *kobj,
563 +static ssize_t omap_sr_efuse_vdd1_show(struct kobject *kobj,
564 struct kobj_attribute *attr,
567 - return sprintf(buf, "%08x\n%08x\n%08x\n%08x\n%08x\n", sr1.opp1_nvalue,
568 + return sprintf(buf, "%08x\n%08x\n%08x\n%08x\n%08x\n%08x\n%08x\n%08x\n%08x\n",
582 -static struct kobj_attribute sr_efuse = {
583 +static struct kobj_attribute sr_efuse_vdd1 = {
586 + .name = "efuse_vdd1",
589 - .show = omap_sr_opp1_efuse_show,
590 + .show = omap_sr_efuse_vdd1_show,
593 +static ssize_t omap_sr_vdd1_voltage_show(struct kobject *kobj,
594 + struct kobj_attribute *attr,
597 + u32 prm_vp1_voltage;
598 + mutex_lock(&dvfs_mutex);
599 + prm_vp1_voltage = prm_read_mod_reg(OMAP3430_GR_MOD,
600 + OMAP3_PRM_VP1_VOLTAGE_OFFSET);
601 + mutex_unlock(&dvfs_mutex);
602 + return sprintf(buf,"%u\n",prm_vp1_voltage);
605 +static struct kobj_attribute sr_vdd1_voltage = {
607 + .name = "sr_vdd1_voltage",
610 + .show = omap_sr_vdd1_voltage_show,
613 +static ssize_t omap_sr_efuse_vdd2_show(struct kobject *kobj,
614 + struct kobj_attribute *attr,
617 + return sprintf(buf, "%08x\n%08x\n%08x\n", sr2.opp1_nvalue,
623 +static struct kobj_attribute sr_efuse_vdd2 = {
625 + .name = "efuse_vdd2",
628 + .show = omap_sr_efuse_vdd2_show,
631 +static ssize_t omap_sr_vdd2_voltage_show(struct kobject *kobj,
632 + struct kobj_attribute *attr,
635 + u32 prm_vp2_voltage;
636 + mutex_lock(&dvfs_mutex);
637 + prm_vp2_voltage = prm_read_mod_reg(OMAP3430_GR_MOD,
638 + OMAP3_PRM_VP2_VOLTAGE_OFFSET);
639 + mutex_unlock(&dvfs_mutex);
640 + return sprintf(buf,"%u\n",prm_vp2_voltage);
643 +static struct kobj_attribute sr_vdd2_voltage = {
645 + .name = "sr_vdd2_voltage",
648 + .show = omap_sr_vdd2_voltage_show,
651 +static ssize_t omap_sr_vdd1_dsp_boost_show(struct kobject *kobj,
652 + struct kobj_attribute *attr,
655 + return sprintf(buf,"%u\n",atomic_read(&sr_vdd1_dsp_boost_coeff));
658 +static ssize_t omap_sr_vdd1_dsp_boost_store(struct kobject *kobj,
659 + struct kobj_attribute *attr,
660 + const char *buf, size_t n)
664 + if (sscanf(buf, "%u", &value) != 1 || (value > 250)) {
665 + printk(KERN_ERR "sr_vdd1_dsp_boost: Invalid value\n");
668 + atomic_set(&sr_vdd1_dsp_boost_coeff,value);
673 +static struct kobj_attribute sr_vdd1_dsp_boost = {
675 + .name = __stringify(sr_vdd1_dsp_boost),
678 + .show = omap_sr_vdd1_dsp_boost_show,
679 + .store = omap_sr_vdd1_dsp_boost_store,
682 static int __init omap3_sr_init(void)
688 + /* Set default dsp boost value */
689 + atomic_set(&sr_vdd1_dsp_boost_coeff,125);
691 /* Enable SR on T2 */
692 ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &RdReg,
694 @@ -1084,9 +1394,25 @@
696 printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
698 - ret = sysfs_create_file(power_kobj, &sr_efuse.attr);
699 + ret = sysfs_create_file(power_kobj, &sr_efuse_vdd1.attr);
701 + printk(KERN_ERR "sysfs_create_file failed for VDD1 efuse data: %d\n", ret);
703 + ret = sysfs_create_file(power_kobj, &sr_vdd1_voltage.attr);
705 + printk(KERN_ERR "sysfs_create_file failed for VDD1 voltage data: %d\n", ret);
707 + ret = sysfs_create_file(power_kobj, &sr_efuse_vdd2.attr);
709 + printk(KERN_ERR "sysfs_create_file failed for VDD2 efuse data: %d\n", ret);
711 + ret = sysfs_create_file(power_kobj, &sr_vdd2_voltage.attr);
713 + printk(KERN_ERR "sysfs_create_file failed for VDD2 voltage data: %d\n", ret);
715 + ret = sysfs_create_file(power_kobj, &sr_vdd1_dsp_boost.attr);
717 - printk(KERN_ERR "sysfs_create_file failed for OPP data: %d\n", ret);
718 + printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
722 diff -urN kernel-power-2.6.28/arch/arm/mach-omap2/smartreflex.h kernel-power-2.6.28.new/arch/arm/mach-omap2/smartreflex.h
723 --- kernel-power-2.6.28/arch/arm/mach-omap2/smartreflex.h 2012-01-07 13:49:16.543132598 +0000
724 +++ kernel-power-2.6.28.new/arch/arm/mach-omap2/smartreflex.h 2011-12-31 12:54:23.820044299 +0000
727 /* PRM_VP1_VSTEPMAX */
728 #define PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX (0x01F4 << 8)
729 -#define PRM_VP1_VSTEPMAX_VSTEPMAX (0x04 << 0)
730 +#define PRM_VP1_VSTEPMAX_VSTEPMAX (0x01 << 0)
732 /* PRM_VP1_VLIMITTO */
733 #define PRM_VP1_VLIMITTO_VDDMAX (0x3C << 24)
735 ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x4))
736 #define PRCM_VDD1_OPP5 (OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
737 ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x5))
738 -#define PRCM_NO_VDD1_OPPS 5
739 +#define PRCM_VDD1_OPP6 (OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
740 + ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x6))
741 +#define PRCM_VDD1_OPP7 (OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
742 + ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x7))
743 +#define PRCM_VDD1_OPP8 (OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
744 + ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x8))
745 +#define PRCM_VDD1_OPP9 (OMAP(AT_3430_ES2) | OTHER_ID_TYPE(ID_OPP) | \
746 + ID_VDD(PRCM_VDD1) | ID_OPP_NO(0x9))
747 +#define PRCM_NO_VDD1_OPPS VDD1_OPP9
752 /* XXX: end remove/move */
754 /* SR_MAX_LOW_OPP: the highest of the "low OPPs", 1 and 2. */
755 -#define SR_MAX_LOW_OPP 3
756 +#define SR_MAX_LOW_OPP VDD1_OPP2
758 /* XXX: find more appropriate place for these once DVFS is in place */
759 extern u32 current_vdd1_opp;
760 @@ -273,10 +281,10 @@
762 #ifdef CONFIG_OMAP_SMARTREFLEX
763 void enable_smartreflex(int srid);
764 -void disable_smartreflex(int srid);
765 +void disable_smartreflex(int srid,u32 cur_opp_no);
766 int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel);
767 void sr_start_vddautocomap(int srid, u32 target_opp_no);
768 -int sr_stop_vddautocomap(int srid);
769 +int sr_stop_vddautocomap(int srid,u32 cur_opp_no);
771 static inline void enable_smartreflex(int srid) {}
772 static inline void disable_smartreflex(int srid) {}
773 diff -urN kernel-power-2.6.28/arch/arm/plat-omap/include/mach/omap34xx.h kernel-power-2.6.28.new/arch/arm/plat-omap/include/mach/omap34xx.h
774 --- kernel-power-2.6.28/arch/arm/plat-omap/include/mach/omap34xx.h 2012-01-07 13:49:16.503856035 +0000
775 +++ kernel-power-2.6.28.new/arch/arm/plat-omap/include/mach/omap34xx.h 2011-12-31 12:54:23.820044299 +0000
777 #define VDD1_OPP3 0x3
778 #define VDD1_OPP4 0x4
779 #define VDD1_OPP5 0x5
780 +#define VDD1_OPP6 0x6
781 +#define VDD1_OPP7 0x7
782 +#define VDD1_OPP8 0x8
783 +#define VDD1_OPP9 0x9
784 +#define VDD1_OPP10 0xA
785 +#define VDD1_OPP11 0xB
786 +#define VDD1_OPP12 0xC
787 +#define VDD1_OPP13 0xD
790 #define VDD2_OPP1 0x1
792 #define VDD2_OPP3 0x3
794 #define MIN_VDD1_OPP VDD1_OPP1
795 -/*#define MAX_VDD1_OPP VDD1_OPP5*/
796 -#define MAX_VDD1_OPP 15
797 +#define MAX_VDD1_OPP VDD1_OPP13
798 #define MIN_VDD2_OPP VDD2_OPP1
799 #define MAX_VDD2_OPP VDD2_OPP3
801 diff -urN kernel-power-2.6.28/arch/arm/plat-omap/include/mach/omap-pm.h kernel-power-2.6.28.new/arch/arm/plat-omap/include/mach/omap-pm.h
802 --- kernel-power-2.6.28/arch/arm/plat-omap/include/mach/omap-pm.h 2012-01-07 13:49:16.487184834 +0000
803 +++ kernel-power-2.6.28.new/arch/arm/plat-omap/include/mach/omap-pm.h 2012-01-06 07:35:45.000000000 +0000
806 void omap_pm_dsp_set_min_opp(u8 opp_id);
810 + * omap_pm_dsp_get_min_opp - return desired minimum OPP ID from DSP Bridge
812 + * Get a minimum OPP ID for the DSP.
814 +#ifdef CONFIG_OMAP_PM_NONE
815 +static inline u8 omap_pm_dsp_get_min_opp(void) { }
817 +u8 omap_pm_dsp_get_min_opp(void);
821 * omap_pm_dsp_get_opp - report the current DSP OPP ID
822 diff -urN kernel-power-2.6.28/arch/arm/plat-omap/omap-pm-srf.c kernel-power-2.6.28.new/arch/arm/plat-omap/omap-pm-srf.c
823 --- kernel-power-2.6.28/arch/arm/plat-omap/omap-pm-srf.c 2012-01-07 13:49:16.470963471 +0000
824 +++ kernel-power-2.6.28.new/arch/arm/plat-omap/omap-pm-srf.c 2012-01-07 13:45:44.000000000 +0000
826 #define LAT_RES_POSTAMBLE "_latency"
827 #define MAX_LATENCY_RES_NAME 30
829 +atomic_t dsp_min_opp;
831 + * Smartreflex module enable/disable interface.
832 + * NOTE: if smartreflex is not enabled from sysfs, these functions will not
835 +#ifdef CONFIG_OMAP_SMARTREFLEX
836 +void sr_start_vddautocomap(int srid, u32 target_opp_no);
837 +int sr_stop_vddautocomap(int srid,u32 cur_opp_no);
844 * get_lat_res_name - gets the latency resource name given a power domain name
845 * @pwrdm_name: Name of the power domain.
846 @@ -205,13 +219,29 @@
848 void omap_pm_dsp_set_min_opp(u8 opp_id)
850 + u8 curr_dsp_min_opp;
851 + pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id);
857 - pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id);
859 + curr_dsp_min_opp = omap_pm_dsp_get_min_opp();
860 + atomic_set(&dsp_min_opp,opp_id);
861 +#ifdef CONFIG_OMAP_SMARTREFLEX
862 + if(curr_dsp_min_opp == VDD1_OPP1 || opp_id == VDD1_OPP1)
864 + /* DSP is about to be enabled/disabled, restart SR,
865 + * so DSP voltage boost to be applied or removed.
866 + * This is needed in case current OPP has DSP overclocking frequency
868 + u8 curr_opp = omap_pm_dsp_get_opp();
870 + if(sr_stop_vddautocomap(SR1 , curr_opp))
871 + sr_start_vddautocomap(SR1 , curr_opp);
876 * For now pass a dummy_dev struct for SRF to identify the caller.
877 * Maybe its good to have DSP pass this as an argument
880 EXPORT_SYMBOL(omap_pm_dsp_set_min_opp);
882 +u8 omap_pm_dsp_get_min_opp(void)
884 + return atomic_read(&dsp_min_opp);
886 +EXPORT_SYMBOL(omap_pm_dsp_get_min_opp);
888 u8 omap_pm_dsp_get_opp(void)
890 pr_debug("OMAP PM: DSP requests current DSP OPP ID\n");
892 mpu_opps = mpu_opp_table;
893 dsp_opps = dsp_opp_table;
894 l3_opps = l3_opp_table;
895 + atomic_set(&dsp_min_opp,VDD1_OPP1);