public inbox for linux-clk@vger.kernel.org
 help / color / mirror / Atom feed
From: Stephen Boyd <sboyd@kernel.org>
To: Biju Das <biju.das.jz@bp.renesas.com>,
	Michael Turquette <mturquette@baylibre.com>
Cc: Biju Das <biju.das.jz@bp.renesas.com>,
	linux-clk@vger.kernel.org,
	Geert Uytterhoeven <geert+renesas@glider.be>,
	Fabrizio Castro <fabrizio.castro.jz@renesas.com>,
	linux-renesas-soc@vger.kernel.org
Subject: Re: [PATCH RFC 2/3] drivers: clk: Add support for versa3 clock driver
Date: Mon, 06 Mar 2023 12:22:16 -0800	[thread overview]
Message-ID: <dc7ff43b610bf898d581eb70f4a166c9.sboyd@kernel.org> (raw)
In-Reply-To: <20230220131307.269100-3-biju.das.jz@bp.renesas.com>

Quoting Biju Das (2023-02-20 05:13:06)
> diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c
> new file mode 100644
> index 000000000000..561cfad8a243
> --- /dev/null
> +++ b/drivers/clk/clk-versaclock3.c
> @@ -0,0 +1,1134 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Driver for Renesas Versaclock 3
> + *
> + * Copyright (C) 2021 Renesas Electronics Corp.
> + */
> +
> +#include <linux/clk.h>

Please remove this include after moving to 'struct clk_parent_data'.

> +#include <linux/clk-provider.h>
> +#include <linux/i2c.h>
> +#include <linux/limits.h>
> +#include <linux/module.h>
> +#include <linux/regmap.h>
> +
> +#define NUM_CONFIG_REGISTERS           37
> +
[...]
> +
> +static void vc3_clk_flags_parse_dt(struct device *dev, u32 *crt_clks)
> +{
> +       struct device_node *np = dev->of_node;
> +       struct property *prop;
> +       const __be32 *p;
> +       u32 i = 0;
> +       u32 val;
> +
> +       of_property_for_each_u32(np, "renesas,clock-flags", prop, p, val) {
> +               if (i >= ARRAY_SIZE(clk_out_data))
> +                       break;
> +               *crt_clks++ = val;
> +               i++;
> +       }
> +}
> +
> +static void vc3_fill_init_data(struct clk_init_data *init,
> +                              const struct vc3_clk_data *mux,
> +                              const struct clk_ops *ops,
> +                              u32 flags, int n,
> +                              const char **pll_parent_names,
> +                              const char **clkin_name)
> +{
> +       unsigned int i;
> +
> +       init->name = mux->name;
> +       init->ops = ops;
> +       init->flags = CLK_SET_RATE_PARENT;
> +       init->num_parents = n;
> +       for (i = 0; i < n; i++) {
> +               if (!mux->parent_names[i])
> +                       pll_parent_names[i] = clkin_name[0];
> +               else
> +                       pll_parent_names[i] = mux->parent_names[i];

Instead of string names please use clk_hw pointers or 'struct
clk_parent_data'.

> +       }
> +
> +       init->parent_names = pll_parent_names;
> +}
> +
> +static int vc3_clk_register(struct device *dev, struct vc3_driver_data *vc3,
> +                           struct vc3_hw_data *data, const void *clk_data,
> +                           struct clk_init_data *init, int n)

const init pointer?

> +{
> +       data->hw.init = init;
> +       data->num = n;
> +       data->vc3 = vc3;
> +       data->data = clk_data;
> +
> +       return devm_clk_hw_register(dev, &data->hw);
> +}
> +
> +static int vc3_probe(struct i2c_client *client)
> +{
> +       struct device *dev = &client->dev;
> +       u8 settings[NUM_CONFIG_REGISTERS];
> +       const char *pll_parent_names[3];
> +       struct vc3_driver_data *vc3;
> +       const char *clkin_name[1];
> +       struct clk_init_data init;
> +       u32 crit_clks[6] = {};
> +       struct clk *clk;
> +       int ret, i;
> +
> +       vc3 = devm_kzalloc(dev, sizeof(*vc3), GFP_KERNEL);
> +       if (!vc3)
> +               return -ENOMEM;
> +
> +       i2c_set_clientdata(client, vc3);
> +       vc3->client = client;
> +
> +       vc3->regmap = devm_regmap_init_i2c(client, &vc3_regmap_config);
> +       if (IS_ERR(vc3->regmap))
> +               return dev_err_probe(dev, PTR_ERR(vc3->regmap),
> +                                    "failed to allocate register map\n");
> +
> +       ret = of_property_read_u8_array(dev->of_node, "renesas,settings",
> +                                       settings, ARRAY_SIZE(settings));
> +       if (!ret) {
> +               /*
> +                * A raw settings array was specified in the DT. Write the
> +                * settings to the device immediately.
> +                */
> +               for  (i = 0; i < NUM_CONFIG_REGISTERS; i++) {
> +                       ret = regmap_write(vc3->regmap, i, settings[i]);
> +                       if (ret) {
> +                               dev_err(dev, "error writing to chip (%i)\n", ret);
> +                               return ret;
> +                       }
> +               }
> +       } else if (ret == -EOVERFLOW) {
> +               dev_err(&client->dev, "EOVERFLOW reg settings. ARRAY_SIZE: %zu",
> +                       ARRAY_SIZE(settings));
> +               return ret;
> +       }
> +
> +       /* Register clock ref */
> +       memset(&init, 0, sizeof(init));
> +
> +       clk = devm_clk_get(dev, "x1");
> +       if (PTR_ERR(clk) == -EPROBE_DEFER)
> +               return -EPROBE_DEFER;
> +
> +       if (!IS_ERR(clk)) {
> +               clkin_name[0] = __clk_get_name(clk);
> +       } else {
> +               clk = devm_clk_get(dev, "clkin");
> +               if (PTR_ERR(clk) == -EPROBE_DEFER)
> +                       return -EPROBE_DEFER;
> +
> +               if (!IS_ERR(clk))
> +                       clkin_name[0] = __clk_get_name(clk);
> +       }

Please use 'struct clk_parent_data' instead of clk consumer APIs.

> +
> +       if (IS_ERR_OR_NULL(clk))
> +               return dev_err_probe(&client->dev, -EINVAL, "no input clk\n");
> +
> +       /* Register pfd muxes */
> +       for (i = 0; i < ARRAY_SIZE(pfd_mux_data); i++) {
> +               vc3_fill_init_data(&init, &pfd_mux_data[i], &vc3_pfd_mux_ops,
> +                                  CLK_SET_RATE_PARENT, 2, pll_parent_names,
> +                                  clkin_name);
> +               ret = vc3_clk_register(dev, vc3, &vc3->clk_pfd_mux[i],
> +                                      &pfd_mux_data[i], &init, i);
> +               if (ret)
> +                       return dev_err_probe(dev, ret, "%s failed\n", init.name);
> +       }
> +
> +       /* Register pfd's */
> +       for (i = 0; i < ARRAY_SIZE(pfd_data); i++) {
> +               if (i == VC3_PFD1)
> +                       pll_parent_names[0] = clkin_name[0];
> +               else
> +                       pll_parent_names[0] = pfd_mux_data[i - 1].name;
> +
> +               init.name = pfd_data[i].name;
> +               init.ops = &vc3_pfd_ops;
> +               init.flags = CLK_SET_RATE_PARENT;
> +               init.num_parents = 1;
> +               init.parent_names = pll_parent_names;
> +
> +               ret = vc3_clk_register(dev, vc3, &vc3->clk_pfd[i],
> +                                      &pfd_data[i], &init, i);
> +               if (ret)
> +                       return dev_err_probe(dev, ret, "%s failed\n", init.name);
> +       }
> +
> +       /* Register pll's */
> +       for (i = 0; i < ARRAY_SIZE(pll_data); i++) {
> +               pll_parent_names[0] = pfd_data[i].name;
> +               init.name = pll_data[i].name;
> +               init.ops = &vc3_pll_ops;
> +               init.flags = CLK_SET_RATE_PARENT;
> +               init.num_parents = 1;
> +               init.parent_names = pll_parent_names;
> +
> +               ret = vc3_clk_register(dev, vc3, &vc3->clk_pll[i],
> +                                      &pll_data[i], &init, i);
> +               if (ret)
> +                       return dev_err_probe(dev, ret, "%s failed\n", init.name);
> +       }
> +
> +       /* Register divider muxes */
> +       for (i = 0; i < ARRAY_SIZE(div_mux_data); i++) {
> +               vc3_fill_init_data(&init, &div_mux_data[i], &vc3_div_mux_ops,
> +                                  CLK_SET_RATE_PARENT, 2, pll_parent_names,
> +                                  clkin_name);
> +               ret = vc3_clk_register(dev, vc3, &vc3->clk_div_mux[i],
> +                                      &div_mux_data[i], &init, i);
> +               if (ret)
> +                       return dev_err_probe(dev, ret, "%s failed\n", init.name);
> +       }
> +
> +       vc3_divider_type_parse_dt(dev, vc3);
> +       /* Register dividers */
> +       for (i = 0; i < ARRAY_SIZE(div_data); i++) {
> +               switch (i) {
> +               case VC3_DIV1:
> +                       pll_parent_names[0] = div_mux_data[VC3_DIV1_MUX].name;
> +                       break;
> +               case VC3_DIV2:
> +                       pll_parent_names[0] = pll_data[VC3_PLL1].name;
> +                       break;
> +               case VC3_DIV3:
> +                       pll_parent_names[0] = div_mux_data[VC3_DIV3_MUX].name;
> +                       break;
> +               case VC3_DIV4:
> +                       pll_parent_names[0] = div_mux_data[VC3_DIV4_MUX].name;
> +                       break;
> +               case VC3_DIV5:
> +                       pll_parent_names[0] = pll_data[VC3_PLL3].name;
> +                       break;
> +               }
> +
> +               init.name = div_data[i].name;
> +               init.ops = &vc3_div_ops;
> +               init.flags = CLK_SET_RATE_PARENT;
> +               init.num_parents = 1;
> +               init.parent_names = pll_parent_names;
> +
> +               ret = vc3_clk_register(dev, vc3, &vc3->clk_div[i],
> +                                      &div_data[i], &init, i);
> +               if (ret)
> +                       return dev_err_probe(dev, ret, "%s failed\n", init.name);
> +       }
> +
> +       /* Register clk muxes */
> +       for (i = 0; i < ARRAY_SIZE(clk_mux_data); i++) {
> +               vc3_fill_init_data(&init, &clk_mux_data[i], &vc3_clk_mux_ops,
> +                                  CLK_SET_RATE_PARENT, 2, pll_parent_names,
> +                                  clkin_name);
> +               ret = vc3_clk_register(dev, vc3, &vc3->clk_mux[i],
> +                                      &clk_mux_data[i], &init, i);
> +               if (ret)
> +                       return dev_err_probe(dev, ret, "%s failed\n", init.name);
> +       }
> +
> +       /* Register clk outputs */
> +       vc3_clk_flags_parse_dt(dev, crit_clks);
> +       for (i = 0; i < ARRAY_SIZE(clk_out_data); i++) {
> +               vc3_fill_init_data(&init, &clk_out_data[i], &vc3_clk_out_ops,
> +                                  crit_clks[i], 1, pll_parent_names,
> +                                  clkin_name);
> +               ret = vc3_clk_register(dev, vc3, &vc3->clk_out[i],
> +                                      &clk_out_data[i], &init, i);
> +               if (ret)
> +                       return dev_err_probe(dev, ret, "%s failed\n", init.name);
> +       }
> +
> +       ret = of_clk_add_hw_provider(client->dev.of_node, vc3_of_clk_get, vc3);

Can you use devm?

> +       if (ret)
> +               return dev_err_probe(dev, ret, "unable to add clk provider\n");
> +
> +       return ret;
> +}
> +
> +static void vc3_remove(struct i2c_client *client)
> +{
> +       of_clk_del_provider(client->dev.of_node);
> +}

Using devm means this whole function can be removed.

  reply	other threads:[~2023-03-06 20:22 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-20 13:13 [PATCH RFC 0/3] Add Versa3 clock generator support Biju Das
2023-02-20 13:13 ` [PATCH RFC 1/3] dt-bindings: clock: Add Renesas versa3 clock generator bindings Biju Das
2023-02-22  9:34   ` Krzysztof Kozlowski
2023-03-08 14:39     ` Biju Das
2023-03-08 14:50       ` Geert Uytterhoeven
2023-03-08 14:57         ` Biju Das
2023-03-08 18:47       ` Krzysztof Kozlowski
2023-03-08 18:55         ` Biju Das
2023-03-08 19:17           ` Krzysztof Kozlowski
2023-03-09  7:57             ` Biju Das
2023-03-09  9:13               ` Krzysztof Kozlowski
2023-03-09  9:18                 ` Biju Das
2023-03-09  9:44                   ` Krzysztof Kozlowski
2023-03-09  9:53                     ` Biju Das
2023-03-09 10:15                       ` Krzysztof Kozlowski
2023-03-09 11:18                         ` Biju Das
2023-03-09  9:58                     ` Geert Uytterhoeven
2023-03-09 10:17                       ` Krzysztof Kozlowski
2023-03-09 10:25                         ` Geert Uytterhoeven
2023-03-09 15:15                           ` Biju Das
2023-03-09 10:30                       ` Biju Das
2023-02-20 13:13 ` [PATCH RFC 2/3] drivers: clk: Add support for versa3 clock driver Biju Das
2023-03-06 20:22   ` Stephen Boyd [this message]
2023-03-09 12:25     ` Biju Das
2023-02-20 13:13 ` [PATCH RFC 3/3] arm64: dts: renesas: rzg2l-smarc: Use versa3 clk for audio mclk Biju Das
2023-02-20 13:18 ` [PATCH RFC 0/3] Add Versa3 clock generator support Biju Das

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=dc7ff43b610bf898d581eb70f4a166c9.sboyd@kernel.org \
    --to=sboyd@kernel.org \
    --cc=biju.das.jz@bp.renesas.com \
    --cc=fabrizio.castro.jz@renesas.com \
    --cc=geert+renesas@glider.be \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-renesas-soc@vger.kernel.org \
    --cc=mturquette@baylibre.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