77e9a75b6225147d059639339243275cbe48efb7
[openembedded.git] /
1 From 8d78b8198d220d5ebade7587caf664a0ef8c8fe7 Mon Sep 17 00:00:00 2001
2 From: Ranjith Lohithakshan <ranjithl@ti.com>
3 Date: Mon, 12 Jul 2010 16:25:14 +0530
4 Subject: [PATCH 4/9] OMAP3630: PM: implement Foward Body-Bias for OPP1G
5
6 Introduces voltscale_adaptive_body_bias function to voltage.c.
7 voltscale_adaptive_body_bias is called by omap_voltage_scale after a
8 voltage transition has occured.  Currently voltscale_adaptive_body_bias
9 only implements Forward Body-Bias (FBB) for OMAP3630 when MPU runs at
10 1GHz or higher.  In the future Reverse Body-Bias might be included.
11
12 FBB is an Adaptive Body-Bias technique to boost performance for weak
13 process devices at high OPPs. This results in voltage boost on the VDD1
14 PMOS back gates when running at maximum OPP.  Current recommendations
15 are to enable FBB on all 3630 regardless of silicon characteristics and
16 EFUSE values.
17
18 ABB applies to all OMAP family of devices based on 45nm process,
19 which includes OMAP3630, OMAP4, TI816x and TI814x.
20
21 Signed-off-by: Ranjith Lohithakshan <ranjithl@ti.com>
22 ---
23  arch/arm/mach-omap2/prm-regbits-34xx.h |   18 +++++
24  arch/arm/mach-omap2/prm.h              |    4 +
25  arch/arm/mach-omap2/smartreflex.c      |  130 ++++++++++++++++++++++++++++++++
26  3 files changed, 152 insertions(+), 0 deletions(-)
27
28 diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
29 index 0066693..8dee7e0 100644
30 --- a/arch/arm/mach-omap2/prm-regbits-34xx.h
31 +++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
32 @@ -212,6 +212,8 @@
33  /* PRM_SYSCONFIG specific bits */
34  
35  /* PRM_IRQSTATUS_MPU specific bits */
36 +#define OMAP3630_ABB_LDO_TRANXDONE_ST_SHIFT                    26
37 +#define OMAP3630_ABB_LDO_TRANXDONE_ST                  (1 << 26)
38  #define OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT           25
39  #define OMAP3430ES2_SND_PERIPH_DPLL_ST                 (1 << 25)
40  #define OMAP3430_VC_TIMEOUTERR_ST                      (1 << 24)
41 @@ -581,6 +583,22 @@
42  
43  /* PRM_VP2_STATUS specific bits */
44  
45 +/* PRM_LDO_ABB_SETUP specific bits */
46 +#define OMAP3630_SR2_IN_TRANSITION                     (1 << 6)
47 +#define OMAP3630_SR2_STATUS_SHIFT                      3
48 +#define OMAP3630_SR2_STATUS_MASK                       (3 << 3)
49 +#define OMAP3630_OPP_CHANGE                            (1 << 2)
50 +#define OMAP3630_OPP_SEL_SHIFT                         0
51 +#define OMAP3630_OPP_SEL_MASK                          (3 << 0)
52 +
53 +/* PRM_LDO_ABB_CTRL specific bits */
54 +#define OMAP3630_SR2_WTCNT_VALUE_SHIFT                 8
55 +#define OMAP3630_SR2_WTCNT_VALUE_MASK                  (0xff << 8)
56 +#define OMAP3630_SLEEP_RBB_SEL                         (1 << 3)
57 +#define OMAP3630_ACTIVE_FBB_SEL                                (1 << 2)
58 +#define OMAP3630_ACTIVE_RBB_SEL                                (1 << 1)
59 +#define OMAP3630_SR2EN                                 (1 << 0)
60 +
61  /* RM_RSTST_NEON specific bits */
62  
63  /* PM_WKDEP_NEON specific bits */
64 diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
65 index ea050ce..b7f95d7 100644
66 --- a/arch/arm/mach-omap2/prm.h
67 +++ b/arch/arm/mach-omap2/prm.h
68 @@ -158,6 +158,10 @@
69  #define OMAP3430_PRM_VP2_VOLTAGE       OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0)
70  #define OMAP3_PRM_VP2_STATUS_OFFSET    0x00e4
71  #define OMAP3430_PRM_VP2_STATUS                OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
72 +#define OMAP3_PRM_LDO_ABB_SETUP_OFFSET  0X00f0
73 +#define OMAP3630_PRM_LDO_ABB_SETUP  OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0X00f0)
74 +#define OMAP3_PRM_LDO_ABB_CTRL_OFFSET   0X00f4
75 +#define OMAP3630_PRM_LDO_ABB_CTRL   OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0X00f4)
76  
77  #define OMAP3_PRM_CLKSEL_OFFSET        0x0040
78  #define OMAP3430_PRM_CLKSEL            OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
79 diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
80 index fdd9540..d7c8a04 100644
81 --- a/arch/arm/mach-omap2/smartreflex.c
82 +++ b/arch/arm/mach-omap2/smartreflex.c
83 @@ -42,6 +42,11 @@
84  #define SWCALC_OPP6_DELTA_NNT  379
85  #define SWCALC_OPP6_DELTA_PNT  227
86  
87 +#define ABB_MAX_SETTLING_TIME  30
88 +
89 +#define ABB_FAST_OPP                   1
90 +#define ABB_NOMINAL_OPP                        2
91 +#define ABB_SLOW_OPP                   3
92  
93  /*
94   * VDD1 and VDD2 OPPs derived from the bootarg 'mpurate'
95 @@ -397,6 +402,126 @@ static void sr_set_nvalues(struct omap_sr *sr)
96                 sr_set_efuse_nvalues(sr);
97  }
98  
99 +/**
100 + * sr_voltagescale_adaptive_body_bias - controls ABB ldo during voltage scaling
101 + * @target_volt: target voltage determines if ABB ldo is active or bypassed
102 + *
103 + * Adaptive Body-Bias is a technique in all OMAP silicon that uses the 45nm
104 + * process.  ABB can boost voltage in high OPPs for silicon with weak
105 + * characteristics (forward Body-Bias) as well as lower voltage in low OPPs
106 + * for silicon with strong characteristics (Reverse Body-Bias).
107 + *
108 + * Only Foward Body-Bias for operating at high OPPs is implemented below, per
109 + * recommendations from silicon team.
110 + * Reverse Body-Bias for saving power in active cases and sleep cases is not
111 + * yet implemented.
112 + */
113 +static int sr_voltagescale_adaptive_body_bias(u32 target_opp_no)
114 +{
115 +       u32 sr2en_enabled;
116 +       int timeout;
117 +       int sr2_wtcnt_value;
118 +       struct clk *sys_ck;
119 +
120 +       sys_ck = clk_get(NULL, "sys_ck");
121 +       if (IS_ERR(sys_ck)) {
122 +               pr_warning("%s: Could not get the sys clk to calculate"
123 +            "SR2_WTCNT_VALUE \n", __func__);
124 +        return -ENOENT;
125 +    }
126 +
127 +       /* calculate SR2_WTCNT_VALUE settling time */
128 +       sr2_wtcnt_value = (ABB_MAX_SETTLING_TIME *
129 +               (clk_get_rate(sys_ck) / 1000000) / 8);
130 +
131 +       clk_put(sys_ck);
132 +
133 +       /* has SR2EN been enabled previously? */
134 +       sr2en_enabled = (prm_read_mod_reg(OMAP3430_GR_MOD,
135 +                       OMAP3_PRM_LDO_ABB_CTRL_OFFSET) &
136 +                       OMAP3630_SR2EN);
137 +
138 +       /* select fast, nominal or slow OPP for ABB ldo */
139 +       if (target_opp_no >= VDD1_OPP4) {
140 +               /* program for fast opp - enable FBB */
141 +               prm_rmw_mod_reg_bits(OMAP3630_OPP_SEL_MASK,
142 +                               (ABB_FAST_OPP << OMAP3630_OPP_SEL_SHIFT),
143 +                               OMAP3430_GR_MOD,
144 +                               OMAP3_PRM_LDO_ABB_SETUP_OFFSET);
145 +
146 +               /* enable the ABB ldo if not done already */
147 +               if (!sr2en_enabled)
148 +                       prm_set_mod_reg_bits(OMAP3630_SR2EN,
149 +                                       OMAP3430_GR_MOD,
150 +                                       OMAP3_PRM_LDO_ABB_CTRL_OFFSET);
151 +       } else if (sr2en_enabled) {
152 +               /* program for nominal opp - bypass ABB ldo */
153 +               prm_rmw_mod_reg_bits(OMAP3630_OPP_SEL_MASK,
154 +                               (ABB_NOMINAL_OPP << OMAP3630_OPP_SEL_SHIFT),
155 +                               OMAP3430_GR_MOD,
156 +                               OMAP3_PRM_LDO_ABB_SETUP_OFFSET);
157 +       } else {
158 +               /* nothing to do here yet... might enable RBB here someday */
159 +               return 0;
160 +       }
161 +
162 +       /* set ACTIVE_FBB_SEL for all 45nm silicon */
163 +       prm_set_mod_reg_bits(OMAP3630_ACTIVE_FBB_SEL,
164 +                       OMAP3430_GR_MOD,
165 +                       OMAP3_PRM_LDO_ABB_CTRL_OFFSET);
166 +
167 +       /* program settling time of 30us for ABB ldo transition */
168 +       prm_rmw_mod_reg_bits(OMAP3630_SR2_WTCNT_VALUE_MASK,
169 +                       (sr2_wtcnt_value << OMAP3630_SR2_WTCNT_VALUE_SHIFT),
170 +                       OMAP3430_GR_MOD,
171 +                       OMAP3_PRM_LDO_ABB_CTRL_OFFSET);
172 +
173 +       /* clear ABB ldo interrupt status */
174 +       prm_write_mod_reg(OMAP3630_ABB_LDO_TRANXDONE_ST,
175 +                       OCP_MOD,
176 +                       OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
177 +
178 +       /* enable ABB LDO OPP change */
179 +       prm_set_mod_reg_bits(OMAP3630_OPP_CHANGE,
180 +                       OMAP3430_GR_MOD,
181 +                       OMAP3_PRM_LDO_ABB_SETUP_OFFSET);
182 +
183 +       timeout = 0;
184 +
185 +       /* wait until OPP change completes */
186 +       while ((timeout < ABB_MAX_SETTLING_TIME ) &&
187 +                       (!(prm_read_mod_reg(OCP_MOD,
188 +                                               OMAP2_PRCM_IRQSTATUS_MPU_OFFSET) &
189 +                                       OMAP3630_ABB_LDO_TRANXDONE_ST))) {
190 +               udelay(1);
191 +               timeout++;
192 +       }
193 +
194 +       if (timeout == ABB_MAX_SETTLING_TIME)
195 +               pr_debug("ABB: TRANXDONE timed out waiting for OPP change\n");
196 +
197 +       timeout = 0;
198 +
199 +       /* Clear all pending TRANXDONE interrupts/status */
200 +       while (timeout < ABB_MAX_SETTLING_TIME) {
201 +               prm_write_mod_reg(OMAP3630_ABB_LDO_TRANXDONE_ST,
202 +                               OCP_MOD,
203 +                               OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
204 +               if (!(prm_read_mod_reg(OCP_MOD,
205 +                                               OMAP2_PRCM_IRQSTATUS_MPU_OFFSET)
206 +                                       & OMAP3630_ABB_LDO_TRANXDONE_ST))
207 +                       break;
208 +
209 +               udelay(1);
210 +               timeout++;
211 +       }
212 +       if (timeout == ABB_MAX_SETTLING_TIME)
213 +               pr_debug("ABB: TRANXDONE timed out trying to clear status\n");
214 +
215 +       return 0;
216 +}
217 +
218 +
219  static void sr_configure_vp(int srid)
220  {
221         u32 vpconfig;
222 @@ -462,6 +587,8 @@ static void sr_configure_vp(int srid)
223                 prm_clear_mod_reg_bits(OMAP3430_FORCEUPDATE, OMAP3430_GR_MOD,
224                                        OMAP3_PRM_VP1_CONFIG_OFFSET);
225  
226 +               if(cpu_is_omap3630())
227 +                       sr_voltagescale_adaptive_body_bias(target_opp_no);
228         } else if (srid == SR2) {
229                 if (vdd2_opp == 0)
230                         target_opp_no = get_vdd2_opp();
231 @@ -1031,6 +1158,9 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp,
232         t2_smps_delay = ((t2_smps_steps * 125) / 40) + 2;
233         udelay(t2_smps_delay);
234  
235 +       if (cpu_is_omap3630() && (vdd == VDD1_OPP))
236 +               sr_voltagescale_adaptive_body_bias(target_opp_no);
237 +
238         if (sr_status) {
239                 if (vdd == VDD1_OPP)
240                         sr_start_vddautocomap(SR1, target_opp_no);
241 -- 
242 1.6.2.4
243