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