summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/serial/fsl_lpuart.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index eb6b6f0aeae5..9da8a9acd614 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1639,21 +1639,35 @@ lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp;
u32 clk = sport->port.uartclk;
+ /*
+ * The idea is to use the best OSR (over-sampling rate) possible.
+ * Note, OSR is typically hard-set to 16 in other LPUART instantiations.
+ * Loop to find the best OSR value possible, one that generates minimum
+ * baud_diff iterate through the rest of the supported values of OSR.
+ *
+ * Calculation Formula:
+ * Baud Rate = baud clock / ((OSR+1) × SBR)
+ */
baud_diff = baudrate;
osr = 0;
sbr = 0;
+
for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
+ /* calculate the temporary sbr value */
tmp_sbr = (clk / (baudrate * tmp_osr));
if (tmp_sbr == 0)
tmp_sbr = 1;
- /*calculate difference in actual buad w/ current values */
- tmp_diff = (clk / (tmp_osr * tmp_sbr));
- tmp_diff = tmp_diff - baudrate;
+ /*
+ * calculate the baud rate difference based on the temporary
+ * osr and sbr values
+ */
+ tmp_diff = clk / (tmp_osr * tmp_sbr) - baudrate;
/* select best values between sbr and sbr+1 */
- if (tmp_diff > (baudrate - (clk / (tmp_osr * (tmp_sbr + 1))))) {
- tmp_diff = baudrate - (clk / (tmp_osr * (tmp_sbr + 1)));
+ tmp = clk / (tmp_osr * (tmp_sbr + 1));
+ if (tmp_diff > (baudrate - tmp)) {
+ tmp_diff = baudrate - tmp;
tmp_sbr++;
}
@@ -1667,6 +1681,11 @@ lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)
}
}
+ /* handle buadrate outside acceptable rate */
+ if (baud_diff > ((baudrate / 100) * 3))
+ dev_warn(sport->port.dev,
+ "unacceptable baud rate difference of more than 3%%\n");
+
tmp = lpuart32_read(sport->port.membase + UARTBAUD);
if ((osr > 3) && (osr < 8))