mirror of https://lore.kernel.org/linux-amlogic/
 help / color / mirror / Atom feed
From: mturquette@baylibre.com (Michael Turquette)
To: linus-amlogic@lists.infradead.org
Subject: [PATCH v2 5/9] clk: meson: mpll: add rw operation
Date: Tue, 21 Mar 2017 16:19:40 -0700	[thread overview]
Message-ID: <149013838063.54062.4258647016605052547@resonance> (raw)
In-Reply-To: <20170309104154.28295-6-jbrunet@baylibre.com>

Quoting Jerome Brunet (2017-03-09 02:41:50)
> This patch adds new callbacks to the meson-mpll driver to control
> and set the pll rate. For this, we also need to add the enable bit and
> sdm enable bit. The corresponding parameters are added to mpll data
> structure.
> 
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

Patch looks good to me. I'm really happy to see the mpll's get sorted
out finally!

Regards,
Mike

> ---
>  drivers/clk/meson/clk-mpll.c | 152 +++++++++++++++++++++++++++++++++++++++++--
>  drivers/clk/meson/clkc.h     |   4 +-
>  drivers/clk/meson/gxbb.c     |  30 +++++++++
>  3 files changed, 180 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
> index 03af79005ddb..342b85d4e22a 100644
> --- a/drivers/clk/meson/clk-mpll.c
> +++ b/drivers/clk/meson/clk-mpll.c
> @@ -64,16 +64,50 @@
>  #include <linux/clk-provider.h>
>  #include "clkc.h"
>  
> -#define SDM_MAX 16384
> +#define SDM_DEN 16384
> +#define SDM_MIN 1
> +#define SDM_MAX 16383
> +#define N2_MIN 4
> +#define N2_MAX 127
>  
>  #define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
>  
> +static unsigned long rate_from_params(unsigned long parent_rate,
> +                                     unsigned long sdm,
> +                                     unsigned long n2)
> +{
> +       return (parent_rate * SDM_DEN) / ((SDM_DEN * n2) + sdm);
> +}
> +
> +static void params_from_rate(unsigned long requested_rate,
> +                            unsigned long parent_rate,
> +                            unsigned long *sdm,
> +                            unsigned long *n2)
> +{
> +       uint64_t div = parent_rate;
> +       unsigned long rem = do_div(div, requested_rate);
> +
> +       if (div < N2_MIN) {
> +               *n2 = N2_MIN;
> +               *sdm = SDM_MIN;
> +       } else if (div > N2_MAX) {
> +               *n2 = N2_MAX;
> +               *sdm = SDM_MAX;
> +       } else {
> +               *n2 = div;
> +               *sdm = DIV_ROUND_UP(rem * SDM_DEN, requested_rate);
> +               if (*sdm < SDM_MIN)
> +                       *sdm = SDM_MIN;
> +               else if (*sdm > SDM_MAX)
> +                       *sdm = SDM_MAX;
> +       }
> +}
> +
>  static unsigned long mpll_recalc_rate(struct clk_hw *hw,
>                 unsigned long parent_rate)
>  {
>         struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
>         struct parm *p;
> -       unsigned long rate = 0;
>         unsigned long reg, sdm, n2;
>  
>         p = &mpll->sdm;
> @@ -84,11 +118,119 @@ static unsigned long mpll_recalc_rate(struct clk_hw *hw,
>         reg = readl(mpll->base + p->reg_off);
>         n2 = PARM_GET(p->width, p->shift, reg);
>  
> -       rate = (parent_rate * SDM_MAX) / ((SDM_MAX * n2) + sdm);
> +       return rate_from_params(parent_rate, sdm, n2);
> +}
> +
> +static long mpll_round_rate(struct clk_hw *hw,
> +                           unsigned long rate,
> +                           unsigned long *parent_rate)
> +{
> +       unsigned long sdm, n2;
> +
> +       params_from_rate(rate, *parent_rate, &sdm, &n2);
> +       return rate_from_params(*parent_rate, sdm, n2);
> +}
> +
> +static int mpll_set_rate(struct clk_hw *hw,
> +                        unsigned long rate,
> +                        unsigned long parent_rate)
> +{
> +       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
> +       struct parm *p;
> +       unsigned long reg, sdm, n2;
> +       unsigned long flags = 0;
> +
> +       params_from_rate(rate, parent_rate, &sdm, &n2);
> +
> +       if (mpll->lock)
> +               spin_lock_irqsave(mpll->lock, flags);
> +       else
> +               __acquire(mpll->lock);
> +
> +       p = &mpll->sdm;
> +       reg = readl(mpll->base + p->reg_off);
> +       reg = PARM_SET(p->width, p->shift, reg, sdm);
> +       writel(reg, mpll->base + p->reg_off);
> +
> +       p = &mpll->sdm_en;
> +       reg = readl(mpll->base + p->reg_off);
> +       reg = PARM_SET(p->width, p->shift, reg, 1);
> +       writel(reg, mpll->base + p->reg_off);
> +
> +       p = &mpll->n2;
> +       reg = readl(mpll->base + p->reg_off);
> +       reg = PARM_SET(p->width, p->shift, reg, n2);
> +       writel(reg, mpll->base + p->reg_off);
> +
> +       if (mpll->lock)
> +               spin_unlock_irqrestore(mpll->lock, flags);
> +       else
> +               __release(mpll->lock);
>  
> -       return rate;
> +       return 0;
> +}
> +
> +static void mpll_enable_core(struct clk_hw *hw, int enable)
> +{
> +       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
> +       struct parm *p;
> +       unsigned long reg;
> +       unsigned long flags = 0;
> +
> +       if (mpll->lock)
> +               spin_lock_irqsave(mpll->lock, flags);
> +       else
> +               __acquire(mpll->lock);
> +
> +       p = &mpll->en;
> +       reg = readl(mpll->base + p->reg_off);
> +       reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0);
> +       writel(reg, mpll->base + p->reg_off);
> +
> +       if (mpll->lock)
> +               spin_unlock_irqrestore(mpll->lock, flags);
> +       else
> +               __release(mpll->lock);
> +}
> +
> +
> +static int mpll_enable(struct clk_hw *hw)
> +{
> +       mpll_enable_core(hw, 1);
> +
> +       return 0;
> +}
> +
> +static void mpll_disable(struct clk_hw *hw)
> +{
> +       mpll_enable_core(hw, 0);
> +}
> +
> +static int mpll_is_enabled(struct clk_hw *hw)
> +{
> +       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
> +       struct parm *p;
> +       unsigned long reg;
> +       int en;
> +
> +       p = &mpll->en;
> +       reg = readl(mpll->base + p->reg_off);
> +       en = PARM_GET(p->width, p->shift, reg);
> +
> +       return en;
>  }
>  
>  const struct clk_ops meson_clk_mpll_ro_ops = {
> -       .recalc_rate = mpll_recalc_rate,
> +       .recalc_rate    = mpll_recalc_rate,
> +       .round_rate     = mpll_round_rate,
> +       .is_enabled     = mpll_is_enabled,
> +};
> +
> +const struct clk_ops meson_clk_mpll_ops = {
> +       .recalc_rate    = mpll_recalc_rate,
> +       .round_rate     = mpll_round_rate,
> +       .set_rate       = mpll_set_rate,
> +       .enable         = mpll_enable,
> +       .disable        = mpll_disable,
> +       .is_enabled     = mpll_is_enabled,
>  };
> diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
> index c6be77dd8694..ad254675edd8 100644
> --- a/drivers/clk/meson/clkc.h
> +++ b/drivers/clk/meson/clkc.h
> @@ -92,8 +92,9 @@ struct meson_clk_mpll {
>         struct clk_hw hw;
>         void __iomem *base;
>         struct parm sdm;
> +       struct parm sdm_en;
>         struct parm n2;
> -       /* FIXME ssen gate control? */
> +       struct parm en;
>         spinlock_t *lock;
>  };
>  
> @@ -116,5 +117,6 @@ extern const struct clk_ops meson_clk_pll_ro_ops;
>  extern const struct clk_ops meson_clk_pll_ops;
>  extern const struct clk_ops meson_clk_cpu_ops;
>  extern const struct clk_ops meson_clk_mpll_ro_ops;
> +extern const struct clk_ops meson_clk_mpll_ops;
>  
>  #endif /* __CLKC_H */
> diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
> index 79e9313e6703..79fb8989f8dd 100644
> --- a/drivers/clk/meson/gxbb.c
> +++ b/drivers/clk/meson/gxbb.c
> @@ -441,11 +441,21 @@ static struct meson_clk_mpll gxbb_mpll0 = {
>                 .shift   = 0,
>                 .width   = 14,
>         },
> +       .sdm_en = {
> +               .reg_off = HHI_MPLL_CNTL7,
> +               .shift   = 15,
> +               .width   = 1,
> +       },
>         .n2 = {
>                 .reg_off = HHI_MPLL_CNTL7,
>                 .shift   = 16,
>                 .width   = 9,
>         },
> +       .en = {
> +               .reg_off = HHI_MPLL_CNTL7,
> +               .shift   = 14,
> +               .width   = 1,
> +       },
>         .lock = &clk_lock,
>         .hw.init = &(struct clk_init_data){
>                 .name = "mpll0",
> @@ -461,11 +471,21 @@ static struct meson_clk_mpll gxbb_mpll1 = {
>                 .shift   = 0,
>                 .width   = 14,
>         },
> +       .sdm_en = {
> +               .reg_off = HHI_MPLL_CNTL8,
> +               .shift   = 15,
> +               .width   = 1,
> +       },
>         .n2 = {
>                 .reg_off = HHI_MPLL_CNTL8,
>                 .shift   = 16,
>                 .width   = 9,
>         },
> +       .en = {
> +               .reg_off = HHI_MPLL_CNTL8,
> +               .shift   = 14,
> +               .width   = 1,
> +       },
>         .lock = &clk_lock,
>         .hw.init = &(struct clk_init_data){
>                 .name = "mpll1",
> @@ -481,11 +501,21 @@ static struct meson_clk_mpll gxbb_mpll2 = {
>                 .shift   = 0,
>                 .width   = 14,
>         },
> +       .sdm_en = {
> +               .reg_off = HHI_MPLL_CNTL9,
> +               .shift   = 15,
> +               .width   = 1,
> +       },
>         .n2 = {
>                 .reg_off = HHI_MPLL_CNTL9,
>                 .shift   = 16,
>                 .width   = 9,
>         },
> +       .en = {
> +               .reg_off = HHI_MPLL_CNTL9,
> +               .shift   = 14,
> +               .width   = 1,
> +       },
>         .lock = &clk_lock,
>         .hw.init = &(struct clk_init_data){
>                 .name = "mpll2",
> -- 
> 2.9.3
> 

  reply	other threads:[~2017-03-21 23:19 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-09 10:41 [PATCH v2 0/9] clk: meson: update clock controller for audio support Jerome Brunet
2017-03-09 10:41 ` [PATCH v2 1/9] clk: meson: fix SET_PARM macro Jerome Brunet
2017-03-09 10:41 ` [PATCH v2 2/9] clk: meson: add missing const qualifiers on gate arrays Jerome Brunet
2017-03-09 10:41 ` [PATCH v2 3/9] clk: meson8b: put dividers and muxes in tables Jerome Brunet
2017-03-21 23:10   ` Michael Turquette
2017-03-09 10:41 ` [PATCH v2 4/9] clk: gxbb: " Jerome Brunet
2017-03-21 23:10   ` Michael Turquette
2017-03-09 10:41 ` [PATCH v2 5/9] clk: meson: mpll: add rw operation Jerome Brunet
2017-03-21 23:19   ` Michael Turquette [this message]
2017-03-09 10:41 ` [PATCH v2 6/9] clk: meson: gxbb: mpll: use " Jerome Brunet
2017-03-21 23:20   ` Michael Turquette
2017-03-09 10:41 ` [PATCH v2 7/9] clk: meson8b: add the mplls clocks 0, 1 and 2 Jerome Brunet
2017-03-21 23:21   ` Michael Turquette
2017-03-09 10:41 ` [PATCH v2 8/9] clk: meson: mpll: correct N2 maximum value Jerome Brunet
2017-03-09 10:41 ` [PATCH v2 9/9] dt-bindings: clk: gxbb: expose i2s output clock gates Jerome Brunet
2017-03-11  0:39 ` [PATCH v2 0/9] clk: meson: update clock controller for audio support Kevin Hilman
2017-03-27 19:52   ` 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=149013838063.54062.4258647016605052547@resonance \
    --to=mturquette@baylibre.com \
    --cc=linus-amlogic@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

all inboxes | Powered by JetHome®