aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/sh-sci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/sh-sci.c')
-rw-r--r--drivers/tty/serial/sh-sci.c81
1 files changed, 53 insertions, 28 deletions
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index fdbbff547106..b46b146524ce 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -160,6 +160,7 @@ struct sci_port {
160#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS 160#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
161 161
162static struct sci_port sci_ports[SCI_NPORTS]; 162static struct sci_port sci_ports[SCI_NPORTS];
163static unsigned long sci_ports_in_use;
163static struct uart_driver sci_uart_driver; 164static struct uart_driver sci_uart_driver;
164 165
165static inline struct sci_port * 166static inline struct sci_port *
@@ -2390,6 +2391,27 @@ done:
2390 2391
2391 uart_update_timeout(port, termios->c_cflag, baud); 2392 uart_update_timeout(port, termios->c_cflag, baud);
2392 2393
2394 /* byte size and parity */
2395 switch (termios->c_cflag & CSIZE) {
2396 case CS5:
2397 bits = 7;
2398 break;
2399 case CS6:
2400 bits = 8;
2401 break;
2402 case CS7:
2403 bits = 9;
2404 break;
2405 default:
2406 bits = 10;
2407 break;
2408 }
2409
2410 if (termios->c_cflag & CSTOPB)
2411 bits++;
2412 if (termios->c_cflag & PARENB)
2413 bits++;
2414
2393 if (best_clk >= 0) { 2415 if (best_clk >= 0) {
2394 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) 2416 if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
2395 switch (srr + 1) { 2417 switch (srr + 1) {
@@ -2406,8 +2428,27 @@ done:
2406 serial_port_out(port, SCSCR, scr_val | s->hscif_tot); 2428 serial_port_out(port, SCSCR, scr_val | s->hscif_tot);
2407 serial_port_out(port, SCSMR, smr_val); 2429 serial_port_out(port, SCSMR, smr_val);
2408 serial_port_out(port, SCBRR, brr); 2430 serial_port_out(port, SCBRR, brr);
2409 if (sci_getreg(port, HSSRR)->size) 2431 if (sci_getreg(port, HSSRR)->size) {
2410 serial_port_out(port, HSSRR, srr | HSCIF_SRE); 2432 unsigned int hssrr = srr | HSCIF_SRE;
2433 /* Calculate deviation from intended rate at the
2434 * center of the last stop bit in sampling clocks.
2435 */
2436 int last_stop = bits * 2 - 1;
2437 int deviation = min_err * srr * last_stop / 2 / baud;
2438
2439 if (abs(deviation) >= 2) {
2440 /* At least two sampling clocks off at the
2441 * last stop bit; we can increase the error
2442 * margin by shifting the sampling point.
2443 */
2444 int shift = min(-8, max(7, deviation / 2));
2445
2446 hssrr |= (shift << HSCIF_SRHP_SHIFT) &
2447 HSCIF_SRHP_MASK;
2448 hssrr |= HSCIF_SRDE;
2449 }
2450 serial_port_out(port, HSSRR, hssrr);
2451 }
2411 2452
2412 /* Wait one bit interval */ 2453 /* Wait one bit interval */
2413 udelay((1000000 + (baud - 1)) / baud); 2454 udelay((1000000 + (baud - 1)) / baud);
@@ -2474,27 +2515,6 @@ done:
2474 * value obtained by this formula is too small. Therefore, if the value 2515 * value obtained by this formula is too small. Therefore, if the value
2475 * is smaller than 20ms, use 20ms as the timeout value for DMA. 2516 * is smaller than 20ms, use 20ms as the timeout value for DMA.
2476 */ 2517 */
2477 /* byte size and parity */
2478 switch (termios->c_cflag & CSIZE) {
2479 case CS5:
2480 bits = 7;
2481 break;
2482 case CS6:
2483 bits = 8;
2484 break;
2485 case CS7:
2486 bits = 9;
2487 break;
2488 default:
2489 bits = 10;
2490 break;
2491 }
2492
2493 if (termios->c_cflag & CSTOPB)
2494 bits++;
2495 if (termios->c_cflag & PARENB)
2496 bits++;
2497
2498 s->rx_frame = (10000 * bits) / (baud / 100); 2518 s->rx_frame = (10000 * bits) / (baud / 100);
2499#ifdef CONFIG_SERIAL_SH_SCI_DMA 2519#ifdef CONFIG_SERIAL_SH_SCI_DMA
2500 s->rx_timeout = s->buf_len_rx * 2 * s->rx_frame; 2520 s->rx_timeout = s->buf_len_rx * 2 * s->rx_frame;
@@ -2890,16 +2910,15 @@ static void serial_console_write(struct console *co, const char *s,
2890 unsigned long flags; 2910 unsigned long flags;
2891 int locked = 1; 2911 int locked = 1;
2892 2912
2893 local_irq_save(flags);
2894#if defined(SUPPORT_SYSRQ) 2913#if defined(SUPPORT_SYSRQ)
2895 if (port->sysrq) 2914 if (port->sysrq)
2896 locked = 0; 2915 locked = 0;
2897 else 2916 else
2898#endif 2917#endif
2899 if (oops_in_progress) 2918 if (oops_in_progress)
2900 locked = spin_trylock(&port->lock); 2919 locked = spin_trylock_irqsave(&port->lock, flags);
2901 else 2920 else
2902 spin_lock(&port->lock); 2921 spin_lock_irqsave(&port->lock, flags);
2903 2922
2904 /* first save SCSCR then disable interrupts, keep clock source */ 2923 /* first save SCSCR then disable interrupts, keep clock source */
2905 ctrl = serial_port_in(port, SCSCR); 2924 ctrl = serial_port_in(port, SCSCR);
@@ -2919,8 +2938,7 @@ static void serial_console_write(struct console *co, const char *s,
2919 serial_port_out(port, SCSCR, ctrl); 2938 serial_port_out(port, SCSCR, ctrl);
2920 2939
2921 if (locked) 2940 if (locked)
2922 spin_unlock(&port->lock); 2941 spin_unlock_irqrestore(&port->lock, flags);
2923 local_irq_restore(flags);
2924} 2942}
2925 2943
2926static int serial_console_setup(struct console *co, char *options) 2944static int serial_console_setup(struct console *co, char *options)
@@ -3026,6 +3044,7 @@ static int sci_remove(struct platform_device *dev)
3026{ 3044{
3027 struct sci_port *port = platform_get_drvdata(dev); 3045 struct sci_port *port = platform_get_drvdata(dev);
3028 3046
3047 sci_ports_in_use &= ~BIT(port->port.line);
3029 uart_remove_one_port(&sci_uart_driver, &port->port); 3048 uart_remove_one_port(&sci_uart_driver, &port->port);
3030 3049
3031 sci_cleanup_single(port); 3050 sci_cleanup_single(port);
@@ -3107,6 +3126,8 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
3107 3126
3108 /* Get the line number from the aliases node. */ 3127 /* Get the line number from the aliases node. */
3109 id = of_alias_get_id(np, "serial"); 3128 id = of_alias_get_id(np, "serial");
3129 if (id < 0 && ~sci_ports_in_use)
3130 id = ffz(sci_ports_in_use);
3110 if (id < 0) { 3131 if (id < 0) {
3111 dev_err(&pdev->dev, "failed to get alias id (%d)\n", id); 3132 dev_err(&pdev->dev, "failed to get alias id (%d)\n", id);
3112 return NULL; 3133 return NULL;
@@ -3141,6 +3162,9 @@ static int sci_probe_single(struct platform_device *dev,
3141 dev_notice(&dev->dev, "Consider bumping CONFIG_SERIAL_SH_SCI_NR_UARTS!\n"); 3162 dev_notice(&dev->dev, "Consider bumping CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
3142 return -EINVAL; 3163 return -EINVAL;
3143 } 3164 }
3165 BUILD_BUG_ON(SCI_NPORTS > sizeof(sci_ports_in_use) * 8);
3166 if (sci_ports_in_use & BIT(index))
3167 return -EBUSY;
3144 3168
3145 mutex_lock(&sci_uart_registration_lock); 3169 mutex_lock(&sci_uart_registration_lock);
3146 if (!sci_uart_driver.state) { 3170 if (!sci_uart_driver.state) {
@@ -3239,6 +3263,7 @@ static int sci_probe(struct platform_device *dev)
3239 sh_bios_gdb_detach(); 3263 sh_bios_gdb_detach();
3240#endif 3264#endif
3241 3265
3266 sci_ports_in_use |= BIT(dev_id);
3242 return 0; 3267 return 0;
3243} 3268}
3244 3269