aboutsummaryrefslogtreecommitdiff
path: root/drivers/tty/serial/mrst_max3110.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/mrst_max3110.c')
-rw-r--r--drivers/tty/serial/mrst_max3110.c87
1 files changed, 46 insertions, 41 deletions
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c
index 58734d7e746..db0448ae59d 100644
--- a/drivers/tty/serial/mrst_max3110.c
+++ b/drivers/tty/serial/mrst_max3110.c
@@ -43,6 +43,7 @@
#include <linux/kthread.h>
#include <linux/spi/spi.h>
+#include <linux/pm.h>
#include "mrst_max3110.h"
@@ -61,6 +62,7 @@ struct uart_max3110 {
struct task_struct *main_thread;
struct task_struct *read_thread;
struct mutex thread_mutex;
+ struct mutex io_mutex;
u32 baud;
u16 cur_conf;
@@ -90,6 +92,7 @@ static int max3110_write_then_read(struct uart_max3110 *max,
struct spi_transfer x;
int ret;
+ mutex_lock(&max->io_mutex);
spi_message_init(&message);
memset(&x, 0, sizeof x);
x.len = len;
@@ -104,6 +107,7 @@ static int max3110_write_then_read(struct uart_max3110 *max,
/* Do the i/o */
ret = spi_sync(spi, &message);
+ mutex_unlock(&max->io_mutex);
return ret;
}
@@ -339,7 +343,7 @@ static int
receive_chars(struct uart_max3110 *max, unsigned short *str, int len)
{
struct uart_port *port = &max->port;
- struct tty_struct *tty;
+ struct tty_port *tport;
char buf[M3110_RX_FIFO_DEPTH];
int r, w, usable;
@@ -347,9 +351,7 @@ receive_chars(struct uart_max3110 *max, unsigned short *str, int len)
if (!port->state)
return 0;
- tty = tty_port_tty_get(&port->state->port);
- if (!tty)
- return 0;
+ tport = &port->state->port;
for (r = 0, w = 0; r < len; r++) {
if (str[r] & MAX3110_BREAK &&
@@ -364,20 +366,17 @@ receive_chars(struct uart_max3110 *max, unsigned short *str, int len)
}
}
- if (!w) {
- tty_kref_put(tty);
+ if (!w)
return 0;
- }
for (r = 0; w; r += usable, w -= usable) {
- usable = tty_buffer_request_room(tty, w);
+ usable = tty_buffer_request_room(tport, w);
if (usable) {
- tty_insert_flip_string(tty, buf + r, usable);
+ tty_insert_flip_string(tport, buf + r, usable);
port->icount.rx += usable;
}
}
- tty_flip_buffer_push(tty);
- tty_kref_put(tty);
+ tty_flip_buffer_push(tport);
return r;
}
@@ -493,22 +492,12 @@ static int serial_m3110_startup(struct uart_port *port)
| WC_BAUD_DR2;
/* as we use thread to handle tx/rx, need set low latency */
- port->state->port.tty->low_latency = 1;
+ port->state->port.low_latency = 1;
if (max->irq) {
- max->read_thread = NULL;
- ret = request_irq(max->irq, serial_m3110_irq,
- IRQ_TYPE_EDGE_FALLING, "max3110", max);
- if (ret) {
- max->irq = 0;
- pr_err(PR_FMT "unable to allocate IRQ, polling\n");
- } else {
- /* Enable RX IRQ only */
- config |= WC_RXA_IRQ_ENABLE;
- }
- }
-
- if (max->irq == 0) {
+ /* Enable RX IRQ only */
+ config |= WC_RXA_IRQ_ENABLE;
+ } else {
/* If IRQ is disabled, start a read thread for input data */
max->read_thread =
kthread_run(max3110_read_thread, max, "max3110_read");
@@ -522,8 +511,6 @@ static int serial_m3110_startup(struct uart_port *port)
ret = max3110_out(max, config);
if (ret) {
- if (max->irq)
- free_irq(max->irq, max);
if (max->read_thread)
kthread_stop(max->read_thread);
max->read_thread = NULL;
@@ -545,9 +532,6 @@ static void serial_m3110_shutdown(struct uart_port *port)
max->read_thread = NULL;
}
- if (max->irq)
- free_irq(max->irq, max);
-
/* Disable interrupts from this port */
config = WC_TAG | WC_SW_SHDI;
max3110_out(max, config);
@@ -718,7 +702,7 @@ static void serial_m3110_enable_ms(struct uart_port *port)
{
}
-struct uart_ops serial_m3110_ops = {
+static struct uart_ops serial_m3110_ops = {
.tx_empty = serial_m3110_tx_empty,
.set_mctrl = serial_m3110_set_mctrl,
.get_mctrl = serial_m3110_get_mctrl,
@@ -748,29 +732,37 @@ static struct uart_driver serial_m3110_reg = {
.cons = &serial_m3110_console,
};
-#ifdef CONFIG_PM
-static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int serial_m3110_suspend(struct device *dev)
{
+ struct spi_device *spi = to_spi_device(dev);
struct uart_max3110 *max = spi_get_drvdata(spi);
- disable_irq(max->irq);
+ if (max->irq > 0)
+ disable_irq(max->irq);
uart_suspend_port(&serial_m3110_reg, &max->port);
max3110_out(max, max->cur_conf | WC_SW_SHDI);
return 0;
}
-static int serial_m3110_resume(struct spi_device *spi)
+static int serial_m3110_resume(struct device *dev)
{
+ struct spi_device *spi = to_spi_device(dev);
struct uart_max3110 *max = spi_get_drvdata(spi);
max3110_out(max, max->cur_conf);
uart_resume_port(&serial_m3110_reg, &max->port);
- enable_irq(max->irq);
+ if (max->irq > 0)
+ enable_irq(max->irq);
return 0;
}
+
+static SIMPLE_DEV_PM_OPS(serial_m3110_pm_ops, serial_m3110_suspend,
+ serial_m3110_resume);
+#define SERIAL_M3110_PM_OPS (&serial_m3110_pm_ops)
+
#else
-#define serial_m3110_suspend NULL
-#define serial_m3110_resume NULL
+#define SERIAL_M3110_PM_OPS NULL
#endif
static int serial_m3110_probe(struct spi_device *spi)
@@ -802,6 +794,7 @@ static int serial_m3110_probe(struct spi_device *spi)
max->irq = (u16)spi->irq;
mutex_init(&max->thread_mutex);
+ mutex_init(&max->io_mutex);
max->word_7bits = 0;
max->parity = 0;
@@ -839,11 +832,21 @@ static int serial_m3110_probe(struct spi_device *spi)
goto err_kthread;
}
+ if (max->irq) {
+ ret = request_irq(max->irq, serial_m3110_irq,
+ IRQ_TYPE_EDGE_FALLING, "max3110", max);
+ if (ret) {
+ max->irq = 0;
+ dev_warn(&spi->dev,
+ "unable to allocate IRQ, will use polling method\n");
+ }
+ }
+
spi_set_drvdata(spi, max);
pmax = max;
/* Give membase a psudo value to pass serial_core's check */
- max->port.membase = (void *)0xff110000;
+ max->port.membase = (unsigned char __iomem *)0xff110000;
uart_add_one_port(&serial_m3110_reg, &max->port);
return 0;
@@ -866,6 +869,9 @@ static int serial_m3110_remove(struct spi_device *dev)
free_page((unsigned long)max->con_xmit.buf);
+ if (max->irq)
+ free_irq(max->irq, max);
+
if (max->main_thread)
kthread_stop(max->main_thread);
@@ -877,11 +883,10 @@ static struct spi_driver uart_max3110_driver = {
.driver = {
.name = "spi_max3111",
.owner = THIS_MODULE,
+ .pm = SERIAL_M3110_PM_OPS,
},
.probe = serial_m3110_probe,
.remove = serial_m3110_remove,
- .suspend = serial_m3110_suspend,
- .resume = serial_m3110_resume,
};
static int __init serial_m3110_init(void)