summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Tsunaev <vladimirt@motorola.com>2014-06-09 14:05:31 -0400
committerVladimir Tsunaev <vladimirt@motorola.com>2014-06-09 15:04:35 -0400
commit53edb57d3c450d21332bb7761110853005b2b3df (patch)
tree30e64d8568330dcdd76063c4d60566bc2f15dde1
parent4f375998dbe2515e83ff368411ea48daf3106e68 (diff)
downloadolio-linux-3.10-53edb57d3c450d21332bb7761110853005b2b3df.tar.xz
olio-linux-3.10-53edb57d3c450d21332bb7761110853005b2b3df.zip
IKXCLOCK-1638 Idle Mode Retention
Signed-off-by: Vladimir Tsunaev <vladimirt@motorola.com>
-rw-r--r--arch/arm/mach-omap2/board-minnow.c1
-rw-r--r--arch/arm/mach-omap2/cpuidle34xx.c2
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c2
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.h2
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c4
-rw-r--r--arch/arm/mach-omap2/pm34xx.c25
-rw-r--r--arch/arm/mach-omap2/serial.c4
-rw-r--r--drivers/misc/ti-st/st_core.c52
-rw-r--r--drivers/misc/ti-st/st_kim.c3
-rw-r--r--drivers/misc/ti-st/st_ll.c8
-rw-r--r--drivers/tty/serial/omap-serial.c185
-rw-r--r--drivers/usb/phy/phy-tusb.c2
-rw-r--r--include/linux/platform_data/serial-omap.h6
-rw-r--r--include/linux/ti_wilink_st.h3
14 files changed, 163 insertions, 136 deletions
diff --git a/arch/arm/mach-omap2/board-minnow.c b/arch/arm/mach-omap2/board-minnow.c
index 82748e2f6ce..af6f13b371d 100644
--- a/arch/arm/mach-omap2/board-minnow.c
+++ b/arch/arm/mach-omap2/board-minnow.c
@@ -45,6 +45,7 @@ static const char *omap3_gp_boards_compat[] __initdata = {
struct ti_st_plat_data wilink_pdata = {
.nshutdown_gpio = 83,
.dev_name = "/dev/ttyO1",
+ .port_index = 1,
.flow_cntrl = 1,
.baud_rate = 3000000,
.suspend = platform_wilink_kim_suspend,
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 4e176916fd2..039fe44215d 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -86,7 +86,7 @@ static struct omap3_idle_statedata omap3_idle_data[] = {
{
.mpu_state = PWRDM_POWER_RET,
.core_state = PWRDM_POWER_RET,
- .per_min_state = PWRDM_POWER_OFF,
+ .per_min_state = PWRDM_POWER_RET,
},
{
.mpu_state = PWRDM_POWER_OFF,
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 7341eff63f5..5cc51234add 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2015,7 +2015,7 @@ static int _reset(struct omap_hwmod *oh)
* XXX When the PRM code is moved to drivers, this function can be removed,
* as the PRM infrastructure should abstract this.
*/
-static void _reconfigure_io_chain(void)
+void _reconfigure_io_chain(void)
{
unsigned long flags;
diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h
index 0c898f58ac9..dd6852ff898 100644
--- a/arch/arm/mach-omap2/omap_hwmod.h
+++ b/arch/arm/mach-omap2/omap_hwmod.h
@@ -703,4 +703,6 @@ extern int am33xx_hwmod_init(void);
extern int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois);
+void _reconfigure_io_chain(void);
+
#endif
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 7c5a6b81875..36c70965ddc 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -490,7 +490,6 @@ static struct omap_hwmod omap3xxx_uart1_hwmod = {
.mpu_irqs = omap2_uart1_mpu_irqs,
.sdma_reqs = omap2_uart1_sdma_reqs,
.main_clk = "uart1_fck",
- .flags = HWMOD_SWSUP_SIDLE_ACT,
.prcm = {
.omap2 = {
.module_offs = CORE_MOD,
@@ -509,7 +508,6 @@ static struct omap_hwmod omap3xxx_uart2_hwmod = {
.mpu_irqs = omap2_uart2_mpu_irqs,
.sdma_reqs = omap2_uart2_sdma_reqs,
.main_clk = "uart2_fck",
- .flags = HWMOD_SWSUP_SIDLE_ACT,
.prcm = {
.omap2 = {
.module_offs = CORE_MOD,
@@ -528,7 +526,6 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = {
.mpu_irqs = omap2_uart3_mpu_irqs,
.sdma_reqs = omap2_uart3_sdma_reqs,
.main_clk = "uart3_fck",
- .flags = HWMOD_SWSUP_SIDLE_ACT,
.prcm = {
.omap2 = {
.module_offs = OMAP3430_PER_MOD,
@@ -558,7 +555,6 @@ static struct omap_hwmod omap36xx_uart4_hwmod = {
.mpu_irqs = uart4_mpu_irqs,
.sdma_reqs = uart4_sdma_reqs,
.main_clk = "uart4_fck",
- .flags = HWMOD_SWSUP_SIDLE_ACT,
.prcm = {
.omap2 = {
.module_offs = OMAP3430_PER_MOD,
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 65f4a7f8185..ceedc07fea0 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -30,6 +30,7 @@
#include <linux/slab.h>
#include <linux/omap-dma.h>
#include <linux/platform_data/gpio-omap.h>
+#include <linux/pm_runtime.h>
#include <trace/events/power.h>
@@ -53,6 +54,7 @@
#include "control.h"
#include "pm-debug-regs.h"
#include "iomap.h"
+#include "omap_device.h"
#include "pad_wkup.h"
@@ -77,6 +79,7 @@ void (*omap3_do_wfi_sram)(void);
static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
static struct powerdomain *core_pwrdm, *per_pwrdm;
static struct powerdomain *dss_pwrdm;
+static struct omap_hwmod *wd_hwmod;
static void omap3_core_save_context(void)
{
@@ -151,6 +154,7 @@ static void omap3_save_secure_ram_context(void)
*/
static int prcm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
{
+ static struct clk *per_dpll_clk;
u32 wkst, fclk, iclk, clken;
u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1;
u16 fclk_off = (regs == 3) ? OMAP3430ES2_CM_FCLKEN3 : CM_FCLKEN1;
@@ -163,6 +167,16 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
wkst &= omap2_prm_read_mod_reg(module, grpsel_off);
wkst &= ~ignore_bits;
if (wkst) {
+ if (module != WKUP_MOD) {
+ if (per_dpll_clk == NULL) {
+ per_dpll_clk = clk_get(NULL, "dpll4_ck");
+ if (per_dpll_clk == NULL) {
+ pr_emerg("Unable to get dpll4_ck\n");
+ BUG();
+ }
+ }
+ clk_enable(per_dpll_clk);
+ }
iclk = omap2_cm_read_mod_reg(module, iclk_off);
fclk = omap2_cm_read_mod_reg(module, fclk_off);
while (wkst) {
@@ -191,6 +205,8 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
}
omap2_cm_write_mod_reg(iclk, module, iclk_off);
omap2_cm_write_mod_reg(fclk, module, fclk_off);
+ if (module != WKUP_MOD)
+ clk_disable(per_dpll_clk);
}
return c;
@@ -200,6 +216,7 @@ static irqreturn_t _prcm_int_handle_io(int irq, void *unused)
{
int c;
+ _reconfigure_io_chain();
c = prcm_clear_mod_irqs(WKUP_MOD, 1,
~(OMAP3430_ST_IO_MASK | OMAP3430_ST_IO_CHAIN_MASK));
@@ -309,6 +326,10 @@ void omap_sram_idle(bool in_suspend)
/* CORE */
if (core_next_state < PWRDM_POWER_ON) {
+ _reconfigure_io_chain();
+ if (!in_suspend && wd_hwmod != NULL)
+ platform_pm_suspend(&wd_hwmod->od->pdev->dev);
+
if (core_next_state == PWRDM_POWER_OFF) {
omap3_core_save_context();
omap3_cm_save_context();
@@ -360,6 +381,9 @@ void omap_sram_idle(bool in_suspend)
/* CORE */
if (core_next_state < PWRDM_POWER_ON) {
+ if (!in_suspend && wd_hwmod != NULL)
+ platform_pm_resume(&wd_hwmod->od->pdev->dev);
+
core_prev_state = pwrdm_read_prev_pwrst(core_pwrdm);
if (core_prev_state == PWRDM_POWER_OFF) {
omap3_core_restore_context();
@@ -750,6 +774,7 @@ int __init omap3_pm_init(void)
ret = -EINVAL;
goto err3;
}
+ wd_hwmod = omap_hwmod_lookup("wd_timer2");
neon_pwrdm = pwrdm_lookup("neon_pwrdm");
per_pwrdm = pwrdm_lookup("per_pwrdm");
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index f6601563aa6..80cd45fa8d8 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -81,7 +81,7 @@ static struct omap_uart_port_info omap_serial_default_info[] __initdata = {
};
#ifdef CONFIG_PM
-static void omap_uart_enable_wakeup(struct device *dev, bool enable)
+void omap_uart_enable_wakeup(struct device *dev, bool enable)
{
struct platform_device *pdev = to_platform_device(dev);
struct omap_device *od = to_omap_device(pdev);
@@ -96,7 +96,7 @@ static void omap_uart_enable_wakeup(struct device *dev, bool enable)
}
#else
-static void omap_uart_enable_wakeup(struct device *dev, bool enable)
+void omap_uart_enable_wakeup(struct device *dev, bool enable)
{}
#endif /* CONFIG_PM */
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index ef6e56907c2..d0bf4e9e46d 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -20,6 +20,7 @@
*/
#define pr_fmt(fmt) "(stc): " fmt
+#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -36,14 +37,6 @@
static struct wake_lock st_wk_lock_timeout;
-struct st_pm_qos_t {
- struct pm_qos_request st_pm_qos_request;
- u32 st_pm_qos_latency;
- spinlock_t st_pm_qos_lock; /* protect internal members */
-};
-
-static struct st_pm_qos_t st_pm_qos;
-
extern void st_kim_recv(void *, const unsigned char *, long);
void st_int_recv(void *, const unsigned char *, long);
/* function pointer pointing to either,
@@ -71,44 +64,6 @@ static void remove_channel_from_table(struct st_data_s *st_gdata,
}
/*
- * called when Bluetooth IC changes sleep state.
- *
- * This function dynamically changes pm_qos to allow
- * CPU to go to deep idle state when there is no
- * communication between host and Bluetooth IC.
- */
-void st_pm_qos_update(struct st_data_s *st_gdata, bool awake)
-{
- struct kim_data_s *kim_plat_data;
- u32 latency;
- unsigned long flags;
-
- if (unlikely(st_gdata == NULL || st_gdata->kim_data == NULL)) {
- pr_err("%s: Invalid argument\n", __func__);
- return;
- }
-
- spin_lock_irqsave(&st_pm_qos.st_pm_qos_lock, flags);
-
- kim_plat_data = (struct kim_data_s *)st_gdata->kim_data;
- if (awake) {
- /* UART FIFO is 64 bytes */
- latency = (USEC_PER_SEC * 64) / (kim_plat_data->baud_rate / 8);
- } else {
- /* drop PM QoS constraint */
- latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
- }
-
- if (st_pm_qos.st_pm_qos_latency != latency) {
- st_pm_qos.st_pm_qos_latency = latency;
- pm_qos_update_request(&st_pm_qos.st_pm_qos_request,
- st_pm_qos.st_pm_qos_latency);
- }
-
- spin_unlock_irqrestore(&st_pm_qos.st_pm_qos_lock, flags);
-}
-
-/*
* called from KIM during firmware download.
*
* This is a wrapper function to tty->ops->write_room.
@@ -899,10 +854,6 @@ int st_core_init(struct st_data_s **core_data)
long err;
wake_lock_init(&st_wk_lock_timeout, WAKE_LOCK_SUSPEND, "st_wake_lock");
- spin_lock_init(&st_pm_qos.st_pm_qos_lock);
- pm_qos_add_request(&st_pm_qos.st_pm_qos_request,
- PM_QOS_CPU_DMA_LATENCY,
- PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE);
err = tty_register_ldisc(N_TI_WL, &st_ldisc_ops);
if (err) {
pr_err("error registering %d line discipline %ld\n",
@@ -964,7 +915,6 @@ void st_core_exit(struct st_data_s *st_gdata)
/* free the global data pointer */
kfree(st_gdata);
}
- pm_qos_remove_request(&st_pm_qos.st_pm_qos_request);
wake_lock_destroy(&st_wk_lock_timeout);
}
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 00450fdb8a1..16e2cd81b10 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -465,7 +465,7 @@ long st_kim_start(void *kim_data)
pr_info("%s\n", __func__);
pdata = kim_gdata->kim_pdev->dev.platform_data;
-
+ omap_serial_runtime_get(pdata->port_index);
do {
/* platform specific enabling code here */
if (pdata->chip_enable)
@@ -507,6 +507,7 @@ long st_kim_start(void *kim_data)
}
}
} while (retry--);
+ omap_serial_runtime_put(pdata->port_index);
return err;
}
diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c
index 9b9ef562073..d746071db81 100644
--- a/drivers/misc/ti-st/st_ll.c
+++ b/drivers/misc/ti-st/st_ll.c
@@ -30,16 +30,20 @@
static void send_ll_cmd(struct st_data_s *st_data,
unsigned char cmd)
{
+ struct kim_data_s *kim_plat_data;
+ struct ti_st_plat_data *pdata;
pr_debug("%s: writing %x\n", __func__, cmd);
+ kim_plat_data = (struct kim_data_s *)st_data->kim_data;
+ pdata = kim_plat_data->kim_pdev->dev.platform_data;
if (cmd == LL_WAKE_UP_IND || cmd == LL_WAKE_UP_ACK)
- st_pm_qos_update(st_data, 1);
+ omap_serial_runtime_get(pdata->port_index);
st_int_write(st_data, &cmd, 1);
if (cmd == LL_SLEEP_ACK)
- st_pm_qos_update(st_data, 0);
+ omap_serial_runtime_put(pdata->port_index);
return;
}
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 93a6329be81..aaad63b7fe8 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -61,6 +61,7 @@
#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7)
#define OMAP_UART_SCR_TX_TRIG_GRANU1_MASK (1 << 6)
#define OMAP_UART_SCR_TX_EMPTY (1 << 3)
+#define OMAP_UART_SCR_RX_CTS_WU_EN (1 << 4)
/* FCR register bitmasks */
#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK (0x3 << 6)
@@ -150,19 +151,21 @@ struct uart_omap_port {
unsigned long port_activity;
int context_loss_cnt;
u32 errata;
- u8 wakeups_enabled;
int DTR_gpio;
int DTR_inverted;
int DTR_active;
- bool pm_qos_disabled;
struct pm_qos_request pm_qos_request;
u32 latency;
u32 calc_latency;
struct work_struct qos_work;
struct pinctrl *pins;
bool is_suspending;
+ bool in_transmit;
+ int ext_rt_cnt;
+ bool open_close_pm;
+ int (*get_context_loss_count)(struct device *);
};
#define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port)))
@@ -172,7 +175,44 @@ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
/* Forward declaration of functions */
static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1);
-static struct workqueue_struct *serial_omap_uart_wq;
+
+void omap_serial_runtime_get(int port_index)
+{
+ struct uart_omap_port *up;
+ int ext_rt_cnt;
+
+ if (port_index >= OMAP_MAX_HSUART_PORTS)
+ return;
+ up = ui[port_index];
+
+ spin_lock(&up->port.lock);
+ ext_rt_cnt = up->ext_rt_cnt;
+ up->ext_rt_cnt = 1;
+ spin_unlock(&up->port.lock);
+
+ if (up->dev && !ext_rt_cnt)
+ pm_runtime_get_sync(up->dev);
+}
+
+void omap_serial_runtime_put(int port_index)
+{
+ struct uart_omap_port *up;
+ int ext_rt_cnt;
+
+ if (port_index >= OMAP_MAX_HSUART_PORTS)
+ return;
+ up = ui[port_index];
+
+ spin_lock(&up->port.lock);
+ ext_rt_cnt = up->ext_rt_cnt;
+ up->ext_rt_cnt = 0;
+ spin_unlock(&up->port.lock);
+
+ if (up->dev && ext_rt_cnt) {
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
+ }
+}
static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
{
@@ -196,22 +236,9 @@ static inline void serial_omap_clear_fifos(struct uart_omap_port *up)
static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
{
- struct omap_uart_port_info *pdata = up->dev->platform_data;
-
- if (!pdata || !pdata->get_context_loss_count)
+ if (!up->get_context_loss_count)
return 0;
-
- return pdata->get_context_loss_count(up->dev);
-}
-
-static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
-{
- struct omap_uart_port_info *pdata = up->dev->platform_data;
-
- if (!pdata || !pdata->enable_wakeup)
- return;
-
- pdata->enable_wakeup(up->dev, enable);
+ return up->get_context_loss_count(up->dev);
}
/*
@@ -272,12 +299,31 @@ static void serial_omap_enable_ms(struct uart_port *port)
static void serial_omap_stop_tx(struct uart_port *port)
{
+ int cnt;
struct uart_omap_port *up = to_uart_omap_port(port);
pm_runtime_get_sync(up->dev);
if (up->ier & UART_IER_THRI) {
up->ier &= ~UART_IER_THRI;
serial_out(up, UART_IER, up->ier);
+ /*
+ * wait for empty fifo before release pm runtime
+ * 2500 * 200 = 500mS delay. If external devices holding
+ * transmission so long, then asume it is dead and clear FIFO
+ */
+ cnt = 2500;
+ while (!(serial_in(up, UART_LSR) & UART_LSR_TEMT) && cnt) {
+ udelay(200); /* about 3 bytes with 115.2 */
+ cnt--;
+ }
+ if (!cnt)
+ serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT);
+
+ if (up->in_transmit) {
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
+ up->in_transmit = false;
+ }
}
pm_runtime_mark_last_busy(up->dev);
@@ -302,15 +348,28 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
int count;
if (up->port.x_char) {
+ if (!up->in_transmit) {
+ up->in_transmit = true;
+ pm_runtime_get_sync(up->dev);
+ }
serial_out(up, UART_TX, up->port.x_char);
up->port.icount.tx++;
up->port.x_char = 0;
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+ if (up->in_transmit) {
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
+ up->in_transmit = false;
+ }
serial_omap_stop_tx(&up->port);
return;
}
+ if (!up->in_transmit) {
+ up->in_transmit = true;
+ pm_runtime_get_sync(up->dev);
+ }
count = up->port.fifosize / 4;
do {
serial_out(up, UART_TX, xmit->buf[xmit->tail]);
@@ -596,17 +655,19 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
UART_MCR_DTR | UART_MCR_RTS);
up->mcr = old_mcr | mcr;
serial_out(up, UART_MCR, up->mcr);
- pm_runtime_mark_last_busy(up->dev);
- pm_runtime_put_autosuspend(up->dev);
if (gpio_is_valid(up->DTR_gpio) &&
!!(mctrl & TIOCM_DTR) != up->DTR_active) {
up->DTR_active = !up->DTR_active;
- if (gpio_cansleep(up->DTR_gpio))
- schedule_work(&up->qos_work);
- else
+ if (gpio_cansleep(up->DTR_gpio)) {
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
+ } else
gpio_set_value(up->DTR_gpio,
up->DTR_active != up->DTR_inverted);
+ } else {
+ pm_runtime_mark_last_busy(up->dev);
+ pm_runtime_put_autosuspend(up->dev);
}
}
@@ -728,12 +789,9 @@ static void serial_omap_shutdown(struct uart_port *port)
free_irq(up->port.irq, up);
}
-static void serial_omap_uart_qos_work(struct work_struct *work)
+static void serial_omap_uart_qos(struct uart_omap_port *up)
{
- struct uart_omap_port *up = container_of(work, struct uart_omap_port,
- qos_work);
- if (!up->pm_qos_disabled)
- pm_qos_update_request(&up->pm_qos_request, up->latency);
+ pm_qos_update_request(&up->pm_qos_request, up->latency);
if (gpio_is_valid(up->DTR_gpio))
gpio_set_value_cansleep(up->DTR_gpio,
@@ -784,7 +842,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
/* calculate wakeup latency constraint */
up->calc_latency = (USEC_PER_SEC * up->port.fifosize) / (baud / 8);
up->latency = up->calc_latency;
- schedule_work(&up->qos_work);
up->dll = quot & 0xff;
up->dlh = quot >> 8;
@@ -867,6 +924,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
/* FIFO ENABLE, DMA MODE */
up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;
+
/*
* NOTE: Setting OMAP_UART_SCR_RX_TRIG_GRANU1_MASK
* sets Enables the granularity of 1 for TRIGGER RX
@@ -1000,15 +1058,6 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line);
}
-static int serial_omap_set_wake(struct uart_port *port, unsigned int state)
-{
- struct uart_omap_port *up = to_uart_omap_port(port);
-
- serial_omap_enable_wakeup(up, state);
-
- return 0;
-}
-
static void
serial_omap_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
@@ -1029,12 +1078,10 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
serial_out(up, UART_EFR, efr);
serial_out(up, UART_LCR, 0);
- if (!device_may_wakeup(up->dev)) {
- if (!state)
- pm_runtime_forbid(up->dev);
- else
- pm_runtime_allow(up->dev);
- }
+ if (!state && (up->open_close_pm || !device_may_wakeup(up->dev)))
+ pm_runtime_forbid(up->dev);
+ else if (state && (up->open_close_pm || !device_may_wakeup(up->dev)))
+ pm_runtime_allow(up->dev);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
@@ -1271,7 +1318,6 @@ static struct uart_ops serial_omap_pops = {
.shutdown = serial_omap_shutdown,
.set_termios = serial_omap_set_termios,
.pm = serial_omap_pm,
- .set_wake = serial_omap_set_wake,
.type = serial_omap_type,
.release_port = serial_omap_release_port,
.request_port = serial_omap_request_port,
@@ -1313,7 +1359,6 @@ static int serial_omap_suspend(struct device *dev)
struct uart_omap_port *up = dev_get_drvdata(dev);
uart_suspend_port(&serial_omap_reg, &up->port);
- flush_work(&up->qos_work);
return 0;
}
@@ -1396,9 +1441,12 @@ static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
&omap_up_info->uartclk);
of_property_read_u32(dev->of_node, "flags",
&omap_up_info->flags);
- omap_up_info->pm_qos_disabled = of_property_read_bool(dev->of_node,
- "ti,no-pm-qos");
-
+ omap_up_info->wakeup_capable = of_property_read_bool(dev->of_node,
+ "wakeup-capable");
+ of_property_read_u32(dev->of_node, "autosuspend-delay",
+ &omap_up_info->autosuspend_timeout);
+ omap_up_info->open_close_pm = of_property_read_bool(dev->of_node,
+ "open_close_pm");
return omap_up_info;
}
@@ -1502,13 +1550,11 @@ static int serial_omap_probe(struct platform_device *pdev)
up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
up->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
- up->pm_qos_disabled = omap_up_info->pm_qos_disabled;
pm_qos_add_request(&up->pm_qos_request,
PM_QOS_CPU_DMA_LATENCY, up->latency);
- serial_omap_uart_wq = create_singlethread_workqueue(up->name);
- INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
platform_set_drvdata(pdev, up);
+
pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev,
@@ -1517,6 +1563,9 @@ static int serial_omap_probe(struct platform_device *pdev)
pm_runtime_irq_safe(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
+ if (omap_up_info->wakeup_capable)
+ device_init_wakeup(&pdev->dev, true);
+
omap_serial_fill_features_erratas(up);
ui[up->port.line] = up;
@@ -1526,6 +1575,9 @@ static int serial_omap_probe(struct platform_device *pdev)
if (ret != 0)
goto err_add_port;
+ up->open_close_pm = omap_up_info->open_close_pm;
+ up->get_context_loss_count = omap_pm_get_dev_context_loss_count;
+
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
return 0;
@@ -1619,7 +1671,6 @@ static void serial_omap_restore_context(struct uart_omap_port *up)
static int serial_omap_runtime_suspend(struct device *dev)
{
struct uart_omap_port *up = dev_get_drvdata(dev);
- struct omap_uart_port_info *pdata = dev->platform_data;
/*
* When using 'no_console_suspend', the console UART must not be
@@ -1634,26 +1685,14 @@ static int serial_omap_runtime_suspend(struct device *dev)
if (!up)
return -EINVAL;
- if (!pdata)
- goto qos;
-
up->context_loss_cnt = serial_omap_get_context_loss_count(up);
if (device_may_wakeup(dev)) {
- if (!up->wakeups_enabled) {
- serial_omap_enable_wakeup(up, true);
- up->wakeups_enabled = true;
- }
- } else {
- if (up->wakeups_enabled) {
- serial_omap_enable_wakeup(up, false);
- up->wakeups_enabled = false;
- }
+ up->scr |= OMAP_UART_SCR_RX_CTS_WU_EN;
+ serial_out(up, UART_OMAP_SCR, up->scr);
}
-
-qos:
up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
- schedule_work(&up->qos_work);
+ serial_omap_uart_qos(up);
return 0;
}
@@ -1663,17 +1702,17 @@ static int serial_omap_runtime_resume(struct device *dev)
struct uart_omap_port *up = dev_get_drvdata(dev);
int loss_cnt = serial_omap_get_context_loss_count(up);
-
if (loss_cnt < 0) {
- dev_err(dev, "serial_omap_get_context_loss_count failed : %d\n",
- loss_cnt);
serial_omap_restore_context(up);
} else if (up->context_loss_cnt != loss_cnt) {
serial_omap_restore_context(up);
}
+ if (device_may_wakeup(dev)) {
+ up->scr &= ~OMAP_UART_SCR_RX_CTS_WU_EN;
+ serial_out(up, UART_OMAP_SCR, up->scr);
+ }
up->latency = up->calc_latency;
- schedule_work(&up->qos_work);
-
+ serial_omap_uart_qos(up);
return 0;
}
#endif
diff --git a/drivers/usb/phy/phy-tusb.c b/drivers/usb/phy/phy-tusb.c
index 451ac248c27..3f52584627e 100644
--- a/drivers/usb/phy/phy-tusb.c
+++ b/drivers/usb/phy/phy-tusb.c
@@ -183,10 +183,12 @@ static void tusb_usb_work_func(struct work_struct *work)
atomic_notifier_call_chain(&tusb->phy.notifier,
USB_EVENT_VBUS, NULL);
tusb->phy.last_event = USB_EVENT_VBUS;
+ omap_musb_mailbox(OMAP_MUSB_VBUS_VALID);
} else {
atomic_notifier_call_chain(&tusb->phy.notifier,
USB_EVENT_NONE, NULL);
tusb->phy.last_event = USB_EVENT_NONE;
+ omap_musb_mailbox(OMAP_MUSB_VBUS_OFF);
}
power_supply_changed(&tusb->psy);
diff --git a/include/linux/platform_data/serial-omap.h b/include/linux/platform_data/serial-omap.h
index 9041c6d5169..b2239557aa2 100644
--- a/include/linux/platform_data/serial-omap.h
+++ b/include/linux/platform_data/serial-omap.h
@@ -41,10 +41,14 @@ struct omap_uart_port_info {
int DTR_gpio;
int DTR_inverted;
int DTR_present;
- bool pm_qos_disabled;
+ bool wakeup_capable;
+ bool open_close_pm;
int (*get_context_loss_count)(struct device *);
void (*enable_wakeup)(struct device *, bool);
};
+extern void omap_uart_enable_wakeup(struct device *dev, bool enable);
+extern int omap_pm_get_dev_context_loss_count(struct device *dev);
+
#endif /* __OMAP_SERIAL_H__ */
diff --git a/include/linux/ti_wilink_st.h b/include/linux/ti_wilink_st.h
index bf2a954c848..d914cd9085c 100644
--- a/include/linux/ti_wilink_st.h
+++ b/include/linux/ti_wilink_st.h
@@ -401,6 +401,8 @@ void st_ll_disable(struct st_data_s *);
unsigned long st_ll_getstate(struct st_data_s *);
unsigned long st_ll_sleep_state(struct st_data_s *, unsigned char);
void st_ll_wakeup(struct st_data_s *);
+void omap_serial_runtime_get(int port_index);
+void omap_serial_runtime_put(int port_index);
/*
* header information used by st_core.c for FM and GPS
@@ -455,6 +457,7 @@ struct ti_st_plat_data {
int (*chip_disable) (struct kim_data_s *);
int (*chip_asleep) (struct kim_data_s *);
int (*chip_awake) (struct kim_data_s *);
+ int port_index;
};
#endif /* TI_WILINK_ST_H */