Group and resource assignments for TWL4030
[linux-ginger.git] / arch / arm / mach-omap2 / smartreflex.c
blobf26a9a1831f24884dd7bce75df8894abd0b0b98d
1 /*
2 * linux/arch/arm/mach-omap3/smartreflex.c
4 * OMAP34XX SmartReflex Voltage Control
6 * Copyright (C) 2008 Nokia Corporation
7 * Kalle Jokiniemi
9 * Copyright (C) 2007 Texas Instruments, Inc.
10 * Lesly A M <x0080970@ti.com>
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.
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>
30 #include <mach/omap34xx.h>
31 #include <mach/control.h>
32 #include <mach/clock.h>
34 #include "prm.h"
35 #include "smartreflex.h"
36 #include "prm-regbits-34xx.h"
38 /* XXX: These should be relocated where-ever the OPP implementation will be */
39 u32 current_vdd1_opp;
40 u32 current_vdd2_opp;
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;
56 #define SR_REGADDR(offs) (sr->srbase_addr + offset)
58 static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
60 __raw_writel(value, SR_REGADDR(offset));
63 static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
64 u32 value)
66 u32 reg_val;
68 reg_val = __raw_readl(SR_REGADDR(offset));
69 reg_val &= ~mask;
70 reg_val |= value;
72 __raw_writel(reg_val, SR_REGADDR(offset));
75 static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
77 return __raw_readl(SR_REGADDR(offset));
80 static int sr_clk_enable(struct omap_sr *sr)
82 if (clk_enable(sr->clk) != 0) {
83 printk(KERN_ERR "Could not enable %s\n", sr->clk->name);
84 return -1;
87 /* set fclk- active , iclk- idle */
88 sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
89 SR_CLKACTIVITY_IOFF_FON);
91 return 0;
94 static void sr_clk_disable(struct omap_sr *sr)
96 /* set fclk, iclk- idle */
97 sr_modify_reg(sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
98 SR_CLKACTIVITY_IOFF_FOFF);
100 clk_disable(sr->clk);
101 sr->is_sr_reset = 1;
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),
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),
120 static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen)
122 u32 gn, rn, mul;
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;
134 static u32 cal_test_nvalue(u32 sennval, u32 senpval)
136 u32 senpgain, senngain;
137 u32 rnsenp, rnsenn;
139 /* Calculating the gain and reciprocal of the SenN and SenP values */
140 cal_reciprocal(senpval, &senpgain, &rnsenp);
141 cal_reciprocal(sennval, &senngain, &rnsenn);
143 return ((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |
144 (senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |
145 (rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |
146 (rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));
149 static void sr_set_clk_length(struct omap_sr *sr)
151 struct clk *osc_sys_ck;
152 u32 sys_clk = 0;
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);
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;
180 static void sr_set_efuse_nvalues(struct omap_sr *sr)
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;
187 sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
188 OMAP343X_SR1_SENPENABLE_MASK) >>
189 OMAP343X_SR1_SENPENABLE_SHIFT;
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;
206 sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
207 OMAP343X_SR2_SENPENABLE_MASK) >>
208 OMAP343X_SR2_SENPENABLE_SHIFT;
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);
219 /* Hard coded nvalues for testing purposes, may cause device to hang! */
220 static void sr_set_testing_nvalues(struct omap_sr *sr)
222 if (sr->srid == SR1) {
223 sr->senp_mod = 0x03; /* SenN-M5 enabled */
224 sr->senn_mod = 0x03;
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;
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);
243 static void sr_set_nvalues(struct omap_sr *sr)
245 if (SR_TESTING_NVALUES)
246 sr_set_testing_nvalues(sr);
247 else
248 sr_set_efuse_nvalues(sr);
251 static void sr_configure_vp(int srid)
253 u32 vpconfig;
255 if (srid == SR1) {
256 vpconfig = PRM_VP1_CONFIG_ERROROFFSET | PRM_VP1_CONFIG_ERRORGAIN
257 | PRM_VP1_CONFIG_INITVOLTAGE
258 | PRM_VP1_CONFIG_TIMEOUTEN;
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);
267 prm_write_mod_reg(PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX |
268 PRM_VP1_VSTEPMAX_VSTEPMAX,
269 OMAP3430_GR_MOD,
270 OMAP3_PRM_VP1_VSTEPMAX_OFFSET);
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);
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);
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;
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);
297 prm_write_mod_reg(PRM_VP2_VSTEPMAX_SMPSWAITTIMEMAX |
298 PRM_VP2_VSTEPMAX_VSTEPMAX,
299 OMAP3430_GR_MOD,
300 OMAP3_PRM_VP2_VSTEPMAX_OFFSET);
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);
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);
318 static void sr_configure(struct omap_sr *sr)
320 u32 sr_config;
321 u32 senp_en , senn_en;
323 if (sr->clk_length == 0)
324 sr_set_clk_length(sr);
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;
337 sr_write_reg(sr, SRCONFIG, sr_config);
338 sr_write_reg(sr, AVGWEIGHT, SR1_AVGWEIGHT_SENPAVGWEIGHT |
339 SR1_AVGWEIGHT_SENNAVGWEIGHT);
341 sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |
342 SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
343 (SR1_ERRWEIGHT | SR1_ERRMAXLIMIT | SR1_ERRMINLIMIT));
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;
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));
362 sr->is_sr_reset = 0;
365 static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
367 u32 nvalue_reciprocal;
369 sr->req_opp_no = target_opp_no;
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;
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;
409 if (nvalue_reciprocal == 0) {
410 printk(KERN_NOTICE "OPP%d doesn't support SmartReflex\n",
411 target_opp_no);
412 return SR_FALSE;
415 sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
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);
431 /* SRCONFIG - enable SR */
432 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
433 return SR_TRUE;
436 static void sr_disable(struct omap_sr *sr)
438 sr->is_sr_reset = 1;
440 /* SRCONFIG - disable SR */
441 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, ~SRCONFIG_SRENABLE);
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);
455 void sr_start_vddautocomap(int srid, u32 target_opp_no)
457 struct omap_sr *sr = NULL;
459 if (srid == SR1)
460 sr = &sr1;
461 else if (srid == SR2)
462 sr = &sr2;
464 if (sr->is_sr_reset == 1) {
465 sr_clk_enable(sr);
466 sr_configure(sr);
469 if (sr->is_autocomp_active == 1)
470 printk(KERN_WARNING "SR%d: VDD autocomp is already active\n",
471 srid);
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);
481 EXPORT_SYMBOL(sr_start_vddautocomap);
483 int sr_stop_vddautocomap(int srid)
485 struct omap_sr *sr = NULL;
487 if (srid == SR1)
488 sr = &sr1;
489 else if (srid == SR2)
490 sr = &sr2;
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;
504 EXPORT_SYMBOL(sr_stop_vddautocomap);
506 void enable_smartreflex(int srid)
508 u32 target_opp_no = 0;
509 struct omap_sr *sr = NULL;
511 if (srid == SR1)
512 sr = &sr1;
513 else if (srid == SR2)
514 sr = &sr2;
516 if (sr->is_autocomp_active == 1) {
517 if (sr->is_sr_reset == 1) {
518 /* Enable SR clks */
519 sr_clk_enable(sr);
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);
526 sr_configure(sr);
528 if (!sr_enable(sr, target_opp_no))
529 sr_clk_disable(sr);
534 void disable_smartreflex(int srid)
536 struct omap_sr *sr = NULL;
538 if (srid == SR1)
539 sr = &sr1;
540 else if (srid == SR2)
541 sr = &sr2;
543 if (sr->is_autocomp_active == 1) {
544 if (sr->is_sr_reset == 0) {
546 sr->is_sr_reset = 1;
547 /* SRCONFIG - disable SR */
548 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
549 ~SRCONFIG_SRENABLE);
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);
568 /* Voltage Scaling using SR VCBYPASS */
569 int sr_voltagescale_vcbypass(u32 target_opp, u8 vsel)
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;
577 vdd = get_vdd(target_opp);
578 target_opp_no = get_opp_no(target_opp);
580 if (vdd == PRCM_VDD1) {
581 sr_status = sr_stop_vddautocomap(SR1);
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;
589 } else if (vdd == PRCM_VDD2) {
590 sr_status = sr_stop_vddautocomap(SR2);
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;
599 vc_bypass_value = (vsel << OMAP3430_DATA_SHIFT) |
600 (reg_addr << OMAP3430_REGADDR_SHIFT) |
601 (R_SRI2C_SLAVE_ADDR << OMAP3430_SLAVEADDR_SHIFT);
603 prm_write_mod_reg(vc_bypass_value, OMAP3430_GR_MOD,
604 OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
606 vc_bypass_value = prm_set_mod_reg_bits(OMAP3430_VALID, OMAP3430_GR_MOD,
607 OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
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;
616 if (loop_cnt > 50) {
617 retries_cnt++;
618 loop_cnt = 0;
619 udelay(10);
621 vc_bypass_value = prm_read_mod_reg(OMAP3430_GR_MOD,
622 OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
625 udelay(T2_SMPS_UPDATE_DELAY);
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);
634 return SR_PASS;
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)
641 return sprintf(buf, "%d\n", sr1.is_autocomp_active);
644 static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj,
645 struct kobj_attribute *attr,
646 const char *buf, size_t n)
648 u32 current_vdd1opp_no;
649 unsigned short value;
651 if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
652 printk(KERN_ERR "sr_vdd1_autocomp: Invalid value\n");
653 return -EINVAL;
656 current_vdd1opp_no = get_opp_no(current_vdd1_opp);
658 if (value == 0)
659 sr_stop_vddautocomap(SR1);
660 else
661 sr_start_vddautocomap(SR1, current_vdd1opp_no);
663 return n;
666 static struct kobj_attribute sr_vdd1_autocomp = {
667 .attr = {
668 .name = __stringify(sr_vdd1_autocomp),
669 .mode = 0644,
671 .show = omap_sr_vdd1_autocomp_show,
672 .store = omap_sr_vdd1_autocomp_store,
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)
679 return sprintf(buf, "%d\n", sr2.is_autocomp_active);
682 static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj,
683 struct kobj_attribute *attr,
684 const char *buf, size_t n)
686 u32 current_vdd2opp_no;
687 unsigned short value;
689 if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
690 printk(KERN_ERR "sr_vdd2_autocomp: Invalid value\n");
691 return -EINVAL;
694 current_vdd2opp_no = get_opp_no(current_vdd2_opp);
696 if (value == 0)
697 sr_stop_vddautocomap(SR2);
698 else
699 sr_start_vddautocomap(SR2, current_vdd2opp_no);
701 return n;
704 static struct kobj_attribute sr_vdd2_autocomp = {
705 .attr = {
706 .name = __stringify(sr_vdd2_autocomp),
707 .mode = 0644,
709 .show = omap_sr_vdd2_autocomp_show,
710 .store = omap_sr_vdd2_autocomp_store,
715 static int __init omap3_sr_init(void)
717 int ret = 0;
718 u8 RdReg;
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;
727 if (cpu_is_omap34xx()) {
728 sr1.clk = clk_get(NULL, "sr1_fck");
729 sr2.clk = clk_get(NULL, "sr2_fck");
731 sr_set_clk_length(&sr1);
732 sr_set_clk_length(&sr2);
734 /* Call the VPConfig, VCConfig, set N Values. */
735 sr_set_nvalues(&sr1);
736 sr_configure_vp(SR1);
738 sr_set_nvalues(&sr2);
739 sr_configure_vp(SR2);
741 /* Enable SR on T2 */
742 ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &RdReg,
743 R_DCDC_GLOBAL_CFG);
745 RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
746 ret |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
747 R_DCDC_GLOBAL_CFG);
749 printk(KERN_INFO "SmartReflex driver initialized\n");
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);
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);
759 return 0;
762 late_initcall(omap3_sr_init);