Re: [PATCH] clk: add si5351 i2c common clock driver

2013-02-10 Thread Mike Turquette
Quoting Sebastian Hesselbarth (2013-02-09 04:59:32)
> This patch adds a common clock driver for Silicon Labs Si5351a/b/c
> i2c programmable clock generators. Currently, the driver supports
> DT kernels only and VXCO feature of si5351b is not implemented. DT
> bindings selectively allow to overwrite stored Si5351 configuration
> which is very helpful for clock generators with empty eeprom
> configuration. Corresponding device tree binding documentation is
> also added.
> 
> Signed-off-by: Sebastian Hesselbarth 
> ---
> Notes:
> - During development I used a debugfs clock consumer that I can also
>   post if there is interest in it.

Please do.  I have a set of patches that implement a fake clock subtree
for testing the core framework.  I've been thinking of pushing this to
the list once it is more presentable and your work might fit into that
nicely.

> - With current (3.8-rc6) common clock framework there is two (minor)
>   issues:
>   * although clocks are registered with devm_clk_register they are not
> removed from the clock tree on unloading. That makes reloading of
> clk-si5351 as module impossible.

This is a known issue.  clk_unregister is a NOP and defining it has
always been deferred until the day that someone needed it.  Care to
take a crack at it?

>   * potentially there could be more than one different external si5351
> generators but clocks are registered with names that do not refer
> to e.g. the device name. Maybe common clock framework should
> prepend the device name for each registered clock, i.e. 0-0060.clk0.
> That would also avoid name collisions with same clock names from
> different drivers (clk0 is likely to be used by others ;))

More unfinished work, just like clk_unregister above.  I'm sure you are
aware that clk_register takes struct device *dev as input, but does
nothing with it.  It wouldn't take much to concatenate the device name
and clock name if dev is present.  However a complication here is that
the registration code takes a parent string name to match parents up for
discrete subtrees; how could statically defined data know about the
device name ahead of time?

The above design decision took place before the big DT push we have
today and was short-sighted.  It would be better to change the framework
to rely less on string name lookups and DT is one way out of that.

3.8-rc7 is already out and I don't plan to take anything that hasn't
already been submitted for 3.9 now.  Can you resubmit this after 3.9-rc1
comes out?

Thanks,
Mike
___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH] clk: add si5351 i2c common clock driver

2013-02-11 Thread Sebastian Hesselbarth

On 02/11/2013 06:46 AM, Mike Turquette wrote:

Quoting Sebastian Hesselbarth (2013-02-09 04:59:32)

This patch adds a common clock driver for Silicon Labs Si5351a/b/c
i2c programmable clock generators. Currently, the driver supports
DT kernels only and VXCO feature of si5351b is not implemented. DT
bindings selectively allow to overwrite stored Si5351 configuration
which is very helpful for clock generators with empty eeprom
configuration. Corresponding device tree binding documentation is
also added.

Signed-off-by: Sebastian Hesselbarth
---
Notes:
- During development I used a debugfs clock consumer that I can also
   post if there is interest in it.


Please do.  I have a set of patches that implement a fake clock subtree
for testing the core framework.  I've been thinking of pushing this to
the list once it is more presentable and your work might fit into that
nicely.


Mike,

then I will clean the debugfs driver and post it together with this
patch for 3.9-rc1 as an individual patch.


- With current (3.8-rc6) common clock framework there is two (minor)
   issues:
   * although clocks are registered with devm_clk_register they are not
 removed from the clock tree on unloading. That makes reloading of
 clk-si5351 as module impossible.


This is a known issue.  clk_unregister is a NOP and defining it has
always been deferred until the day that someone needed it.  Care to
take a crack at it?


Ok. I can have a look at it and propose a patch but that will take a
while as other stuff came in between. But IMHO, preparing/enabling
clocks by clock consumers should increase reference count so referenced
modules cannot be unloaded.. but that I have never had a look at, yet ;)


   * potentially there could be more than one different external si5351
 generators but clocks are registered with names that do not refer
 to e.g. the device name. Maybe common clock framework should
 prepend the device name for each registered clock, i.e. 0-0060.clk0.
 That would also avoid name collisions with same clock names from
 different drivers (clk0 is likely to be used by others ;))


More unfinished work, just like clk_unregister above.  I'm sure you are
aware that clk_register takes struct device *dev as input, but does
nothing with it.  It wouldn't take much to concatenate the device name
and clock name if dev is present.  However a complication here is that
the registration code takes a parent string name to match parents up for
discrete subtrees; how could statically defined data know about the
device name ahead of time?


I see. Wrt the above comment about spare time, would prepending DT
clocks be sufficient? Or/And use a fallback mechanism that first tries
a full match, full match with own device name, and relaxed match for
clock name as it is now?


The above design decision took place before the big DT push we have
today and was short-sighted.  It would be better to change the framework
to rely less on string name lookups and DT is one way out of that.

3.8-rc7 is already out and I don't plan to take anything that hasn't
already been submitted for 3.9 now.  Can you resubmit this after 3.9-rc1
comes out?


Sure, but I'll be not available next 2 weeks or so. If 3.8 falls
within that time, I will re-post it later. It is ok for me, if it has
to go in after 3.9 also.

Sebastian
___
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss


Re: [PATCH] clk: add si5351 i2c common clock driver

2013-02-18 Thread Daniel Mack
Hi Sebastian,

On 09.02.2013 13:59, Sebastian Hesselbarth wrote:
> This patch adds a common clock driver for Silicon Labs Si5351a/b/c
> i2c programmable clock generators. Currently, the driver supports
> DT kernels only and VXCO feature of si5351b is not implemented. DT
> bindings selectively allow to overwrite stored Si5351 configuration
> which is very helpful for clock generators with empty eeprom
> configuration. Corresponding device tree binding documentation is
> also added.

Thank you very much for your work! I had to wait for OMAP platforms to
move over to the common clock framework, but with that in place now, I
could finally give it a test.

Some comments below.

> - The driver has been frequency tested for some common video/audio
>   clocks and manages it to tune in every frequency successfully. A
>   comparison with silabs windows tool shows a different heuristic
>   for vco frequencies. The tests have been comfirmed by visual
>   check on an 500MHz oscilloscope but no jitter measurements have
>   been carried out. I will provide comparison by email on request.

I would be interested in more tests, yes. My first checks set up clkout1
to 32.768 KHz, and on my oscilloscope,  I measured some 1.04 KHz only.
Will do some debugging later.

> +/*
> + * Si5351 xtal clock input
> + */
> +static int si5351_xtal_prepare(struct clk_hw *hw)
> +{
> + struct si5351_driver_data *drvdata =
> + container_of(hw, struct si5351_driver_data, xtal);
> + si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE,
> + SI5351_XTAL_ENABLE, SI5351_XTAL_ENABLE);
> + return 0;
> +}
> +
> +static void si5351_xtal_unprepare(struct clk_hw *hw)
> +{
> + struct si5351_driver_data *drvdata =
> + container_of(hw, struct si5351_driver_data, xtal);
> + si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE,
> + SI5351_XTAL_ENABLE, 0);
> +}
> +
> +static int si5351_xtal_is_enabled(struct clk_hw *hw)
> +{
> + struct si5351_driver_data *drvdata =
> + container_of(hw, struct si5351_driver_data, xtal);
> + unsigned char reg;
> + reg = si5351_reg_read(drvdata, SI5351_FANOUT_ENABLE);
> + return (reg & SI5351_XTAL_ENABLE) ? 1 : 0;
> +}

On an AM33xx platform, I got tons of BUGs like this one:


[5.028525] BUG: scheduling while atomic: swapper/1/0x0002
[5.034600] INFO: lockdep is turned off.
[5.038682] Modules linked in:
[5.041866] irq event stamp: 136090
[5.045496] hardirqs last  enabled at (136089): []
_raw_spin_unlock_irqrestore+0x60/0x68
[5.054843] hardirqs last disabled at (136090): []
_raw_spin_lock_irqsave+0x1c/0x60
[5.063733] softirqs last  enabled at (135026): []
__do_softirq+0x150/0x1b4
[5.071907] softirqs last disabled at (135019): []
irq_exit+0x98/0xa0
[5.079541] [] (unwind_backtrace+0x0/0xf8) from
[] (__schedule_bug+0x58/0x78)
[5.088793] [] (__schedule_bug+0x58/0x78) from []
(__schedule+0x3c8/0x45c)
[5.097773] [] (__schedule+0x3c8/0x45c) from []
(schedule_timeout+0x120/0x1d4)
[5.107114] [] (schedule_timeout+0x120/0x1d4) from
[] (msleep+0x14/0x20)
[5.115912] [] (msleep+0x14/0x20) from []
(omap_i2c_wait_for_bb+0x68/0xb0)
[5.124890] [] (omap_i2c_wait_for_bb+0x68/0xb0) from
[] (omap_i2c_xfer+0x3c/0xfc)
[5.134503] [] (omap_i2c_xfer+0x3c/0xfc) from []
(__i2c_transfer+0x44/0x80)
[5.143575] [] (__i2c_transfer+0x44/0x80) from []
(i2c_transfer+0x5c/0xbc)
[5.152555] [] (i2c_transfer+0x5c/0xbc) from []
(regmap_i2c_read+0x4c/0x6c)
[5.161625] [] (regmap_i2c_read+0x4c/0x6c) from
[] (_regmap_raw_read+0x98/0xdc)
[5.171056] [] (_regmap_raw_read+0x98/0xdc) from
[] (_regmap_read+0x64/0x9c)
[5.180215] [] (_regmap_read+0x64/0x9c) from []
(regmap_read+0x44/0x5c)
[5.188923] [] (regmap_read+0x44/0x5c) from []
(si5351_clkout_is_enabled+0x74/0xb8)
[5.198720] [] (si5351_clkout_is_enabled+0x74/0xb8) from
[] (clk_disable_unused_subtree+0x68/0xac)
[5.209873] [] (clk_disable_unused_subtree+0x68/0xac) from
[] (clk_disable_unused_subtree+0x20/0xac)

This is because clk_disable_unused_subtree() calls ->is_enabled() with a
spinlock held, but si5351_xtal_is_enabled() will be sleeping, either by
acquiring a mutex in the regmap core, or in the OMAP's i2c transfer
routine. So bottom line is to make this callback atomic, and I did that
locally for now by caching the 'prepare' state of xtal, clkin and the
individual clocks. I can share a patch if you like.

> +static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw,
> +unsigned long parent_rate)
> +{
> + struct si5351_hw_data *hwdata =
> + container_of(hw, struct si5351_hw_data, hw);
> + unsigned char reg = SI5351_CLK0_PARAMETERS +
> + (SI5351_PARAMETERS_LENGTH * hwdata->num);
> + unsigned long long rate;
> + unsigned long m;
> +
> + if (!hwdata->params.valid)
> + si5351_read_parameters(hwdata->drvdata, reg, &hwdata->params);
> +

Re: [PATCH] clk: add si5351 i2c common clock driver

2013-02-19 Thread Daniel Mack
Hi Sebastian,

I did some more tests today and it took me a while to dig for the root
cause why things were not working for me in the first place - see below.


On 09.02.2013 13:59, Sebastian Hesselbarth wrote:

> +==Example==
> +
> +/* 25MHz reference crystal */
> +ref25: ref25M {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + clock-frequency = <2500>;
> +};
> +
> +i2c-master-node {
> +
> + /* Si5351a msop10 i2c clock generator */
> + si5351a: clock-generator@60 {
> + compatible = "silabs,si5351a-msop";
> + reg = <0x60>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + #clock-cells = <1>;
> +
> + /* connect xtal input to 25MHz reference */
> + clocks = <&ref25>;

As referred to in another thread, registering the ref25M clock that way
didn't suffice for me on my platform - but that's a different story.

> +static void si5351_read_parameters(struct si5351_driver_data *drvdata,
> + unsigned char reg, struct si5351_parameters *params)
> +{
> + unsigned char buf[SI5351_PARAMETERS_LENGTH];

On a general note, I think you can use u8 instead of unsigned char all
over the place here, which will save you some indentation trouble.

> +static inline int _si5351_clkout_reparent(struct si5351_driver_data *drvdata,
> +   unsigned char num, unsigned char parent)
> +{
> + struct clk *pclk;
> +
> + if (num > 8 ||
> + (drvdata->variant == SI5351_VARIANT_A3 && num > 3))
> + return -EINVAL;
> +
> + switch (parent) {
> + case 0:
> + pclk = drvdata->msynth[num].hw.clk;
> + break;
> + case 1:
> + pclk = drvdata->msynth[0].hw.clk;
> + if (num >= 4)
> + pclk = drvdata->msynth[4].hw.clk;
> + break;
> + case 2:
> + pclk = drvdata->xtal.clk;
> + break;
> + case 3:
> + if (drvdata->variant != SI5351_VARIANT_C)
> + return -EINVAL;
> + pclk = drvdata->clkin.clk;
> + break;
> + default:
> + return -EINVAL;
> + }
> + return clk_set_parent(drvdata->clkout[num].hw.clk, pclk);
> +}

[...]

> +static int si5351_clkout_set_parent(struct clk_hw *hw, u8 index)
> +{
> + struct si5351_hw_data *hwdata =
> + container_of(hw, struct si5351_hw_data, hw);
> + unsigned val;
> +
> + val = 0;
> + hw->clk->flags &= ~CLK_SET_RATE_PARENT;
> + switch (index) {
> + case 0:
> + hw->clk->flags |= CLK_SET_RATE_PARENT;
> + val = SI5351_CLK_INPUT_MULTISYNTH_N;
> + break;

I fugured that _si5351_clkout_reparent() wouldn't actually call
->set_parent() on the clock, which leads to the fact that
CLK_SET_RATE_PARENT is not set in the flags. That way, only the clkout
end leaf is actually supplied with a new rate, which leads to incorrect
effective clocks, depending on the current multisynth/pll configuration.

The reason for this is in clk_set_parent() itself, which bails if the
parent is already set to the passed value:

if (clk->parent == parent)
goto out;

I fixed that for now by explicitly setting the clock's parent to NULL
before calling clk_set_parent() in _si5351_clkout_reparent(), so the
calbacks are triggered. But there might be a nicer way, for example to
factor out the CLK_SET_RATE_PARENT handling to some function called from
_si5351_clkout_reparent() or so.

Anyway, with this hack in place along with the other details I mentioned
in my first mail, the driver seems to work for me now, which is great. I
will do more extensive tests later that week when I have access to
better scopes ...


Many thanks again,
Daniel



> + case 1:
> + /* clk0/clk4 can only connect to its own multisync */
> + if (hwdata->num == 0 || hwdata->num == 4)
> + val = SI5351_CLK_INPUT_MULTISYNTH_N;
> + else
> + val = SI5351_CLK_INPUT_MULTISYNTH_0_4;
> + break;
> + case 2:
> + val = SI5351_CLK_INPUT_XTAL;
> + break;
> + case 3:
> + val = SI5351_CLK_INPUT_CLKIN;
> + break;
> + }
> + si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num,
> + SI5351_CLK_INPUT_MASK, val);
> +
> + return 0;
> +}
> +
> +static unsigned long si5351_clkout_recalc_rate(struct clk_hw *hw,
> +unsigned long parent_rate)
> +{
> + struct si5351_hw_data *hwdata =
> + container_of(hw, struct si5351_hw_data, hw);
> + unsigned char reg = SI5351_CLK0_PARAMETERS +
> + (SI5351_PARAMETERS_LENGTH * hwdata->num);
> + unsigned char rdiv;
> +
> + rdiv = (si5351_reg_read(hwdata->drvdata, reg + 2) &
> + SI5351_OUTPUT_CLK_DIV_MASK) >> SI5351_OUTPUT_CLK_DIV_SHIFT;
> +
> +

Re: [PATCH] clk: add si5351 i2c common clock driver

2013-02-27 Thread Sebastian Hesselbarth
Daniel,

first of all sorry for the late answer but thanks for testing the driver.

On 2/19/13, Daniel Mack  wrote:
> Hi Sebastian,
>
> I did some more tests today and it took me a while to dig for the root
> cause why things were not working for me in the first place - see below.
>
>
> On 09.02.2013 13:59, Sebastian Hesselbarth wrote:
>
>> +==Example==
>> +
>> +/* 25MHz reference crystal */
>> +ref25: ref25M {
>> +compatible = "fixed-clock";
>> +#clock-cells = <0>;
>> +clock-frequency = <2500>;
>> +};
>> +
>> +i2c-master-node {
>> +
>> +/* Si5351a msop10 i2c clock generator */
>> +si5351a: clock-generator@60 {
>> +compatible = "silabs,si5351a-msop";
>> +reg = <0x60>;
>> +#address-cells = <1>;
>> +#size-cells = <0>;
>> +#clock-cells = <1>;
>> +
>> +/* connect xtal input to 25MHz reference */
>> +clocks = <&ref25>;
>
> As referred to in another thread, registering the ref25M clock that way
> didn't suffice for me on my platform - but that's a different story.

I guess "fixed-clock" isn't registered by OMAP's clock init code? I had
to do this on dove, too. Actually, I will come back to clock initialization for
dove later and was hoping that there will be some global way of registering
core common clock drivers (or at least fixed-clock) until then.

>> +static void si5351_read_parameters(struct si5351_driver_data *drvdata,
>> +unsigned char reg, struct si5351_parameters *params)
>> +{
>> +unsigned char buf[SI5351_PARAMETERS_LENGTH];
>
> On a general note, I think you can use u8 instead of unsigned char all
> over the place here, which will save you some indentation trouble.

Ok, I guess I was deriving "unsigned char" usage from other clock drivers
and never went to u8. But I ll reconsider using u8 when all issues are
worked out.

>> +static inline int _si5351_clkout_reparent(struct si5351_driver_data
>> *drvdata,
>> +  unsigned char num, unsigned char parent)
>> +{
>> +struct clk *pclk;
>> +
>> +if (num > 8 ||
>> +(drvdata->variant == SI5351_VARIANT_A3 && num > 3))
>> +return -EINVAL;
>> +
>> +switch (parent) {
>> +case 0:
>> +pclk = drvdata->msynth[num].hw.clk;
>> +break;
>> +case 1:
>> +pclk = drvdata->msynth[0].hw.clk;
>> +if (num >= 4)
>> +pclk = drvdata->msynth[4].hw.clk;
>> +break;
>> +case 2:
>> +pclk = drvdata->xtal.clk;
>> +break;
>> +case 3:
>> +if (drvdata->variant != SI5351_VARIANT_C)
>> +return -EINVAL;
>> +pclk = drvdata->clkin.clk;
>> +break;
>> +default:
>> +return -EINVAL;
>> +}
>> +return clk_set_parent(drvdata->clkout[num].hw.clk, pclk);
>> +}
>
> [...]
>
>> +static int si5351_clkout_set_parent(struct clk_hw *hw, u8 index)
>> +{
>> +struct si5351_hw_data *hwdata =
>> +container_of(hw, struct si5351_hw_data, hw);
>> +unsigned val;
>> +
>> +val = 0;
>> +hw->clk->flags &= ~CLK_SET_RATE_PARENT;
>> +switch (index) {
>> +case 0:
>> +hw->clk->flags |= CLK_SET_RATE_PARENT;
>> +val = SI5351_CLK_INPUT_MULTISYNTH_N;
>> +break;
>
> I fugured that _si5351_clkout_reparent() wouldn't actually call
> ->set_parent() on the clock, which leads to the fact that
> CLK_SET_RATE_PARENT is not set in the flags. That way, only the clkout
> end leaf is actually supplied with a new rate, which leads to incorrect
> effective clocks, depending on the current multisynth/pll configuration.

Yeah, true. Unfortunately, _clkout_reparent() is more like a dirty hack to
allow to reparent the clock output. At registration internal configuration of
si5351 is not known and when I parse the DT for clock configuration I might
have been already assigned to the same parent clk that you later explicitly
configure.

What I basically want for si5351 (or any other eeprom based programmable
clock gen) is that stored configuration is not touched. But it can be changed
after eeprom contents have been copied into device's sram - and this _is_
mandatory for the si5351 that I use on CuBox where there is no useful config
stored at all.

Anyway, there still seem to be some more issues with doing it right on current
common clk framwork - thanks for pointing it out.

> The reason for this is in clk_set_parent() itself, which bails if the
> parent is already set to the passed value:
>
>   if (clk->parent == parent)
>   goto out;
>
> I fixed that for now by explicitly setting the clock's parent to NULL
> before calling clk_set_parent() in _si5351_clkout_reparent(), so the
> calbacks are triggered. But there might be a nicer way, for example to
> factor out the CLK_SET_RATE_PARENT handling to some function called from
> _si5351_clkout_reparent() or so.
>
> Anyway, with this hack in place along w

Re: [PATCH] clk: add si5351 i2c common clock driver

2013-03-01 Thread Daniel Mack
Hi Sebastian,

On 27.02.2013 11:01, Sebastian Hesselbarth wrote:
> first of all sorry for the late answer but thanks for testing the driver.
> 
> On 2/19/13, Daniel Mack  wrote:
>> Hi Sebastian,
>>
>> I did some more tests today and it took me a while to dig for the root
>> cause why things were not working for me in the first place - see below.
>>
>>
>> On 09.02.2013 13:59, Sebastian Hesselbarth wrote:
>>
>>> +==Example==
>>> +
>>> +/* 25MHz reference crystal */
>>> +ref25: ref25M {
>>> +   compatible = "fixed-clock";
>>> +   #clock-cells = <0>;
>>> +   clock-frequency = <2500>;
>>> +};
>>> +
>>> +i2c-master-node {
>>> +
>>> +   /* Si5351a msop10 i2c clock generator */
>>> +   si5351a: clock-generator@60 {
>>> +   compatible = "silabs,si5351a-msop";
>>> +   reg = <0x60>;
>>> +   #address-cells = <1>;
>>> +   #size-cells = <0>;
>>> +   #clock-cells = <1>;
>>> +
>>> +   /* connect xtal input to 25MHz reference */
>>> +   clocks = <&ref25>;
>>
>> As referred to in another thread, registering the ref25M clock that way
>> didn't suffice for me on my platform - but that's a different story.
> 
> I guess "fixed-clock" isn't registered by OMAP's clock init code? I had
> to do this on dove, too. Actually, I will come back to clock initialization 
> for
> dove later and was hoping that there will be some global way of registering
> core common clock drivers (or at least fixed-clock) until then.
> 
>>> +static void si5351_read_parameters(struct si5351_driver_data *drvdata,
>>> +   unsigned char reg, struct si5351_parameters *params)
>>> +{
>>> +   unsigned char buf[SI5351_PARAMETERS_LENGTH];
>>
>> On a general note, I think you can use u8 instead of unsigned char all
>> over the place here, which will save you some indentation trouble.
> 
> Ok, I guess I was deriving "unsigned char" usage from other clock drivers
> and never went to u8. But I ll reconsider using u8 when all issues are
> worked out.
> 
>>> +static inline int _si5351_clkout_reparent(struct si5351_driver_data
>>> *drvdata,
>>> + unsigned char num, unsigned char parent)
>>> +{
>>> +   struct clk *pclk;
>>> +
>>> +   if (num > 8 ||
>>> +   (drvdata->variant == SI5351_VARIANT_A3 && num > 3))
>>> +   return -EINVAL;
>>> +
>>> +   switch (parent) {
>>> +   case 0:
>>> +   pclk = drvdata->msynth[num].hw.clk;
>>> +   break;
>>> +   case 1:
>>> +   pclk = drvdata->msynth[0].hw.clk;
>>> +   if (num >= 4)
>>> +   pclk = drvdata->msynth[4].hw.clk;
>>> +   break;
>>> +   case 2:
>>> +   pclk = drvdata->xtal.clk;
>>> +   break;
>>> +   case 3:
>>> +   if (drvdata->variant != SI5351_VARIANT_C)
>>> +   return -EINVAL;
>>> +   pclk = drvdata->clkin.clk;
>>> +   break;
>>> +   default:
>>> +   return -EINVAL;
>>> +   }
>>> +   return clk_set_parent(drvdata->clkout[num].hw.clk, pclk);
>>> +}
>>
>> [...]
>>
>>> +static int si5351_clkout_set_parent(struct clk_hw *hw, u8 index)
>>> +{
>>> +   struct si5351_hw_data *hwdata =
>>> +   container_of(hw, struct si5351_hw_data, hw);
>>> +   unsigned val;
>>> +
>>> +   val = 0;
>>> +   hw->clk->flags &= ~CLK_SET_RATE_PARENT;
>>> +   switch (index) {
>>> +   case 0:
>>> +   hw->clk->flags |= CLK_SET_RATE_PARENT;
>>> +   val = SI5351_CLK_INPUT_MULTISYNTH_N;
>>> +   break;
>>
>> I fugured that _si5351_clkout_reparent() wouldn't actually call
>> ->set_parent() on the clock, which leads to the fact that
>> CLK_SET_RATE_PARENT is not set in the flags. That way, only the clkout
>> end leaf is actually supplied with a new rate, which leads to incorrect
>> effective clocks, depending on the current multisynth/pll configuration.
> 
> Yeah, true. Unfortunately, _clkout_reparent() is more like a dirty hack to
> allow to reparent the clock output. At registration internal configuration of
> si5351 is not known and when I parse the DT for clock configuration I might
> have been already assigned to the same parent clk that you later explicitly
> configure.

Hmm, but then we need to either set the configuration on the chip to
match the internal state of the driver, or tell the clock framework that
the current state is not currently known (don't know if that's possible).

> What I basically want for si5351 (or any other eeprom based programmable
> clock gen) is that stored configuration is not touched. But it can be changed
> after eeprom contents have been copied into device's sram - and this _is_
> mandatory for the si5351 that I use on CuBox where there is no useful config
> stored at all.

Yes, same here. We set up the si5351 from the bootloader with some
binary blob via i2c to bring some components to live before the kernel
boots.

> Anyway, there still seem to be some more issues with doing it right on current
> common clk framwork - thanks for pointing it out.

I'd be happy to test more versio