On 6/24/20 8:33 AM, Paolo Bonzini wrote:
> On 23/06/20 22:07, Eric Blake wrote:
>>>
>>>              uint64_t baud = ((value & UART_CTRL_NCO) >> 16);
>>>               baud *= 1000;
>>> -            baud /= 2 ^ 20;
>>> +            baud >>= 20;
>>
>> Dividing by 1M instead of 22 seems much more logical, indeed :)
> 
> Based on the spec, the "* 1000" is the clock, in other words this is a
> fixed point value relative to the clock:
> 
> f_baud = NCO * f_clock / 2^20
> 
> The example in the spec (https://docs.opentitan.org/hw/ip/uart/doc/) has
> f_clock = 50 MHz, while here it's only 1 kHz.  And the register is only
> 16 bit, so the above would only allow a baud rate up to 62 (65535 * 1000
> / 2^20).
> 
> Should the clock be a property of the device instead?

Ideally the device should use qdev_get_clock_in(),
(see docs/devel/clocks.rst):

  static void ibex_uart_init(Object *obj)
  {
     ...
     s->f_clk = qdev_get_clock_in(DEVICE(obj), "f_clock");
     ...

Then in ibex_uart_write():

     uint64_t baud = ((value & UART_CTRL_NCO) >> 16);
     baud *= clock_get_hz(dev->f_clk));
     baud >>= 20;

Devices not using the QDEV_CLOCK API use QDEV properties.

> 
> Thanks,
> 
> Paolo
> 
>> It's odd that we are scaling up by 1000, down by 1024*1024, then
>>
>>>                 s->char_tx_time = (NANOSECONDS_PER_SECOND / baud) * 10; 
> 
> 


Reply via email to