Re: [PATCH] serial: 8250: Tolerate clock variance for max baud rate

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 03/04/2015 03:54 AM, James Hogan wrote:
> On Tue, Mar 03, 2015 at 02:08:45PM -0500, Peter Hurley wrote:
>> On 03/03/2015 05:11 AM, James Hogan wrote:
>>> Hi Peter,
>>>
>>> On Mon, Mar 02, 2015 at 01:37:07PM -0500, Peter Hurley wrote:
>>>> [ +cc common clock maintainers ]
>>>>
>>>> On 02/26/2015 12:34 PM, James Hogan wrote:
>>>>> Hi Peter,
>>>>>
>>>>> On 26/02/15 16:54, Peter Hurley wrote:
>>>>>> On 02/26/2015 09:44 AM, James Hogan wrote:
>>>>>>> On 26/02/15 13:45, Peter Hurley wrote:
>>>>>>>> Hi James,
>>>>>>>>
>>>>>>>> On 02/26/2015 06:25 AM, James Hogan wrote:
>>>>>>>>> Hi Sebastian,
>>>>>>>>>
>>>>>>>>> On 26/02/15 08:51, Sebastian Andrzej Siewior wrote:
>>>>>>>>>> On 02/26/2015 01:21 AM, James Hogan wrote:
>>>>>>>>>>> When the UART clock is set slightly under 1.8432MHz, the 8250 driver
>>>>>>>>>>> core doesn't permit the 115200 baud rate since it calculates the maximum
>>>>>>>>>>> frequency to pass to uart_get_baud_rate by simply dividing the uart
>>>>>>>>>>> clock by 16 which yields a value slightly under 115200, even though the
>>>>>>>>>>> frequency is close enough for the UART to operate reliably.
>>>>>>>>>>>
>>>>>>>>>>> Therefore add some tolerance in the calculation of the maximum baud
>>>>>>>>>>> rate, specifically +1/128th (~0.8%), to allow the 115200 baud rate to
>>>>>>>>>>> be closen for a UART clock as low as 1.8149MHz. For an external divider
>>>>>>>>>>> set as close as possible to 1.8432MHz, this should cover every possible
>>>>>>>>>>> input frequency above 118.9MHz.
>>>>>>>>>>>
>>>>>>>>>>> Signed-off-by: James Hogan <james.hogan@xxxxxxxxxx>
>>>>>>>>>>> Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
>>>>>>>>>>> Cc: Jiri Slaby <jslaby@xxxxxxx>
>>>>>>>>>>> Cc: Anton Vorontsov <avorontsov@xxxxxxxxxxxxx>
>>>>>>>>>>> Cc: Peter Hurley <peter@xxxxxxxxxxxxxxxxxx>
>>>>>>>>>>> Cc: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
>>>>>>>>>>> Cc: linux-serial@xxxxxxxxxxxxxxx
>>>>>>>>>>> ---
>>>>>>>>>>> As far as I can tell from reading the link below, this tolerance should
>>>>>>>>>>> be okay, and it definitely covers the range of input frequencies I
>>>>>>>>>>> expect for my particular hardware. I'm open to better ways of handling
>>>>>>>>>>> it though.
>>>>>>>>>>
>>>>>>>>>> What is your hardware?
>>>>>>>>>
>>>>>>>>> SoC is TZ1090 (metag based). UART clock is best derived from system
>>>>>>>>> clock which would normally be somewhere between 180MHz and 240MHz, using
>>>>>>>>> an integer divider.
>>>>>>>>>
>>>>>>>>>> (1814900 + 1814900 / 128) / 16
>>>>>>>>>>         114317
>>>>>>>>>> It is not 115200 but close enough to get you the 115200 baud rate. It
>>>>>>>>>> might make sense to increase the tolerance rather than increasing the
>>>>>>>>>> the clock but it is up to Peter / Alan to decide.
>>>>>>>>>
>>>>>>>>> One random example configuration I have here is:
>>>>>>>>>
>>>>>>>>> # cat /sys/kernel/debug/clk/clk_summary
>>>>>>>>>    clock                         enable_cnt  prepare_cnt        rate
>>>>>>>>> --------------------------------------------------------------------
>>>>>>>>>  xtal1                                    2            2    24576000
>>>>>>>>>     sys_sw                                1            1    24576000
>>>>>>>>>        sys_pll                            1            1   719965090
>>>>>>>>>           sys_div                         1            1   719965090
>>>>>>>>>              sys_x2_undeleted             1            1   719965090
>>>>>>>>>                 sys_undeleted             2            2   179991273
>>>>>>>>>                    uart_sw                1            1   179991273
>>>>>>>>>                       uart_en             1            1   179991273
>>>>>>>>>                          uart             1            1     1836646
>>>>>>>>>
>>>>>>>>> sys_undeleted  divide     uart    baud          error
>>>>>>>>>     179991273      97  1855580  115973   774 =  0.67%
>>>>>>>>>     179991273      98  1836646  114790  -410 = -0.36% (chosen)
>>>>>>>>>
>>>>>>>>> At this sys_undeleted frequency, the difference between two consecutive
>>>>>>>>> divider values is about 1183 Hz.
>>>>>>>>> For round to closest, the max error is about 591.5 Hz = 0.513%.
>>>>>>>>> For round up (i.e. increasing the clock), the max error is about 1183 Hz
>>>>>>>>> = 1.03%.
>>>>>>>>>
>>>>>>>>> So my reasoning is that rounding to closest and fixing 8250 driver to
>>>>>>>>> accept it and getting as accurate a baud rate as possible is better than
>>>>>>>>> having a less accurate baud rate and having to add a new rounding mode
>>>>>>>>> to common clock muxes and dividers.
>>>>>>>>>
>>>>>>>>> Note that AFAICT for faster input clocks the 8250 driver would accept a
>>>>>>>>> 115200 baud rate regardless of how inaccurate the resulting baud rate
>>>>>>>>> would be after division, so arguably the tolerance could be much higher.
>>>>>>>>>
>>>>>>>>> The serial core also calculates the divider with DIV_ROUND_CLOSEST, so
>>>>>>>>> there is precedent for using that rounding mode right up through the
>>>>>>>>> clock tree.
>>>>>>>>
>>>>>>>> Why clock the uart so low?
>>>>>>>
>>>>>>> I tried forcing uart = sys_undeleted / 1 a couple of years ago when
>>>>>>> switching to common clock & DT, relying instead on the divider internal
>>>>>>> to the UART, but it didn't work for everybody. It was presumed at the
>>>>>>> time that the UART input was effectively being overclocked between the
>>>>>>> divider and the uart so wasn't reliable at higher frequencies.
>>>>>>
>>>>>> 180 Mhz uart clock :)
>>>>>>
>>>>>>> The hardware manual lists Fmax/ideal as 25MHz, but I didn't want to set
>>>>>>> it to a specific value such as 25MHz as the combination of the 2
>>>>>>> dividers (the one in the uart block and the external one in the SoC)
>>>>>>> will reduce the precision that can be attained.
>>>>>>>
>>>>>>> So that really only leaves the option of aiming for the right uart
>>>>>>> frequency with the external divider and using an internal divide by 1.
>>>>>>
>>>>>> Dividing down the sys clock by 14 and the uart clock by 7 yields an
>>>>>> identical baud rate of 114790 (as does dividing the sys clock by 7
>>>>>> but that sets the uart clock to 25.713 Mhz which may be too high for
>>>>>> the IP block).
>>>>>>
>>>>>> Also, dividing sys clock by 49 and uart clock by 2 = 114790
>>>>>
>>>>> Sure, but it doesn't generalise very easily. The system/core/DDR clocks
>>>>> are statically configured by the bootloader depending on a whole bunch
>>>>> of board specifics (particularly for the DDR). I.e. it can be virtually
>>>>> anything (including prime number multiples of 115200*16). Linux then
>>>>> configures the rest of the clocks as it needs, using the common clock
>>>>> framework. This would require adding knowledge of max intermediate clock
>>>>> rates to common clock,
>>>>
>>>> The common clock framework will need to support this anyway, because a
>>>> 2-level clock tree can't possibly work with UART, ADC, GPU, etc. off a
>>>> single common clock without independent intermediate stages (maybe for
>>>> your limited application it does, but it doesn't generalize to other
>>>> designs).
>>>>
>>>>> and adding the UART internal divider into the decision making,
>>>>
>>>> Constrained dividers are already supported by many clock drivers.
>>>>
>>>>> i.e. the UART driver trying to set a bunch of rates,
>>>>> multiples of 115200*16 for each internal divider value, and seeing which
>>>>> gives the best baud rate, which would be even more complicated, and its
>>>>> all to appease an arguably nonsensical constraint in the driver.
>>>>
>>>> The true constraint you're trying to workaround is that the common clock
>>>> framework doesn't adequately support your use-case yet. But that's where
>>>> your requirement needs to be solved.
>>>>
>>>> ISTM that the clock api should provide helpers so the intermediate parent
>>>> clock can compute the best-fit clock rate given the constraints of
>>>> the input sys clock rate, the {min,max} intermediate clock rate range,
>>>> and the desired sample rate multiple of the clock consumer.
>>>
>>> Even with those other constraints fully implemented, is it really a
>>> correct constraint that the uart input clock must be strictly >=
>>> 115200*16? A value under this may give the closest baud rate even taking
>>> all other constraints into account.
>>
>> I spent some time last night experimenting with a simple brute-force
>> solver.
>>
>> And while there are input clock rates for which the best-fit output clock is
>> < 115200 * 16 (for that target rate or its multiples), for the same input
>> clock rate there always seems to be faster multiples within some degree
>> of error, although not as low as you initially proposed.
>>
>> For example, an input clock = 152785600 has a best-fit output clock =
>> 1840790 (div=83, baud=115049, error=0.13%). That same input clock rate
>> has fastest multiples with div=82 and div=41 with a error=1.3%
>>
>> However, the error limit you initially proposed (as you noted in the
>> commit log) is only suitable for input clock rates above 118Mhz; lower
>> clock rates would require larger error limits.
>>
>> I plan to experiment further on the actual effects of a slow uart clock
>> and a suitable error limit, but any further information you can provide
>> wrt sample error might be helpful.


I finally had some time to further consider and experiment with this
solution. And while I still believe that the root cause of this problem
needs to be solved within the common clock framework, I see no problem
with allowing a small undershoot at the limits. So,

Reviewed-by: Peter Hurley <peter@xxxxxxxxxxxxxxxxxx>

PS - I'm certain this patch needs resent, as Greg will no longer have a copy.



> My only other comment is that the overall error tolerance is shared
> with the other end. The following article suggests overall 2% error
> would be pushing it for a "nasty" case of only sampling accurately 50%
> of the bit time (e.g. a long capacitive connection, though I don't know
> how realistic that case is). So if one end is 1.3% fast as in your
> example, the other end only needs to be 0.7% slow for it to be a
> problem.
> 
> http://www.maximintegrated.com/en/app-notes/index.mvp/id/2141
> 
> This was my rationale for wanting round to closest throughout the
> calculation.
> 
> Thanks
> James
> 
>>
>> Regards,
>> Peter Hurley
>>
>>
>>>>> At the moment I just need this patch and the following added in the uart
>>>>> DT node, and it should basically work for all system clock rates I care
>>>>> about:
>>>>>
>>>>> 	assigned-clocks = <&top_clks CLK_TOP_UART>;
>>>>> 	assigned-clock-rates = <1843200>;
>>>>>
>>>>> Cheers
>>>>> James
>>>>>
>>>>
>>

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux