[PATCH v3 10/15] serial: stm32-usart: Add STM32 USART Driver

Peter Hurley peter at hurleysoftware.com
Tue Mar 24 10:44:53 PDT 2015


Hi Maxime,

On 03/24/2015 01:21 PM, Maxime Coquelin wrote:
> Hi Peter,
> 
> 2015-03-19 18:35 GMT+01:00 Maxime Coquelin <mcoquelin.stm32 at gmail.com>:
>> 2015-03-19 15:58 GMT+01:00 Peter Hurley <peter at hurleysoftware.com>:
>>> On 03/19/2015 09:55 AM, Maxime Coquelin wrote:
>>>>>>>> +static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
>>>>>>>> +                           struct ktermios *old)
>>> [...]
>>>>>>>> +       usardiv = (port->uartclk * 25) / (baud * 4);
>>>>>>>> +       mantissa = (usardiv / 100) << USART_BRR_DIV_M_SHIFT;
>>>>>>>> +       fraction = DIV_ROUND_CLOSEST((usardiv % 100) * 16, 100);
>>>>>>>> +       if (fraction & ~USART_BRR_DIV_F_MASK) {
>>>>>>>> +               fraction = 0;
>>>>>>>> +               mantissa += (1 << USART_BRR_DIV_M_SHIFT);
>>>>>>>> +       }
>>> [...]
>>>> Really, I would prefer keeping this fractional divider as it is
>>>> implemented today.
>>>
>>> You have to admit that's basically an unintelligible mess;
>>> how would anyone ever be able to refactor and replace that with a
>>> common divider implementation?
>>>
>>> At the very least, please comment on the formula and format.
>>
>> Ok, I will refactor the implementation, and comment it.
> 
> The implementation was indeed a mess.
> I found some time to refactor the code, and also added support for 8
> times oversampling (16 by default).
> It will allow to achieve higher speeds, with the side effect of being
> less tolerant to clock deviations.
> 
> What do you think about the code below?
> 
> 
>     usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud);
> 
>     /*
>      * The USART supports 16 or 8 times oversampling.
>      * By default we prefer 16 times oversampling, so that the receiver
>      * has a better tolerance to clock deviations.
>      * 8 times oversampling is only used to achieve higher speeds.
>      */
>     if (usartdiv < 16) {
>         oversampling = 8;
>         stm32_set_bits(port, USART_CR1, USART_CR1_OVER8);
>     } else {
>         oversampling = 16;
>         stm32_clr_bits(port, USART_CR1, USART_CR1_OVER8);
>     }
> 
>     mantissa = (usartdiv / oversampling) << USART_BRR_DIV_M_SHIFT;
>     fraction = usartdiv % oversampling;
>     writel_relaxed(mantissa | fraction, port->membase + USART_BRR)

Thanks! Way better :)
Much more obvious this is a fixed-point divisor.

Regards,
Peter Hurley






More information about the linux-arm-kernel mailing list