diff options
author | Patrice Chotard <patrice.chotard@st.com> | 2017-06-08 07:26:55 (GMT) |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2017-06-12 12:38:38 (GMT) |
commit | 1afcf9cb25d4db2c2dd320eb93f463c55cdad040 (patch) | |
tree | b133f174cb34b4cea9a929a31f5a980012de0739 /drivers/serial | |
parent | 1113ad49dce7d56429c6ad37738d06e7aef21fac (diff) | |
download | u-boot-1afcf9cb25d4db2c2dd320eb93f463c55cdad040.tar.xz |
serial: stm32x7: simplify baud rate register calculation
Simplify baud rate register formula and use the oversampling
uart feature.
This code is aligned with what is implemented in kernel driver
drivers/tty/serial/stm32-usart.c since kernel v4.9.
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Reviewed-by: Christophe KERELLO <christophe.kerello@st.com>
Reviewed-by: Patrick DELAUNAY <patrick.delaunay@st.com>
Acked-by: Vikas MANOCHA <vikas.manocha@st.com>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/serial_stm32x7.c | 21 | ||||
-rw-r--r-- | drivers/serial/serial_stm32x7.h | 3 |
2 files changed, 17 insertions, 7 deletions
diff --git a/drivers/serial/serial_stm32x7.c b/drivers/serial/serial_stm32x7.c index 7693159..61e8167 100644 --- a/drivers/serial/serial_stm32x7.c +++ b/drivers/serial/serial_stm32x7.c @@ -20,7 +20,7 @@ static int stm32_serial_setbrg(struct udevice *dev, int baudrate) { struct stm32x7_serial_platdata *plat = dev->platdata; struct stm32_usart *const usart = plat->base; - u32 clock, int_div, frac_div, tmp; + u32 clock, int_div, mantissa, fraction, oversampling; if (((u32)usart & STM32_BUS_MASK) == APB1_PERIPH_BASE) clock = clock_get(CLOCK_APB1); @@ -29,11 +29,20 @@ static int stm32_serial_setbrg(struct udevice *dev, int baudrate) else return -EINVAL; - int_div = (25 * clock) / (4 * baudrate); - tmp = ((int_div / 100) << USART_BRR_M_SHIFT) & USART_BRR_M_MASK; - frac_div = int_div - (100 * (tmp >> USART_BRR_M_SHIFT)); - tmp |= (((frac_div * 16) + 50) / 100) & USART_BRR_F_MASK; - writel(tmp, &usart->brr); + int_div = DIV_ROUND_CLOSEST(clock, baudrate); + + if (int_div < 16) { + oversampling = 8; + setbits_le32(&usart->cr1, USART_CR1_OVER8); + } else { + oversampling = 16; + clrbits_le32(&usart->cr1, USART_CR1_OVER8); + } + + mantissa = (int_div / oversampling) << USART_BRR_M_SHIFT; + fraction = int_div % oversampling; + + writel(mantissa | fraction, &usart->brr); return 0; } diff --git a/drivers/serial/serial_stm32x7.h b/drivers/serial/serial_stm32x7.h index 8c02548..facfdba 100644 --- a/drivers/serial/serial_stm32x7.h +++ b/drivers/serial/serial_stm32x7.h @@ -23,8 +23,9 @@ struct stm32_usart { }; -#define USART_CR1_RE (1 << 2) +#define USART_CR1_OVER8 (1 << 15) #define USART_CR1_TE (1 << 3) +#define USART_CR1_RE (1 << 2) #define USART_CR1_UE (1 << 0) #define USART_CR3_OVRDIS (1 << 12) |