diff options
Diffstat (limited to 'drivers/tty')
| -rw-r--r-- | drivers/tty/serial/omap-serial.c | 91 |
1 files changed, 81 insertions, 10 deletions
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 9b19ae172c3..a9c37ae9b2a 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -180,6 +180,8 @@ struct uart_omap_port { unsigned int rx_trig; int wakelock_timeout; int (*get_context_loss_count)(struct device *); + + bool rts_wait; }; #define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port))) @@ -1115,8 +1117,41 @@ static void serial_omap_wake_peer(struct uart_port *port) struct omap_uart_port_info *pdata = up->dev->platform_data; if (pdata->wake_peer) - pdata->wake_peer(port); + pdata->wake_peer(port); +} + +static void serial_omap_rts_enable(struct uart_port *port) +{ + struct uart_omap_port *up; + struct omap_uart_port_info *pdata; + + up = to_uart_omap_port(port); + + if ((up != NULL) && (up->dev != NULL) && (up->dev->platform_data != NULL)) { + pdata = up->dev->platform_data; + + if (pdata->rts_enable_fn) { + pdata->rts_enable_fn(); + } + } +} + +static void serial_omap_rts_disable(struct uart_port *port) +{ + struct uart_omap_port *up; + + up = to_uart_omap_port(port); + + if ((up != NULL) && (up->dev != NULL) && (up->dev->platform_data != NULL)) { + struct omap_uart_port_info *pdata = up->dev->platform_data; + + if (pdata->rts_disable_fn) { + pdata->rts_disable_fn(); + } + } } + + static void serial_omap_release_port(struct uart_port *port) { dev_dbg(port->dev, "serial_omap_release_port+\n"); @@ -1348,12 +1383,14 @@ static struct uart_ops serial_omap_pops = { .shutdown = serial_omap_shutdown, .set_termios = serial_omap_set_termios, .pm = serial_omap_pm, - .wake_peer = serial_omap_wake_peer, .type = serial_omap_type, .release_port = serial_omap_release_port, .request_port = serial_omap_request_port, .config_port = serial_omap_config_port, .verify_port = serial_omap_verify_port, + .wake_peer = serial_omap_wake_peer, + .rts_enable = serial_omap_rts_enable, + .rts_disable = serial_omap_rts_disable, #ifdef CONFIG_CONSOLE_POLL .poll_put_char = serial_omap_poll_put_char, .poll_get_char = serial_omap_poll_get_char, @@ -1364,7 +1401,7 @@ static struct uart_driver serial_omap_reg = { .owner = THIS_MODULE, .driver_name = "OMAP-SERIAL", .dev_name = OMAP_SERIAL_NAME, - .nr = OMAP_MAX_HSUART_PORTS, + .nr = OMAP_MAX_HSUART_PORTS, .cons = OMAP_CONSOLE, }; @@ -1372,9 +1409,17 @@ static struct uart_driver serial_omap_reg = { static int serial_omap_prepare(struct device *dev) { struct uart_omap_port *up = dev_get_drvdata(dev); + unsigned long flags; up->is_suspending = true; + if (up->rts_wait) { + spin_lock_irqsave(&up->delayed_rts_lock, flags); + up->port.ops->rts_disable(&(up->port)); + up->need_delayed_rts = 1; + spin_unlock_irqrestore(&up->delayed_rts_lock, flags); + } + return 0; } @@ -1389,6 +1434,12 @@ static void serial_omap_complete(struct device *dev) up->need_delayed_rts = 0; } + /* OLIO: We're not using pinctrl, but we still need rts delayed */ + else if (up->need_delayed_rts) { + up->port.ops->rts_enable(&(up->port)); + up->need_delayed_rts = 0; + } + up->is_suspending = false; spin_unlock_irqrestore(&up->delayed_rts_lock, flags); } @@ -1412,7 +1463,7 @@ static int serial_omap_resume(struct device *dev) } #else #define serial_omap_prepare NULL -#define serial_omap_prepare NULL +#define serial_omap_complete NULL #endif /* CONFIG_PM_SLEEP */ static void omap_serial_fill_features_erratas(struct uart_omap_port *up) @@ -1618,6 +1669,10 @@ static int serial_omap_probe(struct platform_device *pdev) goto err_ioremap; } + /* OLIO */ + if (omap_up_info->rts_wait) + up->rts_wait = omap_up_info->rts_wait; + up->rx_trig = omap_up_info->rx_trig; up->port.flags = omap_up_info->flags; up->port.uartclk = omap_up_info->uartclk; @@ -1781,6 +1836,15 @@ static int serial_omap_runtime_suspend(struct device *dev) up->need_delayed_rts = 0; spin_unlock_irqrestore(&up->delayed_rts_lock, flags); } + + /* OLIO */ + else if (up->rts_wait) { + spin_lock_irqsave(&up->delayed_rts_lock, flags); + up->port.ops->rts_disable(&(up->port)); + up->need_delayed_rts = 0; + spin_unlock_irqrestore(&up->delayed_rts_lock, flags); + } + up->context_loss_cnt = serial_omap_get_context_loss_count(up); if (device_may_wakeup(dev)) { @@ -1810,13 +1874,20 @@ static int serial_omap_runtime_resume(struct device *dev) } up->latency = up->calc_latency; serial_omap_uart_qos(up); - if (up->pin_default && up->pin_idle) { - if (up->is_suspending) - up->need_delayed_rts = 1; - else - pinctrl_select_state(up->pins, up->pin_default); - } + if (up->pin_default && up->pin_idle) { + if (up->is_suspending) + up->need_delayed_rts = 1; + else + pinctrl_select_state(up->pins, up->pin_default); + } + else if (up->rts_wait) { + if (up->is_suspending) + up->need_delayed_rts = 1; + else { + up->port.ops->rts_enable(&(up->port)); + } + } return 0; } #endif |