linux-omap.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tero Kristo <t-kristo@ti.com>
To: linux-omap@vger.kernel.org, khilman@ti.com
Cc: linux-arm-kernel@lists.infradead.org
Subject: [PATCHv6 04/14] ARM: OMAP3: VC: calculate ramp times
Date: Thu, 31 May 2012 16:55:40 +0300	[thread overview]
Message-ID: <1338472550-20743-5-git-send-email-t-kristo@ti.com> (raw)
In-Reply-To: <1338472550-20743-1-git-send-email-t-kristo@ti.com>

OMAP3 VC code now uses voltage deltas + slew rates for calculating actual
ramp times for voltage changes. Previously a static value was used.
Two calculation methods are provided: i2c_timings and off_timings.
I2C timings are used during retention or off mode transition which
is initiated over I2C, and OFF timings are used if PMIC signal
(nsleep) is used to control all the off mode voltages at the same time.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/vc.c |  108 ++++++++++++++++++++++++++++++++++++++-------
 arch/arm/mach-omap2/vc.h |    1 -
 2 files changed, 91 insertions(+), 18 deletions(-)

diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
index a1e0fd6..bba0d7c 100644
--- a/arch/arm/mach-omap2/vc.c
+++ b/arch/arm/mach-omap2/vc.c
@@ -206,29 +206,109 @@ int omap_vc_bypass_scale(struct voltagedomain *voltdm,
 	return 0;
 }
 
-static void __init omap3_vfsm_init(struct voltagedomain *voltdm)
+/**
+ * omap3_set_i2c_timings - sets i2c sleep timings for a channel
+ * @voltdm: channel to configure
+ * @off_mode: select whether retention or off mode values used
+ *
+ * Calculates and sets up voltage controller to use I2C based
+ * voltage scaling for sleep modes. This can be used for either off mode
+ * or retention. Off mode has additionally an option to use sys_off_mode
+ * pad, which uses a global signal to program the whole power IC to
+ * off-mode.
+ */
+static void omap3_set_i2c_timings(struct voltagedomain *voltdm, bool off_mode)
 {
+	unsigned long voltsetup1;
+	u32 tgt_volt;
+
+	if (off_mode)
+		tgt_volt = voltdm->vc_param->off;
+	else
+		tgt_volt = voltdm->vc_param->ret;
+
+	voltsetup1 = (voltdm->vc_param->on - tgt_volt) /
+			voltdm->pmic->slew_rate;
+
+	voltsetup1 = voltsetup1 * voltdm->sys_clk.rate / 8 / 1000000 + 1;
+
+	voltdm->rmw(voltdm->vfsm->voltsetup_mask,
+		voltsetup1 << __ffs(voltdm->vfsm->voltsetup_mask),
+		voltdm->vfsm->voltsetup_reg);
+
 	/*
-	 * Voltage Manager FSM parameters init
-	 * XXX This data should be passed in from the board file
+	 * pmic is not controlling the voltage scaling during retention,
+	 * thus set voltsetup2 to 0
 	 */
-	voltdm->write(OMAP3_CLKSETUP, OMAP3_PRM_CLKSETUP_OFFSET);
-	voltdm->write(OMAP3_VOLTOFFSET, OMAP3_PRM_VOLTOFFSET_OFFSET);
-	voltdm->write(OMAP3_VOLTSETUP2, OMAP3_PRM_VOLTSETUP2_OFFSET);
+	voltdm->write(0, OMAP3_PRM_VOLTSETUP2_OFFSET);
 }
 
-static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
+/**
+ * omap3_set_off_timings - sets off-mode timings for a channel
+ * @voltdm: channel to configure
+ *
+ * Calculates and sets up off-mode timings for a channel. Off-mode
+ * can use either I2C based voltage scaling, or alternatively
+ * sys_off_mode pad can be used to send a global command to power IC.
+ * This function first checks which mode is being used, and calls
+ * omap3_set_i2c_timings() if the system is using I2C control mode.
+ * sys_off_mode has the additional benefit that voltages can be
+ * scaled to zero volt level with TWL4030 / TWL5030, I2C can only
+ * scale to 600mV.
+ */
+static void omap3_set_off_timings(struct voltagedomain *voltdm)
 {
-	static bool is_initialized;
+	unsigned long clksetup;
+	unsigned long voltsetup2;
+	unsigned long voltsetup2_old;
+	u32 val;
 
-	if (is_initialized)
+	/* check if sys_off_mode is used to control off-mode voltages */
+	val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
+	if (!(val & OMAP3430_SEL_OFF_MASK)) {
+		/* No, omap is controlling them over I2C */
+		omap3_set_i2c_timings(voltdm, true);
 		return;
+	}
 
-	omap3_vfsm_init(voltdm);
+	clksetup = voltdm->read(OMAP3_PRM_CLKSETUP_OFFSET);
 
-	is_initialized = true;
+	/* voltsetup 2 in us */
+	voltsetup2 = voltdm->vc_param->on / voltdm->pmic->slew_rate;
+
+	/* convert to 32k clk cycles */
+	voltsetup2 = DIV_ROUND_UP(voltsetup2 * 32768, 1000000);
+
+	voltsetup2_old = voltdm->read(OMAP3_PRM_VOLTSETUP2_OFFSET);
+
+	/*
+	 * Update voltsetup2 if higher than current value (needed because
+	 * we have multiple channels with different ramp times), also
+	 * update voltoffset always to value recommended by TRM
+	 */
+	if (voltsetup2 > voltsetup2_old) {
+		voltdm->write(voltsetup2, OMAP3_PRM_VOLTSETUP2_OFFSET);
+		voltdm->write(clksetup - voltsetup2,
+			OMAP3_PRM_VOLTOFFSET_OFFSET);
+	} else
+		voltdm->write(clksetup - voltsetup2_old,
+			OMAP3_PRM_VOLTOFFSET_OFFSET);
+
+	/*
+	 * omap is not controlling voltage scaling during off-mode,
+	 * thus set voltsetup1 to 0
+	 */
+	voltdm->rmw(voltdm->vfsm->voltsetup_mask, 0,
+		voltdm->vfsm->voltsetup_reg);
+
+	/* voltoffset must be clksetup minus voltsetup2 according to TRM */
+	voltdm->write(clksetup - voltsetup2, OMAP3_PRM_VOLTOFFSET_OFFSET);
 }
 
+static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
+{
+	omap3_set_off_timings(voltdm);
+}
 
 /* OMAP4 specific voltage init functions */
 static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
@@ -339,7 +419,6 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
 	vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr;
 	vc->volt_reg_addr = voltdm->pmic->volt_reg_addr;
 	vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr;
-	vc->setup_time = voltdm->pmic->volt_setup_time;
 
 	/* Configure the i2c slave address for this VC */
 	voltdm->rmw(vc->smps_sa_mask,
@@ -378,11 +457,6 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
 	/* Channel configuration */
 	omap_vc_config_channel(voltdm);
 
-	/* Configure the setup times */
-	voltdm->rmw(voltdm->vfsm->voltsetup_mask,
-		    vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask),
-		    voltdm->vfsm->voltsetup_reg);
-
 	omap_vc_i2c_init(voltdm);
 
 	if (cpu_is_omap34xx())
diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h
index 7618b69..91c8d75 100644
--- a/arch/arm/mach-omap2/vc.h
+++ b/arch/arm/mach-omap2/vc.h
@@ -86,7 +86,6 @@ struct omap_vc_channel {
 	u16 i2c_slave_addr;
 	u16 volt_reg_addr;
 	u16 cmd_reg_addr;
-	u16 setup_time;
 	u8 cfg_channel;
 	bool i2c_high_speed;
 
-- 
1.7.4.1


  parent reply	other threads:[~2012-05-31 13:56 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-31 13:55 [PATCHv6 00/14] ARM: OMAP3+: auto ret / auto off support Tero Kristo
2012-05-31 13:55 ` [PATCHv6 01/14] ARM: OMAP3+: PM: VP: use uV for max and min voltage limits Tero Kristo
2012-05-31 13:55 ` [PATCHv6 02/14] ARM: OMAP: voltage: renamed vp_vddmin and vp_vddmax fields Tero Kristo
2012-05-31 13:55 ` [PATCHv6 03/14] ARM: OMAP3+: voltage: introduce omap vc / vp params for voltagedomains Tero Kristo
2012-05-31 13:55 ` Tero Kristo [this message]
2012-05-31 13:55 ` [PATCHv6 05/14] ARM: OMAP4: voltage: add support for VOLTSETUP_x_OFF register Tero Kristo
2012-05-31 13:55 ` [PATCHv6 06/14] ARM: OMAP4: VC: calculate ramp times Tero Kristo
2012-05-31 13:55 ` [PATCHv6 07/14] ARM: OMAP: add support for oscillator setup Tero Kristo
2012-05-31 13:55 ` [PATCHv6 08/14] ARM: OMAP3+: vp: use new vp_params for calculating vddmin and vddmax Tero Kristo
2012-05-31 13:55 ` [PATCHv6 09/14] ARM: OMAP3+: voltage: use oscillator data to calculate setup times Tero Kristo
2012-05-31 13:55 ` [PATCHv6 10/14] ARM: OMAP: TWL: change the vddmin / vddmax voltages to spec Tero Kristo
2012-05-31 13:55 ` [PATCHv6 11/14] TEMP: ARM: OMAP3: beagle rev-c4: enable OPP6 Tero Kristo
2012-05-31 13:55 ` [PATCHv6 12/14] ARM: OMAP: beagle: set oscillator startup time to 10ms for rev c4 Tero Kristo
2012-05-31 13:55 ` [PATCHv6 13/14] ARM: OMAP3: vc: auto_ret / auto_off support Tero Kristo
2012-06-01 10:18   ` Menon, Nishanth
2012-05-31 13:55 ` [PATCHv6 14/14] ARM: OMAP3+: voltage: remove unused volt_setup_time parameter Tero Kristo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1338472550-20743-5-git-send-email-t-kristo@ti.com \
    --to=t-kristo@ti.com \
    --cc=khilman@ti.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-omap@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).