All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gregory CLEMENT <gregory.clement@free-electrons.com>
To: Michael Turquette <mturquette@baylibre.com>
Cc: "Stephen Boyd" <sboyd@codeaurora.org>,
	 linux-clk@vger.kernel.org,  linux-kernel@vger.kernel.org,
	 "Rob Herring" <robh+dt@kernel.org>,
	 devicetree@vger.kernel.org,
	 "Jason Cooper" <jason@lakedaemon.net>,
	 "Andrew Lunn" <andrew@lunn.ch>,
	 "Sebastian Hesselbarth" <sebastian.hesselbarth@gmail.com>,
	 "Thomas Petazzoni" <thomas.petazzoni@free-electrons.com>,
	 linux-arm-kernel@lists.infradead.org,
	 "Nadav Haklai" <nadavh@marvell.com>,
	 "Victor Gu" <xigu@marvell.com>,
	 "Romain Perier" <romain.perier@free-electrons.com>,
	 "Omri Itach" <omrii@marvell.com>,
	 "Marcin Wojtas" <mw@semihalf.com>,
	 "Wilson Ding" <dingwei@marvell.com>,
	 "Hua Jing" <jinghua@marvell.com>,
	 "Terry Zhou" <bjzhou@marvell.com>
Subject: Re: [PATCH v2 6/6] clk: mvebu: Add the peripheral clock driver for Armada 3700
Date: Tue, 12 Jul 2016 18:30:34 +0200	[thread overview]
Message-ID: <87r3aystsl.fsf@free-electrons.com> (raw)
In-Reply-To: <146800242289.73491.4169295036354147972@resonance> (Michael Turquette's message of "Fri, 08 Jul 2016 11:27:02 -0700")

Hi Michael,
 
 On ven., juil. 08 2016, Michael Turquette <mturquette@baylibre.com> wrote:

> Quoting Gregory CLEMENT (2016-07-07 15:37:51)
>> +#include <linux/clk-provider.h>
>> +#include <linux/clk.h>
>
> Same question as my previous email. Is clk.h necessary? Is this driver
> also a clk consumer?

I think I can remove it indeed.

>
>> +static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
>> +                                        const char * const *parent_name,
>> +                                        void __iomem *reg, spinlock_t *lock,
>> +                                        struct device *dev, struct clk_hw *hw)
>> +{
>> +       const struct clk_ops *mux_ops = NULL, *gate_ops = NULL,
>> +               *div_ops = NULL;
>> +       struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
>> +       const char * const *names;
>> +       struct clk_mux *mux = NULL;
>> +       struct clk_gate *gate = NULL;
>> +       struct clk_divider *div = NULL;
>> +       struct clk_double_div *double_div = NULL;
>> +       int num_parent;
>> +       int ret = 0;
>> +
>> +       if (data->gate_shift != UNUSED) {
>> +               gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
>> +
>> +               if (!gate)
>> +                       return -ENOMEM;
>> +
>> +               gate->reg = reg + CLK_DIS;
>> +               gate->bit_idx = data->gate_shift;
>> +               gate->lock = lock;
>> +               gate_ops = &clk_gate_ops;
>> +               gate_hw = &gate->hw;
>> +       }
>> +
>> +       if (data->mux_shift != UNUSED) {
>> +               mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
>> +
>> +               if (!mux) {
>> +                       ret = -ENOMEM;
>> +                       goto free_gate;
>> +               }
>> +
>> +               mux->reg = reg + TBG_SEL;
>> +               mux->shift = data->mux_shift;
>> +               mux->mask = 0x3;
>> +               mux->lock = lock;
>> +               mux_ops = &clk_mux_ro_ops;
>> +               mux_hw = &mux->hw;
>> +       }
>> +
>> +       if (data->div_reg1 != UNUSED) {
>> +               if (data->div_reg2 == UNUSED) {
>> +                       const struct clk_div_table *clkt;
>> +                       int table_size = 0;
>> +
>> +                       div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
>> +                       if (!div) {
>> +                               ret = -ENOMEM;
>> +                               goto free_mux;
>> +                       }
>> +
>> +                       div->reg = reg + data->div_reg1;
>> +                       div->table = data->table;
>> +                       for (clkt = div->table; clkt->div; clkt++)
>> +                               table_size++;
>> +                       div->width = order_base_2(table_size);
>> +                       div->lock = lock;
>> +                       div_ops = &clk_divider_ro_ops;
>> +                       div_hw = &div->hw;
>> +               } else {
>> +                       double_div = devm_kzalloc(dev, sizeof(*double_div),
>> +                                                 GFP_KERNEL);
>> +                       if (!double_div) {
>> +                               ret = -ENOMEM;
>> +                               goto free_mux;
>> +                       }
>> +
>> +                       double_div->reg1 = reg + data->div_reg1;
>> +                       double_div->shift1 = data->div_shift1;
>> +                       double_div->reg2 = reg + data->div_reg1;
>> +                       double_div->shift2 = data->div_shift2;
>> +                       div_ops = &clk_double_div_ops;
>> +                       div_hw = &double_div->hw;
>> +               }
>> +       }
>> +
>> +       switch (data->flags) {
>> +       case XTAL_CHILD:
>> +               /* the xtal clock is the 5th clock */
>> +               names = &parent_name[4];
>> +               num_parent = 1;
>> +               break;
>> +       case TBGA_S_CHILD:
>> +               /* the TBG A S clock is the 3rd clock */
>> +               names = &parent_name[2];
>> +               num_parent = 1;
>> +               break;
>> +       case GBE_CORE_CHILD:
>> +               names = &gbe_name[1];
>> +               num_parent = 1;
>> +               break;
>> +       case  GBE_50_CHILD:
>> +               names = &gbe_name[0];
>> +               num_parent = 1;
>> +               break;
>> +       case  GBE_125_CHILD:
>> +               names = &gbe_name[2];
>> +               num_parent = 1;
>> +               break;
>> +       default:
>> +               names = parent_name;
>> +               num_parent = 4;
>> +       }
>> +       hw = clk_hw_register_composite(dev, data->name,
>> +                                    names, num_parent,
>> +                                    mux_hw, mux_ops,
>> +                                    div_hw, div_ops,
>> +                                    gate_hw, gate_ops,
>> +                                    CLK_IGNORE_UNUSED);
>> +       if (IS_ERR(hw)) {
>> +               ret = PTR_ERR(hw);
>> +               goto free_div;
>> +       }
>> +
>> +       return 0;
>> +free_div:
>> +       devm_kfree(dev, div);
>> +       devm_kfree(dev, double_div);
>> +free_mux:
>> +       devm_kfree(dev, mux);
>> +free_gate:
>> +       devm_kfree(dev, gate);
>> +       return ret;
>> +}
>
> Can this "add" function (aka registration function) be replaced with
> static data instead? I think that all of the static data exists already,
> this function can be removed and your probe can call clk_hw_register
> directly.
>

I see your point and indeed we can remove some allocation. However using
clk_hw_register with composite clock is not straight forward. Indeed the
clk_ops is filled in the clk_hw_register_composite function and none of
these operations are exported outside the clk-composite.c file.

We can't directly point a clk_gate_ops structure or a clk_divider_ops as
you did in the drivers/clk/meson/gxbb.c file for example. For clk
composite it would need modify the framework to either export all the
operation or to create set of operations directly usable and I would
like to avoid doing it when we are close to the merge window.

However I can use static data for the clk_mux, clk_gate and clk_divider
struct.

Is it OK for you?

Thanks,

Gregory

> It might need a macro though, since composite clock structures are
> rather messy. This avoids a lot of unnecessary allocations and time
> populating data that we already have access to. In general I am trying
> to encourage clk drivers to use only clk_hw_register() in their probe
> instead of the helper registration functions.
>
> Similarly I am discouraging drivers from populating hw.init at run-time,
> since we already have that data for that at compile-time.
>
> Regards,
> Mike

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

WARNING: multiple messages have this Message-ID (diff)
From: gregory.clement@free-electrons.com (Gregory CLEMENT)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 6/6] clk: mvebu: Add the peripheral clock driver for Armada 3700
Date: Tue, 12 Jul 2016 18:30:34 +0200	[thread overview]
Message-ID: <87r3aystsl.fsf@free-electrons.com> (raw)
In-Reply-To: <146800242289.73491.4169295036354147972@resonance> (Michael Turquette's message of "Fri, 08 Jul 2016 11:27:02 -0700")

Hi Michael,
 
 On ven., juil. 08 2016, Michael Turquette <mturquette@baylibre.com> wrote:

> Quoting Gregory CLEMENT (2016-07-07 15:37:51)
>> +#include <linux/clk-provider.h>
>> +#include <linux/clk.h>
>
> Same question as my previous email. Is clk.h necessary? Is this driver
> also a clk consumer?

I think I can remove it indeed.

>
>> +static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
>> +                                        const char * const *parent_name,
>> +                                        void __iomem *reg, spinlock_t *lock,
>> +                                        struct device *dev, struct clk_hw *hw)
>> +{
>> +       const struct clk_ops *mux_ops = NULL, *gate_ops = NULL,
>> +               *div_ops = NULL;
>> +       struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
>> +       const char * const *names;
>> +       struct clk_mux *mux = NULL;
>> +       struct clk_gate *gate = NULL;
>> +       struct clk_divider *div = NULL;
>> +       struct clk_double_div *double_div = NULL;
>> +       int num_parent;
>> +       int ret = 0;
>> +
>> +       if (data->gate_shift != UNUSED) {
>> +               gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
>> +
>> +               if (!gate)
>> +                       return -ENOMEM;
>> +
>> +               gate->reg = reg + CLK_DIS;
>> +               gate->bit_idx = data->gate_shift;
>> +               gate->lock = lock;
>> +               gate_ops = &clk_gate_ops;
>> +               gate_hw = &gate->hw;
>> +       }
>> +
>> +       if (data->mux_shift != UNUSED) {
>> +               mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
>> +
>> +               if (!mux) {
>> +                       ret = -ENOMEM;
>> +                       goto free_gate;
>> +               }
>> +
>> +               mux->reg = reg + TBG_SEL;
>> +               mux->shift = data->mux_shift;
>> +               mux->mask = 0x3;
>> +               mux->lock = lock;
>> +               mux_ops = &clk_mux_ro_ops;
>> +               mux_hw = &mux->hw;
>> +       }
>> +
>> +       if (data->div_reg1 != UNUSED) {
>> +               if (data->div_reg2 == UNUSED) {
>> +                       const struct clk_div_table *clkt;
>> +                       int table_size = 0;
>> +
>> +                       div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
>> +                       if (!div) {
>> +                               ret = -ENOMEM;
>> +                               goto free_mux;
>> +                       }
>> +
>> +                       div->reg = reg + data->div_reg1;
>> +                       div->table = data->table;
>> +                       for (clkt = div->table; clkt->div; clkt++)
>> +                               table_size++;
>> +                       div->width = order_base_2(table_size);
>> +                       div->lock = lock;
>> +                       div_ops = &clk_divider_ro_ops;
>> +                       div_hw = &div->hw;
>> +               } else {
>> +                       double_div = devm_kzalloc(dev, sizeof(*double_div),
>> +                                                 GFP_KERNEL);
>> +                       if (!double_div) {
>> +                               ret = -ENOMEM;
>> +                               goto free_mux;
>> +                       }
>> +
>> +                       double_div->reg1 = reg + data->div_reg1;
>> +                       double_div->shift1 = data->div_shift1;
>> +                       double_div->reg2 = reg + data->div_reg1;
>> +                       double_div->shift2 = data->div_shift2;
>> +                       div_ops = &clk_double_div_ops;
>> +                       div_hw = &double_div->hw;
>> +               }
>> +       }
>> +
>> +       switch (data->flags) {
>> +       case XTAL_CHILD:
>> +               /* the xtal clock is the 5th clock */
>> +               names = &parent_name[4];
>> +               num_parent = 1;
>> +               break;
>> +       case TBGA_S_CHILD:
>> +               /* the TBG A S clock is the 3rd clock */
>> +               names = &parent_name[2];
>> +               num_parent = 1;
>> +               break;
>> +       case GBE_CORE_CHILD:
>> +               names = &gbe_name[1];
>> +               num_parent = 1;
>> +               break;
>> +       case  GBE_50_CHILD:
>> +               names = &gbe_name[0];
>> +               num_parent = 1;
>> +               break;
>> +       case  GBE_125_CHILD:
>> +               names = &gbe_name[2];
>> +               num_parent = 1;
>> +               break;
>> +       default:
>> +               names = parent_name;
>> +               num_parent = 4;
>> +       }
>> +       hw = clk_hw_register_composite(dev, data->name,
>> +                                    names, num_parent,
>> +                                    mux_hw, mux_ops,
>> +                                    div_hw, div_ops,
>> +                                    gate_hw, gate_ops,
>> +                                    CLK_IGNORE_UNUSED);
>> +       if (IS_ERR(hw)) {
>> +               ret = PTR_ERR(hw);
>> +               goto free_div;
>> +       }
>> +
>> +       return 0;
>> +free_div:
>> +       devm_kfree(dev, div);
>> +       devm_kfree(dev, double_div);
>> +free_mux:
>> +       devm_kfree(dev, mux);
>> +free_gate:
>> +       devm_kfree(dev, gate);
>> +       return ret;
>> +}
>
> Can this "add" function (aka registration function) be replaced with
> static data instead? I think that all of the static data exists already,
> this function can be removed and your probe can call clk_hw_register
> directly.
>

I see your point and indeed we can remove some allocation. However using
clk_hw_register with composite clock is not straight forward. Indeed the
clk_ops is filled in the clk_hw_register_composite function and none of
these operations are exported outside the clk-composite.c file.

We can't directly point a clk_gate_ops structure or a clk_divider_ops as
you did in the drivers/clk/meson/gxbb.c file for example. For clk
composite it would need modify the framework to either export all the
operation or to create set of operations directly usable and I would
like to avoid doing it when we are close to the merge window.

However I can use static data for the clk_mux, clk_gate and clk_divider
struct.

Is it OK for you?

Thanks,

Gregory

> It might need a macro though, since composite clock structures are
> rather messy. This avoids a lot of unnecessary allocations and time
> populating data that we already have access to. In general I am trying
> to encourage clk drivers to use only clk_hw_register() in their probe
> instead of the helper registration functions.
>
> Similarly I am discouraging drivers from populating hw.init at run-time,
> since we already have that data for that at compile-time.
>
> Regards,
> Mike

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

  reply	other threads:[~2016-07-12 16:30 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-07 22:37 [PATCH v2 0/6] Add clock support for Armada 37xx SoCs Gregory CLEMENT
2016-07-07 22:37 ` Gregory CLEMENT
2016-07-07 22:37 ` Gregory CLEMENT
2016-07-07 22:37 ` [PATCH v2 1/6] dt-bindings: clock: add DT binding for the Xtal clock on Armada 3700 Gregory CLEMENT
2016-07-07 22:37   ` Gregory CLEMENT
2016-07-08  7:31   ` Thomas Petazzoni
2016-07-08  7:31     ` Thomas Petazzoni
2016-07-11 16:12     ` Gregory CLEMENT
2016-07-11 16:12       ` Gregory CLEMENT
2016-07-07 22:37 ` [PATCH v2 2/6] clk: mvebu: Add the xtal clock for Armada 3700 SoC Gregory CLEMENT
2016-07-07 22:37   ` Gregory CLEMENT
2016-07-07 22:37   ` Gregory CLEMENT
2016-07-08 17:32   ` Michael Turquette
2016-07-08 17:32     ` Michael Turquette
2016-07-08 17:32     ` Michael Turquette
2016-07-08 17:32     ` Michael Turquette
2016-07-12 10:42     ` Gregory CLEMENT
2016-07-12 10:42       ` Gregory CLEMENT
2016-07-09 23:34   ` Paul Gortmaker
2016-07-09 23:34     ` Paul Gortmaker
2016-07-12 10:43     ` Gregory CLEMENT
2016-07-12 10:43       ` Gregory CLEMENT
2016-07-12 10:43       ` Gregory CLEMENT
2016-07-07 22:37 ` [PATCH v2 3/6] dt-bindings: clock: add DT binding for the TBG clocks on Armada 3700 Gregory CLEMENT
2016-07-07 22:37   ` Gregory CLEMENT
2016-07-07 22:37   ` Gregory CLEMENT
2016-07-07 22:37 ` [PATCH v2 4/6] clk: mvebu Add the time base generator clocks for " Gregory CLEMENT
2016-07-07 22:37   ` Gregory CLEMENT
2016-07-07 22:37   ` Gregory CLEMENT
2016-07-07 22:37 ` [PATCH v2 5/6] dt-bindings: clock: add DT binding for the peripheral clocks on " Gregory CLEMENT
2016-07-07 22:37   ` Gregory CLEMENT
2016-07-07 22:37 ` [PATCH v2 6/6] clk: mvebu: Add the peripheral clock driver for " Gregory CLEMENT
2016-07-07 22:37   ` Gregory CLEMENT
2016-07-07 22:37   ` Gregory CLEMENT
2016-07-08 18:27   ` Michael Turquette
2016-07-08 18:27     ` Michael Turquette
2016-07-08 18:27     ` Michael Turquette
2016-07-08 18:27     ` Michael Turquette
2016-07-12 16:30     ` Gregory CLEMENT [this message]
2016-07-12 16:30       ` Gregory CLEMENT
2016-07-12 17:28       ` Michael Turquette
2016-07-12 17:28         ` Michael Turquette
2016-07-12 17:28         ` Michael Turquette

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=87r3aystsl.fsf@free-electrons.com \
    --to=gregory.clement@free-electrons.com \
    --cc=andrew@lunn.ch \
    --cc=bjzhou@marvell.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dingwei@marvell.com \
    --cc=jason@lakedaemon.net \
    --cc=jinghua@marvell.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mturquette@baylibre.com \
    --cc=mw@semihalf.com \
    --cc=nadavh@marvell.com \
    --cc=omrii@marvell.com \
    --cc=robh+dt@kernel.org \
    --cc=romain.perier@free-electrons.com \
    --cc=sboyd@codeaurora.org \
    --cc=sebastian.hesselbarth@gmail.com \
    --cc=thomas.petazzoni@free-electrons.com \
    --cc=xigu@marvell.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.