Lines Matching +full:clk +full:- +full:csr
1 // SPDX-License-Identifier: GPL-2.0+
10 #include <linux/clk.h>
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)
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()
267 u8 csr; member
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()
308 u8 i, acr = 0, csr = 0, mr0 = 0; in sccnxp_set_baud() local
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()
315 csr = CSR_TIMER_MODE; 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()
330 csr = baud_std[i].csr; in sccnxp_set_baud()
336 if (chip->flags & SCCNXP_HAVE_MR0) { in sccnxp_set_baud()
345 sccnxp_port_write(port, SCCNXP_CSR_REG, (csr << 4) | csr); 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 tty_port *tport = &port->state->port; 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()
452 if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(port)) { in sccnxp_handle_tx()
458 if (s->chip->flags & SCCNXP_HAVE_IO) in sccnxp_handle_tx()
477 if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) in sccnxp_handle_tx()
487 isr = sccnxp_read(&s->port[0], SCCNXP_ISR_REG); in sccnxp_handle_events()
488 isr &= s->imr; in sccnxp_handle_events()
492 for (i = 0; i < s->uart.nr; i++) { in sccnxp_handle_events()
493 if (s->opened[i] && (isr & ISR_RXRDY(i))) in sccnxp_handle_events()
494 sccnxp_handle_rx(&s->port[i]); in sccnxp_handle_events()
495 if (s->opened[i] && (isr & ISR_TXRDY(i))) in sccnxp_handle_events()
496 sccnxp_handle_tx(&s->port[i]); in sccnxp_handle_events()
506 spin_lock_irqsave(&s->lock, flags); in sccnxp_timer()
508 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_timer()
510 mod_timer(&s->timer, jiffies + usecs_to_jiffies(s->pdata.poll_time_us)); in sccnxp_timer()
518 spin_lock_irqsave(&s->lock, flags); in sccnxp_ist()
520 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_ist()
527 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_start_tx()
530 spin_lock_irqsave(&s->lock, flags); in sccnxp_start_tx()
533 if (s->chip->flags & SCCNXP_HAVE_IO) in sccnxp_start_tx()
538 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_start_tx()
548 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_stop_rx()
551 spin_lock_irqsave(&s->lock, flags); in sccnxp_stop_rx()
553 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_stop_rx()
560 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_tx_empty()
562 spin_lock_irqsave(&s->lock, flags); in sccnxp_tx_empty()
564 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_tx_empty()
571 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_set_mctrl()
574 if (!(s->chip->flags & SCCNXP_HAVE_IO)) in sccnxp_set_mctrl()
577 spin_lock_irqsave(&s->lock, flags); in sccnxp_set_mctrl()
582 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_set_mctrl()
589 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_get_mctrl()
592 if (!(s->chip->flags & SCCNXP_HAVE_IO)) in sccnxp_get_mctrl()
595 spin_lock_irqsave(&s->lock, flags); in sccnxp_get_mctrl()
599 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DSR_IP)) { in sccnxp_get_mctrl()
600 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], in sccnxp_get_mctrl()
605 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(CTS_IP)) { in sccnxp_get_mctrl()
606 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], in sccnxp_get_mctrl()
611 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(DCD_IP)) { in sccnxp_get_mctrl()
612 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], in sccnxp_get_mctrl()
617 if (s->pdata.mctrl_cfg[port->line] & MCTRL_MASK(RNG_IP)) { in sccnxp_get_mctrl()
618 bitmask = 1 << MCTRL_IBIT(s->pdata.mctrl_cfg[port->line], in sccnxp_get_mctrl()
624 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_get_mctrl()
631 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_break_ctl()
634 spin_lock_irqsave(&s->lock, flags); in sccnxp_break_ctl()
637 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_break_ctl()
644 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_set_termios()
649 spin_lock_irqsave(&s->lock, flags); in sccnxp_set_termios()
652 termios->c_cflag &= ~CMSPAR; in sccnxp_set_termios()
662 switch (termios->c_cflag & CSIZE) { in sccnxp_set_termios()
679 if (termios->c_cflag & PARENB) { in sccnxp_set_termios()
680 if (termios->c_cflag & PARODD) in sccnxp_set_termios()
686 mr2 = (termios->c_cflag & CSTOPB) ? MR2_STOP2 : MR2_STOP1; in sccnxp_set_termios()
694 port->read_status_mask = SR_OVR; in sccnxp_set_termios()
695 if (termios->c_iflag & INPCK) in sccnxp_set_termios()
696 port->read_status_mask |= SR_PE | SR_FE; in sccnxp_set_termios()
697 if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) in sccnxp_set_termios()
698 port->read_status_mask |= SR_BRK; in sccnxp_set_termios()
701 port->ignore_status_mask = 0; in sccnxp_set_termios()
702 if (termios->c_iflag & IGNBRK) in sccnxp_set_termios()
703 port->ignore_status_mask |= SR_BRK; in sccnxp_set_termios()
704 if (termios->c_iflag & IGNPAR) in sccnxp_set_termios()
705 port->ignore_status_mask |= SR_PE; in sccnxp_set_termios()
706 if (!(termios->c_cflag & CREAD)) in sccnxp_set_termios()
707 port->ignore_status_mask |= SR_PE | SR_OVR | SR_FE | SR_BRK; in sccnxp_set_termios()
711 (s->chip->flags & SCCNXP_HAVE_MR0) ? in sccnxp_set_termios()
716 uart_update_timeout(port, termios->c_cflag, baud); in sccnxp_set_termios()
725 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_set_termios()
730 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_startup()
733 spin_lock_irqsave(&s->lock, flags); in sccnxp_startup()
735 if (s->chip->flags & SCCNXP_HAVE_IO) { in sccnxp_startup()
752 s->opened[port->line] = 1; in sccnxp_startup()
754 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_startup()
761 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_shutdown()
764 spin_lock_irqsave(&s->lock, flags); in sccnxp_shutdown()
766 s->opened[port->line] = 0; in sccnxp_shutdown()
775 if (s->chip->flags & SCCNXP_HAVE_IO) in sccnxp_shutdown()
778 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_shutdown()
783 struct sccnxp_port *s = dev_get_drvdata(port->dev); in sccnxp_type()
785 return (port->type == PORT_SC26XX) ? s->chip->name : NULL; in sccnxp_type()
802 port->type = PORT_SC26XX; in sccnxp_config_port()
807 if ((s->type == PORT_UNKNOWN) || (s->type == PORT_SC26XX)) in sccnxp_verify_port()
809 if (s->irq == port->irq) in sccnxp_verify_port()
812 return -EINVAL; in sccnxp_verify_port()
838 while (tryes--) { in sccnxp_console_putchar()
849 struct sccnxp_port *s = (struct sccnxp_port *)co->data; in sccnxp_console_write()
850 struct uart_port *port = &s->port[co->index]; in sccnxp_console_write()
853 spin_lock_irqsave(&s->lock, flags); in sccnxp_console_write()
855 spin_unlock_irqrestore(&s->lock, flags); in sccnxp_console_write()
860 struct sccnxp_port *s = (struct sccnxp_port *)co->data; in sccnxp_console_setup()
861 struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0]; in sccnxp_console_setup()
886 struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev); in sccnxp_probe()
891 struct clk *clk; in sccnxp_probe() local
897 s = devm_kzalloc(&pdev->dev, sizeof(struct sccnxp_port), GFP_KERNEL); in sccnxp_probe()
899 dev_err(&pdev->dev, "Error allocating port structure\n"); in sccnxp_probe()
900 return -ENOMEM; in sccnxp_probe()
904 spin_lock_init(&s->lock); in sccnxp_probe()
906 s->chip = (struct sccnxp_chip *)pdev->id_entry->driver_data; in sccnxp_probe()
908 s->regulator = devm_regulator_get(&pdev->dev, "vcc"); in sccnxp_probe()
909 if (!IS_ERR(s->regulator)) { in sccnxp_probe()
910 ret = regulator_enable(s->regulator); in sccnxp_probe()
912 dev_err(&pdev->dev, in sccnxp_probe()
916 } else if (PTR_ERR(s->regulator) == -EPROBE_DEFER) in sccnxp_probe()
917 return -EPROBE_DEFER; in sccnxp_probe()
919 clk = devm_clk_get_enabled(&pdev->dev, NULL); in sccnxp_probe()
920 if (IS_ERR(clk)) { in sccnxp_probe()
921 ret = PTR_ERR(clk); in sccnxp_probe()
922 if (ret == -EPROBE_DEFER) in sccnxp_probe()
926 uartclk = clk_get_rate(clk); in sccnxp_probe()
930 dev_notice(&pdev->dev, "Using default clock frequency\n"); in sccnxp_probe()
931 uartclk = s->chip->freq_std; in sccnxp_probe()
935 if ((uartclk < s->chip->freq_min) || (uartclk > s->chip->freq_max)) { in sccnxp_probe()
936 dev_err(&pdev->dev, "Frequency out of bounds\n"); in sccnxp_probe()
937 ret = -EINVAL; in sccnxp_probe()
942 memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata)); in sccnxp_probe()
944 if (s->pdata.poll_time_us) { in sccnxp_probe()
945 dev_info(&pdev->dev, "Using poll mode, resolution %u usecs\n", in sccnxp_probe()
946 s->pdata.poll_time_us); in sccnxp_probe()
947 s->poll = 1; in sccnxp_probe()
950 if (!s->poll) { in sccnxp_probe()
951 s->irq = platform_get_irq(pdev, 0); in sccnxp_probe()
952 if (s->irq < 0) { in sccnxp_probe()
953 ret = -ENXIO; in sccnxp_probe()
958 s->uart.owner = THIS_MODULE; in sccnxp_probe()
959 s->uart.dev_name = "ttySC"; in sccnxp_probe()
960 s->uart.major = SCCNXP_MAJOR; in sccnxp_probe()
961 s->uart.minor = SCCNXP_MINOR; in sccnxp_probe()
962 s->uart.nr = s->chip->nr; in sccnxp_probe()
964 s->uart.cons = &s->console; in sccnxp_probe()
965 s->uart.cons->device = uart_console_device; in sccnxp_probe()
966 s->uart.cons->write = sccnxp_console_write; in sccnxp_probe()
967 s->uart.cons->setup = sccnxp_console_setup; in sccnxp_probe()
968 s->uart.cons->flags = CON_PRINTBUFFER; in sccnxp_probe()
969 s->uart.cons->index = -1; in sccnxp_probe()
970 s->uart.cons->data = s; in sccnxp_probe()
971 strcpy(s->uart.cons->name, "ttySC"); in sccnxp_probe()
973 ret = uart_register_driver(&s->uart); in sccnxp_probe()
975 dev_err(&pdev->dev, "Registering UART driver failed\n"); in sccnxp_probe()
979 for (i = 0; i < s->uart.nr; i++) { in sccnxp_probe()
980 s->port[i].line = i; in sccnxp_probe()
981 s->port[i].dev = &pdev->dev; in sccnxp_probe()
982 s->port[i].irq = s->irq; in sccnxp_probe()
983 s->port[i].type = PORT_SC26XX; in sccnxp_probe()
984 s->port[i].fifosize = s->chip->fifosize; in sccnxp_probe()
985 s->port[i].flags = UPF_SKIP_TEST | UPF_FIXED_TYPE; in sccnxp_probe()
986 s->port[i].iotype = UPIO_MEM; in sccnxp_probe()
987 s->port[i].mapbase = res->start; in sccnxp_probe()
988 s->port[i].membase = membase; in sccnxp_probe()
989 s->port[i].regshift = s->pdata.reg_shift; in sccnxp_probe()
990 s->port[i].uartclk = uartclk; in sccnxp_probe()
991 s->port[i].ops = &sccnxp_ops; in sccnxp_probe()
992 s->port[i].has_sysrq = IS_ENABLED(CONFIG_SERIAL_SCCNXP_CONSOLE); in sccnxp_probe()
993 uart_add_one_port(&s->uart, &s->port[i]); in sccnxp_probe()
995 if (s->chip->flags & SCCNXP_HAVE_IO) in sccnxp_probe()
996 sccnxp_set_bit(&s->port[i], DIR_OP, 0); in sccnxp_probe()
1000 s->imr = 0; in sccnxp_probe()
1001 sccnxp_write(&s->port[0], SCCNXP_IMR_REG, 0); in sccnxp_probe()
1003 if (!s->poll) { in sccnxp_probe()
1004 ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL, in sccnxp_probe()
1008 dev_name(&pdev->dev), s); in sccnxp_probe()
1012 dev_err(&pdev->dev, "Unable to reguest IRQ %i\n", s->irq); in sccnxp_probe()
1014 timer_setup(&s->timer, sccnxp_timer, 0); in sccnxp_probe()
1015 mod_timer(&s->timer, jiffies + in sccnxp_probe()
1016 usecs_to_jiffies(s->pdata.poll_time_us)); in sccnxp_probe()
1020 uart_unregister_driver(&s->uart); in sccnxp_probe()
1022 if (!IS_ERR(s->regulator)) in sccnxp_probe()
1023 regulator_disable(s->regulator); in sccnxp_probe()
1033 if (!s->poll) in sccnxp_remove()
1034 devm_free_irq(&pdev->dev, s->irq, s); in sccnxp_remove()
1036 del_timer_sync(&s->timer); in sccnxp_remove()
1038 for (i = 0; i < s->uart.nr; i++) in sccnxp_remove()
1039 uart_remove_one_port(&s->uart, &s->port[i]); in sccnxp_remove()
1041 uart_unregister_driver(&s->uart); in sccnxp_remove()
1043 if (!IS_ERR(s->regulator)) { in sccnxp_remove()
1044 int ret = regulator_disable(s->regulator); in sccnxp_remove()
1046 dev_err(&pdev->dev, "Failed to disable regulator\n"); in sccnxp_remove()