diff options
author | Dan Murphy <dmurphy@ti.com> | 2012-08-28 11:00:12 -0500 |
---|---|---|
committer | Dan Murphy <dmurphy@ti.com> | 2012-08-28 11:00:12 -0500 |
commit | 4896de1b379ca2e85517eb3315bcc2d9519454e4 (patch) | |
tree | f9ca0e060124e81ede1f490eaf8c462f84c9a53b | |
parent | b1feb717103bbeafa7c8644340504bf35e00c883 (diff) | |
parent | 7a69299552ee88c6be4276157ace2c8be49478c8 (diff) | |
download | omap-omapzoom-4896de1b379ca2e85517eb3315bcc2d9519454e4.tar.gz |
Merge branch 'p-linux-omap-3.4' into p-android-omap-3.4android-3.4-5AI.1.14
* p-linux-omap-3.4:
OMAP4+: HSI: Add omap_hwmod_pad_route_irq() error code check
HACK: OMAP5: HSI: disable 3-wires HSI-C1BUG00085 errata
MFD: twl6040: Change power-up verification policy
HACK: ARM: OMAP5: Do CPUx powerdown sequence for MPU_Cx PD transition to CSWR/INA
OMAP4+: HSI: Add hsi_clocks_enable() error check in tasklet
-rw-r--r-- | arch/arm/mach-omap2/omap-mpuss-lowpower.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_hsi.c | 13 | ||||
-rw-r--r-- | drivers/mfd/twl6040-core.c | 84 | ||||
-rw-r--r-- | drivers/omap_hsi/hsi_driver.c | 8 | ||||
-rw-r--r-- | drivers/omap_hsi/hsi_driver_int.c | 9 | ||||
-rw-r--r-- | include/linux/mfd/twl6040.h | 1 |
6 files changed, 108 insertions, 17 deletions
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index e47c0046ef63..73397b46148a 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -480,7 +480,14 @@ int omap_enter_lowpower(unsigned int cpu, unsigned int power_state) switch (power_state) { case PWRDM_POWER_ON: + save_state = 0; + break; case PWRDM_POWER_INACTIVE: + if (cpu_is_omap54xx()) { + /* HACK: COBRA-1.0BUG00167 Do equivalent to CPUx OFF */ + save_state = 1; + break; + } save_state = 0; break; case PWRDM_POWER_OFF: @@ -488,7 +495,8 @@ int omap_enter_lowpower(unsigned int cpu, unsigned int power_state) break; case PWRDM_POWER_CSWR: if (cpu_is_omap54xx()) { - save_state = 0; + /* HACK: COBRA-1.0BUG00167 Do equivalent to CPUx OFF */ + save_state = 1; break; } default: diff --git a/arch/arm/mach-omap2/omap_hsi.c b/arch/arm/mach-omap2/omap_hsi.c index a9fd77ed9c4f..72fdeb54c91e 100644 --- a/arch/arm/mach-omap2/omap_hsi.c +++ b/arch/arm/mach-omap2/omap_hsi.c @@ -410,10 +410,12 @@ static u32 omap_hsi_configure_errata(void) { u32 errata = 0; + if (cpu_is_omap44xx()) + SET_HSI_ERRATA(errata, HSI_ERRATUM_ixxx_3WIRES_NO_SWAKEUP); + if (cpu_is_omap44xx() || (cpu_is_omap54xx() && (omap_rev() <= OMAP5430_REV_ES1_0))) { SET_HSI_ERRATA(errata, HSI_ERRATUM_i696_SW_RESET_FSM_STUCK); - SET_HSI_ERRATA(errata, HSI_ERRATUM_ixxx_3WIRES_NO_SWAKEUP); SET_HSI_ERRATA(errata, HSI_ERRATUM_i702_PM_HSI_SWAKEUP); } @@ -436,7 +438,7 @@ static int __init omap_hsi_register(struct omap_hwmod *oh, void *user) { struct platform_device *od; struct hsi_platform_data *pdata = &omap_hsi_platform_data; - int i, port; + int i, port, err; if (!oh) { pr_err("Could not look up %s omap_hwmod\n", @@ -450,7 +452,12 @@ static int __init omap_hsi_register(struct omap_hwmod *oh, void *user) for (i = 0; i < pdata->num_ports; i++) { port = pdata->ctx->pctx[i].port_number - 1; - omap_hwmod_pad_route_irq(oh, i, port); + err = omap_hwmod_pad_route_irq(oh, i, port); + if (err < 0) { + pr_err("%s: Could not route the IO PAD wakeup event on IRQ %d for the port %d, error = %d\n", + __func__, oh->mpu_irqs[i].irq, port + 1, err); + return err; + } } od = omap_device_build(OMAP_HSI_PLATFORM_DEVICE_DRIVER_NAME, 0, oh, diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index eb8be6564519..2115f60eb880 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c @@ -216,24 +216,86 @@ static irqreturn_t twl6040_naudint_handler(int irq, void *data) return IRQ_HANDLED; } +static int twl6040_is_powered(struct twl6040 *twl6040) +{ + int ncpctl; + int ldoctl; + int lppllctl; + u8 ncpctl_exp; + u8 ldoctl_exp; + u8 lppllctl_exp; + + /* NCPCTL expected value: NCP enabled */ + ncpctl_exp = (TWL6040_TSHUTENA | TWL6040_NCPENA); + + /* LDOCTL expected value: HS/LS LDOs and Reference enabled */ + ldoctl_exp = (TWL6040_REFENA | TWL6040_HSLDOENA | TWL6040_LSLDOENA); + + /* LPPLLCTL expected value: Low-Power PLL enabled */ + lppllctl_exp = TWL6040_LPLLENA; + + ncpctl = twl6040_reg_read(twl6040, TWL6040_REG_NCPCTL); + if (ncpctl < 0) + return 0; + + ldoctl = twl6040_reg_read(twl6040, TWL6040_REG_LDOCTL); + if (ldoctl < 0) + return 0; + + lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL); + if (lppllctl < 0) + return 0; + + if ((ncpctl != ncpctl_exp) || + (ldoctl != ldoctl_exp) || + (lppllctl != lppllctl_exp)) { + dev_warn(twl6040->dev, + "NCPCTL: 0x%02x (should be 0x%02x)\n" + "LDOCTL: 0x%02x (should be 0x%02x)\n" + "LPLLCTL: 0x%02x (should be 0x%02x)\n", + ncpctl, ncpctl_exp, + ldoctl, ldoctl_exp, + lppllctl, lppllctl_exp); + return 0; + } + + return 1; +} + static int twl6040_power_up_completion(struct twl6040 *twl6040, int naudint) { int time_left; + int round = 0; u8 intid; - time_left = wait_for_completion_timeout(&twl6040->ready, - msecs_to_jiffies(144)); - if (!time_left) { - intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID); - if (!(intid & TWL6040_READYINT)) { - dev_err(twl6040->dev, - "timeout waiting for READYINT\n"); - return -ETIMEDOUT; + do { + INIT_COMPLETION(twl6040->ready); + gpio_set_value(twl6040->audpwron, 1); + time_left = wait_for_completion_timeout(&twl6040->ready, + msecs_to_jiffies(700)); + + if (twl6040_is_powered(twl6040)) + return 0; + + if (!time_left) { + intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID); + if (!(intid & TWL6040_READYINT)) { + dev_err(twl6040->dev, + "timeout waiting for READYINT\n"); + return -ETIMEDOUT; + } } - } - return 0; + /* + * Power on seemingly completed. + * READYINT received, but not in expected state, retry. + */ + gpio_set_value(twl6040->audpwron, 0); + usleep_range(1000, 1500); + } while (round++ < 3); + + return -ENODEV; } int twl6040_power(struct twl6040 *twl6040, int on) @@ -250,8 +312,6 @@ int twl6040_power(struct twl6040 *twl6040, int on) goto out; if (gpio_is_valid(audpwron)) { - /* use AUDPWRON line */ - gpio_set_value(audpwron, 1); /* wait for power-up completion */ ret = twl6040_power_up_completion(twl6040, naudint); if (ret) { diff --git a/drivers/omap_hsi/hsi_driver.c b/drivers/omap_hsi/hsi_driver.c index e54af8f28ed3..cb39c5ee0af4 100644 --- a/drivers/omap_hsi/hsi_driver.c +++ b/drivers/omap_hsi/hsi_driver.c @@ -273,6 +273,10 @@ static void __devexit unregister_hsi_devices(struct hsi_dev *hsi_ctrl) void hsi_set_pm_default(struct hsi_dev *hsi_ctrl) { + /* On OMAP5+, stop interfering with HWMOD mngmnt of SYSCONFIG */ + if (cpu_is_omap54xx()) + return; + /* Set default SYSCONFIG PM settings */ hsi_outl((HSI_AUTOIDLE | HSI_SIDLEMODE_SMART_WAKEUP | HSI_MIDLEMODE_SMART_WAKEUP), @@ -284,6 +288,10 @@ void hsi_set_pm_default(struct hsi_dev *hsi_ctrl) void hsi_set_pm_force_hsi_on(struct hsi_dev *hsi_ctrl) { + /* On OMAP5+, stop interfering with HWMOD mngmnt of SYSCONFIG */ + if (cpu_is_omap54xx()) + return; + /* Force HSI to ON by never acknowledging a PRCM idle request */ /* SIdleAck and MStandby are never asserted */ hsi_outl((HSI_AUTOIDLE | HSI_SIDLEMODE_NO | diff --git a/drivers/omap_hsi/hsi_driver_int.c b/drivers/omap_hsi/hsi_driver_int.c index 9629f0bcc0aa..e4d1f07c662e 100644 --- a/drivers/omap_hsi/hsi_driver_int.c +++ b/drivers/omap_hsi/hsi_driver_int.c @@ -821,16 +821,23 @@ static void do_hsi_tasklet(unsigned long hsi_port) struct hsi_port *pport = (struct hsi_port *)hsi_port; struct hsi_dev *hsi_ctrl = pport->hsi_controller; u32 status_reg; + int err; dev_dbg(hsi_ctrl->dev, "Int Tasklet : clock_enabled=%d\n", hsi_ctrl->clock_enabled); spin_lock(&hsi_ctrl->lock); - hsi_clocks_enable(hsi_ctrl->dev, __func__); + err = hsi_clocks_enable(hsi_ctrl->dev, __func__); + if ((err < 0) && (err != -EEXIST)) { + dev_err(hsi_ctrl->dev, "%s: hsi_clocks_enable error = %d\n", + __func__, err); + goto rback; + } pport->in_int_tasklet = true; status_reg = hsi_process_int_event(pport); pport->in_int_tasklet = false; +rback: clear_bit(HSI_FLAGS_TASKLET_LOCK, &pport->flags); hsi_clocks_disable(hsi_ctrl->dev, __func__); spin_unlock(&hsi_ctrl->lock); diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index cf8a6f62dee5..f2a5fb7c50c3 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h @@ -93,6 +93,7 @@ #define TWL6040_NCPENA 0x01 #define TWL6040_NCPOPEN 0x40 +#define TWL6040_TSHUTENA 0x80 /* LDOCTL (0x06) fields */ |