aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/vc.c108
-rw-r--r--arch/arm/mach-omap2/vc.h1
2 files changed, 91 insertions, 18 deletions
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
index 4c3c41fd2637..73b4bcd67023 100644
--- a/arch/arm/mach-omap2/vc.c
+++ b/arch/arm/mach-omap2/vc.c
@@ -204,29 +204,109 @@ int omap_vc_bypass_scale(struct voltagedomain *voltdm,
204 return 0; 204 return 0;
205} 205}
206 206
207static void __init omap3_vfsm_init(struct voltagedomain *voltdm) 207/**
208 * omap3_set_i2c_timings - sets i2c sleep timings for a channel
209 * @voltdm: channel to configure
210 * @off_mode: select whether retention or off mode values used
211 *
212 * Calculates and sets up voltage controller to use I2C based
213 * voltage scaling for sleep modes. This can be used for either off mode
214 * or retention. Off mode has additionally an option to use sys_off_mode
215 * pad, which uses a global signal to program the whole power IC to
216 * off-mode.
217 */
218static void omap3_set_i2c_timings(struct voltagedomain *voltdm, bool off_mode)
208{ 219{
220 unsigned long voltsetup1;
221 u32 tgt_volt;
222
223 if (off_mode)
224 tgt_volt = voltdm->vc_param->off;
225 else
226 tgt_volt = voltdm->vc_param->ret;
227
228 voltsetup1 = (voltdm->vc_param->on - tgt_volt) /
229 voltdm->pmic->slew_rate;
230
231 voltsetup1 = voltsetup1 * voltdm->sys_clk.rate / 8 / 1000000 + 1;
232
233 voltdm->rmw(voltdm->vfsm->voltsetup_mask,
234 voltsetup1 << __ffs(voltdm->vfsm->voltsetup_mask),
235 voltdm->vfsm->voltsetup_reg);
236
209 /* 237 /*
210 * Voltage Manager FSM parameters init 238 * pmic is not controlling the voltage scaling during retention,
211 * XXX This data should be passed in from the board file 239 * thus set voltsetup2 to 0
212 */ 240 */
213 voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET); 241 voltdm->write(0, OMAP3_PRM_VOLTSETUP2_OFFSET);
214 voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET);
215 voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET);
216} 242}
217 243
218static void __init omap3_vc_init_channel(struct voltagedomain *voltdm) 244/**
245 * omap3_set_off_timings - sets off-mode timings for a channel
246 * @voltdm: channel to configure
247 *
248 * Calculates and sets up off-mode timings for a channel. Off-mode
249 * can use either I2C based voltage scaling, or alternatively
250 * sys_off_mode pad can be used to send a global command to power IC.
251 * This function first checks which mode is being used, and calls
252 * omap3_set_i2c_timings() if the system is using I2C control mode.
253 * sys_off_mode has the additional benefit that voltages can be
254 * scaled to zero volt level with TWL4030 / TWL5030, I2C can only
255 * scale to 600mV.
256 */
257static void omap3_set_off_timings(struct voltagedomain *voltdm)
219{ 258{
220 static bool is_initialized; 259 unsigned long clksetup;
260 unsigned long voltsetup2;
261 unsigned long voltsetup2_old;
262 u32 val;
221 263
222 if (is_initialized) 264 /* check if sys_off_mode is used to control off-mode voltages */
265 val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
266 if (!(val & OMAP3430_SEL_OFF_MASK)) {
267 /* No, omap is controlling them over I2C */
268 omap3_set_i2c_timings(voltdm, true);
223 return; 269 return;
270 }
224 271
225 omap3_vfsm_init(voltdm); 272 clksetup = voltdm->read(OMAP3_PRM_CLKSETUP_OFFSET);
226 273
227 is_initialized = true; 274 /* voltsetup 2 in us */
275 voltsetup2 = voltdm->vc_param->on / voltdm->pmic->slew_rate;
276
277 /* convert to 32k clk cycles */
278 voltsetup2 = DIV_ROUND_UP(voltsetup2 * 32768, 1000000);
279
280 voltsetup2_old = voltdm->read(OMAP3_PRM_VOLTSETUP2_OFFSET);
281
282 /*
283 * Update voltsetup2 if higher than current value (needed because
284 * we have multiple channels with different ramp times), also
285 * update voltoffset always to value recommended by TRM
286 */
287 if (voltsetup2 > voltsetup2_old) {
288 voltdm->write(voltsetup2, OMAP3_PRM_VOLTSETUP2_OFFSET);
289 voltdm->write(clksetup - voltsetup2,
290 OMAP3_PRM_VOLTOFFSET_OFFSET);
291 } else
292 voltdm->write(clksetup - voltsetup2_old,
293 OMAP3_PRM_VOLTOFFSET_OFFSET);
294
295 /*
296 * omap is not controlling voltage scaling during off-mode,
297 * thus set voltsetup1 to 0
298 */
299 voltdm->rmw(voltdm->vfsm->voltsetup_mask, 0,
300 voltdm->vfsm->voltsetup_reg);
301
302 /* voltoffset must be clksetup minus voltsetup2 according to TRM */
303 voltdm->write(clksetup - voltsetup2, OMAP3_PRM_VOLTOFFSET_OFFSET);
228} 304}
229 305
306static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
307{
308 omap3_set_off_timings(voltdm);
309}
230 310
231/* OMAP4 specific voltage init functions */ 311/* OMAP4 specific voltage init functions */
232static void __init omap4_vc_init_channel(struct voltagedomain *voltdm) 312static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
@@ -337,7 +417,6 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
337 vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr; 417 vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr;
338 vc->volt_reg_addr = voltdm->pmic->volt_reg_addr; 418 vc->volt_reg_addr = voltdm->pmic->volt_reg_addr;
339 vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr; 419 vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr;
340 vc->setup_time = voltdm->pmic->volt_setup_time;
341 420
342 /* Configure the i2c slave address for this VC */ 421 /* Configure the i2c slave address for this VC */
343 voltdm->rmw(vc->smps_sa_mask, 422 voltdm->rmw(vc->smps_sa_mask,
@@ -376,11 +455,6 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
376 /* Channel configuration */ 455 /* Channel configuration */
377 omap_vc_config_channel(voltdm); 456 omap_vc_config_channel(voltdm);
378 457
379 /* Configure the setup times */
380 voltdm->rmw(voltdm->vfsm->voltsetup_mask,
381 vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask),
382 voltdm->vfsm->voltsetup_reg);
383
384 omap_vc_i2c_init(voltdm); 458 omap_vc_i2c_init(voltdm);
385 459
386 if (cpu_is_omap34xx()) 460 if (cpu_is_omap34xx())
diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h
index 7618b69811d0..91c8d75bf2ea 100644
--- a/arch/arm/mach-omap2/vc.h
+++ b/arch/arm/mach-omap2/vc.h
@@ -86,7 +86,6 @@ struct omap_vc_channel {
86 u16 i2c_slave_addr; 86 u16 i2c_slave_addr;
87 u16 volt_reg_addr; 87 u16 volt_reg_addr;
88 u16 cmd_reg_addr; 88 u16 cmd_reg_addr;
89 u16 setup_time;
90 u8 cfg_channel; 89 u8 cfg_channel;
91 bool i2c_high_speed; 90 bool i2c_high_speed;
92 91