This patch adds support for the extended baud rate register
available on the aml8726-m6 (and later) SoC which allows for lower speeds. Differential Revision: https://reviews.freebsd.org/D2433 Submitted by: John Wehle
This commit is contained in:
parent
955691fecd
commit
c1e22c8ece
@ -94,4 +94,14 @@
|
||||
#define AML_UART_MISC_RECV_IRQ_CNT_MASK 0xff
|
||||
#define AML_UART_MISC_RECV_IRQ_CNT_SHIFT 0
|
||||
|
||||
/*
|
||||
* The new baud rate register is available on the
|
||||
* aml8726-m6 and later.
|
||||
*/
|
||||
#define AML_UART_NEW_BAUD_REG 20
|
||||
#define AML_UART_NEW_BAUD_USE_XTAL_CLK (1 << 24)
|
||||
#define AML_UART_NEW_BAUD_RATE_EN (1 << 23)
|
||||
#define AML_UART_NEW_BAUD_RATE_MASK (0x7fffff << 0)
|
||||
#define AML_UART_NEW_BAUD_RATE_SHIFT 0
|
||||
|
||||
#endif /* _ARM_AMLOGIC_AML8726_UART_H */
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user