diff options
| -rw-r--r-- | arch/arm/mach-omap2/board-minnow.c | 1 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/cpuidle34xx.c | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.h | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 25 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/serial.c | 4 | ||||
| -rw-r--r-- | drivers/misc/ti-st/st_core.c | 52 | ||||
| -rw-r--r-- | drivers/misc/ti-st/st_kim.c | 3 | ||||
| -rw-r--r-- | drivers/misc/ti-st/st_ll.c | 8 | ||||
| -rw-r--r-- | drivers/tty/serial/omap-serial.c | 185 | ||||
| -rw-r--r-- | drivers/usb/phy/phy-tusb.c | 2 | ||||
| -rw-r--r-- | include/linux/platform_data/serial-omap.h | 6 | ||||
| -rw-r--r-- | include/linux/ti_wilink_st.h | 3 |
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 */ |