diff options
author | Tero Kristo <t-kristo@ti.com> | 2012-09-25 18:33:38 +0200 |
---|---|---|
committer | Kevin Hilman <khilman@ti.com> | 2012-11-06 00:11:32 +0100 |
commit | 9a1729cbaaf1a9d1fd27f80cd488ef182fe033a0 (patch) | |
tree | d5d91e6c8f3830da955ac9bf7e690f4ba4dce295 | |
parent | ARM: OMAP4: voltage: add support for VOLTSETUP_x_OFF register (diff) | |
download | linux-9a1729cbaaf1a9d1fd27f80cd488ef182fe033a0.tar.xz linux-9a1729cbaaf1a9d1fd27f80cd488ef182fe033a0.zip |
ARM: OMAP4: VC: calculate ramp times
OMAP4 VC code now uses voltage deltas + slew rates for calculating
actual ramp times for voltage changes. Both retention / sleep +
off mode voltage ramp times are setup at the same time during
initialization.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
-rw-r--r-- | arch/arm/mach-omap2/vc.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c index 73b4bcd67023..07e2090d7119 100644 --- a/arch/arm/mach-omap2/vc.c +++ b/arch/arm/mach-omap2/vc.c @@ -308,12 +308,106 @@ static void __init omap3_vc_init_channel(struct voltagedomain *voltdm) omap3_set_off_timings(voltdm); } +/** + * omap4_calc_volt_ramp - calculates voltage ramping delays on omap4 + * @voltdm: channel to calculate values for + * @voltage_diff: voltage difference in microvolts + * + * Calculates voltage ramp prescaler + counter values for a voltage + * difference on omap4. Returns a field value suitable for writing to + * VOLTSETUP register for a channel in following format: + * bits[8:9] prescaler ... bits[0:5] counter. See OMAP4 TRM for reference. + */ +static u32 omap4_calc_volt_ramp(struct voltagedomain *voltdm, u32 voltage_diff) +{ + u32 prescaler; + u32 cycles; + u32 time; + + time = voltage_diff / voltdm->pmic->slew_rate; + + cycles = voltdm->sys_clk.rate / 1000 * time / 1000; + + cycles /= 64; + prescaler = 0; + + /* shift to next prescaler until no overflow */ + + /* scale for div 256 = 64 * 4 */ + if (cycles > 63) { + cycles /= 4; + prescaler++; + } + + /* scale for div 512 = 256 * 2 */ + if (cycles > 63) { + cycles /= 2; + prescaler++; + } + + /* scale for div 2048 = 512 * 4 */ + if (cycles > 63) { + cycles /= 4; + prescaler++; + } + + /* check for overflow => invalid ramp time */ + if (cycles > 63) { + pr_warn("%s: invalid setuptime for vdd_%s\n", __func__, + voltdm->name); + return 0; + } + + cycles++; + + return (prescaler << OMAP4430_RAMP_UP_PRESCAL_SHIFT) | + (cycles << OMAP4430_RAMP_UP_COUNT_SHIFT); +} + +/** + * omap4_set_timings - set voltage ramp timings for a channel + * @voltdm: channel to configure + * @off_mode: whether off-mode values are used + * + * Calculates and sets the voltage ramp up / down values for a channel. + */ +static void omap4_set_timings(struct voltagedomain *voltdm, bool off_mode) +{ + u32 val; + u32 ramp; + int offset; + + if (off_mode) { + ramp = omap4_calc_volt_ramp(voltdm, + voltdm->vc_param->on - voltdm->vc_param->off); + offset = voltdm->vfsm->voltsetup_off_reg; + } else { + ramp = omap4_calc_volt_ramp(voltdm, + voltdm->vc_param->on - voltdm->vc_param->ret); + offset = voltdm->vfsm->voltsetup_reg; + } + + if (!ramp) + return; + + val = voltdm->read(offset); + + val |= ramp << OMAP4430_RAMP_DOWN_COUNT_SHIFT; + + val |= ramp << OMAP4430_RAMP_UP_COUNT_SHIFT; + + voltdm->write(val, offset); +} + /* OMAP4 specific voltage init functions */ static void __init omap4_vc_init_channel(struct voltagedomain *voltdm) { static bool is_initialized; u32 vc_val; + omap4_set_timings(voltdm, true); + omap4_set_timings(voltdm, false); + if (is_initialized) return; |