diff options
| author | Vladimir Tsunaev <vladimirt@motorola.com> | 2014-06-09 14:05:31 -0400 | 
|---|---|---|
| committer | Vladimir Tsunaev <vladimirt@motorola.com> | 2014-06-09 15:04:35 -0400 | 
| commit | 53edb57d3c450d21332bb7761110853005b2b3df (patch) | |
| tree | 30e64d8568330dcdd76063c4d60566bc2f15dde1 | |
| parent | 4f375998dbe2515e83ff368411ea48daf3106e68 (diff) | |
| download | olio-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.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 */ |