aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/Kconfig17
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c1
-rw-r--r--arch/arm/mach-omap2/omap_tps6236x.c5
-rw-r--r--arch/arm/mach-omap2/omap_twl.c143
-rw-r--r--arch/arm/mach-omap2/sleep44xx.S49
-rw-r--r--arch/arm/mach-omap2/vc.c2
-rw-r--r--drivers/staging/android/ram_console.c2
-rw-r--r--sound/soc/soc-dsp.c80
8 files changed, 253 insertions, 46 deletions
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 66e5a88..97e7205 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -372,6 +372,23 @@ config OMAP_FIQ_DEBUGGER
help
Enables the serial FIQ debugger on OMAP"
+config OMAP4_PPA_CPU1_ONLINE_BUG
+ bool "Enable Support for CPU1 ONLINE WA for OSWR/OFF"
+ depends on ARCH_OMAP4
+ depends on OMAP_ALLOW_OSWR
+ default y
+ help
+ If an non GP OMAP4 device is used and PPA revision is < v1.7.3,
+ the device does not perform the memory maintenance and TLB sync
+ operations required before releasing CPU1 to HLOS. This results
+ in crash while resuming from OFF mode.
+
+ Disable this option *ONLY IF* you meet the minimum PPA version
+ requirement.
+
+ If, on the other hand, you do not understand the change, leave the
+ default as enabled.
+
endmenu
endif
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 6e16ef6..a650628 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -5466,6 +5466,7 @@ static struct omap_hwmod_ocp_if *omap44xx_uart1_slaves[] = {
static struct omap_hwmod omap44xx_uart1_hwmod = {
.name = "uart1",
.class = &omap44xx_uart_hwmod_class,
+ .flags = HWMOD_SWSUP_SIDLE,
.mpu_irqs = omap44xx_uart1_irqs,
.mpu_irqs_cnt = ARRAY_SIZE(omap44xx_uart1_irqs),
.sdma_reqs = omap44xx_uart1_sdma_reqs,
diff --git a/arch/arm/mach-omap2/omap_tps6236x.c b/arch/arm/mach-omap2/omap_tps6236x.c
index bfb5c00..c369d7a 100644
--- a/arch/arm/mach-omap2/omap_tps6236x.c
+++ b/arch/arm/mach-omap2/omap_tps6236x.c
@@ -178,7 +178,7 @@ static u8 tps6236x_uv_to_vsel(unsigned long uv)
}
static struct omap_voltdm_pmic omap4_mpu_pmic = {
- .slew_rate = 8000,
+ .slew_rate = 32000,
.step_size = STEP_SIZE_TPS6236X,
.on_volt = 1375000,
.onlp_volt = 1375000,
@@ -260,6 +260,9 @@ static int __init omap4_twl_tps62361_enable(struct voltagedomain *voltdm)
/* We would like to ramp the voltage asap */
val |= REG_TPS6236X_RAMP_CTRL_RAMP_PFM;
+ /* We would like to ramp down the voltage asap as well*/
+ val |= REG_TPS6236X_RAMP_CTRL_EN_DISC;
+
ret = omap_vc_bypass_send_i2c_msg(voltdm, voltdm->pmic->i2c_slave_addr,
REG_TPS6236X_RAMP_CTRL, val);
if (ret)
diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
index f66cd2a..2d00a0c 100644
--- a/arch/arm/mach-omap2/omap_twl.c
+++ b/arch/arm/mach-omap2/omap_twl.c
@@ -38,6 +38,24 @@
#define OMAP4_VDD_CORE_SR_VOLT_REG 0x61
#define OMAP4_VDD_CORE_SR_CMD_REG 0x62
+#define TWL6030_REG_VCORE1_CFG_GRP 0x52
+#define TWL6030_REG_VCORE1_CFG_TRANS 0x53
+#define TWL6030_REG_VCORE2_CFG_GRP 0x58
+#define TWL6030_REG_VCORE2_CFG_TRANS 0x59
+#define TWL6030_REG_VCORE3_CFG_GRP 0x5e
+#define TWL6030_REG_VCORE3_CFG_TRANS 0x5f
+#define TWL6030_BIT_APE_GRP BIT(0)
+/*
+ * Setup CFG_TRANS mode as follows:
+ * 0x00 (OFF) when in OFF state(bit offset 4) and in sleep (bit offset 2)
+ * 0x01 (PWM/PFM Auto) when in ACTive state (bit offset 0)
+ * Dont trust Bootloader or reset values to set them up for kernel.
+ */
+#define TWL6030_REG_VCOREx_CFG_TRANS_MODE (0x00 << 4 | \
+ 0x00 << 2 | \
+ 0x01 << 0)
+#define TWL6030_REG_VCOREx_CFG_TRANS_MODE_DESC "OFF=OFF SLEEP=OFF ACT=AUTO"
+
static bool is_offset_valid;
static u8 smps_offset;
/*
@@ -50,6 +68,55 @@ static bool __initdata twl_sr_enable_autoinit;
#define REG_SMPS_OFFSET 0xE0
#define SMARTREFLEX_ENABLE BIT(3)
+/**
+ * struct twl_reg_setup_array - NULL terminated array giving configuration
+ * @addr: reg address to write to
+ * @val: value to write with
+ * @desc: description of this reg for error printing
+ * NOTE: a NULL pointer in this indicates end of array.
+ *
+ * VCORE register configurations as per need.
+ */
+struct twl_reg_setup_array {
+ u8 addr;
+ u8 val;
+ char *desc;
+};
+
+/**
+ * _twl_set_regs() - helper to setup a config array
+ * @gendesc: generic description - used with error message
+ * @sarray: NULL terminated array of configuration values
+ *
+ * Configures TWL with a set of values terminated. If any write fails,
+ * this continues till the last and returns back with the last error
+ * value.
+ */
+static int __init _twl_set_regs(char *gendesc,
+ struct twl_reg_setup_array *sarray)
+{
+ int i = 0;
+ int ret1;
+ int ret = 0;
+
+ while (sarray->desc) {
+ ret1 = twl_i2c_write_u8(TWL6030_MODULE_ID0,
+ sarray->val,
+ sarray->addr);
+ if (ret1) {
+ pr_err("%s: %s: failed(%d), array index=%d, desc=%s, "
+ "reg=0x%02x, val=0x%02x\n",
+ __func__, gendesc, ret1, i,
+ sarray->desc, sarray->addr, sarray->val);
+ ret = ret1;
+ }
+ sarray++;
+ i++;
+ }
+
+ return ret;
+}
+
static unsigned long twl4030_vsel_to_uv(const u8 vsel)
{
return (((vsel * 125) + 6000)) * 100;
@@ -263,7 +330,8 @@ static struct omap_voltdm_pmic omap446x_core_pmic = {
.on_volt = 1200000,
.onlp_volt = 1200000,
.ret_volt = 830000,
- .off_volt = 0,
+ /* OMAP4 + TWL + TPS limitation keep off_volt same as ret_volt */
+ .off_volt = 830000,
.volt_setup_time = 0,
.switch_on_time = 549,
.vp_erroroffset = OMAP4_VP_CONFIG_ERROROFFSET,
@@ -302,6 +370,77 @@ static int __init twl_set_sr(struct voltagedomain *voltdm)
return r;
}
+
+/* OMAP4430 - All vcores: 1, 2 and 3 should go down with PREQ */
+static __initdata struct twl_reg_setup_array omap4430_twl6030_setup[] = {
+ {
+ .addr = TWL6030_REG_VCORE1_CFG_GRP,
+ .val = TWL6030_BIT_APE_GRP,
+ .desc = "Pull VCORE1 down along with App processor's PREQ1",
+ },
+ {
+ .addr = TWL6030_REG_VCORE1_CFG_TRANS,
+ .val = TWL6030_REG_VCOREx_CFG_TRANS_MODE,
+ .desc = "VCORE1" TWL6030_REG_VCOREx_CFG_TRANS_MODE_DESC,
+ },
+ {
+ .addr = TWL6030_REG_VCORE2_CFG_GRP,
+ .val = TWL6030_BIT_APE_GRP,
+ .desc = "Pull VCORE2 down along with App processor's PREQ1",
+ },
+ {
+ .addr = TWL6030_REG_VCORE2_CFG_TRANS,
+ .val = TWL6030_REG_VCOREx_CFG_TRANS_MODE,
+ .desc = "VCORE2" TWL6030_REG_VCOREx_CFG_TRANS_MODE_DESC,
+ },
+ {
+ .addr = TWL6030_REG_VCORE3_CFG_GRP,
+ .val = TWL6030_BIT_APE_GRP,
+ .desc = "Pull VCORE3 down along with App processor's PREQ1",
+ },
+ {
+ .addr = TWL6030_REG_VCORE3_CFG_TRANS,
+ .val = TWL6030_REG_VCOREx_CFG_TRANS_MODE,
+ .desc = "VCORE3" TWL6030_REG_VCOREx_CFG_TRANS_MODE_DESC,
+ },
+ { .desc = NULL} /* TERMINATOR */
+};
+
+static int __init twl_set_4430vcore(struct voltagedomain *voltdm)
+{
+ return _twl_set_regs("OMAP4430 ", omap4430_twl6030_setup);
+}
+
+/* OMAP4460 - VCORE3 is unused, 1 and 2 should go down with PREQ */
+static __initdata struct twl_reg_setup_array omap4460_twl6030_setup[] = {
+ {
+ .addr = TWL6030_REG_VCORE1_CFG_GRP,
+ .val = TWL6030_BIT_APE_GRP,
+ .desc = "Pull VCORE1 down along with App processor's PREQ1",
+ },
+ {
+ .addr = TWL6030_REG_VCORE1_CFG_TRANS,
+ .val = TWL6030_REG_VCOREx_CFG_TRANS_MODE,
+ .desc = "VCORE1" TWL6030_REG_VCOREx_CFG_TRANS_MODE_DESC,
+ },
+ {
+ .addr = TWL6030_REG_VCORE2_CFG_GRP,
+ .val = TWL6030_BIT_APE_GRP,
+ .desc = "Pull VCORE2 down along with App processor's PREQ1",
+ },
+ {
+ .addr = TWL6030_REG_VCORE2_CFG_TRANS,
+ .val = TWL6030_REG_VCOREx_CFG_TRANS_MODE,
+ .desc = "VCORE2" TWL6030_REG_VCOREx_CFG_TRANS_MODE_DESC,
+ },
+ { .desc = NULL} /* TERMINATOR */
+};
+
+static int __init twl_set_4460vcore(struct voltagedomain *voltdm)
+{
+ return _twl_set_regs("OMAP4460 ", omap4460_twl6030_setup);
+}
+
#define OMAP3_TWL4030_USED (CHIP_GE_OMAP3430ES2 | \
CHIP_GE_OMAP3630ES1_1 | \
CHIP_IS_OMAP3630ES1)
@@ -327,11 +466,13 @@ static __initdata struct omap_pmic_map omap_twl_map[] = {
.name = "core",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP443X),
.pmic_data = &omap443x_core_pmic,
+ .special_action = twl_set_4430vcore,
},
{
.name = "core",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP446X),
.pmic_data = &omap446x_core_pmic,
+ .special_action = twl_set_4460vcore,
},
{
.name = "iva",
diff --git a/arch/arm/mach-omap2/sleep44xx.S b/arch/arm/mach-omap2/sleep44xx.S
index 2b37f3b..b025e5f 100644
--- a/arch/arm/mach-omap2/sleep44xx.S
+++ b/arch/arm/mach-omap2/sleep44xx.S
@@ -346,6 +346,55 @@ ENTRY(omap4_cpu_resume)
cmp r0, #1 @ is CPU0 already UP?
beq ppa_cp15_cpu1_configure @ CPU1 HS go to next stage
/*
+ * When CPU1 is released to control of HLOS in the case of OSWR
+ * and OFF mode, PPA below v1.7.3[1] is not performing all
+ * Memory coherency and TLB operations required.
+ *
+ * A WA to recover cleanly from this scenario is to switch CPU1 back to
+ * previous OFF state. This forces a reset of CPU1, which in turn
+ * forces CPU1 not to override MMU descriptors already in place in
+ * internal RAM setup by CPU0. CPU1 will also sync to the in-place
+ * descriptors on the next wakeup. CPU1 wakeup is done by
+ * later kernel subsystems depending on suspend or cpuidle path
+ * being exercised.
+ * NOTE - for OSWR, state provided is 2, and for OFF, state is 3,
+ * Since the bug impacts OFF and OSWR, we need to force a 0x3 to
+ * shut off CPU1
+ *
+ * Since many distributions may not be able to update PPA OR would like
+ * to support platforms with older PPA, we provide a config option.
+ * This is simpler and makes the current code remain cleaner in
+ * comparison to a flag based handling in CPU1 recovery for
+ * board + PPA revision combinations.
+ *
+ * Having this config option enabled even on platforms with fixed PPA
+ * should not impact stability, however, ability to make CPU1 available
+ * for operations a little earlier is curtailed.
+ *
+ * Foot note [1]:
+ * v1.7.3 is the official TI PPA version. Custom PPA could have
+ * the relevant changes ported over to it.
+ */
+#ifdef CONFIG_OMAP4_PPA_CPU1_ONLINE_BUG
+ mov r0, #0x03 @ target CPU1 to OFF(mpusspd=OSWR/OFF)
+ mov r1, #0x00 @ Secure L1 is already clean
+ ldr r12, =SCU_POWER_SECURE_INDEX
+ dsb
+ smc #0
+
+ isb @ Necessary barriers before wfi
+ dsb
+ dmb
+ wfi @ wait for interrupt
+ nop
+ nop
+
+ /*
+ * IF we came out of WFI immediately, something unknown happend.
+ * Fall through AND loop back to the checks. Failing which retry WFI.
+ */
+#endif
+ /*
* CPU0 and CPU1 are release together from OFF mode, however,
* CPU0 can be busy doing restore operations while waking
* from OFF mode, However, for many PPA services we need
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
index 162ee9f..04a50fa 100644
--- a/arch/arm/mach-omap2/vc.c
+++ b/arch/arm/mach-omap2/vc.c
@@ -260,7 +260,7 @@ static int omap_vc_bypass_send_value(struct voltagedomain *voltdm,
* NOTE: This is legacy code. The loop count and retry count needs
* to be revisited.
*/
- while (!(vc_bypass_value & vc_valid)) {
+ while (vc_bypass_value & vc_valid) {
loop_cnt++;
if (retries_cnt > 10) {
diff --git a/drivers/staging/android/ram_console.c b/drivers/staging/android/ram_console.c
index cb42d89..b278d62 100644
--- a/drivers/staging/android/ram_console.c
+++ b/drivers/staging/android/ram_console.c
@@ -143,7 +143,7 @@ ram_console_write(struct console *console, const char *s, unsigned int count)
static struct console ram_console = {
.name = "ram",
.write = ram_console_write,
- .flags = CON_PRINTBUFFER | CON_ENABLED,
+ .flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME,
.index = -1,
};
diff --git a/sound/soc/soc-dsp.c b/sound/soc/soc-dsp.c
index 40e459a..c04b24a 100644
--- a/sound/soc/soc-dsp.c
+++ b/sound/soc/soc-dsp.c
@@ -1103,31 +1103,31 @@ disconnect:
if (be->dsp[stream].state != SND_SOC_DSP_STATE_START)
dsp_params->state = SND_SOC_DSP_LINK_STATE_FREE;
}
- be_disconnect(fe, stream);
+
return ret;
}
-static int dsp_run_update(struct snd_soc_pcm_runtime *fe, int stream,
- int start, int stop)
+static int dsp_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)
{
- int ret = 0;
+ int ret;
fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_BE;
+ ret = dsp_run_update_startup(fe, stream);
+ if (ret < 0)
+ dev_err(&fe->dev, "failed to startup some BEs\n");
+ fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_NO;
- /* startup any new BEs */
- if (start) {
- ret = dsp_run_update_startup(fe, stream);
- if (ret < 0)
- dev_err(&fe->dev, "failed to startup BEs\n");
- }
+ return ret;
+}
- /* close down old BEs */
- if (stop) {
- ret = dsp_run_update_shutdown(fe, stream);
- if (ret < 0)
- dev_err(&fe->dev, "failed to shutdown BEs\n");
- }
+static int dsp_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
+{
+ int ret;
+ fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_BE;
+ ret = dsp_run_update_shutdown(fe, stream);
+ if (ret < 0)
+ dev_err(&fe->dev, "failed to shutdown some BEs\n");
fe->dsp[stream].runtime_update = SND_SOC_DSP_UPDATE_NO;
return ret;
@@ -1167,44 +1167,40 @@ int soc_dsp_runtime_update(struct snd_soc_dapm_widget *widget)
if (!fe->cpu_dai->driver->playback.channels_min)
goto capture;
- /* update any playback paths */
+ /* update new playback paths */
start = dsp_add_new_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, 1);
- stop = dsp_prune_old_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, 1);
- if (!(start || stop))
- goto capture;
-
- /* run PCM ops on new/old playback paths */
- ret = dsp_run_update(fe, SNDRV_PCM_STREAM_PLAYBACK, start, stop);
- if (ret < 0) {
- dev_err(&fe->dev, "failed to update playback FE stream %s\n",
- fe->dai_link->stream_name);
+ if (start) {
+ dsp_run_new_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
}
- /* free old playback links */
- be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
- fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ /* update old playback paths */
+ stop = dsp_prune_old_paths(fe, SNDRV_PCM_STREAM_PLAYBACK, 1);
+ if (stop) {
+ dsp_run_old_update(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ fe_clear_pending(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ be_disconnect(fe, SNDRV_PCM_STREAM_PLAYBACK);
+ }
capture:
/* skip if FE doesn't have capture capability */
if (!fe->cpu_dai->driver->capture.channels_min)
continue;
- /* update any capture paths */
+ /* update new capture paths */
start = dsp_add_new_paths(fe, SNDRV_PCM_STREAM_CAPTURE, 1);
- stop = dsp_prune_old_paths(fe, SNDRV_PCM_STREAM_CAPTURE, 1);
- if (!(start || stop))
- continue;
-
- /* run PCM ops on new/old capture paths */
- ret = dsp_run_update(fe, SNDRV_PCM_STREAM_CAPTURE, start, stop);
- if (ret < 0) {
- dev_err(&fe->dev, "failed to update capture FE stream %s\n",
- fe->dai_link->stream_name);
+ if (start) {
+ dsp_run_new_update(fe, SNDRV_PCM_STREAM_CAPTURE);
+ fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
}
- /* free old capture links */
- be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
- fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
+ /* update old capture paths */
+ stop = dsp_prune_old_paths(fe, SNDRV_PCM_STREAM_CAPTURE, 1);
+ if (stop) {
+ dsp_run_old_update(fe, SNDRV_PCM_STREAM_CAPTURE);
+ fe_clear_pending(fe, SNDRV_PCM_STREAM_CAPTURE);
+ be_disconnect(fe, SNDRV_PCM_STREAM_CAPTURE);
+ }
}
mutex_unlock(&widget->dapm->card->dsp_mutex);