From: sboyd@codeaurora.org (Stephen Boyd)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 1/5] clk: Add a basic multiplier clock
Date: Fri, 2 Oct 2015 13:43:08 -0700 [thread overview]
Message-ID: <20151002204308.GY12338@codeaurora.org> (raw)
In-Reply-To: <1443512353-28073-2-git-send-email-maxime.ripard@free-electrons.com>
On 09/29, Maxime Ripard wrote:
> diff --git a/drivers/clk/clk-multiplier.c b/drivers/clk/clk-multiplier.c
> new file mode 100644
> index 000000000000..61097e365d55
> --- /dev/null
> +++ b/drivers/clk/clk-multiplier.c
> @@ -0,0 +1,176 @@
> +/*
> + * Copyright (C) 2015 Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#include <linux/module.h>
Maybe export.h is more appropriate?
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include <linux/err.h>
> +#include <linux/of.h>
> +
> +#define to_clk_multiplier(_hw) container_of(_hw, struct clk_multiplier, hw)
> +
> +static unsigned long __get_mult(struct clk_multiplier *mult,
> + unsigned long rate,
> + unsigned long parent_rate)
> +{
> + if (mult->flags & CLK_MULTIPLIER_ROUND_CLOSEST)
> + return DIV_ROUND_CLOSEST(rate, parent_rate);
We should include kernel.h for this macro.
> +
> + return rate / parent_rate;
> +}
> +
> +static unsigned long clk_multiplier_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct clk_multiplier *mult = to_clk_multiplier(hw);
> + unsigned long val;
> +
> + val = clk_readl(mult->reg) >> mult->shift;
> + val &= GENMASK(mult->width, 0);
and bitops.h for GENMASK
> +
> + if (!val && mult->flags & CLK_MULTIPLIER_ZERO_BYPASS)
> + val = 1;
> +
> + return parent_rate * val;
> +}
> +
> +static bool __is_best_rate(unsigned long rate, unsigned long new,
> + unsigned long best, unsigned long flags)
> +{
> + if (flags & CLK_MULTIPLIER_ROUND_CLOSEST)
Is the only difference in this function vs the divider one that
flag? Maybe we should make this function generic to the framework
and pass a flag indicating closest or not.
> + return abs(rate - new) < abs(rate - best);
> +
> + return new >= rate && new < best;
> +}
> +
> +static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
> + unsigned long *best_parent_rate,
> + u8 width, unsigned long flags)
> +{
> + unsigned long orig_parent_rate = *best_parent_rate;
> + unsigned long parent_rate, current_rate, best_rate = ~0;
> + unsigned int i, bestmult = 0;
> +
> + if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT))
Please use clk_hw_get_flags. I'd *really* like to kill
__clk_get_flags() but we still have one user in omap code.
> + return rate / *best_parent_rate;
> +
> + for (i = 1; i < ((1 << width) - 1); i++) {
> + if (rate * i == orig_parent_rate) {
> + /*
> + * This is the best case for us if we have a
> + * perfect match without changing the parent
> + * rate.
> + */
> + *best_parent_rate = orig_parent_rate;
> + return i;
> + }
> +
> + parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
> + rate / i);
> + current_rate = parent_rate * i;
> +
> + if (__is_best_rate(rate, current_rate, best_rate, flags)) {
> + bestmult = i;
> + best_rate = current_rate;
> + *best_parent_rate = parent_rate;
> + }
> + }
> +
> + return bestmult;
> +}
> +
> +static int clk_multiplier_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + struct clk_multiplier *mult = to_clk_multiplier(hw);
> + unsigned long factor = __get_mult(mult, rate, parent_rate);
> + unsigned long uninitialized_var(flags);
hmmm ok. We set it to 0 in other drivers.
> + unsigned long val;
> +
> + if (mult->lock)
> + spin_lock_irqsave(mult->lock, flags);
This needs the same "trick" that we did in the generic clock
types to avoid sparse warnings.
> +
> + val = clk_readl(mult->reg);
> + val &= ~GENMASK(mult->width + mult->shift, mult->shift);
> + val |= factor << mult->shift;
> + clk_writel(val, mult->reg);
> +
> + if (mult->lock)
> + spin_unlock_irqrestore(mult->lock, flags);
> +
> + return 0;
> +}
> +
> +struct clk *clk_register_multiplier(struct device *dev, const char *name,
> + const char *parent_name,
> + unsigned long flags,
> + void __iomem *reg, u8 shift, u8 width,
> + u8 clk_mult_flags, spinlock_t *lock)
> +{
> + struct clk_init_data init;
> + struct clk_multiplier *mult;
> + struct clk *clk;
> +
> + mult = kmalloc(sizeof(*mult), GFP_KERNEL);
> + if (!mult) {
> + pr_err("%s: could not allocate multiplier clk\n", __func__);
We don't need allocation error messages.
> + return ERR_PTR(-ENOMEM);
> + }
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
next prev parent reply other threads:[~2015-10-02 20:43 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-29 7:39 [PATCH v3 0/5] clk: sunxi: Add support for the Audio PLL Maxime Ripard
2015-09-29 7:39 ` [PATCH v3 1/5] clk: Add a basic multiplier clock Maxime Ripard
2015-10-02 20:43 ` Stephen Boyd [this message]
2015-10-05 10:19 ` Maxime Ripard
2015-10-05 18:09 ` Stephen Boyd
2015-10-07 11:04 ` Maxime Ripard
2015-10-07 19:17 ` Stephen Boyd
2015-09-29 7:39 ` [PATCH v3 2/5] clk: sunxi: Add a driver for the PLL2 Maxime Ripard
2015-09-29 7:39 ` [PATCH v3 3/5] clk: sunxi: pll2: Add A13 support Maxime Ripard
2015-09-29 7:39 ` [PATCH v3 4/5] clk: sunxi: codec clock support Maxime Ripard
2015-10-02 20:44 ` Stephen Boyd
2015-10-05 9:05 ` Maxime Ripard
2015-09-29 7:39 ` [PATCH v3 5/5] clk: sunxi: mod1 " Maxime Ripard
2015-10-02 20:45 ` Stephen Boyd
2015-10-05 9:44 ` Maxime Ripard
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=20151002204308.GY12338@codeaurora.org \
--to=sboyd@codeaurora.org \
--cc=linux-arm-kernel@lists.infradead.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).