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 <mach/omap34xx.h>
31 #include <mach/control.h>
32 #include <mach/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
;
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
,
68 reg_val
= __raw_readl(SR_REGADDR(offset
));
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
);
87 /* set fclk- active , iclk- idle */
88 sr_modify_reg(sr
, ERRCONFIG
, SR_CLKACTIVITY_MASK
,
89 SR_CLKACTIVITY_IOFF_FON
);
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
);
104 static struct omap_sr sr1
= {
107 .is_autocomp_active
= 0,
109 .srbase_addr
= OMAP2_IO_ADDRESS(OMAP34XX_SR1_BASE
),
112 static struct omap_sr sr2
= {
115 .is_autocomp_active
= 0,
117 .srbase_addr
= OMAP2_IO_ADDRESS(OMAP34XX_SR2_BASE
),
120 static void cal_reciprocal(u32 sensor
, u32
*sengain
, u32
*rnsen
)
124 for (gn
= 0; gn
< GAIN_MAXLIMIT
; gn
++) {
127 if (rn
< R_MAXLIMIT
) {
134 static u32
cal_test_nvalue(u32 sennval
, u32 senpval
)
136 u32 senpgain
, senngain
;
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
;
154 osc_sys_ck
= clk_get(NULL
, "osc_sys_ck");
155 sys_clk
= clk_get_rate(osc_sys_ck
);
160 sr
->clk_length
= SRCLKLENGTH_12MHZ_SYSCLK
;
163 sr
->clk_length
= SRCLKLENGTH_13MHZ_SYSCLK
;
166 sr
->clk_length
= SRCLKLENGTH_19MHZ_SYSCLK
;
169 sr
->clk_length
= SRCLKLENGTH_26MHZ_SYSCLK
;
172 sr
->clk_length
= SRCLKLENGTH_38MHZ_SYSCLK
;
175 printk(KERN_ERR
"Invalid sysclk value: %d\n", sys_clk
);
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 */
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
) {
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
);
248 sr_set_efuse_nvalues(sr
);
251 static void sr_configure_vp(int srid
)
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
,
265 OMAP3_PRM_VP1_VSTEPMIN_OFFSET
);
267 prm_write_mod_reg(PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX
|
268 PRM_VP1_VSTEPMAX_VSTEPMAX
,
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
,
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
,
295 OMAP3_PRM_VP2_VSTEPMIN_OFFSET
);
297 prm_write_mod_reg(PRM_VP2_VSTEPMAX_SMPSWAITTIMEMAX
|
298 PRM_VP2_VSTEPMAX_VSTEPMAX
,
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
,
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
)
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
) |
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
) |
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
));
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
) {
374 nvalue_reciprocal
= sr
->opp5_nvalue
;
377 nvalue_reciprocal
= sr
->opp4_nvalue
;
380 nvalue_reciprocal
= sr
->opp3_nvalue
;
383 nvalue_reciprocal
= sr
->opp2_nvalue
;
386 nvalue_reciprocal
= sr
->opp1_nvalue
;
389 nvalue_reciprocal
= sr
->opp3_nvalue
;
393 switch (target_opp_no
) {
395 nvalue_reciprocal
= sr
->opp3_nvalue
;
398 nvalue_reciprocal
= sr
->opp2_nvalue
;
401 nvalue_reciprocal
= sr
->opp1_nvalue
;
404 nvalue_reciprocal
= sr
->opp3_nvalue
;
409 if (nvalue_reciprocal
== 0) {
410 printk(KERN_NOTICE
"OPP%d doesn't support SmartReflex\n",
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
) {
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
) {
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
);
436 static void sr_disable(struct omap_sr
*sr
)
440 /* SRCONFIG - disable SR */
441 sr_modify_reg(sr
, SRCONFIG
, SRCONFIG_SRENABLE
, ~SRCONFIG_SRENABLE
);
443 if (sr
->srid
== SR1
) {
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
) {
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
;
461 else if (srid
== SR2
)
464 if (sr
->is_sr_reset
== 1) {
469 if (sr
->is_autocomp_active
== 1)
470 printk(KERN_WARNING
"SR%d: VDD autocomp is already active\n",
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)
481 EXPORT_SYMBOL(sr_start_vddautocomap
);
483 int sr_stop_vddautocomap(int srid
)
485 struct omap_sr
*sr
= NULL
;
489 else if (srid
== SR2
)
492 if (sr
->is_autocomp_active
== 1) {
495 sr
->is_autocomp_active
= 0;
498 printk(KERN_WARNING
"SR%d: VDD autocomp is not active\n",
504 EXPORT_SYMBOL(sr_stop_vddautocomap
);
506 void enable_smartreflex(int srid
)
508 u32 target_opp_no
= 0;
509 struct omap_sr
*sr
= NULL
;
513 else if (srid
== SR2
)
516 if (sr
->is_autocomp_active
== 1) {
517 if (sr
->is_sr_reset
== 1) {
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
);
528 if (!sr_enable(sr
, target_opp_no
))
534 void disable_smartreflex(int srid
)
536 struct omap_sr
*sr
= NULL
;
540 else if (srid
== SR2
)
543 if (sr
->is_autocomp_active
== 1) {
544 if (sr
->is_sr_reset
== 0) {
547 /* SRCONFIG - disable SR */
548 sr_modify_reg(sr
, SRCONFIG
, SRCONFIG_SRENABLE
,
553 if (sr
->srid
== SR1
) {
555 prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE
,
557 OMAP3_PRM_VP1_CONFIG_OFFSET
);
558 } else if (sr
->srid
== SR2
) {
560 prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE
,
562 OMAP3_PRM_VP2_CONFIG_OFFSET
);
568 /* Voltage Scaling using SR VCBYPASS */
569 int sr_voltagescale_vcbypass(u32 target_opp
, u8 vsel
)
572 u32 vdd
, target_opp_no
;
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
),
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
),
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) {
611 if (retries_cnt
> 10) {
612 printk(KERN_INFO
"Loop count exceeded in check SR I2C"
621 vc_bypass_value
= prm_read_mod_reg(OMAP3430_GR_MOD
,
622 OMAP3_PRM_VC_BYPASS_VAL_OFFSET
);
625 udelay(T2_SMPS_UPDATE_DELAY
);
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
);
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");
656 current_vdd1opp_no
= get_opp_no(current_vdd1_opp
);
659 sr_stop_vddautocomap(SR1
);
661 sr_start_vddautocomap(SR1
, current_vdd1opp_no
);
666 static struct kobj_attribute sr_vdd1_autocomp
= {
668 .name
= __stringify(sr_vdd1_autocomp
),
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");
694 current_vdd2opp_no
= get_opp_no(current_vdd2_opp
);
697 sr_stop_vddautocomap(SR2
);
699 sr_start_vddautocomap(SR2
, current_vdd2opp_no
);
704 static struct kobj_attribute sr_vdd2_autocomp
= {
706 .name
= __stringify(sr_vdd2_autocomp
),
709 .show
= omap_sr_vdd2_autocomp_show
,
710 .store
= omap_sr_vdd2_autocomp_store
,
715 static int __init
omap3_sr_init(void)
720 if (omap_rev() > OMAP3430_REV_ES1_0
) {
721 current_vdd1_opp
= PRCM_VDD1_OPP3
;
722 current_vdd2_opp
= PRCM_VDD2_OPP3
;
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
,
745 RdReg
|= DCDC_GLOBAL_CFG_ENABLE_SRFLX
;
746 ret
|= twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER
, RdReg
,
749 printk(KERN_INFO
"SmartReflex driver initialized\n");
751 ret
= sysfs_create_file(power_kobj
, &sr_vdd1_autocomp
.attr
);
753 printk(KERN_ERR
"sysfs_create_file failed: %d\n", ret
);
755 ret
= sysfs_create_file(power_kobj
, &sr_vdd2_autocomp
.attr
);
757 printk(KERN_ERR
"sysfs_create_file failed: %d\n", ret
);
762 late_initcall(omap3_sr_init
);