From: Neil Armstrong <narmstrong@baylibre.com>
To: Michael Turquette <mturquette@baylibre.com>,
sboyd@codeaurora.org, carlo@caione.org, khilman@baylibre.com
Cc: linux-clk@vger.kernel.org, linux-amlogic@lists.infradead.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH 1/5] clk: meson: Add support for parameters for specific PLLs
Date: Wed, 22 Mar 2017 10:17:21 +0100 [thread overview]
Message-ID: <ccfe12e8-7108-76e4-7d6b-1addcf6fe95a@baylibre.com> (raw)
In-Reply-To: <149013981400.54062.11268768959465562064@resonance>
On 03/22/2017 12:43 AM, Michael Turquette wrote:
> Quoting Neil Armstrong (2017-03-13 06:26:40)
>> In recent Amlogic GXBB, GXL and GXM SoCs, the GP0 PLL needs some specific
>> parameters in order to initialize and lock correctly.
>>
>> This patch adds an optional PARAM table used to initialize the PLL to a
>> default value with it's parameters in order to achieve to desired frequency.
>>
>> The GP0 PLL in GXBB, GXL/GXM also needs some tweaks in the initialization
>> steps, and these are exposed along the PARAM table.
>>
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>> ---
>> drivers/clk/meson/clk-pll.c | 52 +++++++++++++++++++++++++++++++++++++++++++--
>> drivers/clk/meson/clkc.h | 23 ++++++++++++++++++++
>> 2 files changed, 73 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
>> index 4adc1e8..aff223b 100644
>> --- a/drivers/clk/meson/clk-pll.c
>> +++ b/drivers/clk/meson/clk-pll.c
>> @@ -116,6 +116,29 @@ static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_
>> return NULL;
>> }
>>
>> +/* Specific wait loop for GXL/GXM GP0 PLL */
>> +static int meson_clk_pll_wait_lock_reset(struct meson_clk_pll *pll,
>> + struct parm *p_n)
>> +{
>> + int delay = 100;
>> + u32 reg;
>> +
>> + while (delay > 0) {
>> + reg = readl(pll->base + p_n->reg_off);
>> + writel(reg | MESON_PLL_RESET, pll->base + p_n->reg_off);
>> + udelay(10);
>> + writel(reg & ~MESON_PLL_RESET, pll->base + p_n->reg_off);
>> +
>> + mdelay(1);
>
> Can you add a comment explaining where the delay values come from? Can
> they vary from chip to chip?
Hi,
Ok, the code comes from the vendor tree, and seems to be generic enough to handle
other chips.
But I'm not sure about this particular delay, 1ms seems large enough for a PLL locking...
Neil
>
>> +
>> + reg = readl(pll->base + p_n->reg_off);
>> + if (reg & MESON_PLL_LOCK)
>> + return 0;
>> + delay--;
>> + }
>> + return -ETIMEDOUT;
>> +}
>> +
>> static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
>> struct parm *p_n)
>> {
>> @@ -132,6 +155,15 @@ static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
>> return -ETIMEDOUT;
>> }
>>
>> +static void meson_clk_pll_init_params(struct meson_clk_pll *pll)
>> +{
>> + int i;
>> +
>> + for (i = 0 ; i < pll->params.params_count ; ++i)
>> + writel(pll->params.params_table[i].value,
>> + pll->base + pll->params.params_table[i].reg_off);
>> +}
>> +
>> static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>> unsigned long parent_rate)
>> {
>> @@ -151,10 +183,16 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>> if (!rate_set)
>> return -EINVAL;
>>
>> + /* Initialize the PLL in a clean state if specified */
>> + if (pll->params.params_count)
>> + meson_clk_pll_init_params(pll);
>> +
>> /* PLL reset */
>> p = &pll->n;
>> reg = readl(pll->base + p->reg_off);
>> - writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
>> + /* If no_init_reset is provided, avoid resetting at this point */
>> + if (!pll->params.no_init_reset)
>> + writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
>>
>> reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
>> writel(reg, pll->base + p->reg_off);
>> @@ -184,7 +222,17 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>> }
>>
>> p = &pll->n;
>> - ret = meson_clk_pll_wait_lock(pll, p);
>> + /* If unreset_for_lock is provided, remove the reset bit here */
>> + if (pll->params.unreset_for_lock) {
>
> Small nitpick, but I find "unreset" to be confusing. Since 'reset' here
> is a bit that can be set and unset, maybe use clear_reset_for_lock
> instead?
>
> Regards,
> Mike
>
>> + reg = readl(pll->base + p->reg_off);
>> + writel(reg & ~MESON_PLL_RESET, pll->base + p->reg_off);
>> + }
>> +
>> + /* If reset_lock_loop, use a special loop including resetting */
>> + if (pll->params.reset_lock_loop)
>> + ret = meson_clk_pll_wait_lock_reset(pll, p);
>> + else
>> + ret = meson_clk_pll_wait_lock(pll, p);
>> if (ret) {
>> pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
>> __func__, old_rate);
>> diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
>> index 9bb70e7..5f1c12d 100644
>> --- a/drivers/clk/meson/clkc.h
>> +++ b/drivers/clk/meson/clkc.h
>> @@ -62,6 +62,28 @@ struct pll_rate_table {
>> .frac = (_frac), \
>> } \
>>
>> +struct pll_params_table {
>> + unsigned int reg_off;
>> + unsigned int value;
>> +};
>> +
>> +#define PLL_PARAM(_reg, _val) \
>> + { \
>> + .reg_off = (_reg), \
>> + .value = (_val), \
>> + }
>> +
>> +struct pll_setup_params {
>> + struct pll_params_table *params_table;
>> + unsigned int params_count;
>> + /* Workaround for GP0, do not reset before configuring */
>> + bool no_init_reset;
>> + /* Workaround for GP0, unreset right before checking for lock */
>> + bool unreset_for_lock;
>> + /* Workaround for GXL GP0, reset in the lock checking loop */
>> + bool reset_lock_loop;
>> +};
>> +
>> struct meson_clk_pll {
>> struct clk_hw hw;
>> void __iomem *base;
>> @@ -70,6 +92,7 @@ struct meson_clk_pll {
>> struct parm frac;
>> struct parm od;
>> struct parm od2;
>> + const struct pll_setup_params params;
>> const struct pll_rate_table *rate_table;
>> unsigned int rate_count;
>> spinlock_t *lock;
>> --
>> 1.9.1
>>
next prev parent reply other threads:[~2017-03-22 9:17 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-13 13:26 [PATCH 0/5] clk: meson: Fix GXBB and GXL/GXM GP0 PLL Neil Armstrong
2017-03-13 13:26 ` [PATCH 1/5] clk: meson: Add support for parameters for specific PLLs Neil Armstrong
2017-03-21 23:43 ` Michael Turquette
2017-03-22 9:17 ` Neil Armstrong [this message]
2017-03-22 10:23 ` Neil Armstrong
2017-03-13 13:26 ` [PATCH 2/5] clk: meson-gxbb: Add GP0 PLL init parameters Neil Armstrong
2017-03-13 13:26 ` [PATCH 3/5] clk: meson-gxbb: Add GXL/GXM GP0 Variant Neil Armstrong
2017-03-21 23:49 ` Michael Turquette
2017-03-22 9:22 ` Neil Armstrong
2017-03-23 1:40 ` Michael Turquette
2017-03-13 13:26 ` [PATCH 4/5] clk: meson-gxbb: Expose GP0 dt-bindings clock id Neil Armstrong
2017-03-13 13:26 ` [PATCH 5/5] dt-bindings: clock: gxbb-clkc: Add GXL compatible variant Neil Armstrong
2017-03-20 21:17 ` Rob Herring
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=ccfe12e8-7108-76e4-7d6b-1addcf6fe95a@baylibre.com \
--to=narmstrong@baylibre.com \
--cc=carlo@caione.org \
--cc=khilman@baylibre.com \
--cc=linux-amlogic@lists.infradead.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mturquette@baylibre.com \
--cc=sboyd@codeaurora.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