From: anton Date: Mon, 27 Jun 2022 13:03:32 +0000 (+0000) Subject: Allow the pluart(4) baud rate to be changed. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=c1f87e31ce87e006b3e8b0603d28c939786efb68;p=openbsd Allow the pluart(4) baud rate to be changed. It's most likely that users have the wrong baud rate in /etc/ttys as this was corrected in revision 1.11 of sys/dev/ic/pluart.c. Make sure to change the console baud rate from 38400 to 115200 in /etc/ttys before upgrading. ok visa@ --- diff --git a/sys/dev/fdt/pluart_fdt.c b/sys/dev/fdt/pluart_fdt.c index 969018eccdc..c4c173a7fc6 100644 --- a/sys/dev/fdt/pluart_fdt.c +++ b/sys/dev/fdt/pluart_fdt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pluart_fdt.c,v 1.7 2022/06/11 05:29:24 anton Exp $ */ +/* $OpenBSD: pluart_fdt.c,v 1.8 2022/06/27 13:03:32 anton Exp $ */ /* * Copyright (c) 2014 Patrick Wildt * Copyright (c) 2005 Dale Rahn @@ -27,6 +27,7 @@ #include #include +#include #include int pluart_fdt_match(struct device *, void *, void *); @@ -70,8 +71,12 @@ pluart_fdt_attach(struct device *parent, struct device *self, void *aux) return; } - if (OF_is_compatible(faa->fa_node, "arm,sbsa-uart")) + if (OF_is_compatible(faa->fa_node, "arm,sbsa-uart")) { sc->sc_hwflags |= COM_HW_SBSA; + } else { + clock_enable_all(faa->fa_node); + sc->sc_clkfreq = clock_get_frequency(faa->fa_node, "uartclk"); + } periphid = OF_getpropint(faa->fa_node, "arm,primecell-periphid", 0); if (periphid != 0) diff --git a/sys/dev/ic/pluart.c b/sys/dev/ic/pluart.c index 40e2b1976fb..4ac30b6921d 100644 --- a/sys/dev/ic/pluart.c +++ b/sys/dev/ic/pluart.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pluart.c,v 1.11 2022/06/19 12:52:19 anton Exp $ */ +/* $OpenBSD: pluart.c,v 1.12 2022/06/27 13:03:32 anton Exp $ */ /* * Copyright (c) 2014 Patrick Wildt * Copyright (c) 2005 Dale Rahn @@ -71,9 +71,9 @@ #define UART_ILPR 0x20 /* IrDA low-power counter register */ #define UART_ILPR_ILPDVSR ((x) & 0xf) /* IrDA low-power divisor */ #define UART_IBRD 0x24 /* Integer baud rate register */ -#define UART_IBRD_DIVINT ((x) & 0xff) /* Integer baud rate divisor */ +#define UART_IBRD_DIVINT(x) ((x) & 0xffff) /* Integer baud rate divisor */ #define UART_FBRD 0x28 /* Fractional baud rate register */ -#define UART_FBRD_DIVFRAC ((x) & 0x3f) /* Fractional baud rate divisor */ +#define UART_FBRD_DIVFRAC(x) ((x) & 0x3f) /* Fractional baud rate divisor */ #define UART_LCR_H 0x2c /* Line control register */ #define UART_LCR_H_BRK (1 << 0) /* Send break */ #define UART_LCR_H_PEN (1 << 1) /* Parity enable */ @@ -338,7 +338,9 @@ pluart_param(struct tty *tp, struct termios *t) /* lower dtr */ } - if (ospeed != 0) { + if (sc->sc_clkfreq != 0 && ospeed != 0 && ospeed != tp->t_ospeed) { + int cr, div, lcr; + while (ISSET(tp->t_state, TS_BUSY)) { ++sc->sc_halt; error = ttysleep(tp, &tp->t_outq, @@ -349,7 +351,41 @@ pluart_param(struct tty *tp, struct termios *t) return (error); } } - /* set speed */ + + /* + * Writes to IBRD and FBRD are made effective first when LCR_H + * is written. + */ + lcr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H); + + /* The UART must be disabled while changing the baud rate. */ + cr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, UART_CR); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_CR, + cr & ~UART_CR_UARTEN); + + /* + * The baud rate divisor is expressed relative to the UART clock + * frequency where IBRD represents the quotient using 16 bits + * and FBRD the remainder using 6 bits. The PL011 specification + * provides the following formula: + * + * uartclk/(16 * baudrate) + * + * The formula can be estimated by scaling it with the + * precision 64 (2^6) and letting the resulting upper 16 bits + * represents the quotient and the lower 6 bits the remainder: + * + * 64 * uartclk/(16 * baudrate) = 4 * uartclk/baudrate + */ + div = 4 * sc->sc_clkfreq / ospeed; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_IBRD, + UART_IBRD_DIVINT(div >> 6)); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_FBRD, + UART_FBRD_DIVFRAC(div)); + /* Commit baud rate change. */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_LCR_H, lcr); + /* Enable UART. */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, UART_CR, cr); } /* setup fifo */ @@ -594,13 +630,6 @@ pluartopen(dev_t dev, int flag, int mode, struct proc *p) 5 << IMXUART_FCR_RFDIV_SH | 1 << IMXUART_FCR_RXTL_SH); - bus_space_write_4(iot, ioh, IMXUART_UBIR, - (pluartdefaultrate / 100) - 1); - - /* formula: clk / (rfdiv * 1600) */ - bus_space_write_4(iot, ioh, IMXUART_UBMR, - (clk_get_rate(sc->sc_clk) * 1000) / 1600); - SET(sc->sc_ucr1, IMXUART_CR1_EN|IMXUART_CR1_RRDYEN); SET(sc->sc_ucr2, IMXUART_CR2_TXEN|IMXUART_CR2_RXEN); bus_space_write_4(iot, ioh, IMXUART_UCR1, sc->sc_ucr1); diff --git a/sys/dev/ic/pluartvar.h b/sys/dev/ic/pluartvar.h index 492c2a60b2c..f795dd9454d 100644 --- a/sys/dev/ic/pluartvar.h +++ b/sys/dev/ic/pluartvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pluartvar.h,v 1.4 2022/06/11 05:29:24 anton Exp $ */ +/* $OpenBSD: pluartvar.h,v 1.5 2022/06/27 13:03:32 anton Exp $ */ /* * Copyright (c) 2014 Patrick Wildt * Copyright (c) 2005 Dale Rahn @@ -48,6 +48,7 @@ struct pluart_softc { #define COM_SW_PPS 0x10 int sc_fifolen; int sc_imsc; + int sc_clkfreq; u_int8_t sc_initialize; u_int8_t sc_cua;