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 #define SR_REGADDR(offs) (__force void __iomem *)(sr->srbase_addr + offset)
65 static inline void sr_write_reg(struct omap_sr *sr, int offset, u32 value)
67 __raw_writel(value, SR_REGADDR(offset));
70 static inline void sr_modify_reg(struct omap_sr *sr, int offset, u32 mask,
75 reg_val = __raw_readl(SR_REGADDR(offset));
79 __raw_writel(reg_val, SR_REGADDR(offset));
82 static inline u32 sr_read_reg(struct omap_sr *sr, int offset)
84 return __raw_readl(SR_REGADDR(offset));
87 /* Custom clock handling functions */
88 static int sr_clk_enable(struct clk *clk)
90 struct sr_custom_clk *sr_clk = container_of(clk, struct sr_custom_clk,
93 if (clk_enable(sr_clk->fck) != 0) {
94 printk(KERN_ERR "Could not enable %s\n", sr_clk->fck->name);
98 /* set fclk- active , iclk- idle */
99 sr_modify_reg(sr_clk->sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
100 SR_CLKACTIVITY_IOFF_FON);
108 static void sr_clk_disable(struct clk *clk)
110 struct sr_custom_clk *sr_clk = container_of(clk, struct sr_custom_clk,
113 /* set fclk, iclk- idle */
114 sr_modify_reg(sr_clk->sr, ERRCONFIG, SR_CLKACTIVITY_MASK,
115 SR_CLKACTIVITY_IOFF_FOFF);
117 clk_disable(sr_clk->fck);
118 sr_clk->sr->is_sr_reset = 1;
121 static struct omap_sr sr1 = {
124 .is_autocomp_active = 0,
126 .srbase_addr = OMAP2_IO_ADDRESS(OMAP34XX_SR1_BASE),
129 static struct omap_sr sr2 = {
132 .is_autocomp_active = 0,
134 .srbase_addr = OMAP2_IO_ADDRESS(OMAP34XX_SR2_BASE),
137 static struct sr_custom_clk sr1_custom_clk = {
139 .name = "sr1_custom_clk",
140 .enable = sr_clk_enable,
141 .disable = sr_clk_disable,
146 static struct sr_custom_clk sr2_custom_clk = {
148 .name = "sr2_custom_clk",
149 .enable = sr_clk_enable,
150 .disable = sr_clk_disable,
155 static void cal_reciprocal(u32 sensor, u32 *sengain, u32 *rnsen)
159 for (gn = 0; gn < GAIN_MAXLIMIT; gn++) {
162 if (rn < R_MAXLIMIT) {
169 static u32 cal_test_nvalue(u32 sennval, u32 senpval)
171 u32 senpgain, senngain;
174 /* Calculating the gain and reciprocal of the SenN and SenP values */
175 cal_reciprocal(senpval, &senpgain, &rnsenp);
176 cal_reciprocal(sennval, &senngain, &rnsenn);
178 return ((senpgain << NVALUERECIPROCAL_SENPGAIN_SHIFT) |
179 (senngain << NVALUERECIPROCAL_SENNGAIN_SHIFT) |
180 (rnsenp << NVALUERECIPROCAL_RNSENP_SHIFT) |
181 (rnsenn << NVALUERECIPROCAL_RNSENN_SHIFT));
184 static void sr_clk_init(struct sr_custom_clk *sr_clk)
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");
195 clk_register(&sr_clk->clk);
198 static void sr_set_clk_length(struct omap_sr *sr)
200 struct clk *osc_sys_ck;
203 osc_sys_ck = clk_get(NULL, "osc_sys_ck");
204 sys_clk = clk_get_rate(osc_sys_ck);
209 sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
212 sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK;
215 sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK;
218 sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK;
221 sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
224 printk(KERN_ERR "Invalid sysclk value: %d\n", sys_clk);
229 static void sr_set_efuse_nvalues(struct omap_sr *sr)
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;
236 sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
237 OMAP343X_SR1_SENPENABLE_MASK) >>
238 OMAP343X_SR1_SENPENABLE_SHIFT;
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;
255 sr->senp_mod = (omap_ctrl_readl(OMAP343X_CONTROL_FUSE_SR) &
256 OMAP343X_SR2_SENPENABLE_MASK) >>
257 OMAP343X_SR2_SENPENABLE_SHIFT;
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);
268 /* Hard coded nvalues for testing purposes, may cause device to hang! */
269 static void sr_set_testing_nvalues(struct omap_sr *sr)
271 if (sr->srid == SR1) {
272 sr->senp_mod = 0x03; /* SenN-M5 enabled */
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) {
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);
292 static void sr_set_nvalues(struct omap_sr *sr)
294 if (SR_TESTING_NVALUES)
295 sr_set_testing_nvalues(sr);
297 sr_set_efuse_nvalues(sr);
300 static void sr_configure_vp(int srid)
305 vpconfig = PRM_VP1_CONFIG_ERROROFFSET | PRM_VP1_CONFIG_ERRORGAIN
306 | PRM_VP1_CONFIG_INITVOLTAGE
307 | PRM_VP1_CONFIG_TIMEOUTEN;
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,
314 OMAP3_PRM_VP1_VSTEPMIN_OFFSET);
316 prm_write_mod_reg(PRM_VP1_VSTEPMAX_SMPSWAITTIMEMAX |
317 PRM_VP1_VSTEPMAX_VSTEPMAX,
319 OMAP3_PRM_VP1_VSTEPMAX_OFFSET);
321 prm_write_mod_reg(PRM_VP1_VLIMITTO_VDDMAX |
322 PRM_VP1_VLIMITTO_VDDMIN |
323 PRM_VP1_VLIMITTO_TIMEOUT,
325 OMAP3_PRM_VP1_VLIMITTO_OFFSET);
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);
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;
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,
344 OMAP3_PRM_VP2_VSTEPMIN_OFFSET);
346 prm_write_mod_reg(PRM_VP2_VSTEPMAX_SMPSWAITTIMEMAX |
347 PRM_VP2_VSTEPMAX_VSTEPMAX,
349 OMAP3_PRM_VP2_VSTEPMAX_OFFSET);
351 prm_write_mod_reg(PRM_VP2_VLIMITTO_VDDMAX |
352 PRM_VP2_VLIMITTO_VDDMIN |
353 PRM_VP2_VLIMITTO_TIMEOUT,
355 OMAP3_PRM_VP2_VLIMITTO_OFFSET);
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);
367 static void sr_configure(struct omap_sr *sr)
370 u32 senp_en , senn_en;
372 if (sr->clk_length == 0)
373 sr_set_clk_length(sr);
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) |
386 sr_write_reg(sr, SRCONFIG, sr_config);
387 sr_write_reg(sr, AVGWEIGHT, SR1_AVGWEIGHT_SENPAVGWEIGHT |
388 SR1_AVGWEIGHT_SENNAVGWEIGHT);
390 sr_modify_reg(sr, ERRCONFIG, (SR_ERRWEIGHT_MASK |
391 SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
392 (SR1_ERRWEIGHT | SR1_ERRMAXLIMIT | SR1_ERRMINLIMIT));
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) |
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));
414 static int sr_enable(struct omap_sr *sr, u32 target_opp_no)
416 u32 nvalue_reciprocal;
418 sr->req_opp_no = target_opp_no;
420 if (sr->srid == SR1) {
421 switch (target_opp_no) {
423 nvalue_reciprocal = sr->opp5_nvalue;
426 nvalue_reciprocal = sr->opp4_nvalue;
429 nvalue_reciprocal = sr->opp3_nvalue;
432 nvalue_reciprocal = sr->opp2_nvalue;
435 nvalue_reciprocal = sr->opp1_nvalue;
438 nvalue_reciprocal = sr->opp3_nvalue;
442 switch (target_opp_no) {
444 nvalue_reciprocal = sr->opp3_nvalue;
447 nvalue_reciprocal = sr->opp2_nvalue;
450 nvalue_reciprocal = sr->opp1_nvalue;
453 nvalue_reciprocal = sr->opp3_nvalue;
458 if (nvalue_reciprocal == 0) {
459 printk(KERN_NOTICE "OPP%d doesn't support SmartReflex\n",
464 sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
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) {
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) {
476 prm_set_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, OMAP3430_GR_MOD,
477 OMAP3_PRM_VP2_CONFIG_OFFSET);
480 /* SRCONFIG - enable SR */
481 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
485 static void sr_disable(struct omap_sr *sr)
489 /* SRCONFIG - disable SR */
490 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, ~SRCONFIG_SRENABLE);
492 if (sr->srid == SR1) {
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) {
498 prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, OMAP3430_GR_MOD,
499 OMAP3_PRM_VP2_CONFIG_OFFSET);
504 void sr_start_vddautocomap(int srid, u32 target_opp_no)
506 struct omap_sr *sr = NULL;
510 else if (srid == SR2)
513 if (sr->is_sr_reset == 1) {
518 if (sr->is_autocomp_active == 1)
519 printk(KERN_WARNING "SR%d: VDD autocomp is already active\n",
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);
530 EXPORT_SYMBOL(sr_start_vddautocomap);
532 int sr_stop_vddautocomap(int srid)
534 struct omap_sr *sr = NULL;
538 else if (srid == SR2)
541 if (sr->is_autocomp_active == 1) {
543 clk_disable(sr->clk);
544 sr->is_autocomp_active = 0;
547 printk(KERN_WARNING "SR%d: VDD autocomp is not active\n",
553 EXPORT_SYMBOL(sr_stop_vddautocomap);
555 void enable_smartreflex(int srid)
557 u32 target_opp_no = 0;
558 struct omap_sr *sr = NULL;
562 else if (srid == SR2)
565 if (sr->is_autocomp_active == 1) {
566 if (sr->is_sr_reset == 1) {
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);
577 if (!sr_enable(sr, target_opp_no))
578 clk_disable(sr->clk);
583 void disable_smartreflex(int srid)
585 struct omap_sr *sr = NULL;
589 else if (srid == SR2)
592 if (sr->is_autocomp_active == 1) {
593 if (sr->is_sr_reset == 0) {
596 /* SRCONFIG - disable SR */
597 sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE,
601 clk_disable(sr->clk);
602 if (sr->srid == SR1) {
604 prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE,
606 OMAP3_PRM_VP1_CONFIG_OFFSET);
607 } else if (sr->srid == SR2) {
609 prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE,
611 OMAP3_PRM_VP2_CONFIG_OFFSET);
617 /* Voltage Scaling using SR VCBYPASS */
618 int sr_voltagescale_vcbypass(u32 target_opp, u8 vsel)
621 u32 vdd, target_opp_no;
624 u32 loop_cnt = 0, retries_cnt = 0;
626 vdd = get_vdd(target_opp);
627 target_opp_no = get_opp_no(target_opp);
629 if (vdd == PRCM_VDD1) {
630 sr_status = sr_stop_vddautocomap(SR1);
632 prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
633 (vsel << OMAP3430_VC_CMD_ON_SHIFT),
635 OMAP3_PRM_VC_CMD_VAL_0_OFFSET);
636 reg_addr = R_VDD1_SR_CONTROL;
638 } else if (vdd == PRCM_VDD2) {
639 sr_status = sr_stop_vddautocomap(SR2);
641 prm_rmw_mod_reg_bits(OMAP3430_VC_CMD_ON_MASK,
642 (vsel << OMAP3430_VC_CMD_ON_SHIFT),
644 OMAP3_PRM_VC_CMD_VAL_1_OFFSET);
645 reg_addr = R_VDD2_SR_CONTROL;
648 vc_bypass_value = (vsel << OMAP3430_DATA_SHIFT) |
649 (reg_addr << OMAP3430_REGADDR_SHIFT) |
650 (R_SRI2C_SLAVE_ADDR << OMAP3430_SLAVEADDR_SHIFT);
652 prm_write_mod_reg(vc_bypass_value, OMAP3430_GR_MOD,
653 OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
655 vc_bypass_value = prm_set_mod_reg_bits(OMAP3430_VALID, OMAP3430_GR_MOD,
656 OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
658 while ((vc_bypass_value & OMAP3430_VALID) != 0x0) {
660 if (retries_cnt > 10) {
661 printk(KERN_INFO "Loop count exceeded in check SR I2C"
670 vc_bypass_value = prm_read_mod_reg(OMAP3430_GR_MOD,
671 OMAP3_PRM_VC_BYPASS_VAL_OFFSET);
674 udelay(T2_SMPS_UPDATE_DELAY);
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);
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)
690 return sprintf(buf, "%d\n", sr1.is_autocomp_active);
693 static ssize_t omap_sr_vdd1_autocomp_store(struct kobject *kobj,
694 struct kobj_attribute *attr,
695 const char *buf, size_t n)
697 u32 current_vdd1opp_no;
698 unsigned short value;
700 if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
701 printk(KERN_ERR "sr_vdd1_autocomp: Invalid value\n");
705 current_vdd1opp_no = get_opp_no(current_vdd1_opp);
708 sr_stop_vddautocomap(SR1);
710 sr_start_vddautocomap(SR1, current_vdd1opp_no);
715 static struct kobj_attribute sr_vdd1_autocomp = {
717 .name = __stringify(sr_vdd1_autocomp),
720 .show = omap_sr_vdd1_autocomp_show,
721 .store = omap_sr_vdd1_autocomp_store,
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)
728 return sprintf(buf, "%d\n", sr2.is_autocomp_active);
731 static ssize_t omap_sr_vdd2_autocomp_store(struct kobject *kobj,
732 struct kobj_attribute *attr,
733 const char *buf, size_t n)
735 u32 current_vdd2opp_no;
736 unsigned short value;
738 if (sscanf(buf, "%hu", &value) != 1 || (value > 1)) {
739 printk(KERN_ERR "sr_vdd2_autocomp: Invalid value\n");
743 current_vdd2opp_no = get_opp_no(current_vdd2_opp);
746 sr_stop_vddautocomap(SR2);
748 sr_start_vddautocomap(SR2, current_vdd2opp_no);
753 static struct kobj_attribute sr_vdd2_autocomp = {
755 .name = __stringify(sr_vdd2_autocomp),
758 .show = omap_sr_vdd2_autocomp_show,
759 .store = omap_sr_vdd2_autocomp_store,
764 static int __init omap3_sr_init(void)
769 if (is_sil_rev_greater_than(OMAP3430_REV_ES1_0)) {
770 current_vdd1_opp = PRCM_VDD1_OPP3;
771 current_vdd2_opp = PRCM_VDD2_OPP3;
773 current_vdd1_opp = PRCM_VDD1_OPP1;
774 current_vdd2_opp = PRCM_VDD1_OPP1;
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");
782 sr_set_clk_length(&sr1);
783 sr_set_clk_length(&sr2);
785 /* Call the VPConfig, VCConfig, set N Values. */
786 sr_set_nvalues(&sr1);
787 sr_configure_vp(SR1);
789 sr_set_nvalues(&sr2);
790 sr_configure_vp(SR2);
792 /* Enable SR on T2 */
793 ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &RdReg,
796 RdReg |= DCDC_GLOBAL_CFG_ENABLE_SRFLX;
797 ret |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, RdReg,
800 printk(KERN_INFO "SmartReflex driver initialized\n");
802 ret = sysfs_create_file(power_kobj, &sr_vdd1_autocomp.attr);
804 printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
806 ret = sysfs_create_file(power_kobj, &sr_vdd2_autocomp.attr);
808 printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
813 late_initcall(omap3_sr_init);