summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Murphy <dmurphy@ti.com>2012-08-28 11:00:12 -0500
committerDan Murphy <dmurphy@ti.com>2012-08-28 11:00:12 -0500
commit4896de1b379ca2e85517eb3315bcc2d9519454e4 (patch)
treef9ca0e060124e81ede1f490eaf8c462f84c9a53b
parentb1feb717103bbeafa7c8644340504bf35e00c883 (diff)
parent7a69299552ee88c6be4276157ace2c8be49478c8 (diff)
downloadomap-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.c10
-rw-r--r--arch/arm/mach-omap2/omap_hsi.c13
-rw-r--r--drivers/mfd/twl6040-core.c84
-rw-r--r--drivers/omap_hsi/hsi_driver.c8
-rw-r--r--drivers/omap_hsi/hsi_driver_int.c9
-rw-r--r--include/linux/mfd/twl6040.h1
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 */