Lines Matching +full:uart +full:- +full:fifosize

1 // SPDX-License-Identifier: GPL-2.0+
24 #include <linux/platform_data/serial-sccnxp.h>
27 #define SCCNXP_NAME "uart-sccnxp"
93 #define MCTRL_IBIT(cfg, sig) ((((cfg) >> (sig)) & 0xf) - LINE_IP0)
94 #define MCTRL_OBIT(cfg, sig) ((((cfg) >> (sig)) & 0xf) - LINE_OP0)
106 unsigned int fifosize; member
112 struct uart_driver uart; member
142 .fifosize = 3,
153 .fifosize = 3,
164 .fifosize = 3,
175 .fifosize = 16,
186 .fifosize = 16,
197 .fifosize = 256,
208 .fifosize = 3,
219 .fifosize = 3,
225 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_read()
228 ret = readb(port->membase + (reg << port->regshift)); in sccnxp_read()
230 ndelay(s->chip->trwd); in sccnxp_read()
237 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_write()
239 writeb(v, port->membase + (reg << port->regshift)); in sccnxp_write()
241 ndelay(s->chip->trwd); in sccnxp_write()
246 return sccnxp_read(port, (port->line << 3) + reg); in sccnxp_port_read()
251 sccnxp_write(port, (port->line << 3) + reg, v); in sccnxp_port_write()
256 int err = abs(a - b); in sccnxp_update_best_err()
305 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_set_baud()
307 struct sccnxp_chip *chip = s->chip; in sccnxp_set_baud()
311 div_std = DIV_ROUND_CLOSEST(port->uartclk, 2 * 16 * baud); in sccnxp_set_baud()
313 bestbaud = DIV_ROUND_CLOSEST(port->uartclk, 2 * 16 * div_std); in sccnxp_set_baud()
324 if (baud_std[i].mr0 && !(chip->flags & SCCNXP_HAVE_MR0)) in sccnxp_set_baud()
326 div_std = DIV_ROUND_CLOSEST(chip->freq_std, baud_std[i].baud); in sccnxp_set_baud()
327 tmp_baud = DIV_ROUND_CLOSEST(port->uartclk, div_std); in sccnxp_set_baud()
336 if (chip->flags & SCCNXP_HAVE_MR0) { in sccnxp_set_baud()
348 dev_dbg(port->dev, "Baudrate desired: %i, calculated: %i\n", in sccnxp_set_baud()
356 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_enable_irq()
358 s->imr |= mask << (port->line * 4); in sccnxp_enable_irq()
359 sccnxp_write(port, SCCNXP_IMR_REG, s->imr); in sccnxp_enable_irq()
364 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_disable_irq()
366 s->imr &= ~(mask << (port->line * 4)); in sccnxp_disable_irq()
367 sccnxp_write(port, SCCNXP_IMR_REG, s->imr); in sccnxp_disable_irq()
373 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_set_bit()
375 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(sig)) { in sccnxp_set_bit()
376 bitmask = 1 << MCTRL_OBIT(s->pdata.mctrl_cfg[port->line], sig); in sccnxp_set_bit()
397 port->icount.rx++; in sccnxp_handle_rx()
402 port->icount.brk++; in sccnxp_handle_rx()
408 port->icount.parity++; in sccnxp_handle_rx()
410 port->icount.frame++; in sccnxp_handle_rx()
412 port->icount.overrun++; in sccnxp_handle_rx()
417 sr &= port->read_status_mask; in sccnxp_handle_rx()
431 if (sr & port->ignore_status_mask) in sccnxp_handle_rx()
437 tty_flip_buffer_push(&port->state->port); in sccnxp_handle_rx()
443 struct circ_buf *xmit = &port->state->xmit; in sccnxp_handle_tx()
444 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_handle_tx()
446 if (unlikely(port->x_char)) { in sccnxp_handle_tx()
447 sccnxp_port_write(port, SCCNXP_THR_REG, port->x_char); in sccnxp_handle_tx()
448 port->icount.tx++; in sccnxp_handle_tx()
449 port->x_char = 0; in sccnxp_handle_tx()
459 if (s->chip->flags & SCCNXP_HAVE_IO) in sccnxp_handle_tx()
470 sccnxp_port_write(port, SCCNXP_THR_REG, xmit->buf[xmit->tail]); in sccnxp_handle_tx()
471 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); in sccnxp_handle_tx()
472 port->icount.tx++; in sccnxp_handle_tx()
485 isr = sccnxp_read(&s->port[0], SCCNXP_ISR_REG); in sccnxp_handle_events()
486 isr &= s->imr; in sccnxp_handle_events()
490 for (i = 0; i < s->uart.nr; i++) { in sccnxp_handle_events()
491 if (s->opened[i] && (isr & ISR_RXRDY(i))) in sccnxp_handle_events()
492 sccnxp_handle_rx(&s->port[i]); in sccnxp_handle_events()
493 if (s->opened[i] && (isr & ISR_TXRDY(i))) in sccnxp_handle_events()
494 sccnxp_handle_tx(&s->port[i]); in sccnxp_handle_events()
504 spin_lock_irqsave(&s->lock, flags); in sccnxp_timer()
506 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_timer()
508 mod_timer(&s->timer, jiffies + usecs_to_jiffies(s->pdata.poll_time_us)); in sccnxp_timer()
516 spin_lock_irqsave(&s->lock, flags); in sccnxp_ist()
518 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_ist()
525 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_start_tx()
528 spin_lock_irqsave(&s->lock, flags); in sccnxp_start_tx()
531 if (s->chip->flags & SCCNXP_HAVE_IO) in sccnxp_start_tx()
536 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_start_tx()
546 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_stop_rx()
549 spin_lock_irqsave(&s->lock, flags); in sccnxp_stop_rx()
551 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_stop_rx()
558 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_tx_empty()
560 spin_lock_irqsave(&s->lock, flags); in sccnxp_tx_empty()
562 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_tx_empty()
569 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_set_mctrl()
572 if (!(s->chip->flags & SCCNXP_HAVE_IO)) in sccnxp_set_mctrl()
575 spin_lock_irqsave(&s->lock, flags); in sccnxp_set_mctrl()
580 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_set_mctrl()
587 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_get_mctrl()
590 if (!(s->chip->flags & SCCNXP_HAVE_IO)) in sccnxp_get_mctrl()
593 spin_lock_irqsave(&s->lock, flags); in sccnxp_get_mctrl()
597 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DSR_IP)) { in sccnxp_get_mctrl()
598 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], in sccnxp_get_mctrl()
603 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(CTS_IP)) { in sccnxp_get_mctrl()
604 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], in sccnxp_get_mctrl()
609 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DCD_IP)) { in sccnxp_get_mctrl()
610 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], in sccnxp_get_mctrl()
615 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(RNG_IP)) { in sccnxp_get_mctrl()
616 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], in sccnxp_get_mctrl()
622 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_get_mctrl()
629 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_break_ctl()
632 spin_lock_irqsave(&s->lock, flags); in sccnxp_break_ctl()
635 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_break_ctl()
641 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_set_termios()
646 spin_lock_irqsave(&s->lock, flags); in sccnxp_set_termios()
649 termios->c_cflag &= ~CMSPAR; in sccnxp_set_termios()
659 switch (termios->c_cflag & CSIZE) { in sccnxp_set_termios()
676 if (termios->c_cflag & PARENB) { in sccnxp_set_termios()
677 if (termios->c_cflag & PARODD) in sccnxp_set_termios()
683 mr2 = (termios->c_cflag & CSTOPB) ? MR2_STOP2 : MR2_STOP1; in sccnxp_set_termios()
691 port->read_status_mask = SR_OVR; in sccnxp_set_termios()
692 if (termios->c_iflag & INPCK) in sccnxp_set_termios()
693 port->read_status_mask |= SR_PE | SR_FE; in sccnxp_set_termios()
694 if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) in sccnxp_set_termios()
695 port->read_status_mask |= SR_BRK; in sccnxp_set_termios()
698 port->ignore_status_mask = 0; in sccnxp_set_termios()
699 if (termios->c_iflag & IGNBRK) in sccnxp_set_termios()
700 port->ignore_status_mask |= SR_BRK; in sccnxp_set_termios()
701 if (termios->c_iflag & IGNPAR) in sccnxp_set_termios()
702 port->ignore_status_mask |= SR_PE; in sccnxp_set_termios()
703 if (!(termios->c_cflag & CREAD)) in sccnxp_set_termios()
704 port->ignore_status_mask |= SR_PE | SR_OVR | SR_FE | SR_BRK; in sccnxp_set_termios()
708 (s->chip->flags & SCCNXP_HAVE_MR0) ? in sccnxp_set_termios()
713 uart_update_timeout(port, termios->c_cflag, baud); in sccnxp_set_termios()
722 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_set_termios()
727 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_startup()
730 spin_lock_irqsave(&s->lock, flags); in sccnxp_startup()
732 if (s->chip->flags & SCCNXP_HAVE_IO) { in sccnxp_startup()
749 s->opened[port->line] = 1; in sccnxp_startup()
751 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_startup()
758 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_shutdown()
761 spin_lock_irqsave(&s->lock, flags); in sccnxp_shutdown()
763 s->opened[port->line] = 0; in sccnxp_shutdown()
772 if (s->chip->flags & SCCNXP_HAVE_IO) in sccnxp_shutdown()
775 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_shutdown()
780 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_type()
782 return (port->type == PORT_SC26XX) ? s->chip->name : NULL; in sccnxp_type()
799 port->type = PORT_SC26XX; in sccnxp_config_port()
804 if ((s->type == PORT_UNKNOWN) || (s->type == PORT_SC26XX)) in sccnxp_verify_port()
806 if (s->irq == port->irq) in sccnxp_verify_port()
809 return -EINVAL; in sccnxp_verify_port()
835 while (tryes--) { in sccnxp_console_putchar()
846 struct sccnxp_port *s = (struct sccnxp_port *)co->data; in sccnxp_console_write()
847 struct uart_port *port = &s->port[co->index]; in sccnxp_console_write()
850 spin_lock_irqsave(&s->lock, flags); in sccnxp_console_write()
852 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_console_write()
857 struct sccnxp_port *s = (struct sccnxp_port *)co->data; in sccnxp_console_setup()
858 struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0]; in sccnxp_console_setup()
884 struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev); in sccnxp_probe()
890 membase = devm_ioremap_resource(&pdev->dev, res); in sccnxp_probe()
894 s = devm_kzalloc(&pdev->dev, sizeof(struct sccnxp_port), GFP_KERNEL); in sccnxp_probe()
896 dev_err(&pdev->dev, "Error allocating port structure\n"); in sccnxp_probe()
897 return -ENOMEM; in sccnxp_probe()
901 spin_lock_init(&s->lock); in sccnxp_probe()
903 s->chip = (struct sccnxp_chip *)pdev->id_entry->driver_data; in sccnxp_probe()
905 s->regulator = devm_regulator_get(&pdev->dev, "vcc"); in sccnxp_probe()
906 if (!IS_ERR(s->regulator)) { in sccnxp_probe()
907 ret = regulator_enable(s->regulator); in sccnxp_probe()
909 dev_err(&pdev->dev, in sccnxp_probe()
913 } else if (PTR_ERR(s->regulator) == -EPROBE_DEFER) in sccnxp_probe()
914 return -EPROBE_DEFER; in sccnxp_probe()
916 clk = devm_clk_get(&pdev->dev, NULL); in sccnxp_probe()
919 if (ret == -EPROBE_DEFER) in sccnxp_probe()
927 ret = devm_add_action_or_reset(&pdev->dev, in sccnxp_probe()
937 dev_notice(&pdev->dev, "Using default clock frequency\n"); in sccnxp_probe()
938 uartclk = s->chip->freq_std; in sccnxp_probe()
942 if ((uartclk < s->chip->freq_min) || (uartclk > s->chip->freq_max)) { in sccnxp_probe()
943 dev_err(&pdev->dev, "Frequency out of bounds\n"); in sccnxp_probe()
944 ret = -EINVAL; in sccnxp_probe()
949 memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata)); in sccnxp_probe()
951 if (s->pdata.poll_time_us) { in sccnxp_probe()
952 dev_info(&pdev->dev, "Using poll mode, resolution %u usecs\n", in sccnxp_probe()
953 s->pdata.poll_time_us); in sccnxp_probe()
954 s->poll = 1; in sccnxp_probe()
957 if (!s->poll) { in sccnxp_probe()
958 s->irq = platform_get_irq(pdev, 0); in sccnxp_probe()
959 if (s->irq < 0) { in sccnxp_probe()
960 ret = -ENXIO; in sccnxp_probe()
965 s->uart.owner = THIS_MODULE; in sccnxp_probe()
966 s->uart.dev_name = "ttySC"; in sccnxp_probe()
967 s->uart.major = SCCNXP_MAJOR; in sccnxp_probe()
968 s->uart.minor = SCCNXP_MINOR; in sccnxp_probe()
969 s->uart.nr = s->chip->nr; in sccnxp_probe()
971 s->uart.cons = &s->console; in sccnxp_probe()
972 s->uart.cons->device = uart_console_device; in sccnxp_probe()
973 s->uart.cons->write = sccnxp_console_write; in sccnxp_probe()
974 s->uart.cons->setup = sccnxp_console_setup; in sccnxp_probe()
975 s->uart.cons->flags = CON_PRINTBUFFER; in sccnxp_probe()
976 s->uart.cons->index = -1; in sccnxp_probe()
977 s->uart.cons->data = s; in sccnxp_probe()
978 strcpy(s->uart.cons->name, "ttySC"); in sccnxp_probe()
980 ret = uart_register_driver(&s->uart); in sccnxp_probe()
982 dev_err(&pdev->dev, "Registering UART driver failed\n"); in sccnxp_probe()
986 for (i = 0; i < s->uart.nr; i++) { in sccnxp_probe()
987 s->port[i].line = i; in sccnxp_probe()
988 s->port[i].dev = &pdev->dev; in sccnxp_probe()
989 s->port[i].irq = s->irq; in sccnxp_probe()
990 s->port[i].type = PORT_SC26XX; in sccnxp_probe()
991 s->port[i].fifosize = s->chip->fifosize; in sccnxp_probe()
992 s->port[i].flags = UPF_SKIP_TEST | UPF_FIXED_TYPE; in sccnxp_probe()
993 s->port[i].iotype = UPIO_MEM; in sccnxp_probe()
994 s->port[i].mapbase = res->start; in sccnxp_probe()
995 s->port[i].membase = membase; in sccnxp_probe()
996 s->port[i].regshift = s->pdata.reg_shift; in sccnxp_probe()
997 s->port[i].uartclk = uartclk; in sccnxp_probe()
998 s->port[i].ops = &sccnxp_ops; in sccnxp_probe()
999 s->port[i].has_sysrq = IS_ENABLED(CONFIG_SERIAL_SCCNXP_CONSOLE); in sccnxp_probe()
1000 uart_add_one_port(&s->uart, &s->port[i]); in sccnxp_probe()
1002 if (s->chip->flags & SCCNXP_HAVE_IO) in sccnxp_probe()
1003 sccnxp_set_bit(&s->port[i], DIR_OP, 0); in sccnxp_probe()
1007 s->imr = 0; in sccnxp_probe()
1008 sccnxp_write(&s->port[0], SCCNXP_IMR_REG, 0); in sccnxp_probe()
1010 if (!s->poll) { in sccnxp_probe()
1011 ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL, in sccnxp_probe()
1015 dev_name(&pdev->dev), s); in sccnxp_probe()
1019 dev_err(&pdev->dev, "Unable to reguest IRQ %i\n", s->irq); in sccnxp_probe()
1021 timer_setup(&s->timer, sccnxp_timer, 0); in sccnxp_probe()
1022 mod_timer(&s->timer, jiffies + in sccnxp_probe()
1023 usecs_to_jiffies(s->pdata.poll_time_us)); in sccnxp_probe()
1027 uart_unregister_driver(&s->uart); in sccnxp_probe()
1029 if (!IS_ERR(s->regulator)) in sccnxp_probe()
1030 regulator_disable(s->regulator); in sccnxp_probe()
1040 if (!s->poll) in sccnxp_remove()
1041 devm_free_irq(&pdev->dev, s->irq, s); in sccnxp_remove()
1043 del_timer_sync(&s->timer); in sccnxp_remove()
1045 for (i = 0; i < s->uart.nr; i++) in sccnxp_remove()
1046 uart_remove_one_port(&s->uart, &s->port[i]); in sccnxp_remove()
1048 uart_unregister_driver(&s->uart); in sccnxp_remove()
1050 if (!IS_ERR(s->regulator)) in sccnxp_remove()
1051 return regulator_disable(s->regulator); in sccnxp_remove()