diff options
Diffstat (limited to 'sys/arm/amlogic/aml8726/uart_dev_aml8726.c')
-rw-r--r-- | sys/arm/amlogic/aml8726/uart_dev_aml8726.c | 51 |
1 files changed, 44 insertions, 7 deletions
diff --git a/sys/arm/amlogic/aml8726/uart_dev_aml8726.c b/sys/arm/amlogic/aml8726/uart_dev_aml8726.c index 1dda52f..5d21fb0 100644 --- a/sys/arm/amlogic/aml8726/uart_dev_aml8726.c +++ b/sys/arm/amlogic/aml8726/uart_dev_aml8726.c @@ -31,8 +31,8 @@ * uarts. For example ... though UART A as a 128 byte FIFO, the * others only have a 64 byte FIFO. * - * Also, it's assumed that register 5 (the new baud rate register - * present on the aml8726-m6) has not been activated. + * Also, it's assumed that the USE_XTAL_CLK feature (available on + * the aml8726-m6 and later) has not been activated. */ #include <sys/cdefs.h> @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include <dev/uart/uart_cpu_fdt.h> #include <dev/uart/uart_bus.h> +#include <arm/amlogic/aml8726/aml8726_soc.h> #include <arm/amlogic/aml8726/aml8726_uart.h> #include "uart_if.h" @@ -89,7 +90,7 @@ aml8726_uart_divisor(int rclk, int baudrate) /* integer version of (rclk / baudrate + .5) */ divisor = ((rclk << 1) + baudrate) / (baudrate << 1); - if (divisor == 0 || divisor >= 65536) + if (divisor == 0) return (0); actual_baud = rclk / divisor; @@ -109,6 +110,7 @@ aml8726_uart_param(struct uart_bas *bas, int baudrate, int databits, int stopbit { uint32_t cr; uint32_t mr; + uint32_t nbr; int divisor; cr = uart_getreg(bas, AML_UART_CONTROL_REG); @@ -147,8 +149,29 @@ aml8726_uart_param(struct uart_bas *bas, int baudrate, int databits, int stopbit /* Set baudrate. */ if (baudrate > 0 && bas->rclk != 0) { divisor = aml8726_uart_divisor(bas->rclk / 4, baudrate) - 1; - if (divisor > 0xffff) - return (EINVAL); + + switch (aml8726_soc_hw_rev) { + case AML_SOC_HW_REV_M6: + case AML_SOC_HW_REV_M8: + case AML_SOC_HW_REV_M8B: + if (divisor > (AML_UART_NEW_BAUD_RATE_MASK >> + AML_UART_NEW_BAUD_RATE_SHIFT)) + return (EINVAL); + + nbr = uart_getreg(bas, AML_UART_NEW_BAUD_REG); + nbr &= ~(AML_UART_NEW_BAUD_USE_XTAL_CLK | + AML_UART_NEW_BAUD_RATE_MASK); + nbr |= AML_UART_NEW_BAUD_RATE_EN | + (divisor << AML_UART_NEW_BAUD_RATE_SHIFT); + uart_setreg(bas, AML_UART_NEW_BAUD_REG, nbr); + + divisor = 0; + break; + default: + if (divisor > 0xffff) + return (EINVAL); + break; + } cr &= ~AML_UART_CONTROL_BAUD_MASK; cr |= (divisor & AML_UART_CONTROL_BAUD_MASK); @@ -187,7 +210,7 @@ aml8726_uart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits uint32_t cr; uint32_t mr; - aml8726_uart_param(bas, baudrate, databits, stopbits, parity); + (void)aml8726_uart_param(bas, baudrate, databits, stopbits, parity); cr = uart_getreg(bas, AML_UART_CONTROL_REG); /* Disable all interrupt sources. */ @@ -466,7 +489,7 @@ aml8726_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) { struct uart_bas *bas; int baudrate, divisor, error; - uint32_t cr, mr; + uint32_t cr, mr, nbr; bas = &sc->sc_bas; uart_lock(sc->sc_hwmtx); @@ -483,6 +506,20 @@ aml8726_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) divisor = ((mr >> AML_UART_MISC_BAUD_EXT_SHIFT) << AML_UART_CONTROL_BAUD_WIDTH) | cr; + switch (aml8726_soc_hw_rev) { + case AML_SOC_HW_REV_M6: + case AML_SOC_HW_REV_M8: + case AML_SOC_HW_REV_M8B: + nbr = uart_getreg(bas, AML_UART_NEW_BAUD_REG); + if ((nbr & AML_UART_NEW_BAUD_RATE_EN) != 0) { + divisor = (nbr & AML_UART_NEW_BAUD_RATE_MASK) >> + AML_UART_NEW_BAUD_RATE_SHIFT; + } + break; + default: + break; + } + baudrate = bas->rclk / 4 / (divisor + 1); if (baudrate > 0) *(int*)data = baudrate; |