aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/samsung.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/samsung.c')
-rw-r--r--drivers/tty/serial/samsung.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 7f04717176aa..fb0e0f0bed0e 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -223,8 +223,11 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
223 struct uart_port *port = &ourport->port; 223 struct uart_port *port = &ourport->port;
224 struct tty_struct *tty = port->state->port.tty; 224 struct tty_struct *tty = port->state->port.tty;
225 unsigned int ufcon, ch, flag, ufstat, uerstat; 225 unsigned int ufcon, ch, flag, ufstat, uerstat;
226 unsigned long flags;
226 int max_count = 64; 227 int max_count = 64;
227 228
229 spin_lock_irqsave(&port->lock, flags);
230
228 while (max_count-- > 0) { 231 while (max_count-- > 0) {
229 ufcon = rd_regl(port, S3C2410_UFCON); 232 ufcon = rd_regl(port, S3C2410_UFCON);
230 ufstat = rd_regl(port, S3C2410_UFSTAT); 233 ufstat = rd_regl(port, S3C2410_UFSTAT);
@@ -299,6 +302,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
299 tty_flip_buffer_push(tty); 302 tty_flip_buffer_push(tty);
300 303
301 out: 304 out:
305 spin_unlock_irqrestore(&port->lock, flags);
302 return IRQ_HANDLED; 306 return IRQ_HANDLED;
303} 307}
304 308
@@ -307,8 +311,11 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
307 struct s3c24xx_uart_port *ourport = id; 311 struct s3c24xx_uart_port *ourport = id;
308 struct uart_port *port = &ourport->port; 312 struct uart_port *port = &ourport->port;
309 struct circ_buf *xmit = &port->state->xmit; 313 struct circ_buf *xmit = &port->state->xmit;
314 unsigned long flags;
310 int count = 256; 315 int count = 256;
311 316
317 spin_lock_irqsave(&port->lock, flags);
318
312 if (port->x_char) { 319 if (port->x_char) {
313 wr_regb(port, S3C2410_UTXH, port->x_char); 320 wr_regb(port, S3C2410_UTXH, port->x_char);
314 port->icount.tx++; 321 port->icount.tx++;
@@ -336,13 +343,17 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
336 port->icount.tx++; 343 port->icount.tx++;
337 } 344 }
338 345
339 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 346 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
347 spin_unlock(&port->lock);
340 uart_write_wakeup(port); 348 uart_write_wakeup(port);
349 spin_lock(&port->lock);
350 }
341 351
342 if (uart_circ_empty(xmit)) 352 if (uart_circ_empty(xmit))
343 s3c24xx_serial_stop_tx(port); 353 s3c24xx_serial_stop_tx(port);
344 354
345 out: 355 out:
356 spin_unlock_irqrestore(&port->lock, flags);
346 return IRQ_HANDLED; 357 return IRQ_HANDLED;
347} 358}
348 359
@@ -352,10 +363,8 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
352 struct s3c24xx_uart_port *ourport = id; 363 struct s3c24xx_uart_port *ourport = id;
353 struct uart_port *port = &ourport->port; 364 struct uart_port *port = &ourport->port;
354 unsigned int pend = rd_regl(port, S3C64XX_UINTP); 365 unsigned int pend = rd_regl(port, S3C64XX_UINTP);
355 unsigned long flags;
356 irqreturn_t ret = IRQ_HANDLED; 366 irqreturn_t ret = IRQ_HANDLED;
357 367
358 spin_lock_irqsave(&port->lock, flags);
359 if (pend & S3C64XX_UINTM_RXD_MSK) { 368 if (pend & S3C64XX_UINTM_RXD_MSK) {
360 ret = s3c24xx_serial_rx_chars(irq, id); 369 ret = s3c24xx_serial_rx_chars(irq, id);
361 wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK); 370 wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK);
@@ -364,7 +373,6 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
364 ret = s3c24xx_serial_tx_chars(irq, id); 373 ret = s3c24xx_serial_tx_chars(irq, id);
365 wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK); 374 wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK);
366 } 375 }
367 spin_unlock_irqrestore(&port->lock, flags);
368 return ret; 376 return ret;
369} 377}
370 378
@@ -530,16 +538,16 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
530 switch (level) { 538 switch (level) {
531 case 3: 539 case 3:
532 if (!IS_ERR(ourport->baudclk)) 540 if (!IS_ERR(ourport->baudclk))
533 clk_disable(ourport->baudclk); 541 clk_disable_unprepare(ourport->baudclk);
534 542
535 clk_disable(ourport->clk); 543 clk_disable_unprepare(ourport->clk);
536 break; 544 break;
537 545
538 case 0: 546 case 0:
539 clk_enable(ourport->clk); 547 clk_prepare_enable(ourport->clk);
540 548
541 if (!IS_ERR(ourport->baudclk)) 549 if (!IS_ERR(ourport->baudclk))
542 clk_enable(ourport->baudclk); 550 clk_prepare_enable(ourport->baudclk);
543 551
544 break; 552 break;
545 default: 553 default:
@@ -713,11 +721,11 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
713 s3c24xx_serial_setsource(port, clk_sel); 721 s3c24xx_serial_setsource(port, clk_sel);
714 722
715 if (!IS_ERR(ourport->baudclk)) { 723 if (!IS_ERR(ourport->baudclk)) {
716 clk_disable(ourport->baudclk); 724 clk_disable_unprepare(ourport->baudclk);
717 ourport->baudclk = ERR_PTR(-EINVAL); 725 ourport->baudclk = ERR_PTR(-EINVAL);
718 } 726 }
719 727
720 clk_enable(clk); 728 clk_prepare_enable(clk);
721 729
722 ourport->baudclk = clk; 730 ourport->baudclk = clk;
723 ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0; 731 ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
@@ -1256,7 +1264,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
1256 return ret; 1264 return ret;
1257} 1265}
1258 1266
1259static int __devexit s3c24xx_serial_remove(struct platform_device *dev) 1267static int s3c24xx_serial_remove(struct platform_device *dev)
1260{ 1268{
1261 struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); 1269 struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
1262 1270
@@ -1287,9 +1295,9 @@ static int s3c24xx_serial_resume(struct device *dev)
1287 struct s3c24xx_uart_port *ourport = to_ourport(port); 1295 struct s3c24xx_uart_port *ourport = to_ourport(port);
1288 1296
1289 if (port) { 1297 if (port) {
1290 clk_enable(ourport->clk); 1298 clk_prepare_enable(ourport->clk);
1291 s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port)); 1299 s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
1292 clk_disable(ourport->clk); 1300 clk_disable_unprepare(ourport->clk);
1293 1301
1294 uart_resume_port(&s3c24xx_uart_drv, port); 1302 uart_resume_port(&s3c24xx_uart_drv, port);
1295 } 1303 }
@@ -1701,6 +1709,16 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids);
1701 1709
1702#ifdef CONFIG_OF 1710#ifdef CONFIG_OF
1703static const struct of_device_id s3c24xx_uart_dt_match[] = { 1711static const struct of_device_id s3c24xx_uart_dt_match[] = {
1712 { .compatible = "samsung,s3c2410-uart",
1713 .data = (void *)S3C2410_SERIAL_DRV_DATA },
1714 { .compatible = "samsung,s3c2412-uart",
1715 .data = (void *)S3C2412_SERIAL_DRV_DATA },
1716 { .compatible = "samsung,s3c2440-uart",
1717 .data = (void *)S3C2440_SERIAL_DRV_DATA },
1718 { .compatible = "samsung,s3c6400-uart",
1719 .data = (void *)S3C6400_SERIAL_DRV_DATA },
1720 { .compatible = "samsung,s5pv210-uart",
1721 .data = (void *)S5PV210_SERIAL_DRV_DATA },
1704 { .compatible = "samsung,exynos4210-uart", 1722 { .compatible = "samsung,exynos4210-uart",
1705 .data = (void *)EXYNOS4210_SERIAL_DRV_DATA }, 1723 .data = (void *)EXYNOS4210_SERIAL_DRV_DATA },
1706 {}, 1724 {},
@@ -1712,7 +1730,7 @@ MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
1712 1730
1713static struct platform_driver samsung_serial_driver = { 1731static struct platform_driver samsung_serial_driver = {
1714 .probe = s3c24xx_serial_probe, 1732 .probe = s3c24xx_serial_probe,
1715 .remove = __devexit_p(s3c24xx_serial_remove), 1733 .remove = s3c24xx_serial_remove,
1716 .id_table = s3c24xx_serial_driver_ids, 1734 .id_table = s3c24xx_serial_driver_ids,
1717 .driver = { 1735 .driver = {
1718 .name = "samsung-uart", 1736 .name = "samsung-uart",