mirror of
https://git.yoctoproject.org/meta-ti
synced 2026-07-27 14:28:05 +00:00
53dcf7977a
Ported from Arago the kernel that corresponds to PSP version 04.02.00.07 with corresponding SDK patches applied on top. Signed-off-by: Denys Dmytriyenko <denys@ti.com>
320 lines
12 KiB
Diff
320 lines
12 KiB
Diff
From 0192a1d0731d3e8959b817bbc458c21e1c51408f Mon Sep 17 00:00:00 2001
|
|
From: Greg Guyotte <gguyotte@ti.com>
|
|
Date: Tue, 5 Jun 2012 16:54:26 -0500
|
|
Subject: [PATCH] am37x: Adding ABB Support for 1GHz OPP
|
|
|
|
This patch adds ABB support for the AM37x 1GHz OPP. When 1GHz
|
|
operation occurs, the ABB LDO will be enabled, effectively
|
|
boosting MPU voltage. At any time that we are not operating
|
|
at 1GHz, the ABB LDO will be bypassed. This change is
|
|
required for operation at 1GHz on the AM37x device.
|
|
|
|
This patch only affects AM37x. In the course of booting,
|
|
it boosts the MPU rate to 1GHz and turns on the ABB LDO. It
|
|
is expected that the system will be operating at 800MHz
|
|
prior to this time, as set by Uboot. Also note that after
|
|
MPU rate is changed, the loops_per_jiffy global is updated,
|
|
which is required in order to get the proper readout from
|
|
BogoMIPS.
|
|
|
|
Upstream-Status: Not Appropriate
|
|
* This patch is a quick fix based on an old kernel.
|
|
* This will be reworked for the Linux mainline kernel.
|
|
|
|
Signed-off-by: Greg Guyotte <gguyotte@ti.com>
|
|
---
|
|
arch/arm/mach-omap2/pm.c | 30 +++++++-
|
|
arch/arm/mach-omap2/prm-regbits-34xx.h | 20 +++++
|
|
arch/arm/mach-omap2/prm2xxx_3xxx.h | 5 ++
|
|
arch/arm/mach-omap2/voltage.c | 123 ++++++++++++++++++++++++++++++++
|
|
4 files changed, 176 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
|
|
index f7e4d1b..678877c 100644
|
|
--- a/arch/arm/mach-omap2/pm.c
|
|
+++ b/arch/arm/mach-omap2/pm.c
|
|
@@ -27,6 +27,8 @@
|
|
#include "cm2xxx_3xxx.h"
|
|
#include "pm.h"
|
|
|
|
+#define RATE_1GHZ 1000000000
|
|
+
|
|
static struct omap_device_pm_latency *pm_lats;
|
|
|
|
static struct device *mpu_dev;
|
|
@@ -61,7 +63,6 @@ struct device *omap4_get_dsp_device(void)
|
|
}
|
|
EXPORT_SYMBOL(omap4_get_dsp_device);
|
|
|
|
-#ifndef CONFIG_CPU_FREQ
|
|
static unsigned long compute_lpj(unsigned long ref, u_int div, u_int mult)
|
|
{
|
|
unsigned long new_jiffy_l, new_jiffy_h;
|
|
@@ -81,7 +82,6 @@ static unsigned long compute_lpj(unsigned long ref, u_int div, u_int mult)
|
|
|
|
return new_jiffy_h + new_jiffy_l * 100;
|
|
}
|
|
-#endif
|
|
|
|
/* static int _init_omap_device(struct omap_hwmod *oh, void *user) */
|
|
static int _init_omap_device(char *name, struct device **new_dev)
|
|
@@ -289,6 +289,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
|
|
struct clk *clk;
|
|
struct opp *opp;
|
|
unsigned long freq, bootup_volt;
|
|
+ int ret;
|
|
|
|
if (!vdd_name || !clk_name || !dev) {
|
|
printk(KERN_ERR "%s: Invalid parameters!\n", __func__);
|
|
@@ -311,6 +312,11 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
|
|
|
|
freq = clk->rate;
|
|
clk_put(clk);
|
|
+
|
|
+ /* set up for a voltage to support 1GHz */
|
|
+ if (cpu_is_omap3630())
|
|
+ if (!strcmp(vdd_name, "mpu"))
|
|
+ freq = RATE_1GHZ;
|
|
|
|
opp = opp_find_freq_ceil(dev, &freq);
|
|
if (IS_ERR(opp)) {
|
|
@@ -327,6 +333,26 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
|
|
}
|
|
|
|
omap_voltage_scale_vdd(voltdm, bootup_volt);
|
|
+
|
|
+ /* once voltage is changed, we can scale freq to max */
|
|
+ if (cpu_is_omap3630()) {
|
|
+ if (!strcmp(vdd_name, "mpu")) {
|
|
+ unsigned long cur_rate;
|
|
+ cur_rate = clk->rate;
|
|
+
|
|
+ ret = clk_set_rate(clk, RATE_1GHZ);
|
|
+ if (ret) {
|
|
+ dev_warn(dev, "%s: Unable to set rate to %d\n",
|
|
+ __func__, RATE_1GHZ);
|
|
+ return ret;
|
|
+ }
|
|
+ /* Update loops_per_jiffy because processor speed is
|
|
+ being changed. Necessary to keep BogoMIPS happy. */
|
|
+ loops_per_jiffy = compute_lpj(loops_per_jiffy,
|
|
+ cur_rate / 1000000,
|
|
+ RATE_1GHZ / 1000000);
|
|
+ }
|
|
+ }
|
|
return 0;
|
|
|
|
exit:
|
|
diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
|
|
index 64c087a..2758fa3 100644
|
|
--- a/arch/arm/mach-omap2/prm-regbits-34xx.h
|
|
+++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
|
|
@@ -89,6 +89,7 @@
|
|
#define OMAP3430_LASTPOWERSTATEENTERED_MASK (0x3 << 0)
|
|
|
|
/* PRM_IRQSTATUS_IVA2, PRM_IRQSTATUS_MPU shared bits */
|
|
+#define OMAP3630_ABB_LDO_TRANXDONE_ST (1 << 26)
|
|
#define OMAP3430_WKUP_ST_MASK (1 << 0)
|
|
|
|
/* PRM_IRQENABLE_IVA2, PRM_IRQENABLE_MPU shared bits */
|
|
@@ -216,6 +217,9 @@
|
|
/* PRM_SYSCONFIG specific bits */
|
|
|
|
/* PRM_IRQSTATUS_MPU specific bits */
|
|
+#define OMAP3630_VC_BYPASS_ACK_EN (1 << 28)
|
|
+#define OMAP3630_VC_VP1_ACK_EN (1 << 27)
|
|
+#define OMAP3630_VC_ABB_LDO_TRANXDONE_EN (1 << 26)
|
|
#define OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT 25
|
|
#define OMAP3430ES2_SND_PERIPH_DPLL_ST_MASK (1 << 25)
|
|
#define OMAP3430_VC_TIMEOUTERR_ST_MASK (1 << 24)
|
|
@@ -587,6 +591,22 @@
|
|
|
|
/* PRM_VP2_STATUS specific bits */
|
|
|
|
+/* PRM_LDO_ABB_SETUP */
|
|
+#define OMAP3630_SR2_IN_TRANSITION (1 << 6)
|
|
+#define OMAP3630_SR2_STATUS_SHIFT 3
|
|
+#define OMAP3630_SR2_STATUS_MASK (0x3 << 3)
|
|
+#define OMAP3630_OPP_CHANGE (1 << 2)
|
|
+#define OMAP3630_OPP_SEL_SHIFT 0
|
|
+#define OMAP3630_OPP_SEL_MASK (0x3 << 0)
|
|
+
|
|
+/* PRM_LDO_ABB_CTRL */
|
|
+#define OMAP3630_SR2_WTCNT_VALUE_SHIFT 8
|
|
+#define OMAP3630_SR2_WTCNT_VALUE_MASK (0xff << 8)
|
|
+#define OMAP3630_SLEEP_RBB_SEL (1 << 3)
|
|
+#define OMAP3630_ACTIVE_FBB_SEL (1 << 2)
|
|
+#define OMAP3630_ACTIVE_RBB_SEL (1 << 1)
|
|
+#define OMAP3630_SR2EN (1 << 0)
|
|
+
|
|
/* RM_RSTST_NEON specific bits */
|
|
|
|
/* PM_WKDEP_NEON specific bits */
|
|
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h
|
|
index 613f83c..79c9ad5 100644
|
|
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.h
|
|
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h
|
|
@@ -171,6 +171,11 @@
|
|
#define OMAP3_PRM_VP2_STATUS_OFFSET 0x00e4
|
|
#define OMAP3430_PRM_VP2_STATUS OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
|
|
|
|
+#define OMAP3_PRM_LDO_ABB_SETUP_OFFSET 0x00f0
|
|
+#define OMAP3430_PRM_LDO_ABB_SETUP OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00f0)
|
|
+#define OMAP3_PRM_LDO_ABB_CTRL_OFFSET 0x00f4
|
|
+#define OMAP3430_PRM_LDO_ABB_CTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00f4)
|
|
+
|
|
#define OMAP3_PRM_CLKSEL_OFFSET 0x0040
|
|
#define OMAP3430_PRM_CLKSEL OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
|
|
#define OMAP3_PRM_CLKOUT_CTRL_OFFSET 0x0070
|
|
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
|
|
index 2e015a7..32944d0 100644
|
|
--- a/arch/arm/mach-omap2/voltage.c
|
|
+++ b/arch/arm/mach-omap2/voltage.c
|
|
@@ -45,6 +45,10 @@
|
|
#define VP_TRANXDONE_TIMEOUT 300
|
|
#define VOLTAGE_DIR_SIZE 16
|
|
|
|
+#define ABB_TRANXDONE_TIMEOUT 100
|
|
+#define ABB_FAST_OPP 1
|
|
+#define ABB_NOMINAL_OPP 2
|
|
+
|
|
/* Voltage processor register offsets */
|
|
struct vp_reg_offs {
|
|
u8 vpconfig;
|
|
@@ -764,6 +768,112 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
|
|
return 0;
|
|
}
|
|
|
|
+/**
|
|
+ * omap3630_abb_change_active_opp - handle OPP changes with Adaptive Body-Bias
|
|
+ * @target_opp_no: ABB_FAST_OPP or ABB_NOMINAL_OPP
|
|
+ *
|
|
+ * Adaptive Body-Bias is a 3630-specific technique to boost voltage in high
|
|
+ * OPPs for silicon with weak characteristics as well as lower voltage in low
|
|
+ * OPPs for silicon with strong characteristics.
|
|
+ *
|
|
+ * Only Foward Body-Bias for operating at high OPPs is implemented below.
|
|
+ * Reverse Body-Bias for saving power in active cases and sleep cases is not
|
|
+ * yet implemented.
|
|
+ */
|
|
+static int omap3630_abb_change_active_opp(u32 target_opp_no)
|
|
+{
|
|
+ u32 sr2en_enabled;
|
|
+ int timeout;
|
|
+
|
|
+ /* has SR2EN been enabled previously? */
|
|
+ sr2en_enabled = (omap2_prm_read_mod_reg(OMAP3430_GR_MOD,
|
|
+ OMAP3_PRM_LDO_ABB_CTRL_OFFSET) &
|
|
+ OMAP3630_SR2EN);
|
|
+
|
|
+ /* select OPP */
|
|
+ /* FIXME: shouldn't be hardcoded OPP here */
|
|
+ if (target_opp_no == ABB_FAST_OPP) {
|
|
+ /* program for fast opp - enable fbb */
|
|
+ omap2_prm_rmw_mod_reg_bits(OMAP3630_OPP_SEL_MASK,
|
|
+ (ABB_FAST_OPP << OMAP3630_OPP_SEL_SHIFT),
|
|
+ OMAP3430_GR_MOD,
|
|
+ OMAP3_PRM_LDO_ABB_SETUP_OFFSET);
|
|
+
|
|
+ /* enable the ABB ldo if not done already */
|
|
+ if (!sr2en_enabled)
|
|
+ omap2_prm_set_mod_reg_bits(OMAP3630_SR2EN,
|
|
+ OMAP3430_GR_MOD,
|
|
+ OMAP3_PRM_LDO_ABB_CTRL_OFFSET);
|
|
+ pr_debug("ABB: ABB LDO Enabled\n");
|
|
+ } else if (sr2en_enabled) {
|
|
+ /* program for nominal opp - bypass abb ldo */
|
|
+ omap2_prm_rmw_mod_reg_bits(OMAP3630_OPP_SEL_MASK,
|
|
+ (ABB_NOMINAL_OPP << OMAP3630_OPP_SEL_SHIFT),
|
|
+ OMAP3430_GR_MOD,
|
|
+ OMAP3_PRM_LDO_ABB_SETUP_OFFSET);
|
|
+ pr_debug("ABB: ABB LDO Bypassed\n");
|
|
+ } else {
|
|
+ /* nothing to do here */
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /* set ACTIVE_FBB_SEL for all 3630 silicon */
|
|
+ omap2_prm_set_mod_reg_bits(OMAP3630_ACTIVE_FBB_SEL,
|
|
+ OMAP3430_GR_MOD,
|
|
+ OMAP3_PRM_LDO_ABB_CTRL_OFFSET);
|
|
+
|
|
+ /* program settling time of 30us for ABB ldo transition */
|
|
+ omap2_prm_rmw_mod_reg_bits(OMAP3630_SR2_WTCNT_VALUE_MASK,
|
|
+ (0x62 << OMAP3630_SR2_WTCNT_VALUE_SHIFT),
|
|
+ OMAP3430_GR_MOD,
|
|
+ OMAP3_PRM_LDO_ABB_CTRL_OFFSET);
|
|
+
|
|
+ /* clear ABB ldo interrupt status */
|
|
+ omap2_prm_write_mod_reg(OMAP3630_ABB_LDO_TRANXDONE_ST,
|
|
+ OCP_MOD,
|
|
+ OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
|
+
|
|
+ /* enable ABB LDO OPP change */
|
|
+ omap2_prm_set_mod_reg_bits(OMAP3630_OPP_CHANGE,
|
|
+ OMAP3430_GR_MOD,
|
|
+ OMAP3_PRM_LDO_ABB_SETUP_OFFSET);
|
|
+
|
|
+ timeout = 0;
|
|
+
|
|
+ /* wait until OPP change completes */
|
|
+ while ((timeout < ABB_TRANXDONE_TIMEOUT ) &&
|
|
+ (!(omap2_prm_read_mod_reg(OCP_MOD,
|
|
+ OMAP3_PRM_IRQSTATUS_MPU_OFFSET) &
|
|
+ OMAP3630_ABB_LDO_TRANXDONE_ST))) {
|
|
+ udelay(1);
|
|
+ timeout++;
|
|
+ }
|
|
+
|
|
+ if (timeout == ABB_TRANXDONE_TIMEOUT)
|
|
+ pr_warning("ABB: TRANXDONE timed out waiting for OPP change\n");
|
|
+
|
|
+ timeout = 0;
|
|
+
|
|
+ /* Clear all pending TRANXDONE interrupts/status */
|
|
+ while (timeout < ABB_TRANXDONE_TIMEOUT) {
|
|
+ omap2_prm_write_mod_reg(OMAP3630_ABB_LDO_TRANXDONE_ST,
|
|
+ OCP_MOD,
|
|
+ OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
|
+ if (!(omap2_prm_read_mod_reg(OCP_MOD,
|
|
+ OMAP3_PRM_IRQSTATUS_MPU_OFFSET)
|
|
+ & OMAP3630_ABB_LDO_TRANXDONE_ST))
|
|
+ break;
|
|
+
|
|
+ udelay(1);
|
|
+ timeout++;
|
|
+ }
|
|
+
|
|
+ if (timeout == ABB_TRANXDONE_TIMEOUT)
|
|
+ pr_warning("ABB: TRANXDONE timed out trying to clear status\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/* VP force update method of voltage scaling */
|
|
static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
|
|
unsigned long target_volt)
|
|
@@ -858,6 +968,19 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
|
|
vpconfig &= ~vdd->vp_reg.vpconfig_forceupdate;
|
|
vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
|
|
|
|
+ if (cpu_is_omap3630() && !strcmp(vdd->voltdm.name, "mpu")) {
|
|
+ if (vdd->curr_volt == OMAP3630_VDD_MPU_OPP1G_UV) {
|
|
+ pr_debug("%s: vdd_%s: Attempting ABB enable\n",
|
|
+ __func__, vdd->voltdm.name);
|
|
+ omap3630_abb_change_active_opp(ABB_FAST_OPP);
|
|
+ }
|
|
+ else {
|
|
+ pr_debug("%s: vdd_%s: Attempting ABB disable\n",
|
|
+ __func__, vdd->voltdm.name);
|
|
+ omap3630_abb_change_active_opp(ABB_NOMINAL_OPP);
|
|
+ }
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
--
|
|
1.7.0.4
|
|
|