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)
 {
        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;
        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;
 
 
 #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)