Lines Matching +full:nr +full:- +full:outputs
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)
101 unsigned int nr; member
137 .nr = 2,
148 .nr = 1,
159 .nr = 2,
170 .nr = 1,
181 .nr = 2,
192 .nr = 2,
203 .nr = 2,
214 .nr = 2,
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()
396 port->icount.rx++; in sccnxp_handle_rx()
401 port->icount.brk++; in sccnxp_handle_rx()
407 port->icount.parity++; in sccnxp_handle_rx()
409 port->icount.frame++; in sccnxp_handle_rx()
411 port->icount.overrun++; in sccnxp_handle_rx()
416 sr &= port->read_status_mask; in sccnxp_handle_rx()
430 if (sr & port->ignore_status_mask) in sccnxp_handle_rx()
436 tty_flip_buffer_push(&port->state->port); in sccnxp_handle_rx()
442 struct circ_buf *xmit = &port->state->xmit; in sccnxp_handle_tx()
443 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_handle_tx()
445 if (unlikely(port->x_char)) { in sccnxp_handle_tx()
446 sccnxp_port_write(port, SCCNXP_THR_REG, port->x_char); in sccnxp_handle_tx()
447 port->icount.tx++; in sccnxp_handle_tx()
448 port->x_char = 0; in sccnxp_handle_tx()
458 if (s->chip->flags & SCCNXP_HAVE_IO) in sccnxp_handle_tx()
469 sccnxp_port_write(port, SCCNXP_THR_REG, xmit->buf[xmit->tail]); in sccnxp_handle_tx()
483 isr = sccnxp_read(&s->port[0], SCCNXP_ISR_REG); in sccnxp_handle_events()
484 isr &= s->imr; in sccnxp_handle_events()
488 for (i = 0; i < s->uart.nr; i++) { in sccnxp_handle_events()
489 if (s->opened[i] && (isr & ISR_RXRDY(i))) in sccnxp_handle_events()
490 sccnxp_handle_rx(&s->port[i]); in sccnxp_handle_events()
491 if (s->opened[i] && (isr & ISR_TXRDY(i))) in sccnxp_handle_events()
492 sccnxp_handle_tx(&s->port[i]); in sccnxp_handle_events()
502 spin_lock_irqsave(&s->lock, flags); in sccnxp_timer()
504 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_timer()
506 mod_timer(&s->timer, jiffies + usecs_to_jiffies(s->pdata.poll_time_us)); in sccnxp_timer()
514 spin_lock_irqsave(&s->lock, flags); in sccnxp_ist()
516 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_ist()
523 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_start_tx()
526 spin_lock_irqsave(&s->lock, flags); in sccnxp_start_tx()
529 if (s->chip->flags & SCCNXP_HAVE_IO) in sccnxp_start_tx()
534 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_start_tx()
544 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_stop_rx()
547 spin_lock_irqsave(&s->lock, flags); in sccnxp_stop_rx()
549 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_stop_rx()
556 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_tx_empty()
558 spin_lock_irqsave(&s->lock, flags); in sccnxp_tx_empty()
560 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_tx_empty()
567 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_set_mctrl()
570 if (!(s->chip->flags & SCCNXP_HAVE_IO)) in sccnxp_set_mctrl()
573 spin_lock_irqsave(&s->lock, flags); in sccnxp_set_mctrl()
578 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_set_mctrl()
585 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_get_mctrl()
588 if (!(s->chip->flags & SCCNXP_HAVE_IO)) in sccnxp_get_mctrl()
591 spin_lock_irqsave(&s->lock, flags); in sccnxp_get_mctrl()
595 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DSR_IP)) { in sccnxp_get_mctrl()
596 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], in sccnxp_get_mctrl()
601 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(CTS_IP)) { in sccnxp_get_mctrl()
602 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], in sccnxp_get_mctrl()
607 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DCD_IP)) { in sccnxp_get_mctrl()
608 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], in sccnxp_get_mctrl()
613 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(RNG_IP)) { in sccnxp_get_mctrl()
614 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], in sccnxp_get_mctrl()
620 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_get_mctrl()
627 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_break_ctl()
630 spin_lock_irqsave(&s->lock, flags); in sccnxp_break_ctl()
633 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_break_ctl()
640 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_set_termios()
645 spin_lock_irqsave(&s->lock, flags); in sccnxp_set_termios()
648 termios->c_cflag &= ~CMSPAR; in sccnxp_set_termios()
658 switch (termios->c_cflag & CSIZE) { in sccnxp_set_termios()
675 if (termios->c_cflag & PARENB) { in sccnxp_set_termios()
676 if (termios->c_cflag & PARODD) in sccnxp_set_termios()
682 mr2 = (termios->c_cflag & CSTOPB) ? MR2_STOP2 : MR2_STOP1; in sccnxp_set_termios()
690 port->read_status_mask = SR_OVR; in sccnxp_set_termios()
691 if (termios->c_iflag & INPCK) in sccnxp_set_termios()
692 port->read_status_mask |= SR_PE | SR_FE; in sccnxp_set_termios()
693 if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) in sccnxp_set_termios()
694 port->read_status_mask |= SR_BRK; in sccnxp_set_termios()
697 port->ignore_status_mask = 0; in sccnxp_set_termios()
698 if (termios->c_iflag & IGNBRK) in sccnxp_set_termios()
699 port->ignore_status_mask |= SR_BRK; in sccnxp_set_termios()
700 if (termios->c_iflag & IGNPAR) in sccnxp_set_termios()
701 port->ignore_status_mask |= SR_PE; in sccnxp_set_termios()
702 if (!(termios->c_cflag & CREAD)) in sccnxp_set_termios()
703 port->ignore_status_mask |= SR_PE | SR_OVR | SR_FE | SR_BRK; in sccnxp_set_termios()
707 (s->chip->flags & SCCNXP_HAVE_MR0) ? in sccnxp_set_termios()
712 uart_update_timeout(port, termios->c_cflag, baud); in sccnxp_set_termios()
721 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_set_termios()
726 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_startup()
729 spin_lock_irqsave(&s->lock, flags); in sccnxp_startup()
731 if (s->chip->flags & SCCNXP_HAVE_IO) { in sccnxp_startup()
732 /* Outputs are controlled manually */ in sccnxp_startup()
748 s->opened[port->line] = 1; in sccnxp_startup()
750 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_startup()
757 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_shutdown()
760 spin_lock_irqsave(&s->lock, flags); in sccnxp_shutdown()
762 s->opened[port->line] = 0; in sccnxp_shutdown()
771 if (s->chip->flags & SCCNXP_HAVE_IO) in sccnxp_shutdown()
774 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_shutdown()
779 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_type()
781 return (port->type == PORT_SC26XX) ? s->chip->name : NULL; in sccnxp_type()
798 port->type = PORT_SC26XX; in sccnxp_config_port()
803 if ((s->type == PORT_UNKNOWN) || (s->type == PORT_SC26XX)) in sccnxp_verify_port()
805 if (s->irq == port->irq) in sccnxp_verify_port()
808 return -EINVAL; in sccnxp_verify_port()
834 while (tryes--) { in sccnxp_console_putchar()
845 struct sccnxp_port *s = (struct sccnxp_port *)co->data; in sccnxp_console_write()
846 struct uart_port *port = &s->port[co->index]; in sccnxp_console_write()
849 spin_lock_irqsave(&s->lock, flags); in sccnxp_console_write()
851 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_console_write()
856 struct sccnxp_port *s = (struct sccnxp_port *)co->data; in sccnxp_console_setup()
857 struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0]; in sccnxp_console_setup()
882 struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev); in sccnxp_probe()
893 s = devm_kzalloc(&pdev->dev, sizeof(struct sccnxp_port), GFP_KERNEL); in sccnxp_probe()
895 dev_err(&pdev->dev, "Error allocating port structure\n"); in sccnxp_probe()
896 return -ENOMEM; in sccnxp_probe()
900 spin_lock_init(&s->lock); in sccnxp_probe()
902 s->chip = (struct sccnxp_chip *)pdev->id_entry->driver_data; in sccnxp_probe()
904 s->regulator = devm_regulator_get(&pdev->dev, "vcc"); in sccnxp_probe()
905 if (!IS_ERR(s->regulator)) { in sccnxp_probe()
906 ret = regulator_enable(s->regulator); in sccnxp_probe()
908 dev_err(&pdev->dev, in sccnxp_probe()
912 } else if (PTR_ERR(s->regulator) == -EPROBE_DEFER) in sccnxp_probe()
913 return -EPROBE_DEFER; in sccnxp_probe()
915 clk = devm_clk_get_enabled(&pdev->dev, NULL); in sccnxp_probe()
918 if (ret == -EPROBE_DEFER) in sccnxp_probe()
926 dev_notice(&pdev->dev, "Using default clock frequency\n"); in sccnxp_probe()
927 uartclk = s->chip->freq_std; in sccnxp_probe()
931 if ((uartclk < s->chip->freq_min) || (uartclk > s->chip->freq_max)) { in sccnxp_probe()
932 dev_err(&pdev->dev, "Frequency out of bounds\n"); in sccnxp_probe()
933 ret = -EINVAL; in sccnxp_probe()
938 memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata)); in sccnxp_probe()
940 if (s->pdata.poll_time_us) { in sccnxp_probe()
941 dev_info(&pdev->dev, "Using poll mode, resolution %u usecs\n", in sccnxp_probe()
942 s->pdata.poll_time_us); in sccnxp_probe()
943 s->poll = 1; in sccnxp_probe()
946 if (!s->poll) { in sccnxp_probe()
947 s->irq = platform_get_irq(pdev, 0); in sccnxp_probe()
948 if (s->irq < 0) { in sccnxp_probe()
949 ret = -ENXIO; in sccnxp_probe()
954 s->uart.owner = THIS_MODULE; in sccnxp_probe()
955 s->uart.dev_name = "ttySC"; in sccnxp_probe()
956 s->uart.major = SCCNXP_MAJOR; in sccnxp_probe()
957 s->uart.minor = SCCNXP_MINOR; in sccnxp_probe()
958 s->uart.nr = s->chip->nr; in sccnxp_probe()
960 s->uart.cons = &s->console; in sccnxp_probe()
961 s->uart.cons->device = uart_console_device; in sccnxp_probe()
962 s->uart.cons->write = sccnxp_console_write; in sccnxp_probe()
963 s->uart.cons->setup = sccnxp_console_setup; in sccnxp_probe()
964 s->uart.cons->flags = CON_PRINTBUFFER; in sccnxp_probe()
965 s->uart.cons->index = -1; in sccnxp_probe()
966 s->uart.cons->data = s; in sccnxp_probe()
967 strcpy(s->uart.cons->name, "ttySC"); in sccnxp_probe()
969 ret = uart_register_driver(&s->uart); in sccnxp_probe()
971 dev_err(&pdev->dev, "Registering UART driver failed\n"); in sccnxp_probe()
975 for (i = 0; i < s->uart.nr; i++) { in sccnxp_probe()
976 s->port[i].line = i; in sccnxp_probe()
977 s->port[i].dev = &pdev->dev; in sccnxp_probe()
978 s->port[i].irq = s->irq; in sccnxp_probe()
979 s->port[i].type = PORT_SC26XX; in sccnxp_probe()
980 s->port[i].fifosize = s->chip->fifosize; in sccnxp_probe()
981 s->port[i].flags = UPF_SKIP_TEST | UPF_FIXED_TYPE; in sccnxp_probe()
982 s->port[i].iotype = UPIO_MEM; in sccnxp_probe()
983 s->port[i].mapbase = res->start; in sccnxp_probe()
984 s->port[i].membase = membase; in sccnxp_probe()
985 s->port[i].regshift = s->pdata.reg_shift; in sccnxp_probe()
986 s->port[i].uartclk = uartclk; in sccnxp_probe()
987 s->port[i].ops = &sccnxp_ops; in sccnxp_probe()
988 s->port[i].has_sysrq = IS_ENABLED(CONFIG_SERIAL_SCCNXP_CONSOLE); in sccnxp_probe()
989 uart_add_one_port(&s->uart, &s->port[i]); in sccnxp_probe()
991 if (s->chip->flags & SCCNXP_HAVE_IO) in sccnxp_probe()
992 sccnxp_set_bit(&s->port[i], DIR_OP, 0); in sccnxp_probe()
996 s->imr = 0; in sccnxp_probe()
997 sccnxp_write(&s->port[0], SCCNXP_IMR_REG, 0); in sccnxp_probe()
999 if (!s->poll) { in sccnxp_probe()
1000 ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL, in sccnxp_probe()
1004 dev_name(&pdev->dev), s); in sccnxp_probe()
1008 dev_err(&pdev->dev, "Unable to reguest IRQ %i\n", s->irq); in sccnxp_probe()
1010 timer_setup(&s->timer, sccnxp_timer, 0); in sccnxp_probe()
1011 mod_timer(&s->timer, jiffies + in sccnxp_probe()
1012 usecs_to_jiffies(s->pdata.poll_time_us)); in sccnxp_probe()
1016 uart_unregister_driver(&s->uart); in sccnxp_probe()
1018 if (!IS_ERR(s->regulator)) in sccnxp_probe()
1019 regulator_disable(s->regulator); in sccnxp_probe()
1029 if (!s->poll) in sccnxp_remove()
1030 devm_free_irq(&pdev->dev, s->irq, s); in sccnxp_remove()
1032 del_timer_sync(&s->timer); in sccnxp_remove()
1034 for (i = 0; i < s->uart.nr; i++) in sccnxp_remove()
1035 uart_remove_one_port(&s->uart, &s->port[i]); in sccnxp_remove()
1037 uart_unregister_driver(&s->uart); in sccnxp_remove()
1039 if (!IS_ERR(s->regulator)) in sccnxp_remove()
1040 return regulator_disable(s->regulator); in sccnxp_remove()