linux-clk.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Stephen Boyd <sboyd@kernel.org>
To: Charles Keepax <ckeepax@opensource.cirrus.com>,
	broonie@kernel.org, lee.jones@linaro.org,
	linus.walleij@linaro.org, mturquette@baylibre.com,
	robh+dt@kernel.org
Cc: mark.rutland@arm.com, lgirdwood@gmail.com,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	patches@opensource.cirrus.com, linux-clk@vger.kernel.org,
	linux-gpio@vger.kernel.org
Subject: Re: [PATCH v5 7/8] clk: lochnagar: Add support for the Cirrus Logic Lochnagar
Date: Thu, 29 Nov 2018 23:53:51 -0800	[thread overview]
Message-ID: <154356443157.88331.15749597863624143993@swboyd.mtv.corp.google.com> (raw)
In-Reply-To: <20181120141631.18949-7-ckeepax@opensource.cirrus.com>

Quoting Charles Keepax (2018-11-20 06:16:30)
> diff --git a/drivers/clk/clk-lochnagar.c b/drivers/clk/clk-lochnagar.c
> new file mode 100644
> index 000000000000..8b2a78689715
> --- /dev/null
> +++ b/drivers/clk/clk-lochnagar.c
> @@ -0,0 +1,360 @@
[...]
> +
> +static int lochnagar_regmap_set_parent(struct clk_hw *hw, u8 index)
> +{
> +       struct lochnagar_clk *lclk = lochnagar_hw_to_lclk(hw);
> +       struct lochnagar_clk_priv *priv = lclk->priv;
> +       struct regmap *regmap = priv->regmap;
> +       int ret;
> +
> +       /*
> +        * Some clocks on Lochnagar can either generate a clock themselves
> +        * or accept an external clock, these default to generating the clock
> +        * themselves. If we set a parent however we should update the dir_mask
> +        * to indicate to the hardware that this clock will now be receiving an
> +        * external clock.

Hmm ok. So the plan is to configure parents in DT or from driver code if
the configuration is to accept an external clk? I guess this works.

> +        */
> +       if (lclk->dir_mask) {
> +               ret = regmap_update_bits(regmap, lclk->cfg_reg,
> +                                        lclk->dir_mask, lclk->dir_mask);
> +               if (ret < 0) {
> +                       dev_err(priv->dev, "Failed to set %s direction: %d\n",
> +                               lclk->name, ret);
> +                       return ret;
> +               }
> +       }
> +
> +       ret = regmap_update_bits(regmap, lclk->src_reg, lclk->src_mask, index);
> +       if (ret < 0)
> +               dev_err(priv->dev, "Failed to reparent %s: %d\n",
> +                       lclk->name, ret);
> +
> +       return ret;
> +}
> +
> +static u8 lochnagar_regmap_get_parent(struct clk_hw *hw)
> +{
> +       struct lochnagar_clk *lclk = lochnagar_hw_to_lclk(hw);
> +       struct lochnagar_clk_priv *priv = lclk->priv;
> +       struct regmap *regmap = priv->regmap;
> +       unsigned int val;
> +       int ret;
> +
> +       ret = regmap_read(regmap, lclk->src_reg, &val);
> +       if (ret < 0) {
> +               dev_err(priv->dev, "Failed to read parent of %s: %d\n",
> +                       lclk->name, ret);

The error messages in the above functions could be spammy. Just let
drivers who fail when using these clks ops print errors and maybe
downgrade these to debug? If you don't agree with this it's fine, I'll
just hope to never see these prints change to debug in the future.

> +               return priv->nparents;
> +       }
> +
> +       val &= lclk->src_mask;
> +
> +       return val;
> +}
> +
> +static const struct clk_ops lochnagar_clk_regmap_ops = {
> +       .prepare = lochnagar_regmap_prepare,
> +       .unprepare = lochnagar_regmap_unprepare,
> +       .set_parent = lochnagar_regmap_set_parent,
> +       .get_parent = lochnagar_regmap_get_parent,

Is regmap important to have in the name of these functions and struct?
I'd prefer it was just clk instead of regmap.

> +};
> +
> +static int lochnagar_init_parents(struct lochnagar_clk_priv *priv)
> +{
> +       struct device_node *np = priv->dev->of_node;
> +       int i, j;
> +
> +       switch (priv->type) {
> +       case LOCHNAGAR1:
> +               memcpy(priv->lclks, lochnagar1_clks, sizeof(lochnagar1_clks));
> +
> +               priv->nparents = ARRAY_SIZE(lochnagar1_clk_parents);
> +               priv->parents = devm_kmemdup(priv->dev, lochnagar1_clk_parents,
> +                                            sizeof(lochnagar1_clk_parents),
> +                                            GFP_KERNEL);
> +               break;
> +       case LOCHNAGAR2:
> +               memcpy(priv->lclks, lochnagar2_clks, sizeof(lochnagar2_clks));
> +
> +               priv->nparents = ARRAY_SIZE(lochnagar2_clk_parents);
> +               priv->parents = devm_kmemdup(priv->dev, lochnagar2_clk_parents,
> +                                            sizeof(lochnagar2_clk_parents),
> +                                            GFP_KERNEL);

Why do we need to kmemdup it? The clk framework already deep copies
everything from clk_init structure.

> +               break;
> +       default:
> +               dev_err(priv->dev, "Unknown Lochnagar type: %d\n", priv->type);
> +               return -EINVAL;
> +       }
> +
> +       if (!priv->parents)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < priv->nparents; i++) {
> +               j = of_property_match_string(np, "clock-names",
> +                                            priv->parents[i]);
> +               if (j >= 0)
> +                       priv->parents[i] = of_clk_get_parent_name(np, j);

Isn't this of_clk_parent_fill()? But there are holes or something?

> +       }
> +
> +       return 0;
> +}
> +
> +static int lochnagar_init_clks(struct lochnagar_clk_priv *priv)
> +{
> +       struct clk_init_data clk_init = {
> +               .ops = &lochnagar_clk_regmap_ops,
> +               .parent_names = priv->parents,
> +               .num_parents = priv->nparents,
> +       };
> +       struct lochnagar_clk *lclk;
> +       int ret, i;
> +
> +       for (i = 0; i < ARRAY_SIZE(priv->lclks); i++) {

We already have an array of clks.

> +               lclk = &priv->lclks[i];
> +
> +               if (!lclk->name)
> +                       continue;
> +
> +               clk_init.name = lclk->name;
> +
> +               lclk->priv = priv;
> +               lclk->hw.init = &clk_init;
> +
> +               ret = devm_clk_hw_register(priv->dev, &lclk->hw);
> +               if (ret) {
> +                       dev_err(priv->dev, "Failed to register %s: %d\n",
> +                               lclk->name, ret);
> +                       return ret;
> +               }
> +
> +               priv->clk_data->hws[i] = &lclk->hw;

But then we copy the pointers into here to use of_clk_hw_onecell_get().
Can you just roll your own function to use your own array of clk
structures? I know it's sort of sad, but it avoids a copy.

> +       }
> +
> +       priv->clk_data->num = ARRAY_SIZE(priv->lclks);
> +
> +       ret = devm_of_clk_add_hw_provider(priv->dev, of_clk_hw_onecell_get,
> +                                         priv->clk_data);
> +       if (ret < 0) {
> +               dev_err(priv->dev, "Failed to register provider: %d\n", ret);
> +               return ret;
> +       }
> +
> +       return 0;

Simplify this to

	if (ret < 0)
		dev_err(...)

	return ret;

> +}
> +
> +static const struct of_device_id lochnagar_of_match[] = {
> +       { .compatible = "cirrus,lochnagar1-clk", .data = (void *)LOCHNAGAR1 },
> +       { .compatible = "cirrus,lochnagar2-clk", .data = (void *)LOCHNAGAR2 },
> +       {},

Nitpick: Drop the comma, it's the sentinel so nothing should come after.

> +};

Any MODULE_DEVICE_TABLE?

> +
> +static int lochnagar_clk_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct lochnagar_clk_priv *priv;
> +       const struct of_device_id *of_id;
> +       int ret;
> +
> +       of_id = of_match_device(lochnagar_of_match, dev);
> +       if (!of_id)
> +               return -EINVAL;
> +
> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +       if (!priv)
> +               return -ENOMEM;
> +
> +       priv->clk_data = devm_kzalloc(dev, struct_size(priv->clk_data, hws,
> +                                                      ARRAY_SIZE(priv->lclks)),
> +                                     GFP_KERNEL);
> +       if (!priv->clk_data)
> +               return -ENOMEM;
> +
> +       priv->dev = dev;
> +       priv->regmap = dev_get_regmap(dev->parent, NULL);
> +       priv->type = (enum lochnagar_type)of_id->data;
> +
> +       ret = lochnagar_init_parents(priv);
> +       if (ret)
> +               return ret;
> +
> +       ret = lochnagar_init_clks(priv);
> +       if (ret)
> +               return ret;
> +
> +       return 0;
> +}
> +
> +static struct platform_driver lochnagar_clk_driver = {
> +       .driver = {
> +               .name = "lochnagar-clk",
> +               .of_match_table = of_match_ptr(lochnagar_of_match),

I suspect of_match_ptr() makes the build complain about unused match
table when CONFIG_OF=N. Can you try building it that way?

> +       },
> +

Nitpick: Why the extra newline?

> +       .probe = lochnagar_clk_probe,
> +};
> +module_platform_driver(lochnagar_clk_driver);
> +
> +MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
> +MODULE_DESCRIPTION("Clock driver for Cirrus Logic Lochnagar Board");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:lochnagar-clk");

I think MODULE_ALIAS is not needed if it's this simple?


  reply	other threads:[~2018-11-30  7:54 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-20 14:16 [PATCH v5 1/8] regulator: lochnagar: Move driver to binding from DT Charles Keepax
2018-11-20 14:16 ` [PATCH v5 2/8] mfd: lochnagar: Add initial binding documentation Charles Keepax
2018-11-28  9:18   ` Lee Jones
2018-11-20 14:16 ` [PATCH v5 3/8] clk: " Charles Keepax
2018-11-26 20:16   ` Rob Herring
2018-11-27  9:34     ` Charles Keepax
2018-11-20 14:16 ` [PATCH v5 4/8] pinctrl: " Charles Keepax
2018-12-07 17:07   ` Rob Herring
2018-12-16  0:16   ` Linus Walleij
2018-11-20 14:16 ` [PATCH v5 5/8] regulator: " Charles Keepax
2018-11-20 14:16 ` [PATCH v5 6/8] mfd: lochnagar: Add support for the Cirrus Logic Lochnagar Charles Keepax
2018-11-23  9:00   ` kbuild test robot
2018-11-23  9:15     ` Charles Keepax
2018-11-28  9:22   ` Lee Jones
2018-11-20 14:16 ` [PATCH v5 7/8] clk: " Charles Keepax
2018-11-30  7:53   ` Stephen Boyd [this message]
2018-12-21 13:50     ` Charles Keepax
2018-12-21 15:28       ` Charles Keepax
2018-12-21 20:44       ` Stephen Boyd
2018-11-20 14:16 ` [PATCH v5 8/8] pinctrl: " Charles Keepax

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=154356443157.88331.15749597863624143993@swboyd.mtv.corp.google.com \
    --to=sboyd@kernel.org \
    --cc=broonie@kernel.org \
    --cc=ckeepax@opensource.cirrus.com \
    --cc=devicetree@vger.kernel.org \
    --cc=lee.jones@linaro.org \
    --cc=lgirdwood@gmail.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mturquette@baylibre.com \
    --cc=patches@opensource.cirrus.com \
    --cc=robh+dt@kernel.org \
    /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).