Commit c8a9d043 authored by Erwan Le Ray's avatar Erwan Le Ray Committed by Greg Kroah-Hartman

serial: stm32: fix word length configuration

STM32 supports either:
- 8 and 9 bits word length (including parity bit) for stm32f4 compatible
  devices
- 7, 8 and 9 bits word length (including parity bit) for stm32f7 and
  stm32h7 compatible devices.

As a consequence STM32 supports the following termios configurations:
- CS7 with parity bit, and CS8 (with or without parity bit) for stm32f4
  compatible devices.
- CS6 with parity bit, CS7 and CS8 (with or without parity bit) for
  stm32f7 and stm32h7 compatible devices.

This patch is fixing word length by configuring correctly the SoC with
supported configurations.

Fixes: ada8618f ("serial: stm32: adding support for stm32f7")
Signed-off-by: default avatarErwan Le Ray <erwan.leray@st.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 9c12d739
......@@ -599,6 +599,36 @@ static void stm32_shutdown(struct uart_port *port)
free_irq(port->irq, port);
}
unsigned int stm32_get_databits(struct ktermios *termios)
{
unsigned int bits;
tcflag_t cflag = termios->c_cflag;
switch (cflag & CSIZE) {
/*
* CSIZE settings are not necessarily supported in hardware.
* CSIZE unsupported configurations are handled here to set word length
* to 8 bits word as default configuration and to print debug message.
*/
case CS5:
bits = 5;
break;
case CS6:
bits = 6;
break;
case CS7:
bits = 7;
break;
/* default including CS8 */
default:
bits = 8;
break;
}
return bits;
}
static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
......@@ -606,7 +636,7 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
struct stm32_usart_config *cfg = &stm32_port->info->cfg;
struct serial_rs485 *rs485conf = &port->rs485;
unsigned int baud;
unsigned int baud, bits;
u32 usartdiv, mantissa, fraction, oversampling;
tcflag_t cflag = termios->c_cflag;
u32 cr1, cr2, cr3;
......@@ -632,16 +662,28 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
if (cflag & CSTOPB)
cr2 |= USART_CR2_STOP_2B;
bits = stm32_get_databits(termios);
if (cflag & PARENB) {
bits++;
cr1 |= USART_CR1_PCE;
if ((cflag & CSIZE) == CS8) {
if (cfg->has_7bits_data)
cr1 |= USART_CR1_M0;
else
cr1 |= USART_CR1_M;
}
}
/*
* Word length configuration:
* CS8 + parity, 9 bits word aka [M1:M0] = 0b01
* CS7 or (CS6 + parity), 7 bits word aka [M1:M0] = 0b10
* CS8 or (CS7 + parity), 8 bits word aka [M1:M0] = 0b00
* M0 and M1 already cleared by cr1 initialization.
*/
if (bits == 9)
cr1 |= USART_CR1_M0;
else if ((bits == 7) && cfg->has_7bits_data)
cr1 |= USART_CR1_M1;
else if (bits != 8)
dev_dbg(port->dev, "Unsupported data bits config: %u bits\n"
, bits);
if (cflag & PARODD)
cr1 |= USART_CR1_PS;
......
......@@ -151,8 +151,7 @@ struct stm32_usart_info stm32h7_info = {
#define USART_CR1_PS BIT(9)
#define USART_CR1_PCE BIT(10)
#define USART_CR1_WAKE BIT(11)
#define USART_CR1_M BIT(12)
#define USART_CR1_M0 BIT(12) /* F7 */
#define USART_CR1_M0 BIT(12) /* F7 (CR1_M for F4) */
#define USART_CR1_MME BIT(13) /* F7 */
#define USART_CR1_CMIE BIT(14) /* F7 */
#define USART_CR1_OVER8 BIT(15)
......
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