[U-Boot] [PATCH 14/15] ARM: uniphier: add PLL init code for LD20 SoC

Masahiro Yamada yamada.masahiro at socionext.com
Fri Sep 16 20:33:11 CEST 2016


Initialize the DPLL (PLL for DRAM) in SPL, and others in U-Boot
proper.  Split the common code into pll-base-ld20.c for easier
re-use.

Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
---

 arch/arm/mach-uniphier/board_init.c        |   7 ++
 arch/arm/mach-uniphier/clk/Makefile        |   6 +-
 arch/arm/mach-uniphier/clk/dpll-ld20.c     |  22 ++++++
 arch/arm/mach-uniphier/clk/pll-base-ld20.c | 123 +++++++++++++++++++++++++++++
 arch/arm/mach-uniphier/clk/pll-ld20.c      |  40 ++++++++++
 arch/arm/mach-uniphier/clk/pll.h           |   8 ++
 arch/arm/mach-uniphier/init.h              |   5 ++
 arch/arm/mach-uniphier/init/init-ld20.c    |   6 +-
 arch/arm/mach-uniphier/sc64-regs.h         |  19 +++++
 9 files changed, 232 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/mach-uniphier/clk/dpll-ld20.c
 create mode 100644 arch/arm/mach-uniphier/clk/pll-base-ld20.c
 create mode 100644 arch/arm/mach-uniphier/clk/pll-ld20.c

diff --git a/arch/arm/mach-uniphier/board_init.c b/arch/arm/mach-uniphier/board_init.c
index a1c7541..b57a33f 100644
--- a/arch/arm/mach-uniphier/board_init.c
+++ b/arch/arm/mach-uniphier/board_init.c
@@ -58,8 +58,14 @@ static void uniphier_nand_pin_init(bool cs2)
 
 int board_init(void)
 {
+	const struct uniphier_board_data *bd;
+
 	led_puts("U0");
 
+	bd = uniphier_get_board_param();
+	if (!bd)
+		return -ENODEV;
+
 	switch (uniphier_get_soc_type()) {
 #if defined(CONFIG_ARCH_UNIPHIER_SLD3)
 	case SOC_UNIPHIER_SLD3:
@@ -133,6 +139,7 @@ int board_init(void)
 		sg_set_pinsel(153, 14, 8, 4);	/* XIRQ4    -> XIRQ4 */
 		sg_set_iectrl(153);
 		led_puts("U1");
+		uniphier_ld20_pll_init(bd);
 		uniphier_ld20_clk_init();
 		cci500_init(2);
 		break;
diff --git a/arch/arm/mach-uniphier/clk/Makefile b/arch/arm/mach-uniphier/clk/Makefile
index 233e659..c8d59ea 100644
--- a/arch/arm/mach-uniphier/clk/Makefile
+++ b/arch/arm/mach-uniphier/clk/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_ARCH_UNIPHIER_PRO5)	+= early-clk-pro5.o
 obj-$(CONFIG_ARCH_UNIPHIER_PXS2)	+= early-clk-pxs2.o
 obj-$(CONFIG_ARCH_UNIPHIER_LD6B)	+= early-clk-pxs2.o
 obj-$(CONFIG_ARCH_UNIPHIER_LD11)	+= early-clk-ld11.o
-obj-$(CONFIG_ARCH_UNIPHIER_LD20)	+= early-clk-ld20.o
+obj-$(CONFIG_ARCH_UNIPHIER_LD20)	+= early-clk-ld20.o dpll-ld20.o
 
 else
 
@@ -24,6 +24,8 @@ obj-$(CONFIG_ARCH_UNIPHIER_PRO5)	+= clk-pro5.o
 obj-$(CONFIG_ARCH_UNIPHIER_PXS2)	+= clk-pxs2.o
 obj-$(CONFIG_ARCH_UNIPHIER_LD6B)	+= clk-pxs2.o
 obj-$(CONFIG_ARCH_UNIPHIER_LD11)	+= clk-ld11.o
-obj-$(CONFIG_ARCH_UNIPHIER_LD20)	+= clk-ld20.o
+obj-$(CONFIG_ARCH_UNIPHIER_LD20)	+= clk-ld20.o pll-ld20.o
 
 endif
+
+obj-$(CONFIG_ARCH_UNIPHIER_LD20)	+= pll-base-ld20.o
diff --git a/arch/arm/mach-uniphier/clk/dpll-ld20.c b/arch/arm/mach-uniphier/clk/dpll-ld20.c
new file mode 100644
index 0000000..1132313
--- /dev/null
+++ b/arch/arm/mach-uniphier/clk/dpll-ld20.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "../init.h"
+#include "../sc64-regs.h"
+#include "pll.h"
+
+int uniphier_ld20_dpll_init(const struct uniphier_board_data *bd)
+{
+	unsigned int dpll_ssc_rate = UNIPHIER_BD_DPLL_SSC_GET_RATE(bd->flags);
+	unsigned int dram_freq = bd->dram_freq;
+
+	uniphier_ld20_sscpll_init(SC_DPLL0CTRL, dram_freq, dpll_ssc_rate, 2);
+	uniphier_ld20_sscpll_init(SC_DPLL1CTRL, dram_freq, dpll_ssc_rate, 2);
+	uniphier_ld20_sscpll_init(SC_DPLL2CTRL, dram_freq, dpll_ssc_rate, 2);
+
+	return 0;
+}
diff --git a/arch/arm/mach-uniphier/clk/pll-base-ld20.c b/arch/arm/mach-uniphier/clk/pll-base-ld20.c
new file mode 100644
index 0000000..a5027d2
--- /dev/null
+++ b/arch/arm/mach-uniphier/clk/pll-base-ld20.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+#include "pll.h"
+
+/* PLL type: SSC */
+#define SC_PLLCTRL_SSC_DK_MASK		GENMASK(14, 0)
+#define SC_PLLCTRL_SSC_EN		BIT(31)
+#define SC_PLLCTRL2_NRSTDS		BIT(28)
+#define SC_PLLCTRL2_SSC_JK_MASK		GENMASK(26, 0)
+
+/* PLL type: VPLL27 */
+#define SC_VPLL27CTRL_WP		BIT(0)
+#define SC_VPLL27CTRL3_K_LD		BIT(28)
+
+/* PLL type: DSPLL */
+#define SC_DSPLLCTRL2_K_LD		BIT(28)
+
+int uniphier_ld20_sscpll_init(unsigned long reg_base, unsigned int freq,
+			      unsigned int ssc_rate, unsigned int divn)
+{
+	void __iomem *base;
+	u32 tmp;
+
+	base = ioremap(reg_base, SZ_16);
+	if (!base)
+		return -ENOMEM;
+
+	if (freq != UNIPHIER_PLL_FREQ_DEFAULT) {
+		tmp = readl(base);	/* SSCPLLCTRL */
+		tmp &= ~SC_PLLCTRL_SSC_DK_MASK;
+		tmp |= (487 * freq * ssc_rate / divn / 512) &
+							SC_PLLCTRL_SSC_DK_MASK;
+		writel(tmp, base);
+
+		tmp = readl(base + 4);
+		tmp &= ~SC_PLLCTRL2_SSC_JK_MASK;
+		tmp |= (41859 * freq / divn) & SC_PLLCTRL2_SSC_JK_MASK;
+
+		udelay(50);
+	}
+
+	tmp = readl(base + 4);		/* SSCPLLCTRL2 */
+	tmp |= SC_PLLCTRL2_NRSTDS;
+	writel(tmp, base + 4);
+
+	iounmap(base);
+
+	return 0;
+}
+
+int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base)
+{
+	void __iomem *base;
+	u32 tmp;
+
+	base = ioremap(reg_base, SZ_16);
+	if (!base)
+		return -ENOMEM;
+
+	mdelay(1);
+
+	tmp = readl(base);	/* SSCPLLCTRL */
+	tmp |= SC_PLLCTRL_SSC_EN;
+	writel(tmp, base);
+
+	iounmap(base);
+
+	return 0;
+}
+
+int uniphier_ld20_vpll27_init(unsigned long reg_base)
+{
+	void __iomem *base;
+	u32 tmp;
+
+	base = ioremap(reg_base, SZ_16);
+	if (!base)
+		return -ENOMEM;
+
+	tmp = readl(base);		/* VPLL27CTRL */
+	tmp |= SC_VPLL27CTRL_WP;	/* write protect off */
+	writel(tmp, base);
+
+	tmp = readl(base + 8);		/* VPLL27CTRL3 */
+	tmp |= SC_VPLL27CTRL3_K_LD;
+	writel(tmp, base + 8);
+
+	tmp = readl(base);		/* VPLL27CTRL */
+	tmp &= ~SC_VPLL27CTRL_WP;	/* write protect on */
+	writel(tmp, base);
+
+	iounmap(base);
+
+	return 0;
+}
+
+int uniphier_ld20_dspll_init(unsigned long reg_base)
+{
+	void __iomem *base;
+	u32 tmp;
+
+	base = ioremap(reg_base, SZ_16);
+	if (!base)
+		return -ENOMEM;
+
+	tmp = readl(base + 8);		/* DSPLLCTRL2 */
+	tmp |= SC_DSPLLCTRL2_K_LD;
+	writel(tmp, base + 8);
+
+	iounmap(base);
+
+	return 0;
+}
diff --git a/arch/arm/mach-uniphier/clk/pll-ld20.c b/arch/arm/mach-uniphier/clk/pll-ld20.c
new file mode 100644
index 0000000..5e545da
--- /dev/null
+++ b/arch/arm/mach-uniphier/clk/pll-ld20.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+
+#include "../init.h"
+#include "../sc64-regs.h"
+#include "pll.h"
+
+int uniphier_ld20_pll_init(const struct uniphier_board_data *bd)
+{
+	unsigned int dpll_ssc_rate = UNIPHIER_BD_DPLL_SSC_GET_RATE(bd->flags);
+
+	uniphier_ld20_sscpll_init(SC_CPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 4);
+	/* do nothing for SPLL */
+	uniphier_ld20_sscpll_init(SC_SPLL2CTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 4);
+	uniphier_ld20_sscpll_init(SC_MPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2);
+	uniphier_ld20_sscpll_init(SC_VPPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 4);
+	uniphier_ld20_sscpll_init(SC_GPPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2);
+
+	mdelay(1);
+
+	if (dpll_ssc_rate > 0) {
+		uniphier_ld20_sscpll_ssc_en(SC_DPLL0CTRL);
+		uniphier_ld20_sscpll_ssc_en(SC_DPLL1CTRL);
+		uniphier_ld20_sscpll_ssc_en(SC_DPLL2CTRL);
+	}
+
+	uniphier_ld20_vpll27_init(SC_VPLL27FCTRL);
+	uniphier_ld20_vpll27_init(SC_VPLL27ACTRL);
+
+	uniphier_ld20_dspll_init(SC_VPLL8KCTRL);
+	uniphier_ld20_dspll_init(SC_A2PLLCTRL);
+
+	return 0;
+}
diff --git a/arch/arm/mach-uniphier/clk/pll.h b/arch/arm/mach-uniphier/clk/pll.h
index ef0f722..d7e9303 100644
--- a/arch/arm/mach-uniphier/clk/pll.h
+++ b/arch/arm/mach-uniphier/clk/pll.h
@@ -8,6 +8,14 @@
 #ifndef MACH_PLL_H
 #define MACH_PLL_H
 
+#define UNIPHIER_PLL_FREQ_DEFAULT	(0)
+
 void uniphier_ld4_dpll_ssc_en(void);
 
+int uniphier_ld20_sscpll_init(unsigned long reg_base, unsigned int freq,
+			      unsigned int ssc_rate, unsigned int divn);
+int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base);
+int uniphier_ld20_vpll27_init(unsigned long reg_base);
+int uniphier_ld20_dspll_init(unsigned long reg_base);
+
 #endif /* MACH_PLL_H */
diff --git a/arch/arm/mach-uniphier/init.h b/arch/arm/mach-uniphier/init.h
index d8f5b49..5c7cd6b 100644
--- a/arch/arm/mach-uniphier/init.h
+++ b/arch/arm/mach-uniphier/init.h
@@ -24,6 +24,9 @@ struct uniphier_board_data {
 	struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH];
 	unsigned int flags;
 
+#define UNIPHIER_BD_DPLL_SSC_GET_RATE(f)	(((f) >> 8) & 0x3)
+#define UNIPHIER_BD_DPLL_SSC_RATE(r)		(((r) & 0x3) << 8)
+
 #define UNIPHIER_BD_DDR3PLUS			BIT(2)
 
 #define UNIPHIER_BD_BOARD_GET_TYPE(f)		((f) & 0x3)
@@ -84,6 +87,7 @@ int uniphier_sld3_dpll_init(const struct uniphier_board_data *bd);
 int uniphier_ld4_dpll_init(const struct uniphier_board_data *bd);
 int uniphier_pro4_dpll_init(const struct uniphier_board_data *bd);
 int uniphier_sld8_dpll_init(const struct uniphier_board_data *bd);
+int uniphier_ld20_dpll_init(const struct uniphier_board_data *bd);
 
 int uniphier_ld4_early_clk_init(const struct uniphier_board_data *bd);
 int uniphier_pro5_early_clk_init(const struct uniphier_board_data *bd);
@@ -101,6 +105,7 @@ int uniphier_ld11_umc_init(const struct uniphier_board_data *bd);
 void uniphier_sld3_pll_init(void);
 void uniphier_ld4_pll_init(void);
 void uniphier_pro4_pll_init(void);
+int uniphier_ld20_pll_init(const struct uniphier_board_data *bd);
 
 void uniphier_ld4_clk_init(void);
 void uniphier_pro4_clk_init(void);
diff --git a/arch/arm/mach-uniphier/init/init-ld20.c b/arch/arm/mach-uniphier/init/init-ld20.c
index f23ca09..3add75f 100644
--- a/arch/arm/mach-uniphier/init/init-ld20.c
+++ b/arch/arm/mach-uniphier/init/init-ld20.c
@@ -31,12 +31,14 @@ int uniphier_ld20_init(const struct uniphier_board_data *bd)
 
 	led_puts("L2");
 
-	led_puts("L3");
-
 #ifdef CONFIG_SPL_SERIAL_SUPPORT
 	preloader_console_init();
 #endif
 
+	led_puts("L3");
+
+	uniphier_ld20_dpll_init(bd);
+
 	led_puts("L4");
 
 	{
diff --git a/arch/arm/mach-uniphier/sc64-regs.h b/arch/arm/mach-uniphier/sc64-regs.h
index ef02830..08dc613 100644
--- a/arch/arm/mach-uniphier/sc64-regs.h
+++ b/arch/arm/mach-uniphier/sc64-regs.h
@@ -11,6 +11,25 @@
 
 #define SC_BASE_ADDR		0x61840000
 
+/* PLL type: SSC */
+#define SC_CPLLCTRL	(SC_BASE_ADDR | 0x1400)	/* LD20: CPU/ARM */
+#define SC_SPLLCTRL	(SC_BASE_ADDR | 0x1410)	/* LD20: misc */
+#define SC_SPLL2CTRL	(SC_BASE_ADDR | 0x1420)	/* LD20: IPP */
+#define SC_MPLLCTRL	(SC_BASE_ADDR | 0x1430)	/* LD20: Video codec */
+#define SC_VPPLLCTRL	(SC_BASE_ADDR | 0x1440)	/* LD20: VPE etc. */
+#define SC_GPPLLCTRL	(SC_BASE_ADDR | 0x1450)	/* LD20: GPU/Mali */
+#define SC_DPLL0CTRL	(SC_BASE_ADDR | 0x1460)	/* LD20: DDR memory 0 */
+#define SC_DPLL1CTRL	(SC_BASE_ADDR | 0x1470)	/* LD20: DDR memory 1 */
+#define SC_DPLL2CTRL	(SC_BASE_ADDR | 0x1480)	/* LD20: DDR memory 2 */
+
+/* PLL type: VPLL27 */
+#define SC_VPLL27FCTRL	(SC_BASE_ADDR | 0x1500)
+#define SC_VPLL27ACTRL	(SC_BASE_ADDR | 0x1520)
+
+/* PLL type: DSPLL */
+#define SC_VPLL8KCTRL	(SC_BASE_ADDR | 0x1540)
+#define SC_A2PLLCTRL	(SC_BASE_ADDR | 0x15C0)
+
 #define SC_RSTCTRL		(SC_BASE_ADDR | 0x2000)
 #define SC_RSTCTRL3		(SC_BASE_ADDR | 0x2008)
 #define SC_RSTCTRL4		(SC_BASE_ADDR | 0x200c)
-- 
1.9.1



More information about the U-Boot mailing list