All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH V3 0/4] Prepare i.MX8MM clk
@ 2019-08-09  8:02 Peng Fan
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 1/4] clk: imx: add Kconfig entry for i.MX8MM Peng Fan
                   ` (3 more replies)
  0 siblings, 4 replies; 16+ messages in thread
From: Peng Fan @ 2019-08-09  8:02 UTC (permalink / raw)
  To: u-boot

V3:
 2/4: Fix RST/BYPASS seq issue to avoid glitch
 4/4: ARM clk not use 24M for switch, use pll2_500m  Add R-b/A-b tag
      Fix pll gate shift bit.

V2:
 2/4: fix MASK/SHIFT usage

This is to support i.MX8MM clk driver.
i.MX8MM use similar clock design as i.MX7D, but it has use
different PLL, so we need to add pll14xx driver. And to simplify
the clock usage, import the composite clk driver from Linux Kernel,
then we could have simple clk tree.

This is to split the previous patchset
https://github.com/MrVan/u-boot/commits/imx8mmn-ccf
for i.MX8MM/N support

There are some checkpatch warnings that not addressed,
because import from Linux Kernel.

Peng Fan (4):
  clk: imx: add Kconfig entry for i.MX8MM
  clk: imx: add pll14xx driver
  clk: imx: add i.MX8M composite clk support
  clk: imx: add i.MX8MM clk driver

 drivers/clk/Kconfig                |   4 +-
 drivers/clk/imx/Kconfig            |  16 ++
 drivers/clk/imx/Makefile           |   2 +
 drivers/clk/imx/clk-composite-8m.c | 170 +++++++++++++++
 drivers/clk/imx/clk-imx8mm.c       | 415 +++++++++++++++++++++++++++++++++++++
 drivers/clk/imx/clk-pll14xx.c      | 381 ++++++++++++++++++++++++++++++++++
 drivers/clk/imx/clk.h              |  25 +++
 7 files changed, 1011 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clk/imx/clk-composite-8m.c
 create mode 100644 drivers/clk/imx/clk-imx8mm.c
 create mode 100644 drivers/clk/imx/clk-pll14xx.c

-- 
2.16.4

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 1/4] clk: imx: add Kconfig entry for i.MX8MM
  2019-08-09  8:02 [U-Boot] [PATCH V3 0/4] Prepare i.MX8MM clk Peng Fan
@ 2019-08-09  8:02 ` Peng Fan
  2019-08-09  8:56   ` Ye Li
  2019-08-09 16:50   ` Fabio Estevam
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 2/4] clk: imx: add pll14xx driver Peng Fan
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 16+ messages in thread
From: Peng Fan @ 2019-08-09  8:02 UTC (permalink / raw)
  To: u-boot

Add Kconfig entry for i.MX8MM

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/clk/Kconfig     |  4 ++--
 drivers/clk/imx/Kconfig | 16 ++++++++++++++++
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index a3f0171b45..fce595b4b3 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -48,7 +48,7 @@ config CLK_BOSTON
 
 config SPL_CLK_CCF
 	bool "SPL Common Clock Framework [CCF] support "
-	depends on SPL_CLK_IMX6Q
+	depends on SPL_CLK_IMX6Q || ARCH_IMX8M
 	help
 	  Enable this option if you want to (re-)use the Linux kernel's Common
 	  Clock Framework [CCF] code in U-Boot's SPL.
@@ -62,7 +62,7 @@ config SPL_CLK_COMPOSITE_CCF
 
 config CLK_CCF
 	bool "Common Clock Framework [CCF] support "
-	depends on CLK_IMX6Q || SANDBOX_CLK_CCF
+	depends on CLK_IMX6Q || ARCH_IMX8M || SANDBOX_CLK_CCF
 	help
 	  Enable this option if you want to (re-)use the Linux kernel's Common
 	  Clock Framework [CCF] code in U-Boot's clock driver.
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
index 3e6a980c8c..aae69cf9b0 100644
--- a/drivers/clk/imx/Kconfig
+++ b/drivers/clk/imx/Kconfig
@@ -20,3 +20,19 @@ config CLK_IMX8
 	select CLK
 	help
 	  This enables support clock driver for i.MX8 platforms.
+
+config SPL_CLK_IMX8MM
+	bool "SPL clock support for i.MX8MM"
+	depends on ARCH_IMX8M && SPL
+	select SPL_CLK
+	select SPL_CLK_CCF
+	help
+	  This enables SPL DM/DTS support for clock driver in i.MX8MM
+
+config CLK_IMX8MM
+	bool "Clock support for i.MX8MM"
+	depends on ARCH_IMX8M
+	select CLK
+	select CLK_CCF
+	help
+	  This enables support clock driver for i.MX8MM platforms.
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 2/4] clk: imx: add pll14xx driver
  2019-08-09  8:02 [U-Boot] [PATCH V3 0/4] Prepare i.MX8MM clk Peng Fan
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 1/4] clk: imx: add Kconfig entry for i.MX8MM Peng Fan
@ 2019-08-09  8:02 ` Peng Fan
  2019-08-09  9:05   ` Ye Li
  2019-08-09 16:51   ` Fabio Estevam
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 3/4] clk: imx: add i.MX8M composite clk support Peng Fan
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 4/4] clk: imx: add i.MX8MM clk driver Peng Fan
  3 siblings, 2 replies; 16+ messages in thread
From: Peng Fan @ 2019-08-09  8:02 UTC (permalink / raw)
  To: u-boot

Add pll14xx driver

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/clk/imx/clk-pll14xx.c | 381 ++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/imx/clk.h         |  25 +++
 2 files changed, 406 insertions(+)
 create mode 100644 drivers/clk/imx/clk-pll14xx.c

diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c
new file mode 100644
index 0000000000..2246beb21b
--- /dev/null
+++ b/drivers/clk/imx/clk-pll14xx.c
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2017-2019 NXP.
+ *
+ * Peng Fan <peng.fan@nxp.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <linux/clk-provider.h>
+#include <linux/iopoll.h>
+#include <clk.h>
+#include <div64.h>
+
+#include "clk.h"
+
+#define UBOOT_DM_CLK_IMX_PLL1443X "imx_clk_pll1443x"
+#define UBOOT_DM_CLK_IMX_PLL1416X "imx_clk_pll1416x"
+
+#define GNRL_CTL	0x0
+#define DIV_CTL		0x4
+#define LOCK_STATUS	BIT(31)
+#define LOCK_SEL_MASK	BIT(29)
+#define CLKE_MASK	BIT(11)
+#define RST_MASK	BIT(9)
+#define BYPASS_MASK	BIT(4)
+#define MDIV_SHIFT	12
+#define MDIV_MASK	GENMASK(21, 12)
+#define PDIV_SHIFT	4
+#define PDIV_MASK	GENMASK(9, 4)
+#define SDIV_SHIFT	0
+#define SDIV_MASK	GENMASK(2, 0)
+#define KDIV_SHIFT	0
+#define KDIV_MASK	GENMASK(15, 0)
+
+#define LOCK_TIMEOUT_US		10000
+
+struct clk_pll14xx {
+	struct clk			clk;
+	void __iomem			*base;
+	enum imx_pll14xx_type		type;
+	const struct imx_pll14xx_rate_table *rate_table;
+	int rate_count;
+};
+
+#define to_clk_pll14xx(_clk) container_of(_clk, struct clk_pll14xx, clk)
+
+static const struct imx_pll14xx_rate_table *imx_get_pll_settings(
+		struct clk_pll14xx *pll, unsigned long rate)
+{
+	const struct imx_pll14xx_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 unsigned long clk_pll1416x_recalc_rate(struct clk *clk)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
+	u64 fvco = clk_get_parent_rate(clk);
+	u32 mdiv, pdiv, sdiv, pll_div;
+
+	pll_div = readl(pll->base + 4);
+	mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
+	pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
+	sdiv = (pll_div & SDIV_MASK) >> SDIV_SHIFT;
+
+	fvco *= mdiv;
+	do_div(fvco, pdiv << sdiv);
+
+	return fvco;
+}
+
+static unsigned long clk_pll1443x_recalc_rate(struct clk *clk)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
+	u64 fvco = clk_get_parent_rate(clk);
+	u32 mdiv, pdiv, sdiv, pll_div_ctl0, pll_div_ctl1;
+	short int kdiv;
+
+	pll_div_ctl0 = readl(pll->base + 4);
+	pll_div_ctl1 = readl(pll->base + 8);
+	mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
+	pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
+	sdiv = (pll_div_ctl0 & SDIV_MASK) >> SDIV_SHIFT;
+	kdiv = pll_div_ctl1 & KDIV_MASK;
+
+	/* fvco = (m * 65536 + k) * Fin / (p * 65536) */
+	fvco *= (mdiv * 65536 + kdiv);
+	pdiv *= 65536;
+
+	do_div(fvco, pdiv << sdiv);
+
+	return fvco;
+}
+
+static inline bool clk_pll1416x_mp_change(const struct imx_pll14xx_rate_table *rate,
+					  u32 pll_div)
+{
+	u32 old_mdiv, old_pdiv;
+
+	old_mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
+	old_pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
+
+	return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv;
+}
+
+static inline bool clk_pll1443x_mpk_change(const struct imx_pll14xx_rate_table *rate,
+					   u32 pll_div_ctl0, u32 pll_div_ctl1)
+{
+	u32 old_mdiv, old_pdiv, old_kdiv;
+
+	old_mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
+	old_pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
+	old_kdiv = (pll_div_ctl1 & KDIV_MASK) >> KDIV_SHIFT;
+
+	return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
+		rate->kdiv != old_kdiv;
+}
+
+static inline bool clk_pll1443x_mp_change(const struct imx_pll14xx_rate_table *rate,
+					  u32 pll_div_ctl0, u32 pll_div_ctl1)
+{
+	u32 old_mdiv, old_pdiv, old_kdiv;
+
+	old_mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
+	old_pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
+	old_kdiv = (pll_div_ctl1 & KDIV_MASK) >> KDIV_SHIFT;
+
+	return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
+		rate->kdiv != old_kdiv;
+}
+
+static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
+{
+	u32 val;
+
+	return readl_poll_timeout(pll->base, val, val & LOCK_TIMEOUT_US,
+			LOCK_TIMEOUT_US);
+}
+
+static ulong clk_pll1416x_set_rate(struct clk *clk, unsigned long drate)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
+	const struct imx_pll14xx_rate_table *rate;
+	u32 tmp, div_val;
+	int ret;
+
+	rate = imx_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+		       drate, "xxxx");
+		return -EINVAL;
+	}
+
+	tmp = readl(pll->base + 4);
+
+	if (!clk_pll1416x_mp_change(rate, tmp)) {
+		tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
+		tmp |= rate->sdiv << SDIV_SHIFT;
+		writel(tmp, pll->base + 4);
+
+		return clk_pll1416x_recalc_rate(clk);
+	}
+
+	/* Bypass clock and set lock to pll output lock */
+	tmp = readl(pll->base);
+	tmp |= LOCK_SEL_MASK;
+	writel(tmp, pll->base);
+
+	/* Enable RST */
+	tmp &= ~RST_MASK;
+	writel(tmp, pll->base);
+
+	/* Enable BYPASS */
+	tmp |= BYPASS_MASK;
+	writel(tmp, pll->base);
+
+
+	div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
+		(rate->sdiv << SDIV_SHIFT);
+	writel(div_val, pll->base + 0x4);
+
+	/*
+	 * According to SPEC, t3 - t2 need to be greater than
+	 * 1us and 1/FREF, respectively.
+	 * FREF is FIN / Prediv, the prediv is [1, 63], so choose
+	 * 3us.
+	 */
+	udelay(3);
+
+	/* Disable RST */
+	tmp |= RST_MASK;
+	writel(tmp, pll->base);
+
+	/* Wait Lock */
+	ret = clk_pll14xx_wait_lock(pll);
+	if (ret)
+		return ret;
+
+	/* Bypass */
+	tmp &= ~BYPASS_MASK;
+	writel(tmp, pll->base);
+
+	return clk_pll1416x_recalc_rate(clk);
+}
+
+static ulong clk_pll1443x_set_rate(struct clk *clk, unsigned long drate)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
+	const struct imx_pll14xx_rate_table *rate;
+	u32 tmp, div_val;
+	int ret;
+
+	rate = imx_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+		       drate, "===");
+		return -EINVAL;
+	}
+
+	tmp = readl(pll->base + 4);
+	div_val = readl(pll->base + 8);
+
+	if (!clk_pll1443x_mpk_change(rate, tmp, div_val)) {
+		tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
+		tmp |= rate->sdiv << SDIV_SHIFT;
+		writel(tmp, pll->base + 4);
+
+		return clk_pll1443x_recalc_rate(clk);
+	}
+
+	tmp = readl(pll->base);
+
+	/* Enable RST */
+	tmp &= ~RST_MASK;
+	writel(tmp, pll->base);
+
+	/* Enable BYPASS */
+	tmp |= BYPASS_MASK;
+	writel(tmp, pll->base);
+
+	div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
+		(rate->sdiv << SDIV_SHIFT);
+	writel(div_val, pll->base + 0x4);
+	writel(rate->kdiv << KDIV_SHIFT, pll->base + 0x8);
+
+	/*
+	 * According to SPEC, t3 - t2 need to be greater than
+	 * 1us and 1/FREF, respectively.
+	 * FREF is FIN / Prediv, the prediv is [1, 63], so choose
+	 * 3us.
+	 */
+	udelay(3);
+
+	/* Disable RST */
+	tmp |= RST_MASK;
+	writel(tmp, pll->base);
+
+	/* Wait Lock*/
+	ret = clk_pll14xx_wait_lock(pll);
+	if (ret)
+		return ret;
+
+	/* Bypass */
+	tmp &= ~BYPASS_MASK;
+	writel(tmp, pll->base);
+
+	return clk_pll1443x_recalc_rate(clk);
+}
+
+static int clk_pll14xx_prepare(struct clk *clk)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
+	u32 val;
+
+	/*
+	 * RESETB = 1 from 0, PLL starts its normal
+	 * operation after lock time
+	 */
+	val = readl(pll->base + GNRL_CTL);
+	val |= RST_MASK;
+	writel(val, pll->base + GNRL_CTL);
+
+	return clk_pll14xx_wait_lock(pll);
+}
+
+static int clk_pll14xx_unprepare(struct clk *clk)
+{
+	struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
+	u32 val;
+
+	/*
+	 * Set RST to 0, power down mode is enabled and
+	 * every digital block is reset
+	 */
+	val = readl(pll->base + GNRL_CTL);
+	val &= ~RST_MASK;
+	writel(val, pll->base + GNRL_CTL);
+
+	return 0;
+}
+
+static const struct clk_ops clk_pll1416x_ops = {
+	.enable		= clk_pll14xx_prepare,
+	.disable	= clk_pll14xx_unprepare,
+	.set_rate	= clk_pll1416x_set_rate,
+	.get_rate	= clk_pll1416x_recalc_rate,
+};
+
+static const struct clk_ops clk_pll1443x_ops = {
+	.enable		= clk_pll14xx_prepare,
+	.disable	= clk_pll14xx_unprepare,
+	.set_rate	= clk_pll1443x_set_rate,
+	.get_rate	= clk_pll1443x_recalc_rate,
+};
+
+struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
+			    void __iomem *base,
+			    const struct imx_pll14xx_clk *pll_clk)
+{
+	struct clk_pll14xx *pll;
+	struct clk *clk;
+	char *type_name;
+	int ret;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	switch (pll_clk->type) {
+	case PLL_1416X:
+		type_name = UBOOT_DM_CLK_IMX_PLL1416X;
+		break;
+	case PLL_1443X:
+		type_name = UBOOT_DM_CLK_IMX_PLL1443X;
+		break;
+	default:
+		pr_err("%s: Unknown pll type for pll clk %s\n",
+		       __func__, name);
+		return ERR_PTR(-EINVAL);
+	};
+
+	pll->base = base;
+	pll->type = pll_clk->type;
+	pll->rate_table = pll_clk->rate_table;
+	pll->rate_count = pll_clk->rate_count;
+
+	clk = &pll->clk;
+
+	ret = clk_register(clk, type_name, name, parent_name);
+	if (ret) {
+		pr_err("%s: failed to register pll %s %d\n",
+		       __func__, name, ret);
+		kfree(pll);
+		return ERR_PTR(ret);
+	}
+
+	return clk;
+}
+
+U_BOOT_DRIVER(clk_pll1443x) = {
+	.name	= UBOOT_DM_CLK_IMX_PLL1443X,
+	.id	= UCLASS_CLK,
+	.ops	= &clk_pll1443x_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(clk_pll1416x) = {
+	.name	= UBOOT_DM_CLK_IMX_PLL1416X,
+	.id	= UCLASS_CLK,
+	.ops	= &clk_pll1416x_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 1d480d8722..4956e04a92 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -20,6 +20,31 @@ enum imx_pllv3_type {
 	IMX_PLLV3_DDR_IMX7,
 };
 
+enum imx_pll14xx_type {
+	PLL_1416X,
+	PLL_1443X,
+};
+
+/* NOTE: Rate table should be kept sorted in descending order. */
+struct imx_pll14xx_rate_table {
+	unsigned int rate;
+	unsigned int pdiv;
+	unsigned int mdiv;
+	unsigned int sdiv;
+	unsigned int kdiv;
+};
+
+struct imx_pll14xx_clk {
+	enum imx_pll14xx_type type;
+	const struct imx_pll14xx_rate_table *rate_table;
+	int rate_count;
+	int flags;
+};
+
+struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
+			    void __iomem *base,
+			    const struct imx_pll14xx_clk *pll_clk);
+
 struct clk *clk_register_gate2(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 bit_idx, u8 cgr_val,
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 3/4] clk: imx: add i.MX8M composite clk support
  2019-08-09  8:02 [U-Boot] [PATCH V3 0/4] Prepare i.MX8MM clk Peng Fan
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 1/4] clk: imx: add Kconfig entry for i.MX8MM Peng Fan
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 2/4] clk: imx: add pll14xx driver Peng Fan
@ 2019-08-09  8:02 ` Peng Fan
  2019-08-09  9:08   ` Ye Li
  2019-08-09 16:59   ` Fabio Estevam
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 4/4] clk: imx: add i.MX8MM clk driver Peng Fan
  3 siblings, 2 replies; 16+ messages in thread
From: Peng Fan @ 2019-08-09  8:02 UTC (permalink / raw)
  To: u-boot

Import i.MX8M composite clk from Linux Kernel 5.3.0-rc2

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/clk/imx/clk-composite-8m.c | 170 +++++++++++++++++++++++++++++++++++++
 1 file changed, 170 insertions(+)
 create mode 100644 drivers/clk/imx/clk-composite-8m.c

diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c
new file mode 100644
index 0000000000..57ebbc3bb0
--- /dev/null
+++ b/drivers/clk/imx/clk-composite-8m.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <clk-uclass.h>
+#include <dm/device.h>
+#include <linux/clk-provider.h>
+#include <clk.h>
+#include "clk.h"
+
+#define UBOOT_DM_CLK_IMX_COMPOSITE "imx_clk_composite"
+
+#define PCG_PREDIV_SHIFT	16
+#define PCG_PREDIV_WIDTH	3
+#define PCG_PREDIV_MAX		8
+
+#define PCG_DIV_SHIFT		0
+#define PCG_DIV_WIDTH		6
+#define PCG_DIV_MAX		64
+
+#define PCG_PCS_SHIFT		24
+#define PCG_PCS_MASK		0x7
+
+#define PCG_CGC_SHIFT		28
+
+static unsigned long imx8m_clk_composite_divider_recalc_rate(struct clk *clk)
+{
+	struct clk_divider *divider = (struct clk_divider *)to_clk_divider(clk);
+	struct clk_composite *composite = (struct clk_composite *)clk->data;
+	ulong parent_rate = clk_get_parent_rate(&composite->clk);
+	unsigned long prediv_rate;
+	unsigned int prediv_value;
+	unsigned int div_value;
+
+	debug("%s: name %s prate: %lu reg: %p\n", __func__,
+	      (&composite->clk)->dev->name, parent_rate, divider->reg);
+	prediv_value = readl(divider->reg) >> divider->shift;
+	prediv_value &= clk_div_mask(divider->width);
+
+	prediv_rate = divider_recalc_rate(clk, parent_rate, prediv_value,
+					  NULL, divider->flags,
+					  divider->width);
+
+	div_value = readl(divider->reg) >> PCG_DIV_SHIFT;
+	div_value &= clk_div_mask(PCG_DIV_WIDTH);
+
+	return divider_recalc_rate(clk, prediv_rate, div_value, NULL,
+				   divider->flags, PCG_DIV_WIDTH);
+}
+
+static int imx8m_clk_composite_compute_dividers(unsigned long rate,
+						unsigned long parent_rate,
+						int *prediv, int *postdiv)
+{
+	int div1, div2;
+	int error = INT_MAX;
+	int ret = -EINVAL;
+
+	*prediv = 1;
+	*postdiv = 1;
+
+	for (div1 = 1; div1 <= PCG_PREDIV_MAX; div1++) {
+		for (div2 = 1; div2 <= PCG_DIV_MAX; div2++) {
+			int new_error = ((parent_rate / div1) / div2) - rate;
+
+			if (abs(new_error) < abs(error)) {
+				*prediv = div1;
+				*postdiv = div2;
+				error = new_error;
+				ret = 0;
+			}
+		}
+	}
+	return ret;
+}
+
+/*
+ * The clk are not binded to a dev, because it is part of composite clk
+ * use composite clk to get dev
+ */
+static ulong imx8m_clk_composite_divider_set_rate(struct clk *clk,
+						  unsigned long rate)
+{
+	struct clk_divider *divider = (struct clk_divider *)to_clk_divider(clk);
+	struct clk_composite *composite = (struct clk_composite *)clk->data;
+	ulong parent_rate = clk_get_parent_rate(&composite->clk);
+	int prediv_value;
+	int div_value;
+	int ret;
+	u32 val;
+
+	ret = imx8m_clk_composite_compute_dividers(rate, parent_rate,
+						   &prediv_value, &div_value);
+	if (ret)
+		return -EINVAL;
+
+	val = readl(divider->reg);
+	val &= ~((clk_div_mask(divider->width) << divider->shift) |
+			(clk_div_mask(PCG_DIV_WIDTH) << PCG_DIV_SHIFT));
+
+	val |= (u32)(prediv_value  - 1) << divider->shift;
+	val |= (u32)(div_value - 1) << PCG_DIV_SHIFT;
+	writel(val, divider->reg);
+
+	return clk_get_rate(&composite->clk);
+}
+
+static const struct clk_ops imx8m_clk_composite_divider_ops = {
+	.get_rate = imx8m_clk_composite_divider_recalc_rate,
+	.set_rate = imx8m_clk_composite_divider_set_rate,
+};
+
+struct clk *imx8m_clk_composite_flags(const char *name,
+				      const char * const *parent_names,
+				      int num_parents, void __iomem *reg,
+				      unsigned long flags)
+{
+	struct clk *clk = ERR_PTR(-ENOMEM);
+	struct clk_divider *div = NULL;
+	struct clk_gate *gate = NULL;
+	struct clk_mux *mux = NULL;
+
+	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+	if (!mux)
+		goto fail;
+
+	mux->reg = reg;
+	mux->shift = PCG_PCS_SHIFT;
+	mux->mask = PCG_PCS_MASK;
+	mux->num_parents = num_parents;
+	mux->flags = flags;
+	mux->parent_names = parent_names;
+
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		goto fail;
+
+	div->reg = reg;
+	div->shift = PCG_PREDIV_SHIFT;
+	div->width = PCG_PREDIV_WIDTH;
+	div->flags = CLK_DIVIDER_ROUND_CLOSEST | flags;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		goto fail;
+
+	gate->reg = reg;
+	gate->bit_idx = PCG_CGC_SHIFT;
+	gate->flags = flags;
+
+	clk = clk_register_composite(NULL, name,
+				     parent_names, num_parents,
+				     &mux->clk, &clk_mux_ops, &div->clk,
+				     &imx8m_clk_composite_divider_ops,
+				     &gate->clk, &clk_gate_ops, flags);
+	if (IS_ERR(clk))
+		goto fail;
+
+	return clk;
+
+fail:
+	kfree(gate);
+	kfree(div);
+	kfree(mux);
+	return ERR_CAST(clk);
+}
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 4/4] clk: imx: add i.MX8MM clk driver
  2019-08-09  8:02 [U-Boot] [PATCH V3 0/4] Prepare i.MX8MM clk Peng Fan
                   ` (2 preceding siblings ...)
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 3/4] clk: imx: add i.MX8M composite clk support Peng Fan
@ 2019-08-09  8:02 ` Peng Fan
  2019-08-09  9:10   ` Ye Li
  2019-08-09 21:02   ` Fabio Estevam
  3 siblings, 2 replies; 16+ messages in thread
From: Peng Fan @ 2019-08-09  8:02 UTC (permalink / raw)
  To: u-boot

Add i.MX8MM clk driver support.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/clk/imx/Makefile     |   2 +
 drivers/clk/imx/clk-imx8mm.c | 415 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 417 insertions(+)
 create mode 100644 drivers/clk/imx/clk-imx8mm.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 105a58ca90..5ad7967fe9 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -10,3 +10,5 @@ ifdef CONFIG_CLK_IMX8
 obj-$(CONFIG_IMX8QXP) += clk-imx8qxp.o
 obj-$(CONFIG_IMX8QM) += clk-imx8qm.o
 endif
+obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MM) += clk-imx8mm.o clk-pll14xx.o \
+				clk-composite-8m.o
diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
new file mode 100644
index 0000000000..a2a85b6a1a
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -0,0 +1,415 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 NXP
+ * Peng Fan <peng.fan@nxp.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <dt-bindings/clock/imx8mm-clock.h>
+
+#include "clk.h"
+
+#define PLL_1416X_RATE(_rate, _m, _p, _s)		\
+	{						\
+		.rate	=	(_rate),		\
+		.mdiv	=	(_m),			\
+		.pdiv	=	(_p),			\
+		.sdiv	=	(_s),			\
+	}
+
+#define PLL_1443X_RATE(_rate, _m, _p, _s, _k)		\
+	{						\
+		.rate	=	(_rate),		\
+		.mdiv	=	(_m),			\
+		.pdiv	=	(_p),			\
+		.sdiv	=	(_s),			\
+		.kdiv	=	(_k),			\
+	}
+
+static const struct imx_pll14xx_rate_table imx8mm_pll1416x_tbl[] = {
+	PLL_1416X_RATE(1800000000U, 225, 3, 0),
+	PLL_1416X_RATE(1600000000U, 200, 3, 0),
+	PLL_1416X_RATE(1200000000U, 300, 3, 1),
+	PLL_1416X_RATE(1000000000U, 250, 3, 1),
+	PLL_1416X_RATE(800000000U,  200, 3, 1),
+	PLL_1416X_RATE(750000000U,  250, 2, 2),
+	PLL_1416X_RATE(700000000U,  350, 3, 2),
+	PLL_1416X_RATE(600000000U,  300, 3, 2),
+};
+
+static const struct imx_pll14xx_rate_table imx8mm_drampll_tbl[] = {
+	PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
+};
+
+static struct imx_pll14xx_clk imx8mm_dram_pll __initdata = {
+		.type = PLL_1443X,
+		.rate_table = imx8mm_drampll_tbl,
+		.rate_count = ARRAY_SIZE(imx8mm_drampll_tbl),
+};
+
+static struct imx_pll14xx_clk imx8mm_arm_pll __initdata = {
+		.type = PLL_1416X,
+		.rate_table = imx8mm_pll1416x_tbl,
+		.rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
+};
+
+static struct imx_pll14xx_clk imx8mm_sys_pll __initdata = {
+		.type = PLL_1416X,
+		.rate_table = imx8mm_pll1416x_tbl,
+		.rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
+};
+
+static const char *pll_ref_sels[] = { "clock-osc-24m", "dummy", "dummy", "dummy", };
+static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
+static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char *sys_pll1_bypass_sels[] = {"sys_pll1", "sys_pll1_ref_sel", };
+static const char *sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", };
+static const char *sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
+
+static const char *imx8mm_a53_sels[] = {"clock-osc-24m", "arm_pll_out", "sys_pll2_500m", "sys_pll2_1000m",
+					"sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "sys_pll3_out", };
+
+static const char *imx8mm_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m", "sys_pll1_400m",
+					"sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", };
+
+static const char *imx8mm_enet_axi_sels[] = {"clock-osc-24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_250m",
+					     "sys_pll2_200m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", };
+
+static const char *imx8mm_nand_usdhc_sels[] = {"clock-osc-24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_200m",
+					       "sys_pll1_133m", "sys_pll3_out", "sys_pll2_250m", "audio_pll1_out", };
+
+static const char *imx8mm_usdhc1_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+					   "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
+
+static const char *imx8mm_usdhc2_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+					   "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
+
+static const char *imx8mm_i2c1_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_i2c2_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_i2c3_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_i2c4_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_wdog_sels[] = {"clock-osc-24m", "sys_pll1_133m", "sys_pll1_160m", "vpu_pll_out",
+					 "sys_pll2_125m", "sys_pll3_out", "sys_pll1_80m", "sys_pll2_166m", };
+
+static const char *imx8mm_usdhc3_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+					   "sys_pll3_out", "sys_pll1_266m", "audio_pll2_clk", "sys_pll1_100m", };
+
+static ulong imx8mm_clk_get_rate(struct clk *clk)
+{
+	struct clk *c;
+	int ret;
+
+	debug("%s(#%lu)\n", __func__, clk->id);
+
+	ret = clk_get_by_id(clk->id, &c);
+	if (ret)
+		return ret;
+
+	return clk_get_rate(c);
+}
+
+static ulong imx8mm_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk *c;
+	int ret = 0;
+
+	debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
+
+	ret = clk_get_by_id(clk->id, &c);
+	if (ret)
+		return ret;
+
+	return clk_set_rate(c, rate);
+}
+
+static int __imx8mm_clk_enable(struct clk *clk, bool enable)
+{
+	struct clk *c;
+	int ret = 0;
+
+	debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
+
+	ret = clk_get_by_id(clk->id, &c);
+	if (ret)
+		return ret;
+
+	if (enable)
+		ret = clk_enable(c);
+	else
+		ret = clk_disable(c);
+
+	return ret;
+}
+
+static int imx8mm_clk_disable(struct clk *clk)
+{
+	return __imx8mm_clk_enable(clk, 0);
+}
+
+static int imx8mm_clk_enable(struct clk *clk)
+{
+	return __imx8mm_clk_enable(clk, 1);
+}
+
+static struct clk_ops imx8mm_clk_ops = {
+	.set_rate = imx8mm_clk_set_rate,
+	.get_rate = imx8mm_clk_get_rate,
+	.enable = imx8mm_clk_enable,
+	.disable = imx8mm_clk_disable,
+};
+
+static int imx8mm_clk_probe(struct udevice *dev)
+{
+	void __iomem *base;
+
+	base = (void *)ANATOP_BASE_ADDR;
+
+	clk_dm(IMX8MM_DRAM_PLL_REF_SEL,
+	       imx_clk_mux("dram_pll_ref_sel", base + 0x50, 0, 2,
+			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
+	clk_dm(IMX8MM_ARM_PLL_REF_SEL,
+	       imx_clk_mux("arm_pll_ref_sel", base + 0x84, 0, 2,
+			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
+	clk_dm(IMX8MM_SYS_PLL1_REF_SEL,
+	       imx_clk_mux("sys_pll1_ref_sel", base + 0x94, 0, 2,
+			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
+	clk_dm(IMX8MM_SYS_PLL2_REF_SEL,
+	       imx_clk_mux("sys_pll2_ref_sel", base + 0x104, 0, 2,
+			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
+	clk_dm(IMX8MM_SYS_PLL3_REF_SEL,
+	       imx_clk_mux("sys_pll3_ref_sel", base + 0x114, 0, 2,
+			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
+
+	clk_dm(IMX8MM_DRAM_PLL,
+	       imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel",
+			       base + 0x50, &imx8mm_dram_pll));
+	clk_dm(IMX8MM_ARM_PLL,
+	       imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel",
+			       base + 0x84, &imx8mm_arm_pll));
+	clk_dm(IMX8MM_SYS_PLL1,
+	       imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel",
+			       base + 0x94, &imx8mm_sys_pll));
+	clk_dm(IMX8MM_SYS_PLL2,
+	       imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel",
+			       base + 0x104, &imx8mm_sys_pll));
+	clk_dm(IMX8MM_SYS_PLL3,
+	       imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel",
+			       base + 0x114, &imx8mm_sys_pll));
+
+	/* PLL bypass out */
+	clk_dm(IMX8MM_DRAM_PLL_BYPASS,
+	       imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 4, 1,
+				 dram_pll_bypass_sels,
+				 ARRAY_SIZE(dram_pll_bypass_sels),
+				 CLK_SET_RATE_PARENT));
+	clk_dm(IMX8MM_ARM_PLL_BYPASS,
+	       imx_clk_mux_flags("arm_pll_bypass", base + 0x84, 4, 1,
+				 arm_pll_bypass_sels,
+				 ARRAY_SIZE(arm_pll_bypass_sels),
+				 CLK_SET_RATE_PARENT));
+	clk_dm(IMX8MM_SYS_PLL1_BYPASS,
+	       imx_clk_mux_flags("sys_pll1_bypass", base + 0x94, 4, 1,
+				 sys_pll1_bypass_sels,
+				 ARRAY_SIZE(sys_pll1_bypass_sels),
+				 CLK_SET_RATE_PARENT));
+	clk_dm(IMX8MM_SYS_PLL2_BYPASS,
+	       imx_clk_mux_flags("sys_pll2_bypass", base + 0x104, 4, 1,
+				 sys_pll2_bypass_sels,
+				 ARRAY_SIZE(sys_pll2_bypass_sels),
+				 CLK_SET_RATE_PARENT));
+	clk_dm(IMX8MM_SYS_PLL3_BYPASS,
+	       imx_clk_mux_flags("sys_pll3_bypass", base + 0x114, 4, 1,
+				 sys_pll3_bypass_sels,
+				 ARRAY_SIZE(sys_pll3_bypass_sels),
+				 CLK_SET_RATE_PARENT));
+
+	/* PLL out gate */
+	clk_dm(IMX8MM_DRAM_PLL_OUT,
+	       imx_clk_gate("dram_pll_out", "dram_pll_bypass",
+			    base + 0x50, 13));
+	clk_dm(IMX8MM_ARM_PLL_OUT,
+	       imx_clk_gate("arm_pll_out", "arm_pll_bypass",
+			    base + 0x84, 11));
+	clk_dm(IMX8MM_SYS_PLL1_OUT,
+	       imx_clk_gate("sys_pll1_out", "sys_pll1_bypass",
+			    base + 0x94, 11));
+	clk_dm(IMX8MM_SYS_PLL2_OUT,
+	       imx_clk_gate("sys_pll2_out", "sys_pll2_bypass",
+			    base + 0x104, 11));
+	clk_dm(IMX8MM_SYS_PLL3_OUT,
+	       imx_clk_gate("sys_pll3_out", "sys_pll3_bypass",
+			    base + 0x114, 11));
+
+	/* SYS PLL fixed output */
+	clk_dm(IMX8MM_SYS_PLL1_40M,
+	       imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20));
+	clk_dm(IMX8MM_SYS_PLL1_80M,
+	       imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10));
+	clk_dm(IMX8MM_SYS_PLL1_100M,
+	       imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8));
+	clk_dm(IMX8MM_SYS_PLL1_133M,
+	       imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6));
+	clk_dm(IMX8MM_SYS_PLL1_160M,
+	       imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5));
+	clk_dm(IMX8MM_SYS_PLL1_200M,
+	       imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4));
+	clk_dm(IMX8MM_SYS_PLL1_266M,
+	       imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3));
+	clk_dm(IMX8MM_SYS_PLL1_400M,
+	       imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2));
+	clk_dm(IMX8MM_SYS_PLL1_800M,
+	       imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1));
+
+	clk_dm(IMX8MM_SYS_PLL2_50M,
+	       imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20));
+	clk_dm(IMX8MM_SYS_PLL2_100M,
+	       imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10));
+	clk_dm(IMX8MM_SYS_PLL2_125M,
+	       imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8));
+	clk_dm(IMX8MM_SYS_PLL2_166M,
+	       imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6));
+	clk_dm(IMX8MM_SYS_PLL2_200M,
+	       imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5));
+	clk_dm(IMX8MM_SYS_PLL2_250M,
+	       imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4));
+	clk_dm(IMX8MM_SYS_PLL2_333M,
+	       imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3));
+	clk_dm(IMX8MM_SYS_PLL2_500M,
+	       imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2));
+	clk_dm(IMX8MM_SYS_PLL2_1000M,
+	       imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1));
+
+	base = dev_read_addr_ptr(dev);
+	if (base == (void *)FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	clk_dm(IMX8MM_CLK_A53_SRC,
+	       imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3,
+			    imx8mm_a53_sels, ARRAY_SIZE(imx8mm_a53_sels)));
+	clk_dm(IMX8MM_CLK_A53_CG,
+	       imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28));
+	clk_dm(IMX8MM_CLK_A53_DIV,
+	       imx_clk_divider2("arm_a53_div", "arm_a53_cg",
+				base + 0x8000, 0, 3));
+
+	clk_dm(IMX8MM_CLK_AHB,
+	       imx8m_clk_composite_critical("ahb", imx8mm_ahb_sels,
+					    base + 0x9000));
+	clk_dm(IMX8MM_CLK_IPG_ROOT,
+	       imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1));
+
+	clk_dm(IMX8MM_CLK_ENET_AXI,
+	       imx8m_clk_composite("enet_axi", imx8mm_enet_axi_sels,
+				   base + 0x8880));
+	clk_dm(IMX8MM_CLK_NAND_USDHC_BUS,
+	       imx8m_clk_composite_critical("nand_usdhc_bus",
+					    imx8mm_nand_usdhc_sels,
+					    base + 0x8900));
+
+	/* IP */
+	clk_dm(IMX8MM_CLK_USDHC1,
+	       imx8m_clk_composite("usdhc1", imx8mm_usdhc1_sels,
+				   base + 0xac00));
+	clk_dm(IMX8MM_CLK_USDHC2,
+	       imx8m_clk_composite("usdhc2", imx8mm_usdhc2_sels,
+				   base + 0xac80));
+	clk_dm(IMX8MM_CLK_I2C1,
+	       imx8m_clk_composite("i2c1", imx8mm_i2c1_sels, base + 0xad00));
+	clk_dm(IMX8MM_CLK_I2C2,
+	       imx8m_clk_composite("i2c2", imx8mm_i2c2_sels, base + 0xad80));
+	clk_dm(IMX8MM_CLK_I2C3,
+	       imx8m_clk_composite("i2c3", imx8mm_i2c3_sels, base + 0xae00));
+	clk_dm(IMX8MM_CLK_I2C4,
+	       imx8m_clk_composite("i2c4", imx8mm_i2c4_sels, base + 0xae80));
+	clk_dm(IMX8MM_CLK_WDOG,
+	       imx8m_clk_composite("wdog", imx8mm_wdog_sels, base + 0xb900));
+	clk_dm(IMX8MM_CLK_USDHC3,
+	       imx8m_clk_composite("usdhc3", imx8mm_usdhc3_sels,
+				   base + 0xbc80));
+
+	clk_dm(IMX8MM_CLK_I2C1_ROOT,
+	       imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0));
+	clk_dm(IMX8MM_CLK_I2C2_ROOT,
+	       imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0));
+	clk_dm(IMX8MM_CLK_I2C3_ROOT,
+	       imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0));
+	clk_dm(IMX8MM_CLK_I2C4_ROOT,
+	       imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0));
+	clk_dm(IMX8MM_CLK_OCOTP_ROOT,
+	       imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0));
+	clk_dm(IMX8MM_CLK_USDHC1_ROOT,
+	       imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0));
+	clk_dm(IMX8MM_CLK_USDHC2_ROOT,
+	       imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0));
+	clk_dm(IMX8MM_CLK_WDOG1_ROOT,
+	       imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0));
+	clk_dm(IMX8MM_CLK_WDOG2_ROOT,
+	       imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0));
+	clk_dm(IMX8MM_CLK_WDOG3_ROOT,
+	       imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0));
+	clk_dm(IMX8MM_CLK_USDHC3_ROOT,
+	       imx_clk_gate4("usdhc3_root_clk", "usdhc3", base + 0x45e0, 0));
+
+#ifdef CONFIG_SPL_BUILD
+	struct clk *clkp, *clkp1;
+
+	clk_get_by_id(IMX8MM_CLK_WDOG1_ROOT, &clkp);
+	clk_enable(clkp);
+	clk_get_by_id(IMX8MM_CLK_WDOG2_ROOT, &clkp);
+	clk_enable(clkp);
+	clk_get_by_id(IMX8MM_CLK_WDOG3_ROOT, &clkp);
+	clk_enable(clkp);
+
+	/* Configure SYS_PLL3 to 750MHz */
+	clk_get_by_id(IMX8MM_SYS_PLL3, &clkp);
+	clk_set_rate(clkp, 750000000UL);
+	clk_enable(clkp);
+
+	/* Configure ARM to sys_pll2_500m */
+	clk_get_by_id(IMX8MM_CLK_A53_SRC, &clkp);
+	clk_get_by_id(IMX8MM_SYS_PLL2_OUT, &clkp1);
+	clk_enable(clkp1);
+	clk_get_by_id(IMX8MM_SYS_PLL2_500M, &clkp1);
+	clk_set_parent(clkp, clkp1);
+
+	/* Configure ARM PLL to 1.2GHz */
+	clk_get_by_id(IMX8MM_ARM_PLL, &clkp1);
+	clk_set_rate(clkp1, 1200000000UL);
+	clk_get_by_id(IMX8MM_ARM_PLL_OUT, &clkp1);
+	clk_enable(clkp1);
+	clk_set_parent(clkp, clkp1);
+
+	/* Configure DIV to 1.2GHz */
+	clk_get_by_id(IMX8MM_CLK_A53_DIV, &clkp1);
+	clk_set_rate(clkp1, 1200000000UL);
+#endif
+
+	return 0;
+}
+
+static const struct udevice_id imx8mm_clk_ids[] = {
+	{ .compatible = "fsl,imx8mm-ccm" },
+	{ },
+};
+
+U_BOOT_DRIVER(imx8mm_clk) = {
+	.name = "clk_imx8mm",
+	.id = UCLASS_CLK,
+	.of_match = imx8mm_clk_ids,
+	.ops = &imx8mm_clk_ops,
+	.probe = imx8mm_clk_probe,
+	.flags = DM_FLAG_PRE_RELOC,
+};
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 1/4] clk: imx: add Kconfig entry for i.MX8MM
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 1/4] clk: imx: add Kconfig entry for i.MX8MM Peng Fan
@ 2019-08-09  8:56   ` Ye Li
  2019-08-09 16:50   ` Fabio Estevam
  1 sibling, 0 replies; 16+ messages in thread
From: Ye Li @ 2019-08-09  8:56 UTC (permalink / raw)
  To: u-boot

> Add Kconfig entry for i.MX8MM
> 
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
>  drivers/clk/Kconfig     |  4 ++--
>  drivers/clk/imx/Kconfig | 16 ++++++++++++++++
>  2 files changed, 18 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index a3f0171b45..fce595b4b3 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -48,7 +48,7 @@ config CLK_BOSTON
>  
>  config SPL_CLK_CCF
>  	bool "SPL Common Clock Framework [CCF] support "
> -	depends on SPL_CLK_IMX6Q
> +	depends on SPL_CLK_IMX6Q || ARCH_IMX8M
>  	help
>  	  Enable this option if you want to (re-)use the Linux kernel's Common
>  	  Clock Framework [CCF] code in U-Boot's SPL.
> @@ -62,7 +62,7 @@ config SPL_CLK_COMPOSITE_CCF
>  
>  config CLK_CCF
>  	bool "Common Clock Framework [CCF] support "
> -	depends on CLK_IMX6Q || SANDBOX_CLK_CCF
> +	depends on CLK_IMX6Q || ARCH_IMX8M || SANDBOX_CLK_CCF
>  	help
>  	  Enable this option if you want to (re-)use the Linux kernel's Common
>  	  Clock Framework [CCF] code in U-Boot's clock driver.
> diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
> index 3e6a980c8c..aae69cf9b0 100644
> --- a/drivers/clk/imx/Kconfig
> +++ b/drivers/clk/imx/Kconfig
> @@ -20,3 +20,19 @@ config CLK_IMX8
>  	select CLK
>  	help
>  	  This enables support clock driver for i.MX8 platforms.
> +
> +config SPL_CLK_IMX8MM
> +	bool "SPL clock support for i.MX8MM"
> +	depends on ARCH_IMX8M && SPL
> +	select SPL_CLK
> +	select SPL_CLK_CCF
> +	help
> +	  This enables SPL DM/DTS support for clock driver in i.MX8MM
> +
> +config CLK_IMX8MM
> +	bool "Clock support for i.MX8MM"
> +	depends on ARCH_IMX8M
> +	select CLK
> +	select CLK_CCF
> +	help
> +	  This enables support clock driver for i.MX8MM platforms.
> 
Reviewed-by: Ye Li <ye.li@nxp.com>

Best regards,
Ye Li

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 2/4] clk: imx: add pll14xx driver
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 2/4] clk: imx: add pll14xx driver Peng Fan
@ 2019-08-09  9:05   ` Ye Li
  2019-08-09 16:51   ` Fabio Estevam
  1 sibling, 0 replies; 16+ messages in thread
From: Ye Li @ 2019-08-09  9:05 UTC (permalink / raw)
  To: u-boot

> Add pll14xx driver
> 
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
>  drivers/clk/imx/clk-pll14xx.c | 381 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/imx/clk.h         |  25 +++
>  2 files changed, 406 insertions(+)
>  create mode 100644 drivers/clk/imx/clk-pll14xx.c
> 
> diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c
> new file mode 100644
> index 0000000000..2246beb21b
> --- /dev/null
> +++ b/drivers/clk/imx/clk-pll14xx.c
> @@ -0,0 +1,381 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2017-2019 NXP.
> + *
> + * Peng Fan <peng.fan@nxp.com>
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <malloc.h>
> +#include <clk-uclass.h>
> +#include <dm/device.h>
> +#include <linux/clk-provider.h>
> +#include <linux/iopoll.h>
> +#include <clk.h>
> +#include <div64.h>
> +
> +#include "clk.h"
> +
> +#define UBOOT_DM_CLK_IMX_PLL1443X "imx_clk_pll1443x"
> +#define UBOOT_DM_CLK_IMX_PLL1416X "imx_clk_pll1416x"
> +
> +#define GNRL_CTL	0x0
> +#define DIV_CTL		0x4
> +#define LOCK_STATUS	BIT(31)
> +#define LOCK_SEL_MASK	BIT(29)
> +#define CLKE_MASK	BIT(11)
> +#define RST_MASK	BIT(9)
> +#define BYPASS_MASK	BIT(4)
> +#define MDIV_SHIFT	12
> +#define MDIV_MASK	GENMASK(21, 12)
> +#define PDIV_SHIFT	4
> +#define PDIV_MASK	GENMASK(9, 4)
> +#define SDIV_SHIFT	0
> +#define SDIV_MASK	GENMASK(2, 0)
> +#define KDIV_SHIFT	0
> +#define KDIV_MASK	GENMASK(15, 0)
> +
> +#define LOCK_TIMEOUT_US		10000
> +
> +struct clk_pll14xx {
> +	struct clk			clk;
> +	void __iomem			*base;
> +	enum imx_pll14xx_type		type;
> +	const struct imx_pll14xx_rate_table *rate_table;
> +	int rate_count;
> +};
> +
> +#define to_clk_pll14xx(_clk) container_of(_clk, struct clk_pll14xx, clk)
> +
> +static const struct imx_pll14xx_rate_table *imx_get_pll_settings(
> +		struct clk_pll14xx *pll, unsigned long rate)
> +{
> +	const struct imx_pll14xx_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 unsigned long clk_pll1416x_recalc_rate(struct clk *clk)
> +{
> +	struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
> +	u64 fvco = clk_get_parent_rate(clk);
> +	u32 mdiv, pdiv, sdiv, pll_div;
> +
> +	pll_div = readl(pll->base + 4);
> +	mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
> +	pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
> +	sdiv = (pll_div & SDIV_MASK) >> SDIV_SHIFT;
> +
> +	fvco *= mdiv;
> +	do_div(fvco, pdiv << sdiv);
> +
> +	return fvco;
> +}
> +
> +static unsigned long clk_pll1443x_recalc_rate(struct clk *clk)
> +{
> +	struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
> +	u64 fvco = clk_get_parent_rate(clk);
> +	u32 mdiv, pdiv, sdiv, pll_div_ctl0, pll_div_ctl1;
> +	short int kdiv;
> +
> +	pll_div_ctl0 = readl(pll->base + 4);
> +	pll_div_ctl1 = readl(pll->base + 8);
> +	mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
> +	pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
> +	sdiv = (pll_div_ctl0 & SDIV_MASK) >> SDIV_SHIFT;
> +	kdiv = pll_div_ctl1 & KDIV_MASK;
> +
> +	/* fvco = (m * 65536 + k) * Fin / (p * 65536) */
> +	fvco *= (mdiv * 65536 + kdiv);
> +	pdiv *= 65536;
> +
> +	do_div(fvco, pdiv << sdiv);
> +
> +	return fvco;
> +}
> +
> +static inline bool clk_pll1416x_mp_change(const struct imx_pll14xx_rate_table *rate,
> +					  u32 pll_div)
> +{
> +	u32 old_mdiv, old_pdiv;
> +
> +	old_mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
> +	old_pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
> +
> +	return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv;
> +}
> +
> +static inline bool clk_pll1443x_mpk_change(const struct imx_pll14xx_rate_table *rate,
> +					   u32 pll_div_ctl0, u32 pll_div_ctl1)
> +{
> +	u32 old_mdiv, old_pdiv, old_kdiv;
> +
> +	old_mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
> +	old_pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
> +	old_kdiv = (pll_div_ctl1 & KDIV_MASK) >> KDIV_SHIFT;
> +
> +	return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
> +		rate->kdiv != old_kdiv;
> +}
> +
> +static inline bool clk_pll1443x_mp_change(const struct imx_pll14xx_rate_table *rate,
> +					  u32 pll_div_ctl0, u32 pll_div_ctl1)
> +{
> +	u32 old_mdiv, old_pdiv, old_kdiv;
> +
> +	old_mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
> +	old_pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
> +	old_kdiv = (pll_div_ctl1 & KDIV_MASK) >> KDIV_SHIFT;
> +
> +	return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
> +		rate->kdiv != old_kdiv;
> +}
> +
> +static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
> +{
> +	u32 val;
> +
> +	return readl_poll_timeout(pll->base, val, val & LOCK_TIMEOUT_US,
> +			LOCK_TIMEOUT_US);
> +}
> +
> +static ulong clk_pll1416x_set_rate(struct clk *clk, unsigned long drate)
> +{
> +	struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
> +	const struct imx_pll14xx_rate_table *rate;
> +	u32 tmp, div_val;
> +	int ret;
> +
> +	rate = imx_get_pll_settings(pll, drate);
> +	if (!rate) {
> +		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
> +		       drate, "xxxx");
> +		return -EINVAL;
> +	}
> +
> +	tmp = readl(pll->base + 4);
> +
> +	if (!clk_pll1416x_mp_change(rate, tmp)) {
> +		tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
> +		tmp |= rate->sdiv << SDIV_SHIFT;
> +		writel(tmp, pll->base + 4);
> +
> +		return clk_pll1416x_recalc_rate(clk);
> +	}
> +
> +	/* Bypass clock and set lock to pll output lock */
> +	tmp = readl(pll->base);
> +	tmp |= LOCK_SEL_MASK;
> +	writel(tmp, pll->base);
> +
> +	/* Enable RST */
> +	tmp &= ~RST_MASK;
> +	writel(tmp, pll->base);
> +
> +	/* Enable BYPASS */
> +	tmp |= BYPASS_MASK;
> +	writel(tmp, pll->base);
> +
> +
> +	div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
> +		(rate->sdiv << SDIV_SHIFT);
> +	writel(div_val, pll->base + 0x4);
> +
> +	/*
> +	 * According to SPEC, t3 - t2 need to be greater than
> +	 * 1us and 1/FREF, respectively.
> +	 * FREF is FIN / Prediv, the prediv is [1, 63], so choose
> +	 * 3us.
> +	 */
> +	udelay(3);
> +
> +	/* Disable RST */
> +	tmp |= RST_MASK;
> +	writel(tmp, pll->base);
> +
> +	/* Wait Lock */
> +	ret = clk_pll14xx_wait_lock(pll);
> +	if (ret)
> +		return ret;
> +
> +	/* Bypass */
> +	tmp &= ~BYPASS_MASK;
> +	writel(tmp, pll->base);
> +
> +	return clk_pll1416x_recalc_rate(clk);
> +}
> +
> +static ulong clk_pll1443x_set_rate(struct clk *clk, unsigned long drate)
> +{
> +	struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
> +	const struct imx_pll14xx_rate_table *rate;
> +	u32 tmp, div_val;
> +	int ret;
> +
> +	rate = imx_get_pll_settings(pll, drate);
> +	if (!rate) {
> +		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
> +		       drate, "===");
> +		return -EINVAL;
> +	}
> +
> +	tmp = readl(pll->base + 4);
> +	div_val = readl(pll->base + 8);
> +
> +	if (!clk_pll1443x_mpk_change(rate, tmp, div_val)) {
> +		tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
> +		tmp |= rate->sdiv << SDIV_SHIFT;
> +		writel(tmp, pll->base + 4);
> +
> +		return clk_pll1443x_recalc_rate(clk);
> +	}
> +
> +	tmp = readl(pll->base);
> +
> +	/* Enable RST */
> +	tmp &= ~RST_MASK;
> +	writel(tmp, pll->base);
> +
> +	/* Enable BYPASS */
> +	tmp |= BYPASS_MASK;
> +	writel(tmp, pll->base);
> +
> +	div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
> +		(rate->sdiv << SDIV_SHIFT);
> +	writel(div_val, pll->base + 0x4);
> +	writel(rate->kdiv << KDIV_SHIFT, pll->base + 0x8);
> +
> +	/*
> +	 * According to SPEC, t3 - t2 need to be greater than
> +	 * 1us and 1/FREF, respectively.
> +	 * FREF is FIN / Prediv, the prediv is [1, 63], so choose
> +	 * 3us.
> +	 */
> +	udelay(3);
> +
> +	/* Disable RST */
> +	tmp |= RST_MASK;
> +	writel(tmp, pll->base);
> +
> +	/* Wait Lock*/
> +	ret = clk_pll14xx_wait_lock(pll);
> +	if (ret)
> +		return ret;
> +
> +	/* Bypass */
> +	tmp &= ~BYPASS_MASK;
> +	writel(tmp, pll->base);
> +
> +	return clk_pll1443x_recalc_rate(clk);
> +}
> +
> +static int clk_pll14xx_prepare(struct clk *clk)
> +{
> +	struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
> +	u32 val;
> +
> +	/*
> +	 * RESETB = 1 from 0, PLL starts its normal
> +	 * operation after lock time
> +	 */
> +	val = readl(pll->base + GNRL_CTL);
> +	val |= RST_MASK;
> +	writel(val, pll->base + GNRL_CTL);
> +
> +	return clk_pll14xx_wait_lock(pll);
> +}
> +
> +static int clk_pll14xx_unprepare(struct clk *clk)
> +{
> +	struct clk_pll14xx *pll = to_clk_pll14xx(dev_get_clk_ptr(clk->dev));
> +	u32 val;
> +
> +	/*
> +	 * Set RST to 0, power down mode is enabled and
> +	 * every digital block is reset
> +	 */
> +	val = readl(pll->base + GNRL_CTL);
> +	val &= ~RST_MASK;
> +	writel(val, pll->base + GNRL_CTL);
> +
> +	return 0;
> +}
> +
> +static const struct clk_ops clk_pll1416x_ops = {
> +	.enable		= clk_pll14xx_prepare,
> +	.disable	= clk_pll14xx_unprepare,
> +	.set_rate	= clk_pll1416x_set_rate,
> +	.get_rate	= clk_pll1416x_recalc_rate,
> +};
> +
> +static const struct clk_ops clk_pll1443x_ops = {
> +	.enable		= clk_pll14xx_prepare,
> +	.disable	= clk_pll14xx_unprepare,
> +	.set_rate	= clk_pll1443x_set_rate,
> +	.get_rate	= clk_pll1443x_recalc_rate,
> +};
> +
> +struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
> +			    void __iomem *base,
> +			    const struct imx_pll14xx_clk *pll_clk)
> +{
> +	struct clk_pll14xx *pll;
> +	struct clk *clk;
> +	char *type_name;
> +	int ret;
> +
> +	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
> +	if (!pll)
> +		return ERR_PTR(-ENOMEM);
> +
> +	switch (pll_clk->type) {
> +	case PLL_1416X:
> +		type_name = UBOOT_DM_CLK_IMX_PLL1416X;
> +		break;
> +	case PLL_1443X:
> +		type_name = UBOOT_DM_CLK_IMX_PLL1443X;
> +		break;
> +	default:
> +		pr_err("%s: Unknown pll type for pll clk %s\n",
> +		       __func__, name);
> +		return ERR_PTR(-EINVAL);
> +	};
> +
> +	pll->base = base;
> +	pll->type = pll_clk->type;
> +	pll->rate_table = pll_clk->rate_table;
> +	pll->rate_count = pll_clk->rate_count;
> +
> +	clk = &pll->clk;
> +
> +	ret = clk_register(clk, type_name, name, parent_name);
> +	if (ret) {
> +		pr_err("%s: failed to register pll %s %d\n",
> +		       __func__, name, ret);
> +		kfree(pll);
> +		return ERR_PTR(ret);
> +	}
> +
> +	return clk;
> +}
> +
> +U_BOOT_DRIVER(clk_pll1443x) = {
> +	.name	= UBOOT_DM_CLK_IMX_PLL1443X,
> +	.id	= UCLASS_CLK,
> +	.ops	= &clk_pll1443x_ops,
> +	.flags = DM_FLAG_PRE_RELOC,
> +};
> +
> +U_BOOT_DRIVER(clk_pll1416x) = {
> +	.name	= UBOOT_DM_CLK_IMX_PLL1416X,
> +	.id	= UCLASS_CLK,
> +	.ops	= &clk_pll1416x_ops,
> +	.flags = DM_FLAG_PRE_RELOC,
> +};
> diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
> index 1d480d8722..4956e04a92 100644
> --- a/drivers/clk/imx/clk.h
> +++ b/drivers/clk/imx/clk.h
> @@ -20,6 +20,31 @@ enum imx_pllv3_type {
>  	IMX_PLLV3_DDR_IMX7,
>  };
>  
> +enum imx_pll14xx_type {
> +	PLL_1416X,
> +	PLL_1443X,
> +};
> +
> +/* NOTE: Rate table should be kept sorted in descending order. */
> +struct imx_pll14xx_rate_table {
> +	unsigned int rate;
> +	unsigned int pdiv;
> +	unsigned int mdiv;
> +	unsigned int sdiv;
> +	unsigned int kdiv;
> +};
> +
> +struct imx_pll14xx_clk {
> +	enum imx_pll14xx_type type;
> +	const struct imx_pll14xx_rate_table *rate_table;
> +	int rate_count;
> +	int flags;
> +};
> +
> +struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
> +			    void __iomem *base,
> +			    const struct imx_pll14xx_clk *pll_clk);
> +
>  struct clk *clk_register_gate2(struct device *dev, const char *name,
>  		const char *parent_name, unsigned long flags,
>  		void __iomem *reg, u8 bit_idx, u8 cgr_val,
> 
Reviewed-by: Ye Li <ye.li@nxp.com>

Best regards,
Ye Li

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 3/4] clk: imx: add i.MX8M composite clk support
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 3/4] clk: imx: add i.MX8M composite clk support Peng Fan
@ 2019-08-09  9:08   ` Ye Li
  2019-08-09 16:59   ` Fabio Estevam
  1 sibling, 0 replies; 16+ messages in thread
From: Ye Li @ 2019-08-09  9:08 UTC (permalink / raw)
  To: u-boot

> Import i.MX8M composite clk from Linux Kernel 5.3.0-rc2
> 
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
>  drivers/clk/imx/clk-composite-8m.c | 170 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 170 insertions(+)
>  create mode 100644 drivers/clk/imx/clk-composite-8m.c
> 
> diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c
> new file mode 100644
> index 0000000000..57ebbc3bb0
> --- /dev/null
> +++ b/drivers/clk/imx/clk-composite-8m.c
> @@ -0,0 +1,170 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2019 NXP
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <malloc.h>
> +#include <clk-uclass.h>
> +#include <dm/device.h>
> +#include <linux/clk-provider.h>
> +#include <clk.h>
> +#include "clk.h"
> +
> +#define UBOOT_DM_CLK_IMX_COMPOSITE "imx_clk_composite"
> +
> +#define PCG_PREDIV_SHIFT	16
> +#define PCG_PREDIV_WIDTH	3
> +#define PCG_PREDIV_MAX		8
> +
> +#define PCG_DIV_SHIFT		0
> +#define PCG_DIV_WIDTH		6
> +#define PCG_DIV_MAX		64
> +
> +#define PCG_PCS_SHIFT		24
> +#define PCG_PCS_MASK		0x7
> +
> +#define PCG_CGC_SHIFT		28
> +
> +static unsigned long imx8m_clk_composite_divider_recalc_rate(struct clk *clk)
> +{
> +	struct clk_divider *divider = (struct clk_divider *)to_clk_divider(clk);
> +	struct clk_composite *composite = (struct clk_composite *)clk->data;
> +	ulong parent_rate = clk_get_parent_rate(&composite->clk);
> +	unsigned long prediv_rate;
> +	unsigned int prediv_value;
> +	unsigned int div_value;
> +
> +	debug("%s: name %s prate: %lu reg: %p\n", __func__,
> +	      (&composite->clk)->dev->name, parent_rate, divider->reg);
> +	prediv_value = readl(divider->reg) >> divider->shift;
> +	prediv_value &= clk_div_mask(divider->width);
> +
> +	prediv_rate = divider_recalc_rate(clk, parent_rate, prediv_value,
> +					  NULL, divider->flags,
> +					  divider->width);
> +
> +	div_value = readl(divider->reg) >> PCG_DIV_SHIFT;
> +	div_value &= clk_div_mask(PCG_DIV_WIDTH);
> +
> +	return divider_recalc_rate(clk, prediv_rate, div_value, NULL,
> +				   divider->flags, PCG_DIV_WIDTH);
> +}
> +
> +static int imx8m_clk_composite_compute_dividers(unsigned long rate,
> +						unsigned long parent_rate,
> +						int *prediv, int *postdiv)
> +{
> +	int div1, div2;
> +	int error = INT_MAX;
> +	int ret = -EINVAL;
> +
> +	*prediv = 1;
> +	*postdiv = 1;
> +
> +	for (div1 = 1; div1 <= PCG_PREDIV_MAX; div1++) {
> +		for (div2 = 1; div2 <= PCG_DIV_MAX; div2++) {
> +			int new_error = ((parent_rate / div1) / div2) - rate;
> +
> +			if (abs(new_error) < abs(error)) {
> +				*prediv = div1;
> +				*postdiv = div2;
> +				error = new_error;
> +				ret = 0;
> +			}
> +		}
> +	}
> +	return ret;
> +}
> +
> +/*
> + * The clk are not binded to a dev, because it is part of composite clk
> + * use composite clk to get dev
> + */
> +static ulong imx8m_clk_composite_divider_set_rate(struct clk *clk,
> +						  unsigned long rate)
> +{
> +	struct clk_divider *divider = (struct clk_divider *)to_clk_divider(clk);
> +	struct clk_composite *composite = (struct clk_composite *)clk->data;
> +	ulong parent_rate = clk_get_parent_rate(&composite->clk);
> +	int prediv_value;
> +	int div_value;
> +	int ret;
> +	u32 val;
> +
> +	ret = imx8m_clk_composite_compute_dividers(rate, parent_rate,
> +						   &prediv_value, &div_value);
> +	if (ret)
> +		return -EINVAL;
> +
> +	val = readl(divider->reg);
> +	val &= ~((clk_div_mask(divider->width) << divider->shift) |
> +			(clk_div_mask(PCG_DIV_WIDTH) << PCG_DIV_SHIFT));
> +
> +	val |= (u32)(prediv_value  - 1) << divider->shift;
> +	val |= (u32)(div_value - 1) << PCG_DIV_SHIFT;
> +	writel(val, divider->reg);
> +
> +	return clk_get_rate(&composite->clk);
> +}
> +
> +static const struct clk_ops imx8m_clk_composite_divider_ops = {
> +	.get_rate = imx8m_clk_composite_divider_recalc_rate,
> +	.set_rate = imx8m_clk_composite_divider_set_rate,
> +};
> +
> +struct clk *imx8m_clk_composite_flags(const char *name,
> +				      const char * const *parent_names,
> +				      int num_parents, void __iomem *reg,
> +				      unsigned long flags)
> +{
> +	struct clk *clk = ERR_PTR(-ENOMEM);
> +	struct clk_divider *div = NULL;
> +	struct clk_gate *gate = NULL;
> +	struct clk_mux *mux = NULL;
> +
> +	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
> +	if (!mux)
> +		goto fail;
> +
> +	mux->reg = reg;
> +	mux->shift = PCG_PCS_SHIFT;
> +	mux->mask = PCG_PCS_MASK;
> +	mux->num_parents = num_parents;
> +	mux->flags = flags;
> +	mux->parent_names = parent_names;
> +
> +	div = kzalloc(sizeof(*div), GFP_KERNEL);
> +	if (!div)
> +		goto fail;
> +
> +	div->reg = reg;
> +	div->shift = PCG_PREDIV_SHIFT;
> +	div->width = PCG_PREDIV_WIDTH;
> +	div->flags = CLK_DIVIDER_ROUND_CLOSEST | flags;
> +
> +	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
> +	if (!gate)
> +		goto fail;
> +
> +	gate->reg = reg;
> +	gate->bit_idx = PCG_CGC_SHIFT;
> +	gate->flags = flags;
> +
> +	clk = clk_register_composite(NULL, name,
> +				     parent_names, num_parents,
> +				     &mux->clk, &clk_mux_ops, &div->clk,
> +				     &imx8m_clk_composite_divider_ops,
> +				     &gate->clk, &clk_gate_ops, flags);
> +	if (IS_ERR(clk))
> +		goto fail;
> +
> +	return clk;
> +
> +fail:
> +	kfree(gate);
> +	kfree(div);
> +	kfree(mux);
> +	return ERR_CAST(clk);
> +}
> 
Reviewed-by: Ye Li <ye.li@nxp.com>

Best regards,
Ye Li

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 4/4] clk: imx: add i.MX8MM clk driver
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 4/4] clk: imx: add i.MX8MM clk driver Peng Fan
@ 2019-08-09  9:10   ` Ye Li
  2019-08-09 21:02   ` Fabio Estevam
  1 sibling, 0 replies; 16+ messages in thread
From: Ye Li @ 2019-08-09  9:10 UTC (permalink / raw)
  To: u-boot

> Add i.MX8MM clk driver support.
> 
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
>  drivers/clk/imx/Makefile     |   2 +
>  drivers/clk/imx/clk-imx8mm.c | 415 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 417 insertions(+)
>  create mode 100644 drivers/clk/imx/clk-imx8mm.c
> 
> diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
> index 105a58ca90..5ad7967fe9 100644
> --- a/drivers/clk/imx/Makefile
> +++ b/drivers/clk/imx/Makefile
> @@ -10,3 +10,5 @@ ifdef CONFIG_CLK_IMX8
>  obj-$(CONFIG_IMX8QXP) += clk-imx8qxp.o
>  obj-$(CONFIG_IMX8QM) += clk-imx8qm.o
>  endif
> +obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MM) += clk-imx8mm.o clk-pll14xx.o \
> +				clk-composite-8m.o
> diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
> new file mode 100644
> index 0000000000..a2a85b6a1a
> --- /dev/null
> +++ b/drivers/clk/imx/clk-imx8mm.c
> @@ -0,0 +1,415 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2019 NXP
> + * Peng Fan <peng.fan@nxp.com>
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <clk-uclass.h>
> +#include <dm.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/imx-regs.h>
> +#include <dt-bindings/clock/imx8mm-clock.h>
> +
> +#include "clk.h"
> +
> +#define PLL_1416X_RATE(_rate, _m, _p, _s)		\
> +	{						\
> +		.rate	=	(_rate),		\
> +		.mdiv	=	(_m),			\
> +		.pdiv	=	(_p),			\
> +		.sdiv	=	(_s),			\
> +	}
> +
> +#define PLL_1443X_RATE(_rate, _m, _p, _s, _k)		\
> +	{						\
> +		.rate	=	(_rate),		\
> +		.mdiv	=	(_m),			\
> +		.pdiv	=	(_p),			\
> +		.sdiv	=	(_s),			\
> +		.kdiv	=	(_k),			\
> +	}
> +
> +static const struct imx_pll14xx_rate_table imx8mm_pll1416x_tbl[] = {
> +	PLL_1416X_RATE(1800000000U, 225, 3, 0),
> +	PLL_1416X_RATE(1600000000U, 200, 3, 0),
> +	PLL_1416X_RATE(1200000000U, 300, 3, 1),
> +	PLL_1416X_RATE(1000000000U, 250, 3, 1),
> +	PLL_1416X_RATE(800000000U,  200, 3, 1),
> +	PLL_1416X_RATE(750000000U,  250, 2, 2),
> +	PLL_1416X_RATE(700000000U,  350, 3, 2),
> +	PLL_1416X_RATE(600000000U,  300, 3, 2),
> +};
> +
> +static const struct imx_pll14xx_rate_table imx8mm_drampll_tbl[] = {
> +	PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
> +};
> +
> +static struct imx_pll14xx_clk imx8mm_dram_pll __initdata = {
> +		.type = PLL_1443X,
> +		.rate_table = imx8mm_drampll_tbl,
> +		.rate_count = ARRAY_SIZE(imx8mm_drampll_tbl),
> +};
> +
> +static struct imx_pll14xx_clk imx8mm_arm_pll __initdata = {
> +		.type = PLL_1416X,
> +		.rate_table = imx8mm_pll1416x_tbl,
> +		.rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
> +};
> +
> +static struct imx_pll14xx_clk imx8mm_sys_pll __initdata = {
> +		.type = PLL_1416X,
> +		.rate_table = imx8mm_pll1416x_tbl,
> +		.rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
> +};
> +
> +static const char *pll_ref_sels[] = { "clock-osc-24m", "dummy", "dummy", "dummy", };
> +static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
> +static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
> +static const char *sys_pll1_bypass_sels[] = {"sys_pll1", "sys_pll1_ref_sel", };
> +static const char *sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", };
> +static const char *sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
> +
> +static const char *imx8mm_a53_sels[] = {"clock-osc-24m", "arm_pll_out", "sys_pll2_500m", "sys_pll2_1000m",
> +					"sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "sys_pll3_out", };
> +
> +static const char *imx8mm_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m", "sys_pll1_400m",
> +					"sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", };
> +
> +static const char *imx8mm_enet_axi_sels[] = {"clock-osc-24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_250m",
> +					     "sys_pll2_200m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", };
> +
> +static const char *imx8mm_nand_usdhc_sels[] = {"clock-osc-24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_200m",
> +					       "sys_pll1_133m", "sys_pll3_out", "sys_pll2_250m", "audio_pll1_out", };
> +
> +static const char *imx8mm_usdhc1_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
> +					   "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
> +
> +static const char *imx8mm_usdhc2_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
> +					   "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
> +
> +static const char *imx8mm_i2c1_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
> +					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
> +
> +static const char *imx8mm_i2c2_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
> +					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
> +
> +static const char *imx8mm_i2c3_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
> +					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
> +
> +static const char *imx8mm_i2c4_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
> +					 "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
> +
> +static const char *imx8mm_wdog_sels[] = {"clock-osc-24m", "sys_pll1_133m", "sys_pll1_160m", "vpu_pll_out",
> +					 "sys_pll2_125m", "sys_pll3_out", "sys_pll1_80m", "sys_pll2_166m", };
> +
> +static const char *imx8mm_usdhc3_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
> +					   "sys_pll3_out", "sys_pll1_266m", "audio_pll2_clk", "sys_pll1_100m", };
> +
> +static ulong imx8mm_clk_get_rate(struct clk *clk)
> +{
> +	struct clk *c;
> +	int ret;
> +
> +	debug("%s(#%lu)\n", __func__, clk->id);
> +
> +	ret = clk_get_by_id(clk->id, &c);
> +	if (ret)
> +		return ret;
> +
> +	return clk_get_rate(c);
> +}
> +
> +static ulong imx8mm_clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	struct clk *c;
> +	int ret = 0;
> +
> +	debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
> +
> +	ret = clk_get_by_id(clk->id, &c);
> +	if (ret)
> +		return ret;
> +
> +	return clk_set_rate(c, rate);
> +}
> +
> +static int __imx8mm_clk_enable(struct clk *clk, bool enable)
> +{
> +	struct clk *c;
> +	int ret = 0;
> +
> +	debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
> +
> +	ret = clk_get_by_id(clk->id, &c);
> +	if (ret)
> +		return ret;
> +
> +	if (enable)
> +		ret = clk_enable(c);
> +	else
> +		ret = clk_disable(c);
> +
> +	return ret;
> +}
> +
> +static int imx8mm_clk_disable(struct clk *clk)
> +{
> +	return __imx8mm_clk_enable(clk, 0);
> +}
> +
> +static int imx8mm_clk_enable(struct clk *clk)
> +{
> +	return __imx8mm_clk_enable(clk, 1);
> +}
> +
> +static struct clk_ops imx8mm_clk_ops = {
> +	.set_rate = imx8mm_clk_set_rate,
> +	.get_rate = imx8mm_clk_get_rate,
> +	.enable = imx8mm_clk_enable,
> +	.disable = imx8mm_clk_disable,
> +};
> +
> +static int imx8mm_clk_probe(struct udevice *dev)
> +{
> +	void __iomem *base;
> +
> +	base = (void *)ANATOP_BASE_ADDR;
> +
> +	clk_dm(IMX8MM_DRAM_PLL_REF_SEL,
> +	       imx_clk_mux("dram_pll_ref_sel", base + 0x50, 0, 2,
> +			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
> +	clk_dm(IMX8MM_ARM_PLL_REF_SEL,
> +	       imx_clk_mux("arm_pll_ref_sel", base + 0x84, 0, 2,
> +			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
> +	clk_dm(IMX8MM_SYS_PLL1_REF_SEL,
> +	       imx_clk_mux("sys_pll1_ref_sel", base + 0x94, 0, 2,
> +			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
> +	clk_dm(IMX8MM_SYS_PLL2_REF_SEL,
> +	       imx_clk_mux("sys_pll2_ref_sel", base + 0x104, 0, 2,
> +			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
> +	clk_dm(IMX8MM_SYS_PLL3_REF_SEL,
> +	       imx_clk_mux("sys_pll3_ref_sel", base + 0x114, 0, 2,
> +			   pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
> +
> +	clk_dm(IMX8MM_DRAM_PLL,
> +	       imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel",
> +			       base + 0x50, &imx8mm_dram_pll));
> +	clk_dm(IMX8MM_ARM_PLL,
> +	       imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel",
> +			       base + 0x84, &imx8mm_arm_pll));
> +	clk_dm(IMX8MM_SYS_PLL1,
> +	       imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel",
> +			       base + 0x94, &imx8mm_sys_pll));
> +	clk_dm(IMX8MM_SYS_PLL2,
> +	       imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel",
> +			       base + 0x104, &imx8mm_sys_pll));
> +	clk_dm(IMX8MM_SYS_PLL3,
> +	       imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel",
> +			       base + 0x114, &imx8mm_sys_pll));
> +
> +	/* PLL bypass out */
> +	clk_dm(IMX8MM_DRAM_PLL_BYPASS,
> +	       imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 4, 1,
> +				 dram_pll_bypass_sels,
> +				 ARRAY_SIZE(dram_pll_bypass_sels),
> +				 CLK_SET_RATE_PARENT));
> +	clk_dm(IMX8MM_ARM_PLL_BYPASS,
> +	       imx_clk_mux_flags("arm_pll_bypass", base + 0x84, 4, 1,
> +				 arm_pll_bypass_sels,
> +				 ARRAY_SIZE(arm_pll_bypass_sels),
> +				 CLK_SET_RATE_PARENT));
> +	clk_dm(IMX8MM_SYS_PLL1_BYPASS,
> +	       imx_clk_mux_flags("sys_pll1_bypass", base + 0x94, 4, 1,
> +				 sys_pll1_bypass_sels,
> +				 ARRAY_SIZE(sys_pll1_bypass_sels),
> +				 CLK_SET_RATE_PARENT));
> +	clk_dm(IMX8MM_SYS_PLL2_BYPASS,
> +	       imx_clk_mux_flags("sys_pll2_bypass", base + 0x104, 4, 1,
> +				 sys_pll2_bypass_sels,
> +				 ARRAY_SIZE(sys_pll2_bypass_sels),
> +				 CLK_SET_RATE_PARENT));
> +	clk_dm(IMX8MM_SYS_PLL3_BYPASS,
> +	       imx_clk_mux_flags("sys_pll3_bypass", base + 0x114, 4, 1,
> +				 sys_pll3_bypass_sels,
> +				 ARRAY_SIZE(sys_pll3_bypass_sels),
> +				 CLK_SET_RATE_PARENT));
> +
> +	/* PLL out gate */
> +	clk_dm(IMX8MM_DRAM_PLL_OUT,
> +	       imx_clk_gate("dram_pll_out", "dram_pll_bypass",
> +			    base + 0x50, 13));
> +	clk_dm(IMX8MM_ARM_PLL_OUT,
> +	       imx_clk_gate("arm_pll_out", "arm_pll_bypass",
> +			    base + 0x84, 11));
> +	clk_dm(IMX8MM_SYS_PLL1_OUT,
> +	       imx_clk_gate("sys_pll1_out", "sys_pll1_bypass",
> +			    base + 0x94, 11));
> +	clk_dm(IMX8MM_SYS_PLL2_OUT,
> +	       imx_clk_gate("sys_pll2_out", "sys_pll2_bypass",
> +			    base + 0x104, 11));
> +	clk_dm(IMX8MM_SYS_PLL3_OUT,
> +	       imx_clk_gate("sys_pll3_out", "sys_pll3_bypass",
> +			    base + 0x114, 11));
> +
> +	/* SYS PLL fixed output */
> +	clk_dm(IMX8MM_SYS_PLL1_40M,
> +	       imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20));
> +	clk_dm(IMX8MM_SYS_PLL1_80M,
> +	       imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10));
> +	clk_dm(IMX8MM_SYS_PLL1_100M,
> +	       imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8));
> +	clk_dm(IMX8MM_SYS_PLL1_133M,
> +	       imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6));
> +	clk_dm(IMX8MM_SYS_PLL1_160M,
> +	       imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5));
> +	clk_dm(IMX8MM_SYS_PLL1_200M,
> +	       imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4));
> +	clk_dm(IMX8MM_SYS_PLL1_266M,
> +	       imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3));
> +	clk_dm(IMX8MM_SYS_PLL1_400M,
> +	       imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2));
> +	clk_dm(IMX8MM_SYS_PLL1_800M,
> +	       imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1));
> +
> +	clk_dm(IMX8MM_SYS_PLL2_50M,
> +	       imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20));
> +	clk_dm(IMX8MM_SYS_PLL2_100M,
> +	       imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10));
> +	clk_dm(IMX8MM_SYS_PLL2_125M,
> +	       imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8));
> +	clk_dm(IMX8MM_SYS_PLL2_166M,
> +	       imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6));
> +	clk_dm(IMX8MM_SYS_PLL2_200M,
> +	       imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5));
> +	clk_dm(IMX8MM_SYS_PLL2_250M,
> +	       imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4));
> +	clk_dm(IMX8MM_SYS_PLL2_333M,
> +	       imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3));
> +	clk_dm(IMX8MM_SYS_PLL2_500M,
> +	       imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2));
> +	clk_dm(IMX8MM_SYS_PLL2_1000M,
> +	       imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1));
> +
> +	base = dev_read_addr_ptr(dev);
> +	if (base == (void *)FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	clk_dm(IMX8MM_CLK_A53_SRC,
> +	       imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3,
> +			    imx8mm_a53_sels, ARRAY_SIZE(imx8mm_a53_sels)));
> +	clk_dm(IMX8MM_CLK_A53_CG,
> +	       imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28));
> +	clk_dm(IMX8MM_CLK_A53_DIV,
> +	       imx_clk_divider2("arm_a53_div", "arm_a53_cg",
> +				base + 0x8000, 0, 3));
> +
> +	clk_dm(IMX8MM_CLK_AHB,
> +	       imx8m_clk_composite_critical("ahb", imx8mm_ahb_sels,
> +					    base + 0x9000));
> +	clk_dm(IMX8MM_CLK_IPG_ROOT,
> +	       imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1));
> +
> +	clk_dm(IMX8MM_CLK_ENET_AXI,
> +	       imx8m_clk_composite("enet_axi", imx8mm_enet_axi_sels,
> +				   base + 0x8880));
> +	clk_dm(IMX8MM_CLK_NAND_USDHC_BUS,
> +	       imx8m_clk_composite_critical("nand_usdhc_bus",
> +					    imx8mm_nand_usdhc_sels,
> +					    base + 0x8900));
> +
> +	/* IP */
> +	clk_dm(IMX8MM_CLK_USDHC1,
> +	       imx8m_clk_composite("usdhc1", imx8mm_usdhc1_sels,
> +				   base + 0xac00));
> +	clk_dm(IMX8MM_CLK_USDHC2,
> +	       imx8m_clk_composite("usdhc2", imx8mm_usdhc2_sels,
> +				   base + 0xac80));
> +	clk_dm(IMX8MM_CLK_I2C1,
> +	       imx8m_clk_composite("i2c1", imx8mm_i2c1_sels, base + 0xad00));
> +	clk_dm(IMX8MM_CLK_I2C2,
> +	       imx8m_clk_composite("i2c2", imx8mm_i2c2_sels, base + 0xad80));
> +	clk_dm(IMX8MM_CLK_I2C3,
> +	       imx8m_clk_composite("i2c3", imx8mm_i2c3_sels, base + 0xae00));
> +	clk_dm(IMX8MM_CLK_I2C4,
> +	       imx8m_clk_composite("i2c4", imx8mm_i2c4_sels, base + 0xae80));
> +	clk_dm(IMX8MM_CLK_WDOG,
> +	       imx8m_clk_composite("wdog", imx8mm_wdog_sels, base + 0xb900));
> +	clk_dm(IMX8MM_CLK_USDHC3,
> +	       imx8m_clk_composite("usdhc3", imx8mm_usdhc3_sels,
> +				   base + 0xbc80));
> +
> +	clk_dm(IMX8MM_CLK_I2C1_ROOT,
> +	       imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0));
> +	clk_dm(IMX8MM_CLK_I2C2_ROOT,
> +	       imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0));
> +	clk_dm(IMX8MM_CLK_I2C3_ROOT,
> +	       imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0));
> +	clk_dm(IMX8MM_CLK_I2C4_ROOT,
> +	       imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0));
> +	clk_dm(IMX8MM_CLK_OCOTP_ROOT,
> +	       imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0));
> +	clk_dm(IMX8MM_CLK_USDHC1_ROOT,
> +	       imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0));
> +	clk_dm(IMX8MM_CLK_USDHC2_ROOT,
> +	       imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0));
> +	clk_dm(IMX8MM_CLK_WDOG1_ROOT,
> +	       imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0));
> +	clk_dm(IMX8MM_CLK_WDOG2_ROOT,
> +	       imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0));
> +	clk_dm(IMX8MM_CLK_WDOG3_ROOT,
> +	       imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0));
> +	clk_dm(IMX8MM_CLK_USDHC3_ROOT,
> +	       imx_clk_gate4("usdhc3_root_clk", "usdhc3", base + 0x45e0, 0));
> +
> +#ifdef CONFIG_SPL_BUILD
> +	struct clk *clkp, *clkp1;
> +
> +	clk_get_by_id(IMX8MM_CLK_WDOG1_ROOT, &clkp);
> +	clk_enable(clkp);
> +	clk_get_by_id(IMX8MM_CLK_WDOG2_ROOT, &clkp);
> +	clk_enable(clkp);
> +	clk_get_by_id(IMX8MM_CLK_WDOG3_ROOT, &clkp);
> +	clk_enable(clkp);
> +
> +	/* Configure SYS_PLL3 to 750MHz */
> +	clk_get_by_id(IMX8MM_SYS_PLL3, &clkp);
> +	clk_set_rate(clkp, 750000000UL);
> +	clk_enable(clkp);
> +
> +	/* Configure ARM to sys_pll2_500m */
> +	clk_get_by_id(IMX8MM_CLK_A53_SRC, &clkp);
> +	clk_get_by_id(IMX8MM_SYS_PLL2_OUT, &clkp1);
> +	clk_enable(clkp1);
> +	clk_get_by_id(IMX8MM_SYS_PLL2_500M, &clkp1);
> +	clk_set_parent(clkp, clkp1);
> +
> +	/* Configure ARM PLL to 1.2GHz */
> +	clk_get_by_id(IMX8MM_ARM_PLL, &clkp1);
> +	clk_set_rate(clkp1, 1200000000UL);
> +	clk_get_by_id(IMX8MM_ARM_PLL_OUT, &clkp1);
> +	clk_enable(clkp1);
> +	clk_set_parent(clkp, clkp1);
> +
> +	/* Configure DIV to 1.2GHz */
> +	clk_get_by_id(IMX8MM_CLK_A53_DIV, &clkp1);
> +	clk_set_rate(clkp1, 1200000000UL);
> +#endif
> +
> +	return 0;
> +}
> +
> +static const struct udevice_id imx8mm_clk_ids[] = {
> +	{ .compatible = "fsl,imx8mm-ccm" },
> +	{ },
> +};
> +
> +U_BOOT_DRIVER(imx8mm_clk) = {
> +	.name = "clk_imx8mm",
> +	.id = UCLASS_CLK,
> +	.of_match = imx8mm_clk_ids,
> +	.ops = &imx8mm_clk_ops,
> +	.probe = imx8mm_clk_probe,
> +	.flags = DM_FLAG_PRE_RELOC,
> +};
> 
Reviewed-by: Ye Li <ye.li@nxp.com>

Best regards,
Ye Li

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 1/4] clk: imx: add Kconfig entry for i.MX8MM
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 1/4] clk: imx: add Kconfig entry for i.MX8MM Peng Fan
  2019-08-09  8:56   ` Ye Li
@ 2019-08-09 16:50   ` Fabio Estevam
  2019-08-13  9:07     ` Peng Fan
  1 sibling, 1 reply; 16+ messages in thread
From: Fabio Estevam @ 2019-08-09 16:50 UTC (permalink / raw)
  To: u-boot

Hi Peng,

On Fri, Aug 9, 2019 at 5:02 AM Peng Fan <peng.fan@nxp.com> wrote:
>
> Add Kconfig entry for i.MX8MM
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
>  drivers/clk/Kconfig     |  4 ++--
>  drivers/clk/imx/Kconfig | 16 ++++++++++++++++
>  2 files changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index a3f0171b45..fce595b4b3 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -48,7 +48,7 @@ config CLK_BOSTON
>
>  config SPL_CLK_CCF
>         bool "SPL Common Clock Framework [CCF] support "
> -       depends on SPL_CLK_IMX6Q
> +       depends on SPL_CLK_IMX6Q || ARCH_IMX8M

I am wondering why this depends on i.MX. Shouldn't it be SoC agnostic?

>         help
>           Enable this option if you want to (re-)use the Linux kernel's Common
>           Clock Framework [CCF] code in U-Boot's SPL.
> @@ -62,7 +62,7 @@ config SPL_CLK_COMPOSITE_CCF
>
>  config CLK_CCF
>         bool "Common Clock Framework [CCF] support "
> -       depends on CLK_IMX6Q || SANDBOX_CLK_CCF
> +       depends on CLK_IMX6Q || ARCH_IMX8M || SANDBOX_CLK_CCF

Same here.

It doesn't look like a good idea to keep expanding this Kconfig every
time a new SoC wants to use the CCF.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 2/4] clk: imx: add pll14xx driver
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 2/4] clk: imx: add pll14xx driver Peng Fan
  2019-08-09  9:05   ` Ye Li
@ 2019-08-09 16:51   ` Fabio Estevam
  1 sibling, 0 replies; 16+ messages in thread
From: Fabio Estevam @ 2019-08-09 16:51 UTC (permalink / raw)
  To: u-boot

On Fri, Aug 9, 2019 at 5:02 AM Peng Fan <peng.fan@nxp.com> wrote:
>
> Add pll14xx driver

Please expand this commit log a bit by adding in which SoC it is used,
where this driver comes from (Linux, internal U-Boot tree, etc).

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 3/4] clk: imx: add i.MX8M composite clk support
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 3/4] clk: imx: add i.MX8M composite clk support Peng Fan
  2019-08-09  9:08   ` Ye Li
@ 2019-08-09 16:59   ` Fabio Estevam
  2019-08-13  9:37     ` Peng Fan
  1 sibling, 1 reply; 16+ messages in thread
From: Fabio Estevam @ 2019-08-09 16:59 UTC (permalink / raw)
  To: u-boot

On Fri, Aug 9, 2019 at 5:02 AM Peng Fan <peng.fan@nxp.com> wrote:

> + * The clk are not binded to a dev, because it is part of composite clk

s/binded/bound

> + * use composite clk to get dev
> + */
> +static ulong imx8m_clk_composite_divider_set_rate(struct clk *clk,
> +                                                 unsigned long rate)
> +{
> +       struct clk_divider *divider = (struct clk_divider *)to_clk_divider(clk);
> +       struct clk_composite *composite = (struct clk_composite *)clk->data;
> +       ulong parent_rate = clk_get_parent_rate(&composite->clk);
> +       int prediv_value;
> +       int div_value;
> +       int ret;
> +       u32 val;
> +
> +       ret = imx8m_clk_composite_compute_dividers(rate, parent_rate,
> +                                                  &prediv_value, &div_value);
> +       if (ret)
> +               return -EINVAL;

What about returning ret directly instead?


> +struct clk *imx8m_clk_composite_flags(const char *name,
> +                                     const char * const *parent_names,
> +                                     int num_parents, void __iomem *reg,
> +                                     unsigned long flags)
> +{
> +       struct clk *clk = ERR_PTR(-ENOMEM);
> +       struct clk_divider *div = NULL;
> +       struct clk_gate *gate = NULL;
> +       struct clk_mux *mux = NULL;

Why all these NULL assignments?

> +
> +       mux = kzalloc(sizeof(*mux), GFP_KERNEL);
> +       if (!mux)
> +               goto fail;

It would be better like this:

       mux = kzalloc(sizeof(*mux), GFP_KERNEL);
       if (!mux)
               return ERR_PTR(-ENOMEM);

> +
> +       mux->reg = reg;
> +       mux->shift = PCG_PCS_SHIFT;
> +       mux->mask = PCG_PCS_MASK;
> +       mux->num_parents = num_parents;
> +       mux->flags = flags;
> +       mux->parent_names = parent_names;
> +
> +       div = kzalloc(sizeof(*div), GFP_KERNEL);
> +       if (!div)
> +               goto fail;
> +
> +       div->reg = reg;
> +       div->shift = PCG_PREDIV_SHIFT;
> +       div->width = PCG_PREDIV_WIDTH;
> +       div->flags = CLK_DIVIDER_ROUND_CLOSEST | flags;
> +
> +       gate = kzalloc(sizeof(*gate), GFP_KERNEL);
> +       if (!gate)
> +               goto fail;
> +
> +       gate->reg = reg;
> +       gate->bit_idx = PCG_CGC_SHIFT;
> +       gate->flags = flags;
> +
> +       clk = clk_register_composite(NULL, name,
> +                                    parent_names, num_parents,
> +                                    &mux->clk, &clk_mux_ops, &div->clk,
> +                                    &imx8m_clk_composite_divider_ops,
> +                                    &gate->clk, &clk_gate_ops, flags);
> +       if (IS_ERR(clk))
> +               goto fail;
> +
> +       return clk;
> +
> +fail:
> +       kfree(gate);
> +       kfree(div);
> +       kfree(mux);
> +       return ERR_CAST(clk);

ERR_CAST(clk) is only valid when for the IS_ERR(clk) path.

Please rework the error handling.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 4/4] clk: imx: add i.MX8MM clk driver
  2019-08-09  8:02 ` [U-Boot] [PATCH V3 4/4] clk: imx: add i.MX8MM clk driver Peng Fan
  2019-08-09  9:10   ` Ye Li
@ 2019-08-09 21:02   ` Fabio Estevam
  1 sibling, 0 replies; 16+ messages in thread
From: Fabio Estevam @ 2019-08-09 21:02 UTC (permalink / raw)
  To: u-boot

On Fri, Aug 9, 2019 at 5:02 AM Peng Fan <peng.fan@nxp.com> wrote:
>
> Add i.MX8MM clk driver support.
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
>  drivers/clk/imx/Makefile     |   2 +
>  drivers/clk/imx/clk-imx8mm.c | 415 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 417 insertions(+)
>  create mode 100644 drivers/clk/imx/clk-imx8mm.c
>
> diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
> index 105a58ca90..5ad7967fe9 100644
> --- a/drivers/clk/imx/Makefile
> +++ b/drivers/clk/imx/Makefile
> @@ -10,3 +10,5 @@ ifdef CONFIG_CLK_IMX8
>  obj-$(CONFIG_IMX8QXP) += clk-imx8qxp.o
>  obj-$(CONFIG_IMX8QM) += clk-imx8qm.o
>  endif
> +obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MM) += clk-imx8mm.o clk-pll14xx.o \
> +                               clk-composite-8m.o
> diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
> new file mode 100644
> index 0000000000..a2a85b6a1a
> --- /dev/null
> +++ b/drivers/clk/imx/clk-imx8mm.c
> @@ -0,0 +1,415 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright 2019 NXP
> + * Peng Fan <peng.fan@nxp.com>
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <clk-uclass.h>
> +#include <dm.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/imx-regs.h>
> +#include <dt-bindings/clock/imx8mm-clock.h>
> +
> +#include "clk.h"
> +
> +#define PLL_1416X_RATE(_rate, _m, _p, _s)              \
> +       {                                               \
> +               .rate   =       (_rate),                \
> +               .mdiv   =       (_m),                   \
> +               .pdiv   =       (_p),                   \
> +               .sdiv   =       (_s),                   \
> +       }
> +
> +#define PLL_1443X_RATE(_rate, _m, _p, _s, _k)          \
> +       {                                               \
> +               .rate   =       (_rate),                \
> +               .mdiv   =       (_m),                   \
> +               .pdiv   =       (_p),                   \
> +               .sdiv   =       (_s),                   \
> +               .kdiv   =       (_k),                   \
> +       }
> +
> +static const struct imx_pll14xx_rate_table imx8mm_pll1416x_tbl[] = {
> +       PLL_1416X_RATE(1800000000U, 225, 3, 0),
> +       PLL_1416X_RATE(1600000000U, 200, 3, 0),
> +       PLL_1416X_RATE(1200000000U, 300, 3, 1),
> +       PLL_1416X_RATE(1000000000U, 250, 3, 1),
> +       PLL_1416X_RATE(800000000U,  200, 3, 1),
> +       PLL_1416X_RATE(750000000U,  250, 2, 2),
> +       PLL_1416X_RATE(700000000U,  350, 3, 2),
> +       PLL_1416X_RATE(600000000U,  300, 3, 2),
> +};
> +
> +static const struct imx_pll14xx_rate_table imx8mm_drampll_tbl[] = {
> +       PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
> +};
> +
> +static struct imx_pll14xx_clk imx8mm_dram_pll __initdata = {
> +               .type = PLL_1443X,
> +               .rate_table = imx8mm_drampll_tbl,
> +               .rate_count = ARRAY_SIZE(imx8mm_drampll_tbl),
> +};
> +
> +static struct imx_pll14xx_clk imx8mm_arm_pll __initdata = {
> +               .type = PLL_1416X,
> +               .rate_table = imx8mm_pll1416x_tbl,
> +               .rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
> +};
> +
> +static struct imx_pll14xx_clk imx8mm_sys_pll __initdata = {
> +               .type = PLL_1416X,
> +               .rate_table = imx8mm_pll1416x_tbl,
> +               .rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
> +};
> +
> +static const char *pll_ref_sels[] = { "clock-osc-24m", "dummy", "dummy", "dummy", };
> +static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
> +static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
> +static const char *sys_pll1_bypass_sels[] = {"sys_pll1", "sys_pll1_ref_sel", };
> +static const char *sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", };
> +static const char *sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
> +
> +static const char *imx8mm_a53_sels[] = {"clock-osc-24m", "arm_pll_out", "sys_pll2_500m", "sys_pll2_1000m",
> +                                       "sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "sys_pll3_out", };
> +
> +static const char *imx8mm_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m", "sys_pll1_400m",
> +                                       "sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", };
> +
> +static const char *imx8mm_enet_axi_sels[] = {"clock-osc-24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_250m",
> +                                            "sys_pll2_200m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", };
> +
> +static const char *imx8mm_nand_usdhc_sels[] = {"clock-osc-24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_200m",
> +                                              "sys_pll1_133m", "sys_pll3_out", "sys_pll2_250m", "audio_pll1_out", };
> +
> +static const char *imx8mm_usdhc1_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
> +                                          "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
> +
> +static const char *imx8mm_usdhc2_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
> +                                          "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
> +
> +static const char *imx8mm_i2c1_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
> +                                        "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
> +
> +static const char *imx8mm_i2c2_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
> +                                        "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
> +
> +static const char *imx8mm_i2c3_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
> +                                        "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
> +
> +static const char *imx8mm_i2c4_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
> +                                        "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
> +
> +static const char *imx8mm_wdog_sels[] = {"clock-osc-24m", "sys_pll1_133m", "sys_pll1_160m", "vpu_pll_out",
> +                                        "sys_pll2_125m", "sys_pll3_out", "sys_pll1_80m", "sys_pll2_166m", };
> +
> +static const char *imx8mm_usdhc3_sels[] = {"clock-osc-24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
> +                                          "sys_pll3_out", "sys_pll1_266m", "audio_pll2_clk", "sys_pll1_100m", };
> +
> +static ulong imx8mm_clk_get_rate(struct clk *clk)
> +{
> +       struct clk *c;
> +       int ret;
> +
> +       debug("%s(#%lu)\n", __func__, clk->id);
> +
> +       ret = clk_get_by_id(clk->id, &c);
> +       if (ret)
> +               return ret;
> +
> +       return clk_get_rate(c);
> +}
> +
> +static ulong imx8mm_clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +       struct clk *c;
> +       int ret = 0;

Unneeded initialization.

> +
> +       debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
> +
> +       ret = clk_get_by_id(clk->id, &c);
> +       if (ret)
> +               return ret;
> +
> +       return clk_set_rate(c, rate);
> +}
> +
> +static int __imx8mm_clk_enable(struct clk *clk, bool enable)
> +{
> +       struct clk *c;
> +       int ret = 0;

Same here.


> +
> +       debug("%s(#%lu) en: %d\n", __func__, clk->id, enable);
> +
> +       ret = clk_get_by_id(clk->id, &c);
> +       if (ret)
> +               return ret;
> +
> +       if (enable)
> +               ret = clk_enable(c);
> +       else
> +               ret = clk_disable(c);
> +
> +       return ret;
> +}
> +
> +static int imx8mm_clk_disable(struct clk *clk)
> +{
> +       return __imx8mm_clk_enable(clk, 0);
> +}
> +
> +static int imx8mm_clk_enable(struct clk *clk)
> +{
> +       return __imx8mm_clk_enable(clk, 1);
> +}
> +
> +static struct clk_ops imx8mm_clk_ops = {
> +       .set_rate = imx8mm_clk_set_rate,
> +       .get_rate = imx8mm_clk_get_rate,
> +       .enable = imx8mm_clk_enable,
> +       .disable = imx8mm_clk_disable,
> +};
> +
> +static int imx8mm_clk_probe(struct udevice *dev)
> +{
> +       void __iomem *base;
> +
> +       base = (void *)ANATOP_BASE_ADDR;
> +
> +       clk_dm(IMX8MM_DRAM_PLL_REF_SEL,
> +              imx_clk_mux("dram_pll_ref_sel", base + 0x50, 0, 2,
> +                          pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
> +       clk_dm(IMX8MM_ARM_PLL_REF_SEL,
> +              imx_clk_mux("arm_pll_ref_sel", base + 0x84, 0, 2,
> +                          pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
> +       clk_dm(IMX8MM_SYS_PLL1_REF_SEL,
> +              imx_clk_mux("sys_pll1_ref_sel", base + 0x94, 0, 2,
> +                          pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
> +       clk_dm(IMX8MM_SYS_PLL2_REF_SEL,
> +              imx_clk_mux("sys_pll2_ref_sel", base + 0x104, 0, 2,
> +                          pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
> +       clk_dm(IMX8MM_SYS_PLL3_REF_SEL,
> +              imx_clk_mux("sys_pll3_ref_sel", base + 0x114, 0, 2,
> +                          pll_ref_sels, ARRAY_SIZE(pll_ref_sels)));
> +
> +       clk_dm(IMX8MM_DRAM_PLL,
> +              imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel",
> +                              base + 0x50, &imx8mm_dram_pll));
> +       clk_dm(IMX8MM_ARM_PLL,
> +              imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel",
> +                              base + 0x84, &imx8mm_arm_pll));
> +       clk_dm(IMX8MM_SYS_PLL1,
> +              imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel",
> +                              base + 0x94, &imx8mm_sys_pll));
> +       clk_dm(IMX8MM_SYS_PLL2,
> +              imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel",
> +                              base + 0x104, &imx8mm_sys_pll));
> +       clk_dm(IMX8MM_SYS_PLL3,
> +              imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel",
> +                              base + 0x114, &imx8mm_sys_pll));
> +
> +       /* PLL bypass out */
> +       clk_dm(IMX8MM_DRAM_PLL_BYPASS,
> +              imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 4, 1,
> +                                dram_pll_bypass_sels,
> +                                ARRAY_SIZE(dram_pll_bypass_sels),
> +                                CLK_SET_RATE_PARENT));
> +       clk_dm(IMX8MM_ARM_PLL_BYPASS,
> +              imx_clk_mux_flags("arm_pll_bypass", base + 0x84, 4, 1,
> +                                arm_pll_bypass_sels,
> +                                ARRAY_SIZE(arm_pll_bypass_sels),
> +                                CLK_SET_RATE_PARENT));
> +       clk_dm(IMX8MM_SYS_PLL1_BYPASS,
> +              imx_clk_mux_flags("sys_pll1_bypass", base + 0x94, 4, 1,
> +                                sys_pll1_bypass_sels,
> +                                ARRAY_SIZE(sys_pll1_bypass_sels),
> +                                CLK_SET_RATE_PARENT));
> +       clk_dm(IMX8MM_SYS_PLL2_BYPASS,
> +              imx_clk_mux_flags("sys_pll2_bypass", base + 0x104, 4, 1,
> +                                sys_pll2_bypass_sels,
> +                                ARRAY_SIZE(sys_pll2_bypass_sels),
> +                                CLK_SET_RATE_PARENT));
> +       clk_dm(IMX8MM_SYS_PLL3_BYPASS,
> +              imx_clk_mux_flags("sys_pll3_bypass", base + 0x114, 4, 1,
> +                                sys_pll3_bypass_sels,
> +                                ARRAY_SIZE(sys_pll3_bypass_sels),
> +                                CLK_SET_RATE_PARENT));
> +
> +       /* PLL out gate */
> +       clk_dm(IMX8MM_DRAM_PLL_OUT,
> +              imx_clk_gate("dram_pll_out", "dram_pll_bypass",
> +                           base + 0x50, 13));
> +       clk_dm(IMX8MM_ARM_PLL_OUT,
> +              imx_clk_gate("arm_pll_out", "arm_pll_bypass",
> +                           base + 0x84, 11));
> +       clk_dm(IMX8MM_SYS_PLL1_OUT,
> +              imx_clk_gate("sys_pll1_out", "sys_pll1_bypass",
> +                           base + 0x94, 11));
> +       clk_dm(IMX8MM_SYS_PLL2_OUT,
> +              imx_clk_gate("sys_pll2_out", "sys_pll2_bypass",
> +                           base + 0x104, 11));
> +       clk_dm(IMX8MM_SYS_PLL3_OUT,
> +              imx_clk_gate("sys_pll3_out", "sys_pll3_bypass",
> +                           base + 0x114, 11));
> +
> +       /* SYS PLL fixed output */
> +       clk_dm(IMX8MM_SYS_PLL1_40M,
> +              imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20));
> +       clk_dm(IMX8MM_SYS_PLL1_80M,
> +              imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10));
> +       clk_dm(IMX8MM_SYS_PLL1_100M,
> +              imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8));
> +       clk_dm(IMX8MM_SYS_PLL1_133M,
> +              imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6));
> +       clk_dm(IMX8MM_SYS_PLL1_160M,
> +              imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5));
> +       clk_dm(IMX8MM_SYS_PLL1_200M,
> +              imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4));
> +       clk_dm(IMX8MM_SYS_PLL1_266M,
> +              imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3));
> +       clk_dm(IMX8MM_SYS_PLL1_400M,
> +              imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2));
> +       clk_dm(IMX8MM_SYS_PLL1_800M,
> +              imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1));
> +
> +       clk_dm(IMX8MM_SYS_PLL2_50M,
> +              imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20));
> +       clk_dm(IMX8MM_SYS_PLL2_100M,
> +              imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10));
> +       clk_dm(IMX8MM_SYS_PLL2_125M,
> +              imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8));
> +       clk_dm(IMX8MM_SYS_PLL2_166M,
> +              imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6));
> +       clk_dm(IMX8MM_SYS_PLL2_200M,
> +              imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5));
> +       clk_dm(IMX8MM_SYS_PLL2_250M,
> +              imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4));
> +       clk_dm(IMX8MM_SYS_PLL2_333M,
> +              imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3));
> +       clk_dm(IMX8MM_SYS_PLL2_500M,
> +              imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2));
> +       clk_dm(IMX8MM_SYS_PLL2_1000M,
> +              imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1));
> +
> +       base = dev_read_addr_ptr(dev);
> +       if (base == (void *)FDT_ADDR_T_NONE)
> +               return -EINVAL;
> +
> +       clk_dm(IMX8MM_CLK_A53_SRC,
> +              imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3,
> +                           imx8mm_a53_sels, ARRAY_SIZE(imx8mm_a53_sels)));
> +       clk_dm(IMX8MM_CLK_A53_CG,
> +              imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28));
> +       clk_dm(IMX8MM_CLK_A53_DIV,
> +              imx_clk_divider2("arm_a53_div", "arm_a53_cg",
> +                               base + 0x8000, 0, 3));
> +
> +       clk_dm(IMX8MM_CLK_AHB,
> +              imx8m_clk_composite_critical("ahb", imx8mm_ahb_sels,
> +                                           base + 0x9000));
> +       clk_dm(IMX8MM_CLK_IPG_ROOT,
> +              imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1));
> +
> +       clk_dm(IMX8MM_CLK_ENET_AXI,
> +              imx8m_clk_composite("enet_axi", imx8mm_enet_axi_sels,
> +                                  base + 0x8880));
> +       clk_dm(IMX8MM_CLK_NAND_USDHC_BUS,
> +              imx8m_clk_composite_critical("nand_usdhc_bus",
> +                                           imx8mm_nand_usdhc_sels,
> +                                           base + 0x8900));
> +
> +       /* IP */
> +       clk_dm(IMX8MM_CLK_USDHC1,
> +              imx8m_clk_composite("usdhc1", imx8mm_usdhc1_sels,
> +                                  base + 0xac00));
> +       clk_dm(IMX8MM_CLK_USDHC2,
> +              imx8m_clk_composite("usdhc2", imx8mm_usdhc2_sels,
> +                                  base + 0xac80));
> +       clk_dm(IMX8MM_CLK_I2C1,
> +              imx8m_clk_composite("i2c1", imx8mm_i2c1_sels, base + 0xad00));
> +       clk_dm(IMX8MM_CLK_I2C2,
> +              imx8m_clk_composite("i2c2", imx8mm_i2c2_sels, base + 0xad80));
> +       clk_dm(IMX8MM_CLK_I2C3,
> +              imx8m_clk_composite("i2c3", imx8mm_i2c3_sels, base + 0xae00));
> +       clk_dm(IMX8MM_CLK_I2C4,
> +              imx8m_clk_composite("i2c4", imx8mm_i2c4_sels, base + 0xae80));
> +       clk_dm(IMX8MM_CLK_WDOG,
> +              imx8m_clk_composite("wdog", imx8mm_wdog_sels, base + 0xb900));
> +       clk_dm(IMX8MM_CLK_USDHC3,
> +              imx8m_clk_composite("usdhc3", imx8mm_usdhc3_sels,
> +                                  base + 0xbc80));
> +
> +       clk_dm(IMX8MM_CLK_I2C1_ROOT,
> +              imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0));
> +       clk_dm(IMX8MM_CLK_I2C2_ROOT,
> +              imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0));
> +       clk_dm(IMX8MM_CLK_I2C3_ROOT,
> +              imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0));
> +       clk_dm(IMX8MM_CLK_I2C4_ROOT,
> +              imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0));
> +       clk_dm(IMX8MM_CLK_OCOTP_ROOT,
> +              imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0));
> +       clk_dm(IMX8MM_CLK_USDHC1_ROOT,
> +              imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0));
> +       clk_dm(IMX8MM_CLK_USDHC2_ROOT,
> +              imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0));
> +       clk_dm(IMX8MM_CLK_WDOG1_ROOT,
> +              imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0));
> +       clk_dm(IMX8MM_CLK_WDOG2_ROOT,
> +              imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0));
> +       clk_dm(IMX8MM_CLK_WDOG3_ROOT,
> +              imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0));
> +       clk_dm(IMX8MM_CLK_USDHC3_ROOT,
> +              imx_clk_gate4("usdhc3_root_clk", "usdhc3", base + 0x45e0, 0));
> +
> +#ifdef CONFIG_SPL_BUILD
> +       struct clk *clkp, *clkp1;
> +
> +       clk_get_by_id(IMX8MM_CLK_WDOG1_ROOT, &clkp);
> +       clk_enable(clkp);
> +       clk_get_by_id(IMX8MM_CLK_WDOG2_ROOT, &clkp);
> +       clk_enable(clkp);
> +       clk_get_by_id(IMX8MM_CLK_WDOG3_ROOT, &clkp);
> +       clk_enable(clkp);
> +
> +       /* Configure SYS_PLL3 to 750MHz */
> +       clk_get_by_id(IMX8MM_SYS_PLL3, &clkp);
> +       clk_set_rate(clkp, 750000000UL);
> +       clk_enable(clkp);
> +
> +       /* Configure ARM to sys_pll2_500m */
> +       clk_get_by_id(IMX8MM_CLK_A53_SRC, &clkp);
> +       clk_get_by_id(IMX8MM_SYS_PLL2_OUT, &clkp1);
> +       clk_enable(clkp1);
> +       clk_get_by_id(IMX8MM_SYS_PLL2_500M, &clkp1);
> +       clk_set_parent(clkp, clkp1);
> +
> +       /* Configure ARM PLL to 1.2GHz */
> +       clk_get_by_id(IMX8MM_ARM_PLL, &clkp1);
> +       clk_set_rate(clkp1, 1200000000UL);
> +       clk_get_by_id(IMX8MM_ARM_PLL_OUT, &clkp1);
> +       clk_enable(clkp1);
> +       clk_set_parent(clkp, clkp1);
> +
> +       /* Configure DIV to 1.2GHz */
> +       clk_get_by_id(IMX8MM_CLK_A53_DIV, &clkp1);
> +       clk_set_rate(clkp1, 1200000000UL);
> +#endif
> +
> +       return 0;
> +}
> +
> +static const struct udevice_id imx8mm_clk_ids[] = {
> +       { .compatible = "fsl,imx8mm-ccm" },
> +       { },
> +};
> +
> +U_BOOT_DRIVER(imx8mm_clk) = {
> +       .name = "clk_imx8mm",
> +       .id = UCLASS_CLK,
> +       .of_match = imx8mm_clk_ids,
> +       .ops = &imx8mm_clk_ops,
> +       .probe = imx8mm_clk_probe,
> +       .flags = DM_FLAG_PRE_RELOC,
> +};
> --
> 2.16.4
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 1/4] clk: imx: add Kconfig entry for i.MX8MM
  2019-08-09 16:50   ` Fabio Estevam
@ 2019-08-13  9:07     ` Peng Fan
  2019-08-13  9:41       ` Lukasz Majewski
  0 siblings, 1 reply; 16+ messages in thread
From: Peng Fan @ 2019-08-13  9:07 UTC (permalink / raw)
  To: u-boot

Hi Lukasz,

> Subject: Re: [PATCH V3 1/4] clk: imx: add Kconfig entry for i.MX8MM
> 
> Hi Peng,
> 
> On Fri, Aug 9, 2019 at 5:02 AM Peng Fan <peng.fan@nxp.com> wrote:
> >
> > Add Kconfig entry for i.MX8MM
> >
> > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > ---
> >  drivers/clk/Kconfig     |  4 ++--
> >  drivers/clk/imx/Kconfig | 16 ++++++++++++++++
> >  2 files changed, 18 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index
> > a3f0171b45..fce595b4b3 100644
> > --- a/drivers/clk/Kconfig
> > +++ b/drivers/clk/Kconfig
> > @@ -48,7 +48,7 @@ config CLK_BOSTON
> >
> >  config SPL_CLK_CCF
> >         bool "SPL Common Clock Framework [CCF] support "
> > -       depends on SPL_CLK_IMX6Q
> > +       depends on SPL_CLK_IMX6Q || ARCH_IMX8M
> 
> I am wondering why this depends on i.MX. Shouldn't it be SoC agnostic?

Are you ok to expose the Kconfig for all with remove the depends on?

Thanks
Peng

> 
> >         help
> >           Enable this option if you want to (re-)use the Linux kernel's
> Common
> >           Clock Framework [CCF] code in U-Boot's SPL.
> > @@ -62,7 +62,7 @@ config SPL_CLK_COMPOSITE_CCF
> >
> >  config CLK_CCF
> >         bool "Common Clock Framework [CCF] support "
> > -       depends on CLK_IMX6Q || SANDBOX_CLK_CCF
> > +       depends on CLK_IMX6Q || ARCH_IMX8M || SANDBOX_CLK_CCF
> 
> Same here.
> 
> It doesn't look like a good idea to keep expanding this Kconfig every time a
> new SoC wants to use the CCF.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 3/4] clk: imx: add i.MX8M composite clk support
  2019-08-09 16:59   ` Fabio Estevam
@ 2019-08-13  9:37     ` Peng Fan
  0 siblings, 0 replies; 16+ messages in thread
From: Peng Fan @ 2019-08-13  9:37 UTC (permalink / raw)
  To: u-boot

> Subject: Re: [PATCH V3 3/4] clk: imx: add i.MX8M composite clk support
> 
> On Fri, Aug 9, 2019 at 5:02 AM Peng Fan <peng.fan@nxp.com> wrote:
> 
> > + * The clk are not binded to a dev, because it is part of composite
> > + clk
> 
> s/binded/bound

Fix in V4.

> 
> > + * use composite clk to get dev
> > + */
> > +static ulong imx8m_clk_composite_divider_set_rate(struct clk *clk,
> > +                                                 unsigned long
> rate)
> > +{
> > +       struct clk_divider *divider = (struct clk_divider
> *)to_clk_divider(clk);
> > +       struct clk_composite *composite = (struct clk_composite
> *)clk->data;
> > +       ulong parent_rate = clk_get_parent_rate(&composite->clk);
> > +       int prediv_value;
> > +       int div_value;
> > +       int ret;
> > +       u32 val;
> > +
> > +       ret = imx8m_clk_composite_compute_dividers(rate, parent_rate,
> > +
> &prediv_value, &div_value);
> > +       if (ret)
> > +               return -EINVAL;
> 
> What about returning ret directly instead?

As wrote in commit log. The code was imported from Linux,
I would not modify this.

> 
> 
> > +struct clk *imx8m_clk_composite_flags(const char *name,
> > +                                     const char * const
> *parent_names,
> > +                                     int num_parents, void
> __iomem *reg,
> > +                                     unsigned long flags) {
> > +       struct clk *clk = ERR_PTR(-ENOMEM);
> > +       struct clk_divider *div = NULL;
> > +       struct clk_gate *gate = NULL;
> > +       struct clk_mux *mux = NULL;
> 
> Why all these NULL assignments?

Explained above.

> 
> > +
> > +       mux = kzalloc(sizeof(*mux), GFP_KERNEL);
> > +       if (!mux)
> > +               goto fail;
> 
> It would be better like this:

Ditto

> 
>        mux = kzalloc(sizeof(*mux), GFP_KERNEL);
>        if (!mux)
>                return ERR_PTR(-ENOMEM);
> 
> > +
> > +       mux->reg = reg;
> > +       mux->shift = PCG_PCS_SHIFT;
> > +       mux->mask = PCG_PCS_MASK;
> > +       mux->num_parents = num_parents;
> > +       mux->flags = flags;
> > +       mux->parent_names = parent_names;
> > +
> > +       div = kzalloc(sizeof(*div), GFP_KERNEL);
> > +       if (!div)
> > +               goto fail;
> > +
> > +       div->reg = reg;
> > +       div->shift = PCG_PREDIV_SHIFT;
> > +       div->width = PCG_PREDIV_WIDTH;
> > +       div->flags = CLK_DIVIDER_ROUND_CLOSEST | flags;
> > +
> > +       gate = kzalloc(sizeof(*gate), GFP_KERNEL);
> > +       if (!gate)
> > +               goto fail;
> > +
> > +       gate->reg = reg;
> > +       gate->bit_idx = PCG_CGC_SHIFT;
> > +       gate->flags = flags;
> > +
> > +       clk = clk_register_composite(NULL, name,
> > +                                    parent_names, num_parents,
> > +                                    &mux->clk, &clk_mux_ops,
> &div->clk,
> > +
> &imx8m_clk_composite_divider_ops,
> > +                                    &gate->clk, &clk_gate_ops,
> flags);
> > +       if (IS_ERR(clk))
> > +               goto fail;
> > +
> > +       return clk;
> > +
> > +fail:
> > +       kfree(gate);
> > +       kfree(div);
> > +       kfree(mux);
> > +       return ERR_CAST(clk);
> 
> ERR_CAST(clk) is only valid when for the IS_ERR(clk) path.
> 
> Please rework the error handling.

Ditto.

Thanks,
Peng.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [U-Boot] [PATCH V3 1/4] clk: imx: add Kconfig entry for i.MX8MM
  2019-08-13  9:07     ` Peng Fan
@ 2019-08-13  9:41       ` Lukasz Majewski
  0 siblings, 0 replies; 16+ messages in thread
From: Lukasz Majewski @ 2019-08-13  9:41 UTC (permalink / raw)
  To: u-boot

On Tue, 13 Aug 2019 09:07:03 +0000
Peng Fan <peng.fan@nxp.com> wrote:

> Hi Lukasz,
> 
> > Subject: Re: [PATCH V3 1/4] clk: imx: add Kconfig entry for i.MX8MM
> > 
> > Hi Peng,
> > 
> > On Fri, Aug 9, 2019 at 5:02 AM Peng Fan <peng.fan@nxp.com> wrote:  
> > >
> > > Add Kconfig entry for i.MX8MM
> > >
> > > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > > ---
> > >  drivers/clk/Kconfig     |  4 ++--
> > >  drivers/clk/imx/Kconfig | 16 ++++++++++++++++
> > >  2 files changed, 18 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index
> > > a3f0171b45..fce595b4b3 100644
> > > --- a/drivers/clk/Kconfig
> > > +++ b/drivers/clk/Kconfig
> > > @@ -48,7 +48,7 @@ config CLK_BOSTON
> > >
> > >  config SPL_CLK_CCF
> > >         bool "SPL Common Clock Framework [CCF] support "
> > > -       depends on SPL_CLK_IMX6Q
> > > +       depends on SPL_CLK_IMX6Q || ARCH_IMX8M  
> > 
> > I am wondering why this depends on i.MX. Shouldn't it be SoC
> > agnostic?  
> 
> Are you ok to expose the Kconfig for all with remove the depends on?
> 

If it doesn't harm other SoCs I'm fine with it (but please check it
first).

I will review those patches tonight, or tomorrow morning.

> Thanks
> Peng
> 
> >   
> > >         help
> > >           Enable this option if you want to (re-)use the Linux
> > > kernel's  
> > Common  
> > >           Clock Framework [CCF] code in U-Boot's SPL.
> > > @@ -62,7 +62,7 @@ config SPL_CLK_COMPOSITE_CCF
> > >
> > >  config CLK_CCF
> > >         bool "Common Clock Framework [CCF] support "
> > > -       depends on CLK_IMX6Q || SANDBOX_CLK_CCF
> > > +       depends on CLK_IMX6Q || ARCH_IMX8M || SANDBOX_CLK_CCF  
> > 
> > Same here.
> > 
> > It doesn't look like a good idea to keep expanding this Kconfig
> > every time a new SoC wants to use the CCF.  



Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190813/18d9ae75/attachment.sig>

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2019-08-13  9:41 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-09  8:02 [U-Boot] [PATCH V3 0/4] Prepare i.MX8MM clk Peng Fan
2019-08-09  8:02 ` [U-Boot] [PATCH V3 1/4] clk: imx: add Kconfig entry for i.MX8MM Peng Fan
2019-08-09  8:56   ` Ye Li
2019-08-09 16:50   ` Fabio Estevam
2019-08-13  9:07     ` Peng Fan
2019-08-13  9:41       ` Lukasz Majewski
2019-08-09  8:02 ` [U-Boot] [PATCH V3 2/4] clk: imx: add pll14xx driver Peng Fan
2019-08-09  9:05   ` Ye Li
2019-08-09 16:51   ` Fabio Estevam
2019-08-09  8:02 ` [U-Boot] [PATCH V3 3/4] clk: imx: add i.MX8M composite clk support Peng Fan
2019-08-09  9:08   ` Ye Li
2019-08-09 16:59   ` Fabio Estevam
2019-08-13  9:37     ` Peng Fan
2019-08-09  8:02 ` [U-Boot] [PATCH V3 4/4] clk: imx: add i.MX8MM clk driver Peng Fan
2019-08-09  9:10   ` Ye Li
2019-08-09 21:02   ` Fabio Estevam

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.