Re: [PATCH] dt-bindings: Add silabs,si5341

From: Mike Looijmans
Date: Wed May 01 2019 - 01:47:24 EST


On 30-04-19 02:17, Stephen Boyd wrote:
> Quoting Mike Looijmans (2019-04-27 02:42:56)
>> On 27-04-19 02:44, Stephen Boyd wrote:
>>> Quoting Mike Looijmans (2019-04-25 23:51:15)
>>>> On 26-04-19 01:04, Stephen Boyd wrote:
>>>>>> +
>>>>>> +Optional properties:
>>>>>> +- silabs,pll-m-num, silabs,pll-m-den: Numerator and denominator for PLL
>>>>>> + feedback divider. Must be such that the PLL output is in the valid range. For
>>>>>> + example, to create 14GHz from a 48MHz xtal, use m-num=14000 and m-den=48. Only
>>>>>> + the fraction matters, using 3500 and 12 will deliver the exact same result.
>>>>>> + If these are not specified, and the PLL is not yet programmed when the driver
>>>>>> + probes, the PLL will be set to 14GHz.
>>>>>
>>>>> Can this be done via assigned-clock-rates? Possibly with a table in the
>>>>> clk driver to tell us how to generate those rates.
>>>>
>>>> The PLL frequency choice determines who'll get jitter and who won't. It's
>>>> ridiculously accurate too.
>>>>
>>>> For example, if you need a 26 MHz and a 100 MHz output, there's no solution
>>>> for the PLL that makes both clocks an integer divider (SI is vague about it,
>>>> but apparently integer dividers have less jitter on output). Only the enduser
>>>> can say which clock will get the better quality.
>
> Right. So maybe we make tables of rates and put it in the driver and
> keep adding code in there? I'm worried about having these properties in
> DT and then having to work around them later on by "fixing" the DT. If
> it's only in the driver then we're able to tweak the values to get
> better jitter numbers, etc.

Programming the main PLL is easy, no tables required.

It's all user choice, that's the issue here. Drivers themselves cannot make
this decision.

(user = the person doing board support, writing the devicetree and kernel
config for example)

In my example, the chip has no issue synthesizing both 26 and 100 MHz.
Depending on the main PLL setting, one may have more jitter than the other. If
the PLL is set to 14.0 GHz, the 100 MHz clock will be of better quality, while
if the PLL is set to 13.624 GHz (an even multiple of 26), the 26 MHz will have
better quality.


>>>>>> +- silabs,reprogram: When present, the driver will always assume the device must
>>>>>> + be initialized, and always performs the soft-reset routine. Since this will
>>>>>> + temporarily stop all output clocks, don't do this if the chip is generating
>>>>>> + the CPU clock for example.
>>>>>
>>>>> Could this be done with the reset framework? It almost sounds like if
>>>>> the clk is a CLK_IS_CRITICAL then we shouldn't do the reset, otherwise
>>>>> we probably should reset the chip when the driver probes. If we don't
>>>>> have a case where it's going to be supplying a critical clk for a long
>>>>> time then perhaps we shouldn't even consider this topic until later.
>>>>
>>>> The driver can sort of see that the chips is already configured. This tells
>>>> the driver whether that's expected or just coincidence.
>>>>
>>>> Maybe it'd be clearer if I reversed the logic and name this
>>>> "silabs,preprogrammed", which will skip the driver's initialization routine?
>>>>
>>>
>>> Maybe? Is there any way to look at some register to figure out for sure
>>> if it's been pre-programmed or not? Could TOOL_VERSION be used or
>>> ACTIVE_NVM_BANK or DESIGN_ID0-7?
>>
>> I've experimentally determined that TOOL_VERSION and DESIGN_IDx
>> apparently get filled with zeroes by the clockbuilder anyway.
>>
>> ACTIVE_NVM_BANK works reliably for self-programmed chips.
>>
>> The flag is about "is this chip under full kernel control, or is it
>> generating clocks the kernel doesn't know about (e.g. for realtime cores
>> or FPGA logic)".
>>
>
> Alright.
>
>>
>>
>>>>>> +==Child nodes==
>>>>>> +
>>>>>> +Each of the clock outputs can be overwritten individually by
>>>>>> +using a child node to the I2C device node. If a child node for a clock
>>>>>> +output is not set, the configuration remains unchanged.
>>>>>> +
>>>>>> +Required child node properties:
>>>>>> +- reg: number of clock output.
>>>>>> +
>>>>>> +Optional child node properties:
>>>>>> +- silabs,format: Output format, see [1], 1=differential, 2=low-power, 4=LVCMOS
>>>>>> +- silabs,common-mode: Output common mode, depends on standard.
>>>>>> +- silabs,amplitude: Output amplitude, depends on standard.
>>>>>> +- silabs,synth-source: Select which multisynth to use for this output
>>>>>> +- silabs,synth-frequency: Sets the frequency for the multisynth connected to
>>>>>> + this output. This will affect other outputs connected to this multisynth. The
>>>>>> + setting is applied before silabs,synth-master and clock-frequency.
>>>>>> +- silabs,synth-master: If present, this output is allowed to change the
>>>>>> + multisynth frequency dynamically.
>>>>>
>>>>> These above properties look like highly detailed configuration data to
>>>>> let the driver configure the clk output exactly how it's supposed to be
>>>>> configured. Can these properties be rewritten in more high-level terms
>>>>> that a system integrator would understand? Ideally, I shouldn't have to
>>>>> read the datasheet and the driver and then figure out what DT properties
>>>>> need the values from the datasheet in them so that the driver writes
>>>>> them to a particular register. I don't know if that's possible here,
>>>>> because I haven't read the driver or the datasheet too closely yet, but
>>>>> that should be the goal.
>>>>
>>>> The datasheet is not very helpful in this regard. Silabs just assumes you'll
>>>> use their clockbuilder software for writing these values, which is how we got
>>>> to the "LVDS 3v3" values.
>>>
>>> I hope that can be determined by looking at vdd<N>-supply voltages?
>>
>> Not really, and when asked for a bit more detail, Silabs just says to
>> use the excellent developer friendly clockbuilder software that almost
>> runs on almost any platform.
>>
>>>> I could put in a table of "common" values, so that you can say:
>>>>
>>>> silabs,output-standard = "lvds";
>>>>
>>>> And then use the "raw" properties to expand or override on that.
>>>>
>>>> Extra defines might help, e.g.:
>>>>
>>>> silabs,format = <SI5341_FORMAT_DIFFERENTIAL>;
>>>
>>> I suppose you'll need to reverse engineer the clock builder software to
>>> figure out why a SI5341_FORMAT_DIFFERENTIAL would be specified instead
>>> of some other value. Ideally we don't need any of these vendor specific
>>> properties and the drivers using these clks can ask the clk framework to
>>> configure these properties, or we need to look at making more properties
>>> like 'assigned-clock-parents' that lets us configure things generically.
>>
>> These properties are about how you soldered things together, but yeah,
>> if the clock outputs go to expansion slots, some driver or devicetree
>> fragment control would be desirable, so you can switch the clock mode
>> from differential to single ended for example.
>
> Hmm.. Perhaps we need a clk_set_mode() API? Possibly be an internal API
> that lets the DT configure the mode to be differential or single ended?
> Nobody has required this so far so it's very rare, but I'd like to see
> the properties become standard instead of vendor specific if possible.
>
>>
>>
>>>>>> +- always-on: Immediately and permanently enable this output. Particulary
>>>>>> + useful when combined with assigned-clocks, since that does not prepare clocks.
>>>>>
>>>>> Looks like you want CLK_IS_CRITICAL in DT. We've had that discussion
>>>>> before but maybe we should revisit it here and add a way to indicate
>>>>> that some clk should never be turned off instead of assuming that we
>>>>> can do this from C code all the time.
>>>>
>>>> My issue was that assigned-clocks does not call clk_prepare. If the clock is
>>>> not running, assigned-clocks will not turn it on (at least, that is the case
>>>> on the 4.14 kernel I tested this on), it apparently only prevents it from
>>>> being turned off by marking it as "in use". This just provides a way to use
>>>> assigned-clocks.
>>>>
>>> Do you want the clks to always be prepared and enabled? What use-case is
>>> this? It still looks like CLK_IS_CRITICAL flag needs to be expressed in
>>> DT here.
>>
>> The use case is pretty simple, it's just to enable the clock. Or in this
>> case, "prepare" it, because the I2C client needs to be able to sleep and
>> all actions must be done in the prepare part.
>>
>> Suppose I use the si5341 to generate a 26MHz clock that would normally
>> be provides by a hardware oscillator. The driver itself doesn't have any
>> clock properties to set. Then I'd put into that device's devicetree node
>> the following:
>>
>> assigned-clocks = <&si5341 2>;
>> assigned-clock-rates = <26000000>;
>>
>> When the system boots, the clock framework indeed calls
>> "set_rate(26000000)" before that driver probes, but it never calls
>> "clk_prepare", so the clock's frequency is set okay but the clock won't
>> be running and the device won't function.
>
> Why can't that driver call clk_prepare_enable()? Is there some sort of
> assumption that this clk will always be enabled and not have a driver
> that configures the rate and gates/ungates it?

Not only clk_prepare_enable(), but the driver could also call clk_set_rate()
and clk_set_parent() and the likes, but it doesn't, so that's why there is
"assigned-clocks" right?

There are multiple scenario's, similar to why regulators also have properties
like these.

- The clock is related to hardware that the kernel is not aware of.
- The clock is for a driver that isn't aware of its clock requirements. It
might be an extra clock for an FPGA implemented controller that mimics
existing hardware.

I'd also consider patching "assigned-clocks" to call "clk_prepare_enable()",
would that make sense, or is it intentional that assigned-clocks doesn't do that?