[PATCH v1 1/1] clk: clk-gpio: add actual gated clock
Svyatoslav Ryhel
clamor95 at gmail.com
Fri Dec 15 21:00:10 CET 2023
пт, 15 груд. 2023 р. о 20:45 Sean Anderson <seanga2 at gmail.com> пише:
>
> On 12/15/23 13:26, Svyatoslav Ryhel wrote:
> > пт, 15 груд. 2023 р. о 19:25 Sean Anderson <seanga2 at gmail.com> пише:
> >>
> >> On 11/17/23 02:52, Svyatoslav Ryhel wrote:
> >>> Existing gpio-gate-clock driver acts like a simple GPIO switch without any
> >>> effect on gated clock. Add actual clock actions into enable/disable ops and
> >>> implement get_rate op by passing gated clock if it is enabled.
> >>>
> >>> Signed-off-by: Svyatoslav Ryhel <clamor95 at gmail.com>
> >>> ---
> >>> drivers/clk/clk-gpio.c | 47 +++++++++++++++++++++++++++++++++++-------
> >>> 1 file changed, 40 insertions(+), 7 deletions(-)
> >>>
> >>> diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c
> >>> index 26d795b978..a55470cfbf 100644
> >>> --- a/drivers/clk/clk-gpio.c
> >>> +++ b/drivers/clk/clk-gpio.c
> >>> @@ -3,19 +3,23 @@
> >>> * Copyright (C) 2023 Marek Vasut <marek.vasut+renesas at mailbox.org>
> >>> */
> >>>
> >>> -#include <asm/gpio.h>
> >>> -#include <common.h>
> >>> -#include <clk-uclass.h>
> >>> +#include <clk.h>
> >>> #include <dm.h>
> >>> +#include <clk-uclass.h>
> >>> +#include <linux/clk-provider.h>
> >>> +
> >>> +#include <asm/gpio.h>
> >>>
> >>> struct clk_gpio_priv {
> >>> struct gpio_desc enable;
> >>> + struct clk *clk;
> >>
> >> Please name this "parent".
> >>
> > I see no need in this since clk is generic name and this driver can
> > accept only one clock with any name.
>
> It's good documentation. It makes it clear what the purpose of the member is.
>
This driver uses a single (1) clock with a single purpose.
Why do you think you need a clock in a clock-gpio driver? Hm, I don't
know. This will remain a mystery for future archeo-coders yeah.
> >>> };
> >>>
> >>> static int clk_gpio_enable(struct clk *clk)
> >>> {
> >>> struct clk_gpio_priv *priv = dev_get_priv(clk->dev);
> >>>
> >>> + clk_prepare_enable(priv->clk);
> >>
> >> Just clk_enable is fine. We don't have a separate prepare stage line Linux.
> >>
> > U-Boot supports clk_prepare_enable and since this support is present I
> > see no contradiction in using it.
>
> These functions are only there for to make it easier to port code from Linux.
> Since this code was written for U-Boot, just use the actual function.
>
Then document that its use is discouraged. Until then it is not restricted.
> >>> dm_gpio_set_value(&priv->enable, 1);
> >>>
> >>> return 0;
> >>> @@ -26,21 +30,50 @@ static int clk_gpio_disable(struct clk *clk)
> >>> struct clk_gpio_priv *priv = dev_get_priv(clk->dev);
> >>>
> >>> dm_gpio_set_value(&priv->enable, 0);
> >>> + clk_disable_unprepare(priv->clk);
> >>>
> >>> return 0;
> >>> }
> >>>
> >>> +static ulong clk_gpio_get_rate(struct clk *clk)
> >>> +{
> >>> + struct clk_gpio_priv *priv = dev_get_priv(clk->dev);
> >>> + int ret;
> >>> +
> >>> + ret = dm_gpio_get_value(&priv->enable);
> >>> + if (ret)
> >>> + return clk_get_rate(priv->clk);
> >>> + else
> >>> + return -EINVAL;
> >>
> >> This should always return the parent rate.
> >>
> > How can you return clock rate if the gate is disabled?
>
> This allows consumers to know what the rate will be before they
> enable the clock.
>
I don't quite understand the logic behind this but ok.
> >>> +}
> >>> +
> >>> const struct clk_ops clk_gpio_ops = {
> >>> .enable = clk_gpio_enable,
> >>> .disable = clk_gpio_disable,
> >>> + .get_rate = clk_gpio_get_rate,
> >>> };
> >>>
> >>> -static int clk_gpio_probe(struct udevice *dev)
> >>> +static int clk_gpio_of_to_plat(struct udevice *dev)
> >>
> >> This change should be a separate commit.
> >>
> > This actually should not be accepted first place
> >
> > .of_to_plat - convert device tree data to plat
> > .probe - make a device ready for use
> >
> > https://github.com/u-boot/u-boot/blob/master/doc/develop/driver-model/design.rst
>
> Yes, this is why I was a bit confused :)
>
> >>> {
> >>> struct clk_gpio_priv *priv = dev_get_priv(dev);
> >>> + int ret;
> >>>
> >>> - return gpio_request_by_name(dev, "enable-gpios", 0,
> >>> - &priv->enable, GPIOD_IS_OUT);
> >>> + priv->clk = devm_clk_get(dev, NULL);
> >>> + if (IS_ERR(priv->clk)) {
> >>> + log_err("%s: Could not get gated clock: %ld\n",
> >>> + __func__, PTR_ERR(priv->clk));
> >>> + return PTR_ERR(priv->clk);
> >>> + }
> >>> +
> >>> + ret = gpio_request_by_name(dev, "enable-gpios", 0,
> >>> + &priv->enable, GPIOD_IS_OUT);
> >>> + if (ret) {
> >>> + log_err("%s: Could not decode enable-gpios (%d)\n",
> >>> + __func__, ret);
> >>
> >> Use dev_dbg for probe errors to reduce binary size.
> >>
> > These errors provide intel about probing 2 key parts of the driver.
> > How would you know it fails in case you have no devices which face
> > this error? Iis there any convention or restriction which prohibits
> > this? If yes, then provide a document please.
>
> https://docs.u-boot.org/en/latest/develop/driver-model/design.html#error-codes
>
> | Ideally, messages in drivers should only be displayed when debugging,
> | e.g. by using log_debug() although in extreme cases log_warning() or
> | log_error() may be used.
>
> > All other general clock drivers use log_err/dev_err versions btw.
>
> Yeah, it's something we have not been so consistent with enforcing.
>
Alright
> >>> + return ret;
> >>> + }
> >>> +
> >>> + return 0;
> >>> }
> >>>
> >>> /*
> >>> @@ -59,7 +92,7 @@ U_BOOT_DRIVER(gpio_gate_clock) = {
> >>> .name = "gpio_clock",
> >>> .id = UCLASS_CLK,
> >>> .of_match = clk_gpio_match,
> >>> - .probe = clk_gpio_probe,
> >>> + .of_to_plat = clk_gpio_of_to_plat,
> >>> .priv_auto = sizeof(struct clk_gpio_priv),
> >>> .ops = &clk_gpio_ops,
> >>> .flags = DM_FLAG_PRE_RELOC,
> >>
> >> --Sean
>
More information about the U-Boot
mailing list