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.c90
1 files changed, 38 insertions, 52 deletions
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index c78f43a481ce..7ed76773c274 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -199,12 +199,14 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
199 } 199 }
200} 200}
201 201
202static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port) 202static inline struct s3c24xx_uart_info
203 *s3c24xx_port_to_info(struct uart_port *port)
203{ 204{
204 return to_ourport(port)->info; 205 return to_ourport(port)->info;
205} 206}
206 207
207static inline struct s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port) 208static inline struct s3c2410_uartcfg
209 *s3c24xx_port_to_cfg(struct uart_port *port)
208{ 210{
209 struct s3c24xx_uart_port *ourport; 211 struct s3c24xx_uart_port *ourport;
210 212
@@ -237,7 +239,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
237 struct uart_port *port = &ourport->port; 239 struct uart_port *port = &ourport->port;
238 unsigned int ufcon, ch, flag, ufstat, uerstat; 240 unsigned int ufcon, ch, flag, ufstat, uerstat;
239 unsigned long flags; 241 unsigned long flags;
240 int max_count = 64; 242 int max_count = port->fifosize;
241 243
242 spin_lock_irqsave(&port->lock, flags); 244 spin_lock_irqsave(&port->lock, flags);
243 245
@@ -311,14 +313,14 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
311 uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, 313 uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
312 ch, flag); 314 ch, flag);
313 315
314 ignore_char: 316ignore_char:
315 continue; 317 continue;
316 } 318 }
317 319
318 spin_unlock_irqrestore(&port->lock, flags); 320 spin_unlock_irqrestore(&port->lock, flags);
319 tty_flip_buffer_push(&port->state->port); 321 tty_flip_buffer_push(&port->state->port);
320 322
321 out: 323out:
322 return IRQ_HANDLED; 324 return IRQ_HANDLED;
323} 325}
324 326
@@ -328,7 +330,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
328 struct uart_port *port = &ourport->port; 330 struct uart_port *port = &ourport->port;
329 struct circ_buf *xmit = &port->state->xmit; 331 struct circ_buf *xmit = &port->state->xmit;
330 unsigned long flags; 332 unsigned long flags;
331 int count = 256; 333 int count = port->fifosize;
332 334
333 spin_lock_irqsave(&port->lock, flags); 335 spin_lock_irqsave(&port->lock, flags);
334 336
@@ -368,7 +370,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
368 if (uart_circ_empty(xmit)) 370 if (uart_circ_empty(xmit))
369 s3c24xx_serial_stop_tx(port); 371 s3c24xx_serial_stop_tx(port);
370 372
371 out: 373out:
372 spin_unlock_irqrestore(&port->lock, flags); 374 spin_unlock_irqrestore(&port->lock, flags);
373 return IRQ_HANDLED; 375 return IRQ_HANDLED;
374} 376}
@@ -519,7 +521,7 @@ static int s3c24xx_serial_startup(struct uart_port *port)
519 521
520 return ret; 522 return ret;
521 523
522 err: 524err:
523 s3c24xx_serial_shutdown(port); 525 s3c24xx_serial_shutdown(port);
524 return ret; 526 return ret;
525} 527}
@@ -559,11 +561,15 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
559 unsigned int old) 561 unsigned int old)
560{ 562{
561 struct s3c24xx_uart_port *ourport = to_ourport(port); 563 struct s3c24xx_uart_port *ourport = to_ourport(port);
564 int timeout = 10000;
562 565
563 ourport->pm_level = level; 566 ourport->pm_level = level;
564 567
565 switch (level) { 568 switch (level) {
566 case 3: 569 case 3:
570 while (--timeout && !s3c24xx_serial_txempty_nofifo(port))
571 udelay(100);
572
567 if (!IS_ERR(ourport->baudclk)) 573 if (!IS_ERR(ourport->baudclk))
568 clk_disable_unprepare(ourport->baudclk); 574 clk_disable_unprepare(ourport->baudclk);
569 575
@@ -841,8 +847,8 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
841 */ 847 */
842 port->read_status_mask = S3C2410_UERSTAT_OVERRUN; 848 port->read_status_mask = S3C2410_UERSTAT_OVERRUN;
843 if (termios->c_iflag & INPCK) 849 if (termios->c_iflag & INPCK)
844 port->read_status_mask |= S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_PARITY; 850 port->read_status_mask |= S3C2410_UERSTAT_FRAME |
845 851 S3C2410_UERSTAT_PARITY;
846 /* 852 /*
847 * Which character status flags should we ignore? 853 * Which character status flags should we ignore?
848 */ 854 */
@@ -969,10 +975,13 @@ static struct uart_driver s3c24xx_uart_drv = {
969 .minor = S3C24XX_SERIAL_MINOR, 975 .minor = S3C24XX_SERIAL_MINOR,
970}; 976};
971 977
972static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = { 978#define __PORT_LOCK_UNLOCKED(i) \
979 __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[i].port.lock)
980static struct s3c24xx_uart_port
981s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = {
973 [0] = { 982 [0] = {
974 .port = { 983 .port = {
975 .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock), 984 .lock = __PORT_LOCK_UNLOCKED(0),
976 .iotype = UPIO_MEM, 985 .iotype = UPIO_MEM,
977 .uartclk = 0, 986 .uartclk = 0,
978 .fifosize = 16, 987 .fifosize = 16,
@@ -983,7 +992,7 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS
983 }, 992 },
984 [1] = { 993 [1] = {
985 .port = { 994 .port = {
986 .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock), 995 .lock = __PORT_LOCK_UNLOCKED(1),
987 .iotype = UPIO_MEM, 996 .iotype = UPIO_MEM,
988 .uartclk = 0, 997 .uartclk = 0,
989 .fifosize = 16, 998 .fifosize = 16,
@@ -996,7 +1005,7 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS
996 1005
997 [2] = { 1006 [2] = {
998 .port = { 1007 .port = {
999 .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock), 1008 .lock = __PORT_LOCK_UNLOCKED(2),
1000 .iotype = UPIO_MEM, 1009 .iotype = UPIO_MEM,
1001 .uartclk = 0, 1010 .uartclk = 0,
1002 .fifosize = 16, 1011 .fifosize = 16,
@@ -1009,7 +1018,7 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS
1009#if CONFIG_SERIAL_SAMSUNG_UARTS > 3 1018#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
1010 [3] = { 1019 [3] = {
1011 .port = { 1020 .port = {
1012 .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock), 1021 .lock = __PORT_LOCK_UNLOCKED(3),
1013 .iotype = UPIO_MEM, 1022 .iotype = UPIO_MEM,
1014 .uartclk = 0, 1023 .uartclk = 0,
1015 .fifosize = 16, 1024 .fifosize = 16,
@@ -1020,6 +1029,7 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS
1020 } 1029 }
1021#endif 1030#endif
1022}; 1031};
1032#undef __PORT_LOCK_UNLOCKED
1023 1033
1024/* s3c24xx_serial_resetport 1034/* s3c24xx_serial_resetport
1025 * 1035 *
@@ -1102,11 +1112,12 @@ static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
1102 s3c24xx_serial_set_termios(uport, termios, NULL); 1112 s3c24xx_serial_set_termios(uport, termios, NULL);
1103 } 1113 }
1104 1114
1105 exit: 1115exit:
1106 return 0; 1116 return 0;
1107} 1117}
1108 1118
1109static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port) 1119static inline int
1120s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
1110{ 1121{
1111 port->freq_transition.notifier_call = s3c24xx_serial_cpufreq_transition; 1122 port->freq_transition.notifier_call = s3c24xx_serial_cpufreq_transition;
1112 1123
@@ -1114,19 +1125,22 @@ static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port
1114 CPUFREQ_TRANSITION_NOTIFIER); 1125 CPUFREQ_TRANSITION_NOTIFIER);
1115} 1126}
1116 1127
1117static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port) 1128static inline void
1129s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
1118{ 1130{
1119 cpufreq_unregister_notifier(&port->freq_transition, 1131 cpufreq_unregister_notifier(&port->freq_transition,
1120 CPUFREQ_TRANSITION_NOTIFIER); 1132 CPUFREQ_TRANSITION_NOTIFIER);
1121} 1133}
1122 1134
1123#else 1135#else
1124static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port) 1136static inline int
1137s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port)
1125{ 1138{
1126 return 0; 1139 return 0;
1127} 1140}
1128 1141
1129static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port) 1142static inline void
1143s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port)
1130{ 1144{
1131} 1145}
1132#endif 1146#endif
@@ -1226,24 +1240,6 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
1226 return 0; 1240 return 0;
1227} 1241}
1228 1242
1229#ifdef CONFIG_SAMSUNG_CLOCK
1230static ssize_t s3c24xx_serial_show_clksrc(struct device *dev,
1231 struct device_attribute *attr,
1232 char *buf)
1233{
1234 struct uart_port *port = s3c24xx_dev_to_port(dev);
1235 struct s3c24xx_uart_port *ourport = to_ourport(port);
1236
1237 if (IS_ERR(ourport->baudclk))
1238 return -EINVAL;
1239
1240 return snprintf(buf, PAGE_SIZE, "* %s\n",
1241 ourport->baudclk->name ?: "(null)");
1242}
1243
1244static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL);
1245#endif
1246
1247/* Device driver serial port probe */ 1243/* Device driver serial port probe */
1248 1244
1249static const struct of_device_id s3c24xx_uart_dt_match[]; 1245static const struct of_device_id s3c24xx_uart_dt_match[];
@@ -1296,11 +1292,10 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
1296 of_property_read_u32(np, 1292 of_property_read_u32(np,
1297 "samsung,uart-fifosize", &ourport->port.fifosize); 1293 "samsung,uart-fifosize", &ourport->port.fifosize);
1298 1294
1299 if (!ourport->port.fifosize) { 1295 if (ourport->drv_data->fifosize[index])
1300 ourport->port.fifosize = (ourport->info->fifosize) ? 1296 ourport->port.fifosize = ourport->drv_data->fifosize[index];
1301 ourport->info->fifosize : 1297 else if (ourport->info->fifosize)
1302 ourport->drv_data->fifosize[index]; 1298 ourport->port.fifosize = ourport->info->fifosize;
1303 }
1304 1299
1305 probe_index++; 1300 probe_index++;
1306 1301
@@ -1329,12 +1324,6 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
1329 */ 1324 */
1330 clk_disable_unprepare(ourport->clk); 1325 clk_disable_unprepare(ourport->clk);
1331 1326
1332#ifdef CONFIG_SAMSUNG_CLOCK
1333 ret = device_create_file(&pdev->dev, &dev_attr_clock_source);
1334 if (ret < 0)
1335 dev_err(&pdev->dev, "failed to add clock source attr.\n");
1336#endif
1337
1338 ret = s3c24xx_serial_cpufreq_register(ourport); 1327 ret = s3c24xx_serial_cpufreq_register(ourport);
1339 if (ret < 0) 1328 if (ret < 0)
1340 dev_err(&pdev->dev, "failed to add cpufreq notifier\n"); 1329 dev_err(&pdev->dev, "failed to add cpufreq notifier\n");
@@ -1348,9 +1337,6 @@ static int s3c24xx_serial_remove(struct platform_device *dev)
1348 1337
1349 if (port) { 1338 if (port) {
1350 s3c24xx_serial_cpufreq_deregister(to_ourport(port)); 1339 s3c24xx_serial_cpufreq_deregister(to_ourport(port));
1351#ifdef CONFIG_SAMSUNG_CLOCK
1352 device_remove_file(&dev->dev, &dev_attr_clock_source);
1353#endif
1354 uart_remove_one_port(&s3c24xx_uart_drv, port); 1340 uart_remove_one_port(&s3c24xx_uart_drv, port);
1355 } 1341 }
1356 1342