diff options
Diffstat (limited to 'drivers/tty/serial/samsung.c')
-rw-r--r-- | drivers/tty/serial/samsung.c | 90 |
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 | ||
202 | static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *port) | 202 | static 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 | ||
207 | static inline struct s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port) | 208 | static 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: | 316 | ignore_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: | 323 | out: |
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: | 373 | out: |
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: | 524 | err: |
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 | ||
972 | static 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) | ||
980 | static struct s3c24xx_uart_port | ||
981 | s3c24xx_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: | 1115 | exit: |
1106 | return 0; | 1116 | return 0; |
1107 | } | 1117 | } |
1108 | 1118 | ||
1109 | static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port) | 1119 | static inline int |
1120 | s3c24xx_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 | ||
1117 | static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port) | 1128 | static inline void |
1129 | s3c24xx_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 |
1124 | static inline int s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port) | 1136 | static inline int |
1137 | s3c24xx_serial_cpufreq_register(struct s3c24xx_uart_port *port) | ||
1125 | { | 1138 | { |
1126 | return 0; | 1139 | return 0; |
1127 | } | 1140 | } |
1128 | 1141 | ||
1129 | static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *port) | 1142 | static inline void |
1143 | s3c24xx_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 | ||
1230 | static 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 | |||
1244 | static 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 | ||
1249 | static const struct of_device_id s3c24xx_uart_dt_match[]; | 1245 | static 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 | ||