diff options
-rw-r--r-- | arch/arm/mach-omap2/Kconfig | 17 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_tps6236x.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_twl.c | 143 | ||||
-rw-r--r-- | arch/arm/mach-omap2/sleep44xx.S | 49 | ||||
-rw-r--r-- | arch/arm/mach-omap2/vc.c | 2 | ||||
-rw-r--r-- | drivers/staging/android/ram_console.c | 2 | ||||
-rw-r--r-- | sound/soc/soc-dsp.c | 80 |
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); |