[PATCH v5 02/44] clk: davinci: New driver for davinci PLL clocks
Adam Ford
aford173 at gmail.com
Fri Jan 12 07:30:37 PST 2018
On Fri, Jan 12, 2018 at 9:25 AM, David Lechner <david at lechnology.com> wrote:
> On 01/12/2018 03:21 AM, Sekhar Nori wrote:
>>
>> On Monday 08 January 2018 07:47 AM, David Lechner wrote:
>>>
>>> This adds a new driver for mach-davinci PLL clocks. This is porting the
>>> code from arch/arm/mach-davinci/clock.c to the common clock framework.
>>> Additionally, it adds device tree support for these clocks.
>>>
>>> The ifeq ($(CONFIG_COMMON_CLK), y) in the Makefile is needed to prevent
>>> compile errors until the clock code in arch/arm/mach-davinci is removed.
>>>
>>> Note: although there are similar clocks for TI Keystone we are not able
>>> to share the code for a few reasons. The keystone clocks are device tree
>>> only and use legacy one-node-per-clock bindings. Also the register
>>> layouts are a bit different, which would add even more if/else mess
>>> to the keystone clocks. And the keystone PLL driver doesn't support
>>> setting clock rates.
>>>
>>> Signed-off-by: David Lechner <david at lechnology.com>
>>> ---
>
>
>>> +
>>> +#define PLLM_MASK 0x1f
>>> +#define PREDIV_RATIO_MASK 0x1f
>>
>>
>> May be use the mode modern GENMASK()?
>
>
> I haven't seen that one before. Thanks.
>
> ...
>
>>> +static unsigned long davinci_pll_clk_recalc(struct clk_hw *hw,
>>> + unsigned long parent_rate)
>>> +{
>>> + struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
>>> + unsigned long rate = parent_rate;
>>> + u32 prediv, mult, postdiv;
>>> +
>>> + prediv = readl(pll->base + PREDIV) & PREDIV_RATIO_MASK;
>>> + mult = readl(pll->base + PLLM) & PLLM_MASK;
>>> + postdiv = readl(pll->base + POSTDIV) & POSTDIV_RATIO_MASK;
>>
>>
>> Shouldn't we check if the pre and post dividers are enabled before using
>> them?
>
>
> Indeed.
>
>>
>>> +
>>> + rate /= prediv + 1;
>>> + rate *= mult + 1;
>>> + rate /= postdiv + 1;
>>> +
>>> + return rate;
>>> +}
>>> +
>
>
> ...
>
>>
>> PLL output on DA850 must never be below 300MHz or above 600MHz (see
>> datasheet table "Allowed PLL Operating Conditions"). Does this take care
>> of that? Thats one of the main reasons I recall I went with some
>> specific values of prediv, pllm and post div in
>> arch/arm/mach-davinci/da850.c
>
>
> Apparently, I missed this requirement. It looks like I am going to have to
> rework things so that there is some coordination between the PLL and the
> PLLDIV clocks in order to get the < 300MHz operating points.
>
> ...
>
>>> +
>>> + divider->reg = base + OSCDIV;
>>> + divider->width = OSCDIV_RATIO_WIDTH;
>>
>>
>> can you write OD1EN of OSCDIV here? I guess the reset default is 1 so
>> you didnt need to do that. But not doing exposes us to settings that
>> bootloader left us in.
>>
>
> It looks like I am going to have to make a custom implementation for parts
> of this clock anyway, so I will probably just make new enable/disable
> callbacks that set both OSCDIV_OD1EN and CKEN_OBSCLK.
>
>
>>> +
>>> + clk = clk_register_composite(NULL, name, parent_names,
>>> num_parents,
>>> + &mux->hw, &clk_mux_ops,
>>> + ÷r->hw, &clk_divider_ops,
>>> + &gate->hw, &clk_gate_ops, 0);
>>> + if (IS_ERR(clk)) {
>>> + kfree(divider);
>>> + kfree(gate);
>>> + kfree(mux);
>>> + }
>>> +
>>> + return clk;
>>> +}
>>> +
>>> +struct clk *
>>> +davinci_pll_divclk_register(const struct davinci_pll_divclk_info *info,
>>> + void __iomem *base)
>>> +{
>>> + const struct clk_ops *divider_ops = &clk_divider_ops;
>>
>>
>> setting the sysclk divider requires GOSTAT handling apart from setting
>> the divider value. So I think .set_rate ops above wont work. Other ops
>> can be used, I guess. So we need a private structure here.
>>
>> Can you port over davinci_set_sysclk_rate() too? I understand you cannot
>> test it due to lack of cpufreq support in DT, but I can help testing
>> there.
>>
>> Or leave .set_rate NULL and it can be added later.
>
>
> Yes, I noticed that I missed this after I submitted this series. And I
> will have to rework things to coordinate with the PLL as mentioned above.
>
> FYI, I do have cpufreq-dt working, although the LEGO EV3 has a fixed 1.2V
> regulator, so I am limited in what I can test. Basically, I can only switch
I can test the cpufreq-dt. Are there additional patches or are they
part of the same git repo I have been testing?
The DA850 I have may not run all the way to highest speed, but I'll
see what I can find. I think I had a few at one point, but I don't
think it was part of Logic PD's standard product lineup.
adam
> between 300MHz and 375MHz according to the datasheets. The chip is
> technically
> the 456MHz version. What would happen if I ran it faster or slower with the
> wrong voltage?
>
> ...
>
>>> +
>>> + child = of_get_child_by_name(node, "auxclk");
>>> + if (child && of_device_is_available(child)) {
>>> + char child_name[MAX_NAME_SIZE];
>>> +
>>> + snprintf(child_name, MAX_NAME_SIZE, "%s_aux_clk", name);
>>> +
>>> + clk = davinci_pll_aux_clk_register(child_name,
>>> parent_name, base);
>>> + if (IS_ERR(clk))
>>> + pr_warn("%s: failed to register %s (%ld)\n",
>>> __func__,
>>> + child_name, PTR_ERR(clk));
>>> + else
>>> + of_clk_add_provider(child, of_clk_src_simple_get,
>>> clk);
>>> + }
>>
>>
>> davinci_pll_obs_clk_register() should also be handled here?
>
>
> I omitted it because no one is using it (same reason I left it out of the
> device tree bindings). We can certainly add it, though.
>
>
More information about the linux-arm-kernel
mailing list