2 * linux/arch/arm/mach-omap3/smartreflex.c
4 * OMAP34XX SmartReflex Voltage Control
6 * Copyright (C) 2008 Nokia Corporation
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>
30 #include <asm/arch/omap34xx.h>
31 #include <asm/arch/control.h>
32 #include <asm/arch/clock.h>
35 #include "smartreflex.h"
36 #include "prm-regbits-34xx.h"
38 /* XXX: These should be relocated where-ever the OPP implementation will be */
45 int is_autocomp_active;
49 u32 opp1_nvalue, opp2_nvalue, opp3_nvalue, opp4_nvalue;
51 u32 senp_mod, senn_mod;
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 */
63 static inline void sr_write_reg(struct omap_sr *sr, int offset, u32 value)
65 __raw_writel(value, sr->srbase_addr + offset);
68 static inline void sr_modify_reg(struct omap_sr *sr, int offset, u32 mask,
73 reg_val = __raw_readl(sr->srbase_addr + offset);
77 __raw_writel(reg_val, sr->srbase_addr + offset);
80 static inline u32 sr_read_reg(struct omap_sr *sr, int offset)
82 return __raw_readl(sr->srbase_addr + offset);
85 /* Custom clock handling functions */
86 static int sr_clk_enable(struct clk *clk)
88 struct sr_custom_clk *sr_clk = container_of(clk, struct sr_custom_clk,
91 if (clk_enable(sr_clk->fck) != 0) {
92 printk(KERN_ERR "Could not enable %s\n", sr_clk->fck->name);
96 /* set fclk- active , iclk- idle */
97 sr_modify_reg(sr_clk->sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
98 SR_CLKACTIVITY_IOFF_FON);
106 static void sr_clk_disable(struct clk *clk)
108 struct sr_custom_clk *sr_clk = container_of(clk, struct sr_custom_clk,
111 /* set fclk, iclk- idle */
112 sr_modify_reg(sr_clk->sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
113 SR_CLKACTIVITY_IOFF_FOFF);
115 clk_disable(sr_clk->fck);
116 sr_clk->sr->is_sr_reset = 1;
119 static struct omap_sr sr1 = {
122 .is_autocomp_active = 0,
124 .srbase_addr = OMAP2_IO_ADDRESS(OMAP34XX_SR1_BASE),
127 static struct omap_sr sr2 = {
130 .is_autocomp_active = 0,
132 .srbase_addr = OMAP2_IO_ADDRESS(OMAP34XX_SR2_BASE),
135 static struct sr_custom_clk sr1_custom_clk = {
137 .name = "sr1_custom_clk",
138 .enable = sr_clk_enable,
139 .disable = sr_clk_disable,
144 static struct sr_custom_clk sr2_custom_clk = {
146 .name = "sr2_custom_clk",
147 .enable = sr_clk_enable,
148 .disable = sr_clk_disable,
153 static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen)
157 for (gn = 0; gn < GAIN_MAXLIMIT; gn++) {
160 if (rn < R_MAXLIMIT) {
167 static u32 cal_test_nvalue(u32 sennval, u32 senpval)
169 u32 senpgain, senngain;
172 /* Calculating the gain and reciprocal of the SenN and SenP values */
173 cal_reciprocal(senpval, &senpgain, &rnsenp);
174 cal_reciprocal(sennval, &senngain, &rnsenn);
176 return ((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |
177 (senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |
178 (rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |
179 (rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));
182 static void sr_clk_init(struct sr_custom_clk *sr_clk)
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");
193 clk_register(&sr_clk->clk);
196 static void sr_set_clk_length(struct omap_sr *sr)
198 struct clk *osc_sys_ck;
201 osc_sys_ck = clk_get(NULL, "osc_sys_ck");
202 sys_clk = clk_get_rate(osc_sys_ck);
207 sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
210 sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK;
213 sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK;
216 sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK;
219 sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
222 printk(KERN_ERR "Invalid sysclk value: %d\n", sys_clk);
227 static void sr_set_efuse_nvalues(struct omap_sr *sr)
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;
234 sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
235 OMAP343X_SR1_SENPENABLE_MASK) >>
236 OMAP343X_SR1_SENPENABLE_SHIFT;
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;
253 sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
254 OMAP343X_SR2_SENPENABLE_MASK) >>
255 OMAP343X_SR2_SENPENABLE_SHIFT;
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);
266 /* Hard coded nvalues for testing purposes, may cause device to hang! */
267 static void sr_set_testing_nvalues(struct omap_sr *sr)
269 if (sr->srid == SR1) {
270 sr->senp_mod = 0x03; /* SenN-M5 enabled */
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) {
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);
290 static void sr_set_nvalues(struct omap_sr *sr)
292 if (SR_TESTING_NVALUES)
293 sr_set_testing_nvalues(sr);
295 sr_set_efuse_nvalues(sr);
298 static void sr_configure_vp(int srid)
303 vpconfig = PRM_VP1_CONFIG_ERROROFFSET | PRM_VP1_CONFIG_ERRORGAIN
304 | PRM_VP1_CONFIG_INITVOLTAGE
305 | PRM_VP1_CONFIG_TIMEOUTEN;
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,
312 OMAP3_PRM_VP1_VSTEPMIN_OFFSET);
314 prm_write_mod_reg(PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX |
315 PRM_VP1_VSTEPMAX_VSTEPMAX,
317 OMAP3_PRM_VP1_VSTEPMAX_OFFSET);
319 prm_write_mod_reg(PRM_VP1_VLIMITTO_VDDMAX |
320 PRM_VP1_VLIMITTO_VDDMIN |
321 PRM_VP1_VLIMITTO_TIMEOUT,
323 OMAP3_PRM_VP1_VLIMITTO_OFFSET);
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);
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;
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,
342 OMAP3_PRM_VP2_VSTEPMIN_OFFSET);
344 prm_write_mod_reg(PRM_VP2_VSTEPMAX_SMPSWAITTIMEMAX |
345 PRM_VP2_VSTEPMAX_VSTEPMAX,
347 OMAP3_PRM_VP2_VSTEPMAX_OFFSET);
349 prm_write_mod_reg(PRM_VP2_VLIMITTO_VDDMAX |
350 PRM_VP2_VLIMITTO_VDDMIN |
351 PRM_VP2_VLIMITTO_TIMEOUT,
353 OMAP3_PRM_VP2_VLIMITTO_OFFSET);
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);
365 static void sr_configure_vc(void)
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);
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);
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);
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);
389 prm_write_mod_reg(OMAP3430_CMD1 | OMAP3430_RAV1,
391 OMAP3_PRM_VC_CH_CONF_OFFSET);
393 prm_write_mod_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN | OMAP3430_SREN,
395 OMAP3_PRM_VC_I2C_CFG_OFFSET);
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,
402 OMAP3_PRM_VOLTCTRL_OFFSET);
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);
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);
417 prm_set_mod_reg_bits(OMAP3430_AUTO_RET, OMAP3430_GR_MOD,
418 OMAP3_PRM_VOLTCTRL_OFFSET);
423 static void sr_configure(struct omap_sr *sr)
426 u32 senp_en , senn_en;
428 if (sr->clk_length == 0)
429 sr_set_clk_length(sr);
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) |
442 sr_write_reg(sr, SRCONFIG, sr_config);
443 sr_write_reg(sr, AVGWEIGHT, SR1_AVGWEIGHT_SENPAVGWEIGHT |
444 SR1_AVGWEIGHT_SENNAVGWEIGHT);
446 sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |
447 SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
448 (SR1_ERRWEIGHT | SR1_ERRMAXLIMIT | SR1_ERRMINLIMIT));
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) |
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));
470 static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
472 u32 nvalue_reciprocal;
474 sr->req_opp_no = target_opp_no;
476 if (sr->srid == SR1) {
477 switch (target_opp_no) {
479 nvalue_reciprocal = sr->opp5_nvalue;
482 nvalue_reciprocal = sr->opp4_nvalue;
485 nvalue_reciprocal = sr->opp3_nvalue;
488 nvalue_reciprocal = sr->opp2_nvalue;
491 nvalue_reciprocal = sr->opp1_nvalue;
494 nvalue_reciprocal = sr->opp3_nvalue;
498 switch (target_opp_no) {
500 nvalue_reciprocal = sr->opp3_nvalue;
503 nvalue_reciprocal = sr->opp2_nvalue;
506 nvalue_reciprocal = sr->opp1_nvalue;
509 nvalue_reciprocal = sr->opp3_nvalue;
514 if (nvalue_reciprocal == 0) {
515 printk(KERN_NOTICE "OPP%d doesn't support SmartReflex\n",
520 sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
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) {
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) {
532 prm_set_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, OMAP3430_GR_MOD,
533 OMAP3_PRM_VP2_CONFIG_OFFSET);
536 /* SRCONFIG - enable SR */
537 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
541 static void sr_disable(struct omap_sr *sr)
545 /* SRCONFIG - disable SR */
546 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, ~SRCONFIG_SRENABLE);
548 if (sr->srid == SR1) {
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) {
554 prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, OMAP3430_GR_MOD,
555 OMAP3_PRM_VP2_CONFIG_OFFSET);
560 void sr_start_vddautocomap(int srid, u32 target_opp_no)
562 struct omap_sr *sr = NULL;
566 else if (srid == SR2)
569 if (sr->is_sr_reset == 1) {
574 if (sr->is_autocomp_active == 1)
575 printk(KERN_WARNING "SR%d: VDD autocomp is already active\n",
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);
586 EXPORT_SYMBOL(sr_start_vddautocomap);
588 int sr_stop_vddautocomap(int srid)
590 struct omap_sr *sr = NULL;
594 else if (srid == SR2)
597 if (sr->is_autocomp_active == 1) {
599 clk_disable(sr->clk);
600 sr->is_autocomp_active = 0;
603 printk(KERN_WARNING "SR%d: VDD autocomp is not active\n",
609 EXPORT_SYMBOL(sr_stop_vddautocomap);
611 void enable_smartreflex(int srid)
613 u32 target_opp_no = 0;
614 struct omap_sr *sr = NULL;
618 else if (srid == SR2)
621 if (sr->is_autocomp_active == 1) {
622 if (sr->is_sr_reset == 1) {
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);
633 if (!sr_enable(sr, target_opp_no))
634 clk_disable(sr->clk);
639 void disable_smartreflex(int srid)
641 struct omap_sr *sr = NULL;
645 else if (srid == SR2)
648 if (sr->is_autocomp_active == 1) {
649 if (sr->is_sr_reset == 0) {
652 /* SRCONFIG - disable SR */
653 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
657 clk_disable(sr->clk);
658 if (sr->srid == SR1) {
660 prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE,
662 OMAP3_PRM_VP1_CONFIG_OFFSET);
663 } else if (sr->srid == SR2) {
665 prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE,
667 OMAP3_PRM_VP2_CONFIG_OFFSET);
673 /* Voltage Scaling using SR VCBYPASS */
674 int sr_voltagescale_vcbypass(u32 target_opp, u8 vsel)
677 u32 vdd, target_opp_no;
680 u32 loop_cnt = 0, retries_cnt = 0;
682 vdd = get_vdd(target_opp);
683 target_opp_no = get_opp_no(target_opp);
685 if (vdd == PRCM_VDD1) {
686 sr_status = sr_stop_vddautocomap(SR1);
688 prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
689 (vsel << OMAP3430_VC_CMD_ON_SHIFT),
691 OMAP3_PRM_VC_CMD_VAL_0_OFFSET);
692 reg_addr = R_VDD1_SR_CONTROL;
694 } else if (vdd == PRCM_VDD2) {
695 sr_status = sr_stop_vddautocomap(SR2);
697 prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
698 (vsel << OMAP3430_VC_CMD_ON_SHIFT),
700 OMAP3_PRM_VC_CMD_VAL_1_OFFSET);
701 reg_addr = R_VDD2_SR_CONTROL;
704 vc_bypass_value = (vsel << OMAP3430_DATA_SHIFT) |
705 (reg_addr << OMAP3430_REGADDR_SHIFT) |
706 (R_SRI2C_SLAVE_ADDR << OMAP3430_SLAVEADDR_SHIFT);
708 prm_write_mod_reg(vc_bypass_value, OMAP3430_GR_MOD,
709 OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
711 vc_bypass_value = prm_set_mod_reg_bits(OMAP3430_VALID, OMAP3430_GR_MOD,
712 OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
714 while ((vc_bypass_value & OMAP3430_VALID) != 0x0) {
716 if (retries_cnt > 10) {
717 printk(KERN_INFO "Loop count exceeded in check SR I2C"
726 vc_bypass_value = prm_read_mod_reg(OMAP3430_GR_MOD,
727 OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
730 udelay(T2_SMPS_UPDATE_DELAY);
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);
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)
746 return sprintf(buf, "%d\n", sr1.is_autocomp_active);
749 static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj,
750 struct kobj_attribute *attr,
751 const char *buf, size_t n)
753 u32 current_vdd1opp_no;
754 unsigned short value;
756 if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
757 printk(KERN_ERR "sr_vdd1_autocomp: Invalid value\n");
761 current_vdd1opp_no = get_opp_no(current_vdd1_opp);
764 sr_stop_vddautocomap(SR1);
766 sr_start_vddautocomap(SR1, current_vdd1opp_no);
771 static struct kobj_attribute sr_vdd1_autocomp = {
773 .name = __stringify(sr_vdd1_autocomp),
776 .show = omap_sr_vdd1_autocomp_show,
777 .store = omap_sr_vdd1_autocomp_store,
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)
784 return sprintf(buf, "%d\n", sr2.is_autocomp_active);
787 static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj,
788 struct kobj_attribute *attr,
789 const char *buf, size_t n)
791 u32 current_vdd2opp_no;
792 unsigned short value;
794 if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
795 printk(KERN_ERR "sr_vdd2_autocomp: Invalid value\n");
799 current_vdd2opp_no = get_opp_no(current_vdd2_opp);
802 sr_stop_vddautocomap(SR2);
804 sr_start_vddautocomap(SR2, current_vdd2opp_no);
809 static struct kobj_attribute sr_vdd2_autocomp = {
811 .name = __stringify(sr_vdd2_autocomp),
814 .show = omap_sr_vdd2_autocomp_show,
815 .store = omap_sr_vdd2_autocomp_store,
820 static int __init omap3_sr_init(void)
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;
829 current_vdd1_opp = PRCM_VDD1_OPP1;
830 current_vdd2_opp = PRCM_VDD1_OPP1;
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");
838 sr_set_clk_length(&sr1);
839 sr_set_clk_length(&sr2);
841 /* Call the VPConfig, VCConfig, set N Values. */
842 sr_set_nvalues(&sr1);
843 sr_configure_vp(SR1);
845 sr_set_nvalues(&sr2);
846 sr_configure_vp(SR2);
850 /* Enable SR on T2 */
851 ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &RdReg,
854 RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
855 ret |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
858 printk(KERN_INFO "SmartReflex driver initialized\n");
860 ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
862 printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
864 ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
866 printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
871 late_initcall(omap3_sr_init);