[PATCH 07/25] clk: imx: clk-fracn-gppll: make usable from PBL
Sascha Hauer
s.hauer at pengutronix.de
Fri Nov 10 04:57:42 PST 2023
The PBL code needs to adjust the DDR PLL before setting up DDR.
Factor out the PLL setup code as a static inline function for
PBL usage.
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
drivers/clk/imx/clk-fracn-gppll.c | 135 +++++-----------------------
drivers/clk/imx/clk.h | 28 +-----
include/soc/imx/clk-fracn-gppll.h | 144 ++++++++++++++++++++++++++++++
3 files changed, 165 insertions(+), 142 deletions(-)
create mode 100644 include/soc/imx/clk-fracn-gppll.h
diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c
index 5fbc79f948..24e66fd65f 100644
--- a/drivers/clk/imx/clk-fracn-gppll.c
+++ b/drivers/clk/imx/clk-fracn-gppll.c
@@ -10,38 +10,10 @@
#include <of_address.h>
#include <linux/iopoll.h>
#include <linux/bitfield.h>
+#include <soc/imx/clk-fracn-gppll.h>
#include "clk.h"
-#define PLL_CTRL 0x0
-#define HW_CTRL_SEL BIT(16)
-#define CLKMUX_BYPASS BIT(2)
-#define CLKMUX_EN BIT(1)
-#define POWERUP_MASK BIT(0)
-
-#define PLL_ANA_PRG 0x10
-#define PLL_SPREAD_SPECTRUM 0x30
-
-#define PLL_NUMERATOR 0x40
-#define PLL_MFN_MASK GENMASK(31, 2)
-
-#define PLL_DENOMINATOR 0x50
-#define PLL_MFD_MASK GENMASK(29, 0)
-
-#define PLL_DIV 0x60
-#define PLL_MFI_MASK GENMASK(24, 16)
-#define PLL_RDIV_MASK GENMASK(15, 13)
-#define PLL_ODIV_MASK GENMASK(7, 0)
-
-#define PLL_DFS_CTRL(x) (0x70 + (x) * 0x10)
-
-#define PLL_STATUS 0xF0
-#define LOCK_STATUS BIT(0)
-
-#define DFS_STATUS 0xF4
-
-#define LOCK_TIMEOUT_US 200
-
#define PLL_FRACN_GP(_rate, _mfi, _mfn, _mfd, _rdiv, _odiv) \
{ \
.rate = (_rate), \
@@ -118,19 +90,6 @@ static inline struct clk_fracn_gppll *to_clk_fracn_gppll(struct clk_hw *hw)
return container_of(hw, struct clk_fracn_gppll, hw);
}
-static const struct imx_fracn_gppll_rate_table *
-imx_get_pll_settings(struct clk_fracn_gppll *pll, unsigned long rate)
-{
- const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
- int i;
-
- for (i = 0; i < pll->rate_count; i++)
- if (rate == rate_table[i].rate)
- return &rate_table[i];
-
- return NULL;
-}
-
static long clk_fracn_gppll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
@@ -157,17 +116,17 @@ static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned lon
long rate = 0;
int i;
- pll_numerator = readl_relaxed(pll->base + PLL_NUMERATOR);
- mfn = FIELD_GET(PLL_MFN_MASK, pll_numerator);
+ pll_numerator = readl_relaxed(pll->base + GPPLL_NUMERATOR);
+ mfn = FIELD_GET(GPPLL_MFN_MASK, pll_numerator);
- pll_denominator = readl_relaxed(pll->base + PLL_DENOMINATOR);
- mfd = FIELD_GET(PLL_MFD_MASK, pll_denominator);
+ pll_denominator = readl_relaxed(pll->base + GPPLL_DENOMINATOR);
+ mfd = FIELD_GET(GPPLL_MFD_MASK, pll_denominator);
- pll_div = readl_relaxed(pll->base + PLL_DIV);
- mfi = FIELD_GET(PLL_MFI_MASK, pll_div);
+ pll_div = readl_relaxed(pll->base + GPPLL_DIV);
+ mfi = FIELD_GET(GPPLL_MFI_MASK, pll_div);
- rdiv = FIELD_GET(PLL_RDIV_MASK, pll_div);
- odiv = FIELD_GET(PLL_ODIV_MASK, pll_div);
+ rdiv = FIELD_GET(GPPLL_RDIV_MASK, pll_div);
+ odiv = FIELD_GET(GPPLL_ODIV_MASK, pll_div);
/*
* Sometimes, the recalculated rate has deviation due to
@@ -214,70 +173,16 @@ static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned lon
static int clk_fracn_gppll_wait_lock(struct clk_fracn_gppll *pll)
{
- u32 val;
-
- return readl_poll_timeout(pll->base + PLL_STATUS, val,
- val & LOCK_STATUS, LOCK_TIMEOUT_US);
+ return fracn_gppll_wait_lock(pll->base);
}
static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
{
struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
- const struct imx_fracn_gppll_rate_table *rate;
- u32 tmp, pll_div, ana_mfn;
- int ret;
-
- rate = imx_get_pll_settings(pll, drate);
-
- /* Hardware control select disable. PLL is control by register */
- tmp = readl_relaxed(pll->base + PLL_CTRL);
- tmp &= ~HW_CTRL_SEL;
- writel_relaxed(tmp, pll->base + PLL_CTRL);
-
- /* Disable output */
- tmp = readl_relaxed(pll->base + PLL_CTRL);
- tmp &= ~CLKMUX_EN;
- writel_relaxed(tmp, pll->base + PLL_CTRL);
-
- /* Power Down */
- tmp &= ~POWERUP_MASK;
- writel_relaxed(tmp, pll->base + PLL_CTRL);
-
- /* Disable BYPASS */
- tmp &= ~CLKMUX_BYPASS;
- writel_relaxed(tmp, pll->base + PLL_CTRL);
-
- pll_div = FIELD_PREP(PLL_RDIV_MASK, rate->rdiv) | rate->odiv |
- FIELD_PREP(PLL_MFI_MASK, rate->mfi);
- writel_relaxed(pll_div, pll->base + PLL_DIV);
- if (pll->flags & CLK_FRACN_GPPLL_FRACN) {
- writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR);
- writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR);
- }
-
- /* Wait for 5us according to fracn mode pll doc */
- udelay(5);
- /* Enable Powerup */
- tmp |= POWERUP_MASK;
- writel_relaxed(tmp, pll->base + PLL_CTRL);
-
- /* Wait Lock */
- ret = clk_fracn_gppll_wait_lock(pll);
- if (ret)
- return ret;
-
- /* Enable output */
- tmp |= CLKMUX_EN;
- writel_relaxed(tmp, pll->base + PLL_CTRL);
-
- ana_mfn = readl_relaxed(pll->base + PLL_STATUS);
- ana_mfn = FIELD_GET(PLL_MFN_MASK, ana_mfn);
-
- WARN(ana_mfn != rate->mfn, "ana_mfn != rate->mfn\n");
-
- return 0;
+ return fracn_gppll_set_rate(pll->base, pll->flags, pll->rate_table,
+ pll->rate_count, drate);
}
static int clk_fracn_gppll_prepare(struct clk_hw *hw)
@@ -286,25 +191,25 @@ static int clk_fracn_gppll_prepare(struct clk_hw *hw)
u32 val;
int ret;
- val = readl_relaxed(pll->base + PLL_CTRL);
+ val = readl_relaxed(pll->base + GPPLL_CTRL);
if (val & POWERUP_MASK)
return 0;
val |= CLKMUX_BYPASS;
- writel_relaxed(val, pll->base + PLL_CTRL);
+ writel_relaxed(val, pll->base + GPPLL_CTRL);
val |= POWERUP_MASK;
- writel_relaxed(val, pll->base + PLL_CTRL);
+ writel_relaxed(val, pll->base + GPPLL_CTRL);
val |= CLKMUX_EN;
- writel_relaxed(val, pll->base + PLL_CTRL);
+ writel_relaxed(val, pll->base + GPPLL_CTRL);
ret = clk_fracn_gppll_wait_lock(pll);
if (ret)
return ret;
val &= ~CLKMUX_BYPASS;
- writel_relaxed(val, pll->base + PLL_CTRL);
+ writel_relaxed(val, pll->base + GPPLL_CTRL);
return 0;
}
@@ -314,7 +219,7 @@ static int clk_fracn_gppll_is_prepared(struct clk_hw *hw)
struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
u32 val;
- val = readl_relaxed(pll->base + PLL_CTRL);
+ val = readl_relaxed(pll->base + GPPLL_CTRL);
return (val & POWERUP_MASK) ? 1 : 0;
}
@@ -324,9 +229,9 @@ static void clk_fracn_gppll_unprepare(struct clk_hw *hw)
struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
u32 val;
- val = readl_relaxed(pll->base + PLL_CTRL);
+ val = readl_relaxed(pll->base + GPPLL_CTRL);
val &= ~POWERUP_MASK;
- writel_relaxed(val, pll->base + PLL_CTRL);
+ writel_relaxed(val, pll->base + GPPLL_CTRL);
}
static const struct clk_ops clk_fracn_gppll_ops = {
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 1d3316619f..9058f913d3 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -304,33 +304,7 @@ struct clk *imx8m_clk_composite_flags(const char *name,
#define imx8m_clk_composite_critical(name, parent_names, reg) \
__imx8m_clk_composite(name, parent_names, reg, CLK_IS_CRITICAL)
-#define CLK_FRACN_GPPLL_INTEGER BIT(0)
-#define CLK_FRACN_GPPLL_FRACN BIT(1)
-
-/* NOTE: Rate table should be kept sorted in descending order. */
-struct imx_fracn_gppll_rate_table {
- unsigned int rate;
- unsigned int mfi;
- unsigned int mfn;
- unsigned int mfd;
- unsigned int rdiv;
- unsigned int odiv;
-};
-
-struct imx_fracn_gppll_clk {
- const struct imx_fracn_gppll_rate_table *rate_table;
- int rate_count;
- int flags;
-};
-
-struct clk *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base,
- const struct imx_fracn_gppll_clk *pll_clk);
-struct clk *imx_clk_fracn_gppll_integer(const char *name, const char *parent_name,
- void __iomem *base,
- const struct imx_fracn_gppll_clk *pll_clk);
-
-extern struct imx_fracn_gppll_clk imx_fracn_gppll;
-extern struct imx_fracn_gppll_clk imx_fracn_gppll_integer;
+#include <soc/imx/clk-fracn-gppll.h>
struct clk *imx93_clk_composite_flags(const char *name,
const char * const *parent_names,
diff --git a/include/soc/imx/clk-fracn-gppll.h b/include/soc/imx/clk-fracn-gppll.h
new file mode 100644
index 0000000000..15ab9e67ec
--- /dev/null
+++ b/include/soc/imx/clk-fracn-gppll.h
@@ -0,0 +1,144 @@
+#ifndef __SOC_IMX_CLK_FRACN_GPGPPLL_H
+#define __SOC_IMX_CLK_FRACN_GPGPPLL_H
+
+#include <linux/bitfield.h>
+#include <linux/iopoll.h>
+
+#define GPPLL_CTRL 0x0
+#define HW_CTRL_SEL BIT(16)
+#define CLKMUX_BYPASS BIT(2)
+#define CLKMUX_EN BIT(1)
+#define POWERUP_MASK BIT(0)
+
+#define GPPLL_ANA_PRG 0x10
+#define GPPLL_SPREAD_SPECTRUM 0x30
+
+#define GPPLL_NUMERATOR 0x40
+#define GPPLL_MFN_MASK GENMASK(31, 2)
+
+#define GPPLL_DENOMINATOR 0x50
+#define GPPLL_MFD_MASK GENMASK(29, 0)
+
+#define GPPLL_DIV 0x60
+#define GPPLL_MFI_MASK GENMASK(24, 16)
+#define GPPLL_RDIV_MASK GENMASK(15, 13)
+#define GPPLL_ODIV_MASK GENMASK(7, 0)
+
+#define GPPLL_DFS_CTRL(x) (0x70 + (x) * 0x10)
+
+#define GPPLL_STATUS 0xF0
+#define GPPLL_LOCK_STATUS BIT(0)
+
+#define GPPLL_DFS_STATUS 0xF4
+
+#define GPPLL_LOCK_TIMEOUT_US 200
+
+#define CLK_FRACN_GPPLL_INTEGER BIT(0)
+#define CLK_FRACN_GPPLL_FRACN BIT(1)
+
+/* NOTE: Rate table should be kept sorted in descending order. */
+struct imx_fracn_gppll_rate_table {
+ unsigned int rate;
+ unsigned int mfi;
+ unsigned int mfn;
+ unsigned int mfd;
+ unsigned int rdiv;
+ unsigned int odiv;
+};
+
+struct imx_fracn_gppll_clk {
+ const struct imx_fracn_gppll_rate_table *rate_table;
+ int rate_count;
+ int flags;
+};
+
+struct clk *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base,
+ const struct imx_fracn_gppll_clk *pll_clk);
+struct clk *imx_clk_fracn_gppll_integer(const char *name, const char *parent_name,
+ void __iomem *base,
+ const struct imx_fracn_gppll_clk *pll_clk);
+
+extern struct imx_fracn_gppll_clk imx_fracn_gppll;
+extern struct imx_fracn_gppll_clk imx_fracn_gppll_integer;
+
+static inline int fracn_gppll_wait_lock(void __iomem *base)
+{
+ u32 val;
+
+ return readl_poll_timeout(base + GPPLL_STATUS, val,
+ val & GPPLL_LOCK_STATUS, GPPLL_LOCK_TIMEOUT_US);
+}
+
+static inline const struct imx_fracn_gppll_rate_table *imx_get_gppll_settings(
+ const struct imx_fracn_gppll_rate_table *rate_table, int n_table, unsigned long rate)
+{
+ int i;
+
+ for (i = 0; i < n_table; i++)
+ if (rate == rate_table[i].rate)
+ return &rate_table[i];
+
+ return NULL;
+}
+
+static inline int fracn_gppll_set_rate(void __iomem *base, unsigned int flags,
+ const struct imx_fracn_gppll_rate_table *table, int n_table,
+ unsigned long drate)
+{
+ const struct imx_fracn_gppll_rate_table *rate;
+ u32 tmp, pll_div, ana_mfn;
+ int ret;
+
+ rate = imx_get_gppll_settings(table, n_table, drate);
+
+ /* Hardware control select disable. PLL is control by register */
+ tmp = readl_relaxed(base + GPPLL_CTRL);
+ tmp &= ~HW_CTRL_SEL;
+ writel_relaxed(tmp, base + GPPLL_CTRL);
+
+ /* Disable output */
+ tmp = readl_relaxed(base + GPPLL_CTRL);
+ tmp &= ~CLKMUX_EN;
+ writel_relaxed(tmp, base + GPPLL_CTRL);
+
+ /* Power Down */
+ tmp &= ~POWERUP_MASK;
+ writel_relaxed(tmp, base + GPPLL_CTRL);
+
+ /* Disable BYPASS */
+ tmp &= ~CLKMUX_BYPASS;
+ writel_relaxed(tmp, base + GPPLL_CTRL);
+
+ pll_div = FIELD_PREP(GPPLL_RDIV_MASK, rate->rdiv) | rate->odiv |
+ FIELD_PREP(GPPLL_MFI_MASK, rate->mfi);
+ writel_relaxed(pll_div, base + GPPLL_DIV);
+ if (flags & CLK_FRACN_GPPLL_FRACN) {
+ writel_relaxed(rate->mfd, base + GPPLL_DENOMINATOR);
+ writel_relaxed(FIELD_PREP(GPPLL_MFN_MASK, rate->mfn), base + GPPLL_NUMERATOR);
+ }
+
+ /* Wait for 5us according to fracn mode pll doc */
+ udelay(5);
+
+ /* Enable Powerup */
+ tmp |= POWERUP_MASK;
+ writel_relaxed(tmp, base + GPPLL_CTRL);
+
+ /* Wait Lock */
+ ret = fracn_gppll_wait_lock(base);
+ if (ret)
+ return ret;
+
+ /* Enable output */
+ tmp |= CLKMUX_EN;
+ writel_relaxed(tmp, base + GPPLL_CTRL);
+
+ ana_mfn = readl_relaxed(base + GPPLL_STATUS);
+ ana_mfn = FIELD_GET(GPPLL_MFN_MASK, ana_mfn);
+
+ WARN(ana_mfn != rate->mfn, "ana_mfn != rate->mfn\n");
+
+ return 0;
+}
+
+#endif /* __SOC_IMX_CLK_FRACN_GPGPPLL_H */
--
2.39.2
More information about the barebox
mailing list