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