linux-clk.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Tanwar, Rahul" <rahul.tanwar@linux.intel.com>
To: Stephen Boyd <sboyd@kernel.org>,
	linux-clk@vger.kernel.org, mark.rutland@arm.com,
	mturquette@baylibre.com, robh+dt@kernel.org, robh@kernel.org
Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	andriy.shevchenko@intel.com, qi-ming.wu@intel.com,
	yixin.zhu@linux.intel.com, cheol.yong.kim@intel.com,
	rtanwar <rahul.tanwar@intel.com>
Subject: Re: [PATCH v4 1/2] clk: intel: Add CGU clock driver for a new SoC
Date: Thu, 13 Feb 2020 16:04:46 +0800	[thread overview]
Message-ID: <6b3e8322-40fa-0d79-3212-fae76d04de64@linux.intel.com> (raw)
In-Reply-To: <20200131022405.B98E72067C@mail.kernel.org>


Hi Stephen,

Thanks a lot for taking time out to review and providing feedback. I have
tried to address all your review concerns except few below mentioned points
where i need more clarification.

On 31/1/2020 10:24 AM, Stephen Boyd wrote:
> Quoting Rahul Tanwar (2020-01-30 01:04:02)
>> From: rtanwar <rahul.tanwar@intel.com>
>>
>> Clock Generation Unit(CGU) is a new clock controller IP of a forthcoming

(...)

>> +               raw_spin_unlock_irqrestore(&ctx->lock, flags);
>> +       }
>> +
>> +       return clk_hw_register_fixed_rate(NULL, list->name,
>> +                                         list->parent_names[0],
>> +                                         list->flags, list->mux_flags);
> Can fixed rate clks come from DT? Or does this value change sometimes?

Fixed rate clks may need enable/disable clk ops. That's the only reason
for making it visible to clock driver.

>> +lgm_clk_ddiv_set_rate(struct clk_hw *hw, unsigned long rate,
>> +                     unsigned long prate)
>> +{
>> +       struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);
>> +       u32 div, ddiv1, ddiv2;
>> +       unsigned long flags;
>> +
>> +       div = DIV_ROUND_CLOSEST_ULL((u64)prate, rate);
>> +
>> +       raw_spin_lock_irqsave(&ddiv->lock, flags);
>> +       if (lgm_get_clk_val(ddiv->membase, ddiv->reg, ddiv->shift2, 1)) {
>> +               div = DIV_ROUND_CLOSEST_ULL((u64)div, 5);
>> +               div = div * 2;
>> +       }
>> +       raw_spin_unlock_irqrestore(&ddiv->lock, flags);
> Does the math need to be inside the spinlock? Should probably not have
> any spinlock at all and just read it with lgm_get_clk_val() and trust
> that the hardware will return us something sane?
>
>> +
>> +       if (div <= 0)
>> +               return -EINVAL;
>> +
>> +       if (lgm_clk_get_ddiv_val(div, &ddiv1, &ddiv2))
>> +               return -EINVAL;
>> +
>> +       raw_spin_lock_irqsave(&ddiv->lock, flags);
>> +       lgm_set_clk_val(ddiv->membase, ddiv->reg, ddiv->shift0, ddiv->width0,
>> +                       ddiv1 - 1);
>> +
>> +       lgm_set_clk_val(ddiv->membase, ddiv->reg,  ddiv->shift1, ddiv->width1,
>> +                       ddiv2 - 1);
> Can this not be combined? lgm_set_clk_val is sort of obfuscating the
> code. Please consider inlining it and then holding the spinlock across
> this entire function while doing the read/modify/write.

These two set_clk_val's can not be combined because they have different
non-contiguous bitmaps (shifts) and lgm_set_clk_val() is defined to handle
only one shift. However, i have addressed your other comment i.e. inline it
and hold spinlock across the function during read/modify/write.

>> +struct lgm_clk_mux {
>> +       struct clk_hw hw;
>> +       struct device *dev;
>> +       void __iomem *membase;
>> +       unsigned int reg;
>> +       u8 shift;
>> +       u8 width;
>> +       unsigned long flags;
>> +       raw_spinlock_t lock;
>> +};
>> +
>> +struct lgm_clk_divider {
>> +       struct clk_hw hw;
>> +       struct device *dev;
>> +       void __iomem *membase;
>> +       unsigned int reg;
>> +       u8 shift;
>> +       u8 width;
>> +       u8 shift_gate;
>> +       u8 width_gate;
>> +       unsigned long flags;
>> +       const struct clk_div_table *table;
>> +       raw_spinlock_t lock;
>> +};
>> +
>> +struct lgm_clk_ddiv {
>> +       struct clk_hw hw;
>> +       struct device *dev;
>> +       void __iomem *membase;
>> +       unsigned int reg;
>> +       u8 shift0;
>> +       u8 width0;
>> +       u8 shift1;
>> +       u8 width1;
>> +       u8 shift2;
>> +       u8 width2;
>> +       u8 shift_gate;
>> +       u8 width_gate;
>> +       unsigned int mult;
>> +       unsigned int div;
>> +       unsigned long flags;
>> +       raw_spinlock_t lock;
>> +};
>> +
>> +struct lgm_clk_gate {
>> +       struct clk_hw hw;
>> +       struct device *dev;
> These all have dev pointers, is it necessary? In theory we can have a
> clk_hw API that gets the dev pointer out for you if you want it, now
> that we store the dev pointer when a clk registers

We needed dev pointers just for dev_err() in clk_ops when they are called
back from core. I have now removed dev_err() calls from the driver clk_ops
as i believe the error info was not that useful. And so i have removed dev
pointers from above structures.

However, i think it would be good to have a clk_hw API which returns dev
pointer for drivers. Presently, dev pointer is stored inside clk_hw->clk_core
and clk_core is private to core, inaccessible from clk drivers.

>> +enum pll_type {
>> +       TYPE_ROPLL,
>> +       TYPE_LJPLL,
>> +       TYPE_NONE,
> Is this used? Remove it if not.

It is actually used.

>> +struct lgm_pll_clk_data {
>> +       unsigned int id;
>> +       const char *name;
>> +       const char *const *parent_names;
> Can you use the new way of specifying clk parents instead of using plain
> strings? Reminder to self, write that document.

I have changed it to new way i.e. by using fw_name. Only exception is where we
use clk API's clk_hw_register_fixed_rate() & clk_hw_register_fixed_factor().
In these API's, i am, for now, passing parent_data[0].name as parent_name.

>> +/* clock flags definition */
>> +#define CLOCK_FLAG_VAL_INIT    BIT(16)
>> +#define GATE_CLK_HW            BIT(17)
>> +#define GATE_CLK_SW            BIT(18)
>> +#define MUX_CLK_SW             GATE_CLK_SW
> Why do these bits start at 16? 

To avoid the conflict with clk_flags used across common struct clk
defined in clk-provider.h. Bits 0~13 are already used there. So
we keep some gap and start with 16 :). We don't maintain a separate
pure driver only flags bitmask as that would make it confusing.

> What does _HW and _SW mean? Is there
> hardware control of clks?

GATE_CLK_HW & GATE_CLK_SW is no longer needed for this SoC. So i have
removed it. MUX_CLK_SW is still needed. It is more of a workaround for
one particular combophy module for which get_parent/set_parent does not
apply (no hardware translation to select/query input clk source).
However, other MUX clks in this clk group have valid hardware translation
for parent clock sources.

>> +static const struct clk_div_table dcl_div[] = {
>> +       { .val = 0, .div = 6  },
>> +       { .val = 1, .div = 12 },
>> +       { .val = 2, .div = 24 },
>> +       { .val = 3, .div = 32 },
>> +       { .val = 4, .div = 48 },
>> +       { .val = 5, .div = 96 },
>> +       {}
> I guess 'div' being equal to 0 is the terminator?

Yes, but i am missing your point. Can you please elaborate more ?

>> +       ctx->np = np;
>> +       ctx->dev = dev;
>> +       raw_spin_lock_init(&ctx->lock);
> Why is it a raw spinlock?

Agree. We use CONFIG_SMP with no PREEMPT_RT. So i think it is same.
Have switched to normal spinlocks.

Regards,
Rahul

  reply	other threads:[~2020-02-13  8:04 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-30  9:04 [PATCH v4 0/2] clk: intel: Add a new driver for a new clock controller IP Rahul Tanwar
2020-01-30  9:04 ` [PATCH v4 1/2] clk: intel: Add CGU clock driver for a new SoC Rahul Tanwar
2020-01-31  2:24   ` Stephen Boyd
2020-02-13  8:04     ` Tanwar, Rahul [this message]
2020-01-30  9:04 ` [PATCH v4 2/2] dt-bindings: clk: intel: Add bindings document & header file for CGU Rahul Tanwar
2020-01-31  2:25   ` Stephen Boyd
2020-02-05  9:10     ` Tanwar, Rahul

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6b3e8322-40fa-0d79-3212-fae76d04de64@linux.intel.com \
    --to=rahul.tanwar@linux.intel.com \
    --cc=andriy.shevchenko@intel.com \
    --cc=cheol.yong.kim@intel.com \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mturquette@baylibre.com \
    --cc=qi-ming.wu@intel.com \
    --cc=rahul.tanwar@intel.com \
    --cc=robh+dt@kernel.org \
    --cc=robh@kernel.org \
    --cc=sboyd@kernel.org \
    --cc=yixin.zhu@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).