]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/smartreflex.c
ARM: OMAP: No need to include board-overo.h from hardware.h
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / smartreflex.c
1 /*
2  * linux/arch/arm/mach-omap3/smartreflex.c
3  *
4  * OMAP34XX SmartReflex Voltage Control
5  *
6  * Copyright (C) 2008 Nokia Corporation
7  * Kalle Jokiniemi
8  *
9  * Copyright (C) 2007 Texas Instruments, Inc.
10  * Lesly A M <x0080970@ti.com>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License version 2 as
14  * published by the Free Software Foundation.
15  */
16
17
18 #include <linux/kernel.h>
19 #include <linux/init.h>
20 #include <linux/interrupt.h>
21 #include <linux/module.h>
22 #include <linux/delay.h>
23 #include <linux/err.h>
24 #include <linux/clk.h>
25 #include <linux/sysfs.h>
26 #include <linux/kobject.h>
27 #include <linux/i2c/twl4030.h>
28 #include <linux/io.h>
29
30 #include <mach/omap34xx.h>
31 #include <mach/control.h>
32 #include <mach/clock.h>
33
34 #include "prm.h"
35 #include "smartreflex.h"
36 #include "prm-regbits-34xx.h"
37
38 /* XXX: These should be relocated where-ever the OPP implementation will be */
39 u32 current_vdd1_opp;
40 u32 current_vdd2_opp;
41
42 struct omap_sr {
43         int             srid;
44         int             is_sr_reset;
45         int             is_autocomp_active;
46         struct clk      *clk;
47         u32             clk_length;
48         u32             req_opp_no;
49         u32             opp1_nvalue, opp2_nvalue, opp3_nvalue, opp4_nvalue;
50         u32             opp5_nvalue;
51         u32             senp_mod, senn_mod;
52         void __iomem    *srbase_addr;
53         void __iomem    *vpbase_addr;
54 };
55
56 #define SR_REGADDR(offs)        (sr->srbase_addr + offset)
57
58 static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
59 {
60         __raw_writel(value, SR_REGADDR(offset));
61 }
62
63 static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
64                                         u32 value)
65 {
66         u32 reg_val;
67
68         reg_val = __raw_readl(SR_REGADDR(offset));
69         reg_val &= ~mask;
70         reg_val |= value;
71
72         __raw_writel(reg_val, SR_REGADDR(offset));
73 }
74
75 static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
76 {
77         return __raw_readl(SR_REGADDR(offset));
78 }
79
80 static int sr_clk_enable(struct omap_sr *sr)
81 {
82         if (clk_enable(sr->clk) != 0) {
83                 printk(KERN_ERR "Could not enable %s\n", sr->clk->name);
84                 return -1;
85         }
86
87         /* set fclk- active , iclk- idle */
88         sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
89                       SR_CLKACTIVITY_IOFF_FON);
90
91         return 0;
92 }
93
94 static void sr_clk_disable(struct omap_sr *sr)
95 {
96         /* set fclk, iclk- idle */
97         sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
98                       SR_CLKACTIVITY_IOFF_FOFF);
99
100         clk_disable(sr->clk);
101         sr->is_sr_reset = 1;
102 }
103
104 static struct omap_sr sr1 = {
105         .srid                   = SR1,
106         .is_sr_reset            = 1,
107         .is_autocomp_active     = 0,
108         .clk_length             = 0,
109         .srbase_addr            = OMAP2_IO_ADDRESS(OMAP34XX_SR1_BASE),
110 };
111
112 static struct omap_sr sr2 = {
113         .srid                   = SR2,
114         .is_sr_reset            = 1,
115         .is_autocomp_active     = 0,
116         .clk_length             = 0,
117         .srbase_addr            = OMAP2_IO_ADDRESS(OMAP34XX_SR2_BASE),
118 };
119
120 static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen)
121 {
122         u32 gn, rn, mul;
123
124         for (gn = 0; gn < GAIN_MAXLIMIT; gn++) {
125                 mul = 1 << (gn + 8);
126                 rn = mul / sensor;
127                 if (rn < R_MAXLIMIT) {
128                         *sengain = gn;
129                         *rnsen = rn;
130                 }
131         }
132 }
133
134 static u32 cal_test_nvalue(u32 sennval, u32 senpval)
135 {
136         u32 senpgain, senngain;
137         u32 rnsenp, rnsenn;
138
139         /* Calculating the gain and reciprocal of the SenN and SenP values */
140         cal_reciprocal(senpval, &senpgain, &rnsenp);
141         cal_reciprocal(sennval, &senngain, &rnsenn);
142
143         return ((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |
144                 (senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |
145                 (rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |
146                 (rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));
147 }
148
149 static void sr_set_clk_length(struct omap_sr *sr)
150 {
151         struct clk *osc_sys_ck;
152         u32 sys_clk = 0;
153
154         osc_sys_ck = clk_get(NULL, "osc_sys_ck");
155         sys_clk = clk_get_rate(osc_sys_ck);
156         clk_put(osc_sys_ck);
157
158         switch (sys_clk) {
159         case 12000000:
160                 sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
161                 break;
162         case 13000000:
163                 sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK;
164                 break;
165         case 19200000:
166                 sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK;
167                 break;
168         case 26000000:
169                 sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK;
170                 break;
171         case 38400000:
172                 sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
173                 break;
174         default :
175                 printk(KERN_ERR "Invalid sysclk value: %d\n", sys_clk);
176                 break;
177         }
178 }
179
180 static void sr_set_efuse_nvalues(struct omap_sr *sr)
181 {
182         if (sr->srid == SR1) {
183                 sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
184                                         OMAP343X_SR1_SENNENABLE_MASK) >>
185                                         OMAP343X_SR1_SENNENABLE_SHIFT;
186
187                 sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
188                                         OMAP343X_SR1_SENPENABLE_MASK) >>
189                                         OMAP343X_SR1_SENPENABLE_SHIFT;
190
191                 sr->opp5_nvalue = omap_ctrl_readl(
192                                         OMAP343X_CONTROL_FUSE_OPP5_VDD1);
193                 sr->opp4_nvalue = omap_ctrl_readl(
194                                         OMAP343X_CONTROL_FUSE_OPP4_VDD1);
195                 sr->opp3_nvalue = omap_ctrl_readl(
196                                         OMAP343X_CONTROL_FUSE_OPP3_VDD1);
197                 sr->opp2_nvalue = omap_ctrl_readl(
198                                         OMAP343X_CONTROL_FUSE_OPP2_VDD1);
199                 sr->opp1_nvalue = omap_ctrl_readl(
200                                         OMAP343X_CONTROL_FUSE_OPP1_VDD1);
201         } else if (sr->srid == SR2) {
202                 sr->senn_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
203                                         OMAP343X_SR2_SENNENABLE_MASK) >>
204                                         OMAP343X_SR2_SENNENABLE_SHIFT;
205
206                 sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
207                                         OMAP343X_SR2_SENPENABLE_MASK) >>
208                                         OMAP343X_SR2_SENPENABLE_SHIFT;
209
210                 sr->opp3_nvalue = omap_ctrl_readl(
211                                         OMAP343X_CONTROL_FUSE_OPP3_VDD2);
212                 sr->opp2_nvalue = omap_ctrl_readl(
213                                         OMAP343X_CONTROL_FUSE_OPP2_VDD2);
214                 sr->opp1_nvalue = omap_ctrl_readl(
215                                         OMAP343X_CONTROL_FUSE_OPP1_VDD2);
216         }
217 }
218
219 /* Hard coded nvalues for testing purposes, may cause device to hang! */
220 static void sr_set_testing_nvalues(struct omap_sr *sr)
221 {
222         if (sr->srid == SR1) {
223                 sr->senp_mod = 0x03;    /* SenN-M5 enabled */
224                 sr->senn_mod = 0x03;
225
226                 /* calculate nvalues for each opp */
227                 sr->opp5_nvalue = cal_test_nvalue(0xacd + 0x330, 0x848 + 0x330);
228                 sr->opp4_nvalue = cal_test_nvalue(0x964 + 0x2a0, 0x727 + 0x2a0);
229                 sr->opp3_nvalue = cal_test_nvalue(0x85b + 0x200, 0x655 + 0x200);
230                 sr->opp2_nvalue = cal_test_nvalue(0x506 + 0x1a0, 0x3be + 0x1a0);
231                 sr->opp1_nvalue = cal_test_nvalue(0x373 + 0x100, 0x28c + 0x100);
232         } else if (sr->srid == SR2) {
233                 sr->senp_mod = 0x03;
234                 sr->senn_mod = 0x03;
235
236                 sr->opp3_nvalue = cal_test_nvalue(0x76f + 0x200, 0x579 + 0x200);
237                 sr->opp2_nvalue = cal_test_nvalue(0x4f5 + 0x1c0, 0x390 + 0x1c0);
238                 sr->opp1_nvalue = cal_test_nvalue(0x359, 0x25d);
239         }
240
241 }
242
243 static void sr_set_nvalues(struct omap_sr *sr)
244 {
245         if (SR_TESTING_NVALUES)
246                 sr_set_testing_nvalues(sr);
247         else
248                 sr_set_efuse_nvalues(sr);
249 }
250
251 static void sr_configure_vp(int srid)
252 {
253         u32 vpconfig;
254
255         if (srid == SR1) {
256                 vpconfig = PRM_VP1_CONFIG_ERROROFFSET | PRM_VP1_CONFIG_ERRORGAIN
257                                         | PRM_VP1_CONFIG_INITVOLTAGE
258                                         | PRM_VP1_CONFIG_TIMEOUTEN;
259
260                 prm_write_mod_reg(vpconfig, OMAP3430_GR_MOD,
261                                         OMAP3_PRM_VP1_CONFIG_OFFSET);
262                 prm_write_mod_reg(PRM_VP1_VSTEPMIN_SMPSWAITTIMEMIN |
263                                         PRM_VP1_VSTEPMIN_VSTEPMIN,
264                                         OMAP3430_GR_MOD,
265                                         OMAP3_PRM_VP1_VSTEPMIN_OFFSET);
266
267                 prm_write_mod_reg(PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX |
268                                         PRM_VP1_VSTEPMAX_VSTEPMAX,
269                                         OMAP3430_GR_MOD,
270                                         OMAP3_PRM_VP1_VSTEPMAX_OFFSET);
271
272                 prm_write_mod_reg(PRM_VP1_VLIMITTO_VDDMAX |
273                                         PRM_VP1_VLIMITTO_VDDMIN |
274                                         PRM_VP1_VLIMITTO_TIMEOUT,
275                                         OMAP3430_GR_MOD,
276                                         OMAP3_PRM_VP1_VLIMITTO_OFFSET);
277
278                 /* Trigger initVDD value copy to voltage processor */
279                 prm_set_mod_reg_bits(PRM_VP1_CONFIG_INITVDD, OMAP3430_GR_MOD,
280                                         OMAP3_PRM_VP1_CONFIG_OFFSET);
281                 /* Clear initVDD copy trigger bit */
282                 prm_clear_mod_reg_bits(PRM_VP1_CONFIG_INITVDD, OMAP3430_GR_MOD,
283                                         OMAP3_PRM_VP1_CONFIG_OFFSET);
284
285         } else if (srid == SR2) {
286                 vpconfig = PRM_VP2_CONFIG_ERROROFFSET | PRM_VP2_CONFIG_ERRORGAIN
287                                         | PRM_VP2_CONFIG_INITVOLTAGE
288                                         | PRM_VP2_CONFIG_TIMEOUTEN;
289
290                 prm_write_mod_reg(vpconfig, OMAP3430_GR_MOD,
291                                         OMAP3_PRM_VP2_CONFIG_OFFSET);
292                 prm_write_mod_reg(PRM_VP2_VSTEPMIN_SMPSWAITTIMEMIN |
293                                         PRM_VP2_VSTEPMIN_VSTEPMIN,
294                                         OMAP3430_GR_MOD,
295                                         OMAP3_PRM_VP2_VSTEPMIN_OFFSET);
296
297                 prm_write_mod_reg(PRM_VP2_VSTEPMAX_SMPSWAITTIMEMAX |
298                                         PRM_VP2_VSTEPMAX_VSTEPMAX,
299                                         OMAP3430_GR_MOD,
300                                         OMAP3_PRM_VP2_VSTEPMAX_OFFSET);
301
302                 prm_write_mod_reg(PRM_VP2_VLIMITTO_VDDMAX |
303                                         PRM_VP2_VLIMITTO_VDDMIN |
304                                         PRM_VP2_VLIMITTO_TIMEOUT,
305                                         OMAP3430_GR_MOD,
306                                         OMAP3_PRM_VP2_VLIMITTO_OFFSET);
307
308                 /* Trigger initVDD value copy to voltage processor */
309                 prm_set_mod_reg_bits(PRM_VP2_CONFIG_INITVDD, OMAP3430_GR_MOD,
310                                         OMAP3_PRM_VP2_CONFIG_OFFSET);
311                 /* Reset initVDD copy trigger bit */
312                 prm_clear_mod_reg_bits(PRM_VP2_CONFIG_INITVDD, OMAP3430_GR_MOD,
313                                         OMAP3_PRM_VP2_CONFIG_OFFSET);
314
315         }
316 }
317
318 static void sr_configure(struct omap_sr *sr)
319 {
320         u32 sr_config;
321         u32 senp_en , senn_en;
322
323         if (sr->clk_length == 0)
324                 sr_set_clk_length(sr);
325
326         senp_en = sr->senp_mod;
327         senn_en = sr->senn_mod;
328         if (sr->srid == SR1) {
329                 sr_config = SR1_SRCONFIG_ACCUMDATA |
330                         (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
331                         SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN |
332                         SRCONFIG_MINMAXAVG_EN |
333                         (senn_en << SRCONFIG_SENNENABLE_SHIFT) |
334                         (senp_en << SRCONFIG_SENPENABLE_SHIFT) |
335                         SRCONFIG_DELAYCTRL;
336
337                 sr_write_reg(sr, SRCONFIG, sr_config);
338                 sr_write_reg(sr, AVGWEIGHT, SR1_AVGWEIGHT_SENPAVGWEIGHT |
339                                         SR1_AVGWEIGHT_SENNAVGWEIGHT);
340
341                 sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |
342                         SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
343                         (SR1_ERRWEIGHT | SR1_ERRMAXLIMIT | SR1_ERRMINLIMIT));
344
345         } else if (sr->srid == SR2) {
346                 sr_config = SR2_SRCONFIG_ACCUMDATA |
347                         (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
348                         SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN |
349                         SRCONFIG_MINMAXAVG_EN |
350                         (senn_en << SRCONFIG_SENNENABLE_SHIFT) |
351                         (senp_en << SRCONFIG_SENPENABLE_SHIFT) |
352                         SRCONFIG_DELAYCTRL;
353
354                 sr_write_reg(sr, SRCONFIG, sr_config);
355                 sr_write_reg(sr, AVGWEIGHT, SR2_AVGWEIGHT_SENPAVGWEIGHT |
356                                         SR2_AVGWEIGHT_SENNAVGWEIGHT);
357                 sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |
358                         SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
359                         (SR2_ERRWEIGHT | SR2_ERRMAXLIMIT | SR2_ERRMINLIMIT));
360
361         }
362         sr->is_sr_reset = 0;
363 }
364
365 static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
366 {
367         u32 nvalue_reciprocal;
368
369         sr->req_opp_no = target_opp_no;
370
371         if (sr->srid == SR1) {
372                 switch (target_opp_no) {
373                 case 5:
374                         nvalue_reciprocal = sr->opp5_nvalue;
375                         break;
376                 case 4:
377                         nvalue_reciprocal = sr->opp4_nvalue;
378                         break;
379                 case 3:
380                         nvalue_reciprocal = sr->opp3_nvalue;
381                         break;
382                 case 2:
383                         nvalue_reciprocal = sr->opp2_nvalue;
384                         break;
385                 case 1:
386                         nvalue_reciprocal = sr->opp1_nvalue;
387                         break;
388                 default:
389                         nvalue_reciprocal = sr->opp3_nvalue;
390                         break;
391                 }
392         } else {
393                 switch (target_opp_no) {
394                 case 3:
395                         nvalue_reciprocal = sr->opp3_nvalue;
396                         break;
397                 case 2:
398                         nvalue_reciprocal = sr->opp2_nvalue;
399                         break;
400                 case 1:
401                         nvalue_reciprocal = sr->opp1_nvalue;
402                         break;
403                 default:
404                         nvalue_reciprocal = sr->opp3_nvalue;
405                         break;
406                 }
407         }
408
409         if (nvalue_reciprocal == 0) {
410                 printk(KERN_NOTICE "OPP%d doesn't support SmartReflex\n",
411                                                                 target_opp_no);
412                 return SR_FALSE;
413         }
414
415         sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
416
417         /* Enable the interrupt */
418         sr_modify_reg(sr, ERRCONFIG,
419                         (ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST),
420                         (ERRCONFIG_VPBOUNDINTEN | ERRCONFIG_VPBOUNDINTST));
421         if (sr->srid == SR1) {
422                 /* Enable VP1 */
423                 prm_set_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE, OMAP3430_GR_MOD,
424                                 OMAP3_PRM_VP1_CONFIG_OFFSET);
425         } else if (sr->srid == SR2) {
426                 /* Enable VP2 */
427                 prm_set_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, OMAP3430_GR_MOD,
428                                 OMAP3_PRM_VP2_CONFIG_OFFSET);
429         }
430
431         /* SRCONFIG - enable SR */
432         sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
433         return SR_TRUE;
434 }
435
436 static void sr_disable(struct omap_sr *sr)
437 {
438         sr->is_sr_reset = 1;
439
440         /* SRCONFIG - disable SR */
441         sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, ~SRCONFIG_SRENABLE);
442
443         if (sr->srid == SR1) {
444                 /* Disable VP1 */
445                 prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE, OMAP3430_GR_MOD,
446                                         OMAP3_PRM_VP1_CONFIG_OFFSET);
447         } else if (sr->srid == SR2) {
448                 /* Disable VP2 */
449                 prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, OMAP3430_GR_MOD,
450                                         OMAP3_PRM_VP2_CONFIG_OFFSET);
451         }
452 }
453
454
455 void sr_start_vddautocomap(int srid, u32 target_opp_no)
456 {
457         struct omap_sr *sr = NULL;
458
459         if (srid == SR1)
460                 sr = &sr1;
461         else if (srid == SR2)
462                 sr = &sr2;
463
464         if (sr->is_sr_reset == 1) {
465                 sr_clk_enable(sr);
466                 sr_configure(sr);
467         }
468
469         if (sr->is_autocomp_active == 1)
470                 printk(KERN_WARNING "SR%d: VDD autocomp is already active\n",
471                                                                         srid);
472
473         sr->is_autocomp_active = 1;
474         if (!sr_enable(sr, target_opp_no)) {
475                 printk(KERN_WARNING "SR%d: VDD autocomp not activated\n", srid);
476                 sr->is_autocomp_active = 0;
477                 if (sr->is_sr_reset == 1)
478                         sr_clk_disable(sr);
479         }
480 }
481 EXPORT_SYMBOL(sr_start_vddautocomap);
482
483 int sr_stop_vddautocomap(int srid)
484 {
485         struct omap_sr *sr = NULL;
486
487         if (srid == SR1)
488                 sr = &sr1;
489         else if (srid == SR2)
490                 sr = &sr2;
491
492         if (sr->is_autocomp_active == 1) {
493                 sr_disable(sr);
494                 sr_clk_disable(sr);
495                 sr->is_autocomp_active = 0;
496                 return SR_TRUE;
497         } else {
498                 printk(KERN_WARNING "SR%d: VDD autocomp is not active\n",
499                                                                 srid);
500                 return SR_FALSE;
501         }
502
503 }
504 EXPORT_SYMBOL(sr_stop_vddautocomap);
505
506 void enable_smartreflex(int srid)
507 {
508         u32 target_opp_no = 0;
509         struct omap_sr *sr = NULL;
510
511         if (srid == SR1)
512                 sr = &sr1;
513         else if (srid == SR2)
514                 sr = &sr2;
515
516         if (sr->is_autocomp_active == 1) {
517                 if (sr->is_sr_reset == 1) {
518                         /* Enable SR clks */
519                         sr_clk_enable(sr);
520
521                         if (srid == SR1)
522                                 target_opp_no = get_opp_no(current_vdd1_opp);
523                         else if (srid == SR2)
524                                 target_opp_no = get_opp_no(current_vdd2_opp);
525
526                         sr_configure(sr);
527
528                         if (!sr_enable(sr, target_opp_no))
529                                 sr_clk_disable(sr);
530                 }
531         }
532 }
533
534 void disable_smartreflex(int srid)
535 {
536         struct omap_sr *sr = NULL;
537
538         if (srid == SR1)
539                 sr = &sr1;
540         else if (srid == SR2)
541                 sr = &sr2;
542
543         if (sr->is_autocomp_active == 1) {
544                 if (sr->is_sr_reset == 0) {
545
546                         sr->is_sr_reset = 1;
547                         /* SRCONFIG - disable SR */
548                         sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
549                                                         ~SRCONFIG_SRENABLE);
550
551                         /* Disable SR clk */
552                         sr_clk_disable(sr);
553                         if (sr->srid == SR1) {
554                                 /* Disable VP1 */
555                                 prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE,
556                                                 OMAP3430_GR_MOD,
557                                                 OMAP3_PRM_VP1_CONFIG_OFFSET);
558                         } else if (sr->srid == SR2) {
559                                 /* Disable VP2 */
560                                 prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE,
561                                                 OMAP3430_GR_MOD,
562                                                 OMAP3_PRM_VP2_CONFIG_OFFSET);
563                         }
564                 }
565         }
566 }
567
568 /* Voltage Scaling using SR VCBYPASS */
569 int sr_voltagescale_vcbypass(u32 target_opp, u8 vsel)
570 {
571         int sr_status = 0;
572         u32 vdd, target_opp_no;
573         u32 vc_bypass_value;
574         u32 reg_addr = 0;
575         u32 loop_cnt = 0, retries_cnt = 0;
576
577         vdd = get_vdd(target_opp);
578         target_opp_no = get_opp_no(target_opp);
579
580         if (vdd == PRCM_VDD1) {
581                 sr_status = sr_stop_vddautocomap(SR1);
582
583                 prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
584                                         (vsel << OMAP3430_VC_CMD_ON_SHIFT),
585                                         OMAP3430_GR_MOD,
586                                         OMAP3_PRM_VC_CMD_VAL_0_OFFSET);
587                 reg_addr = R_VDD1_SR_CONTROL;
588
589         } else if (vdd == PRCM_VDD2) {
590                 sr_status = sr_stop_vddautocomap(SR2);
591
592                 prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
593                                         (vsel << OMAP3430_VC_CMD_ON_SHIFT),
594                                         OMAP3430_GR_MOD,
595                                         OMAP3_PRM_VC_CMD_VAL_1_OFFSET);
596                 reg_addr = R_VDD2_SR_CONTROL;
597         }
598
599         vc_bypass_value = (vsel << OMAP3430_DATA_SHIFT) |
600                         (reg_addr << OMAP3430_REGADDR_SHIFT) |
601                         (R_SRI2C_SLAVE_ADDR << OMAP3430_SLAVEADDR_SHIFT);
602
603         prm_write_mod_reg(vc_bypass_value, OMAP3430_GR_MOD,
604                         OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
605
606         vc_bypass_value = prm_set_mod_reg_bits(OMAP3430_VALID, OMAP3430_GR_MOD,
607                                         OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
608
609         while ((vc_bypass_value & OMAP3430_VALID) != 0x0) {
610                 loop_cnt++;
611                 if (retries_cnt > 10) {
612                         printk(KERN_INFO "Loop count exceeded in check SR I2C"
613                                                                 "write\n");
614                         return SR_FAIL;
615                 }
616                 if (loop_cnt > 50) {
617                         retries_cnt++;
618                         loop_cnt = 0;
619                         udelay(10);
620                 }
621                 vc_bypass_value = prm_read_mod_reg(OMAP3430_GR_MOD,
622                                         OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
623         }
624
625         udelay(T2_SMPS_UPDATE_DELAY);
626
627         if (sr_status) {
628                 if (vdd == PRCM_VDD1)
629                         sr_start_vddautocomap(SR1, target_opp_no);
630                 else if (vdd == PRCM_VDD2)
631                         sr_start_vddautocomap(SR2, target_opp_no);
632         }
633
634         return SR_PASS;
635 }
636
637 /* Sysfs interface to select SR VDD1 auto compensation */
638 static ssize_t omap_sr_vdd1_autocomp_show(struct kobject *kobj,
639                                         struct kobj_attribute *attr, char *buf)
640 {
641         return sprintf(buf, "%d\n", sr1.is_autocomp_active);
642 }
643
644 static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj,
645                                         struct kobj_attribute *attr,
646                                         const char *buf, size_t n)
647 {
648         u32 current_vdd1opp_no;
649         unsigned short value;
650
651         if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
652                 printk(KERN_ERR "sr_vdd1_autocomp: Invalid value\n");
653                 return -EINVAL;
654         }
655
656         current_vdd1opp_no = get_opp_no(current_vdd1_opp);
657
658         if (value == 0)
659                 sr_stop_vddautocomap(SR1);
660         else
661                 sr_start_vddautocomap(SR1, current_vdd1opp_no);
662
663         return n;
664 }
665
666 static struct kobj_attribute sr_vdd1_autocomp = {
667         .attr = {
668         .name = __stringify(sr_vdd1_autocomp),
669         .mode = 0644,
670         },
671         .show = omap_sr_vdd1_autocomp_show,
672         .store = omap_sr_vdd1_autocomp_store,
673 };
674
675 /* Sysfs interface to select SR VDD2 auto compensation */
676 static ssize_t omap_sr_vdd2_autocomp_show(struct kobject *kobj,
677                                         struct kobj_attribute *attr, char *buf)
678 {
679         return sprintf(buf, "%d\n", sr2.is_autocomp_active);
680 }
681
682 static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj,
683                                         struct kobj_attribute *attr,
684                                         const char *buf, size_t n)
685 {
686         u32 current_vdd2opp_no;
687         unsigned short value;
688
689         if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
690                 printk(KERN_ERR "sr_vdd2_autocomp: Invalid value\n");
691                 return -EINVAL;
692         }
693
694         current_vdd2opp_no = get_opp_no(current_vdd2_opp);
695
696         if (value == 0)
697                 sr_stop_vddautocomap(SR2);
698         else
699                 sr_start_vddautocomap(SR2, current_vdd2opp_no);
700
701         return n;
702 }
703
704 static struct kobj_attribute sr_vdd2_autocomp = {
705         .attr = {
706         .name = __stringify(sr_vdd2_autocomp),
707         .mode = 0644,
708         },
709         .show = omap_sr_vdd2_autocomp_show,
710         .store = omap_sr_vdd2_autocomp_store,
711 };
712
713
714
715 static int __init omap3_sr_init(void)
716 {
717         int ret = 0;
718         u8 RdReg;
719
720         if (omap_rev() > OMAP3430_REV_ES1_0) {
721                 current_vdd1_opp = PRCM_VDD1_OPP3;
722                 current_vdd2_opp = PRCM_VDD2_OPP3;
723         } else {
724                 current_vdd1_opp = PRCM_VDD1_OPP1;
725                 current_vdd2_opp = PRCM_VDD1_OPP1;
726         }
727         if (cpu_is_omap34xx()) {
728                 sr1.clk = clk_get(NULL, "sr1_fck");
729                 sr2.clk = clk_get(NULL, "sr2_fck");
730         }
731         sr_set_clk_length(&sr1);
732         sr_set_clk_length(&sr2);
733
734         /* Call the VPConfig, VCConfig, set N Values. */
735         sr_set_nvalues(&sr1);
736         sr_configure_vp(SR1);
737
738         sr_set_nvalues(&sr2);
739         sr_configure_vp(SR2);
740
741         /* Enable SR on T2 */
742         ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &RdReg,
743                                         R_DCDC_GLOBAL_CFG);
744
745         RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
746         ret |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
747                                         R_DCDC_GLOBAL_CFG);
748
749         printk(KERN_INFO "SmartReflex driver initialized\n");
750
751         ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
752         if (ret)
753                 printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
754
755         ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
756         if (ret)
757                 printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
758
759         return 0;
760 }
761
762 late_initcall(omap3_sr_init);