Commit 00a7fa83 authored by Yu Tu's avatar Yu Tu Committed by Greg Kroah-Hartman

tty: serial: meson: Add a 12MHz internal clock rate to calculate baud rate in...

tty: serial: meson: Add a 12MHz internal clock rate to calculate baud rate in order to meet the baud rate requirements of special BT modules

A /2 divider over XTAL was introduced since G12A, and is preferred
to be used over the still present /3 divider since it provides much
closer frequencies vs the request baudrate. Especially the BT module
uses 3Mhz baud rate. 8Mhz calculations can lead to baud rate bias,
causing some problems.
Reviewed-by: default avatarNeil Armstrong <narmstrong@baylibre.com>
Signed-off-by: default avatarYu Tu <yu.tu@amlogic.com>
Link: https://lore.kernel.org/r/20220422111320.19234-2-yu.tu@amlogic.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f938948d
...@@ -68,6 +68,7 @@ ...@@ -68,6 +68,7 @@
#define AML_UART_BAUD_MASK 0x7fffff #define AML_UART_BAUD_MASK 0x7fffff
#define AML_UART_BAUD_USE BIT(23) #define AML_UART_BAUD_USE BIT(23)
#define AML_UART_BAUD_XTAL BIT(24) #define AML_UART_BAUD_XTAL BIT(24)
#define AML_UART_BAUD_XTAL_DIV2 BIT(27)
#define AML_UART_PORT_NUM 12 #define AML_UART_PORT_NUM 12
#define AML_UART_PORT_OFFSET 6 #define AML_UART_PORT_OFFSET 6
...@@ -80,6 +81,10 @@ static struct uart_driver meson_uart_driver; ...@@ -80,6 +81,10 @@ static struct uart_driver meson_uart_driver;
static struct uart_port *meson_ports[AML_UART_PORT_NUM]; static struct uart_port *meson_ports[AML_UART_PORT_NUM];
struct meson_uart_data {
bool has_xtal_div2;
};
static void meson_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) static void meson_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{ {
} }
...@@ -293,13 +298,20 @@ static int meson_uart_startup(struct uart_port *port) ...@@ -293,13 +298,20 @@ static int meson_uart_startup(struct uart_port *port)
static void meson_uart_change_speed(struct uart_port *port, unsigned long baud) static void meson_uart_change_speed(struct uart_port *port, unsigned long baud)
{ {
u32 val; const struct meson_uart_data *private_data = port->private_data;
u32 val = 0;
while (!meson_uart_tx_empty(port)) while (!meson_uart_tx_empty(port))
cpu_relax(); cpu_relax();
if (port->uartclk == 24000000) { if (port->uartclk == 24000000) {
val = DIV_ROUND_CLOSEST(port->uartclk / 3, baud) - 1; unsigned int xtal_div = 3;
if (private_data && private_data->has_xtal_div2) {
xtal_div = 2;
val |= AML_UART_BAUD_XTAL_DIV2;
}
val |= DIV_ROUND_CLOSEST(port->uartclk / xtal_div, baud) - 1;
val |= AML_UART_BAUD_XTAL; val |= AML_UART_BAUD_XTAL;
} else { } else {
val = DIV_ROUND_CLOSEST(port->uartclk / 4, baud) - 1; val = DIV_ROUND_CLOSEST(port->uartclk / 4, baud) - 1;
...@@ -749,6 +761,7 @@ static int meson_uart_probe(struct platform_device *pdev) ...@@ -749,6 +761,7 @@ static int meson_uart_probe(struct platform_device *pdev)
port->x_char = 0; port->x_char = 0;
port->ops = &meson_uart_ops; port->ops = &meson_uart_ops;
port->fifosize = fifosize; port->fifosize = fifosize;
port->private_data = (void *)device_get_match_data(&pdev->dev);
meson_ports[pdev->id] = port; meson_ports[pdev->id] = port;
platform_set_drvdata(pdev, port); platform_set_drvdata(pdev, port);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment