[U-Boot] [PATCH 07/14] arm: socfpga: agilex: Add clock manager support

Ley Foon Tan ley.foon.tan at intel.com
Fri May 10 05:54:41 UTC 2019


Add clock manager support for Agilex.

Signed-off-by: Chee Hong Ang <chee.hong.ang at intel.com>
Signed-off-by: Ley Foon Tan <ley.foon.tan at intel.com>
---
 arch/arm/mach-socfpga/Makefile                |   4 +
 arch/arm/mach-socfpga/clock_manager_agilex.c  | 582 ++++++++++++++++++
 .../mach-socfpga/include/mach/clock_manager.h |   2 +
 .../include/mach/clock_manager_agilex.h       | 328 ++++++++++
 4 files changed, 916 insertions(+)
 create mode 100644 arch/arm/mach-socfpga/clock_manager_agilex.c
 create mode 100644 arch/arm/mach-socfpga/include/mach/clock_manager_agilex.h

diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
index 11370cf4c4..5bb36d07df 100644
--- a/arch/arm/mach-socfpga/Makefile
+++ b/arch/arm/mach-socfpga/Makefile
@@ -40,6 +40,10 @@ obj-y	+= wrap_pinmux_config_s10.o
 obj-y	+= wrap_pll_config_s10.o
 endif
 
+ifdef CONFIG_TARGET_SOCFPGA_AGILEX
+obj-y	+= clock_manager_agilex.o
+endif
+
 ifdef CONFIG_SPL_BUILD
 ifdef CONFIG_TARGET_SOCFPGA_GEN5
 obj-y	+= spl_gen5.o
diff --git a/arch/arm/mach-socfpga/clock_manager_agilex.c b/arch/arm/mach-socfpga/clock_manager_agilex.c
new file mode 100644
index 0000000000..d45827fd27
--- /dev/null
+++ b/arch/arm/mach-socfpga/clock_manager_agilex.c
@@ -0,0 +1,582 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/clock_manager.h>
+#include <asm/arch/system_manager.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct socfpga_system_manager *sysmgr_regs =
+		(struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
+
+/* Default clock manager settings for handoff structure */
+const struct cm_config cm_default_handoff = {
+	/* main group */
+	/* main_pll_mpuclk: src = MAIN, cnt = 0 */
+	0x00000000,
+	/* main_pll_nocclk: src = PERI */
+	0x00010000,
+	/* main_pll_nocdiv:
+	 * cspdbgclk = Div4, cstraceckj = Div1, csclk = Div1
+	 * l4spclk = Div4, l4mpclk = Div2, l4mainclk = Div1
+	 */
+	0x10020100,
+	/* main_pll_pllglob: arefclkdiv = 1, drefclkdiv = 0, modclkdiv = 5 */
+	0x15000101,
+	/* main_pll_fdbck: fdiv = 0 */
+	0x00000000,
+	/* main_pll_pllc0: div = 3 */
+	0x00000003 | CLKMGR_PLLCX_EN_SET_MSK,
+	/* main_pll_pllc1: div = 8, mute = 1 */
+	(0x10000008 & ~CLKMGR_PLLCX_MUTE_SET_MSK) | CLKMGR_PLLCX_EN_SET_MSK,
+	/* main_pll_pllc2: div = 6 */
+	0x00000006 | CLKMGR_PLLCX_EN_SET_MSK,
+	/* main_pll_pllc3: div = 15, mute = 1 */
+	(0x1000000f & ~CLKMGR_PLLCX_MUTE_SET_MSK) | CLKMGR_PLLCX_EN_SET_MSK,
+	/* main_pll_pllm: mdiv = 120 */
+	0x00000078,
+
+	/* peripheral group */
+	/* per_pll_emacctl:
+	 * emac0sel = EMACA, emac1sel = EMACA, emac2sel = EMACA
+	 */
+	0x00000000,
+	/* per_pll_gpiodiv: gpiodbclk = 1 */
+	0x00000001,
+	/* per_pll_pllglob: arefclkdiv = 1, drefclkdiv = 0, modclkdiv = 4 */
+	0x14000101,
+	/* per_pll_fdbck: fdiv = 0 */
+	0x22000000,
+	/* per_pll_pllc0: div = 2, mute = 1 */
+	(0x10000002 & ~CLKMGR_PLLCX_MUTE_SET_MSK) | CLKMGR_PLLCX_EN_SET_MSK,
+	/* per_pll_pllc1: div = 6 */
+	0x00000006 | CLKMGR_PLLCX_EN_SET_MSK,
+	/* per_pll_pllc2: div = 5, mute = 1 */
+	(0x10000005 & ~CLKMGR_PLLCX_MUTE_SET_MSK) | CLKMGR_PLLCX_EN_SET_MSK,
+	/* per_pll_pllc3: div = 12 */
+	0x0000000c | CLKMGR_PLLCX_EN_SET_MSK,
+	/* per_pll_pllm: mdiv = 96 */
+	0x00000060,
+
+	/* altera group */
+	/* alt_emacactr: src = MAIN, cnt = 1 */
+	0x00000001,
+	/* alt_emacbctr: src = PERI, cnt = 3 */
+	0x00010003,
+	/* alt_emacptpctr: src = PERI, cnt = 1 */
+	0x00010001,
+	/* alt_gpiodbctr: src = PERI, cnt = 0 */
+	0x00010000,
+	/* alt_sdmmcctr: src = PERI, cnt = 0 */
+	0x00010000,
+	/* alt_s2fuser0ctr: src = MAIN, cnt = 0 */
+	0x00000000,
+	/* alt_s2fuser1ctr: src = MAIN, cnt = 0 */
+	0x00000000,
+	/* alt_psirefctr: src = MAIN, cnt = 0 */
+	0x00000000,
+
+	/* incoming clock */
+	/* hps_osc_clk_hz: 25MHz */
+	0x017d7840,
+	/* fpga_clk_hz: 200MHz */
+	0x0bebc200,
+	/* unused */
+	{
+		0xffffffff,
+		0xffffffff,
+		0xffffffff
+	}
+};
+
+/*
+ * function to write the bypass register which requires a poll of the
+ * busy bit
+ */
+static void cm_write_bypass_mainpll(u32 val)
+{
+	CM_REG_WRITEL(val, CM_MAINPLL_REG_BYPASS);
+	cm_wait_for_fsm();
+}
+
+static void cm_write_bypass_perpll(u32 val)
+{
+	CM_REG_WRITEL(val, CM_PERPLL_REG_BYPASS);
+	cm_wait_for_fsm();
+}
+
+/* function to write the ctrl register which requires a poll of the busy bit */
+static void cm_write_ctrl(u32 val)
+{
+	CM_REG_WRITEL(val, CM_REG_CTRL);
+	cm_wait_for_fsm();
+}
+
+#define MEMBUS_MAINPLL				0
+#define MEMBUS_PERPLL				1
+#define MEMBUS_TIMEOUT				1000
+#define MEMBUS_ADDR_CLKSLICE			0x27
+#define MEMBUS_CLKSLICE_SYNC_MODE_EN		0x80
+
+static int membus_wait_for_req(u32 pll, int timeout)
+{
+	int cnt = 0;
+	u32 req_status;
+
+	if (pll == MEMBUS_MAINPLL)
+		req_status = CM_REG_READL(CM_MAINPLL_REG_MEM);
+	else
+		req_status = CM_REG_READL(CM_PERPLL_REG_MEM);
+
+	while ((cnt < timeout) && (req_status & CLKMGR_MEM_REQ_SET_MSK)) {
+		if (pll == MEMBUS_MAINPLL)
+			req_status = CM_REG_READL(CM_MAINPLL_REG_MEM);
+		else
+			req_status = CM_REG_READL(CM_PERPLL_REG_MEM);
+		cnt++;
+	}
+
+	if (cnt >= timeout)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int membus_write_pll(u32 pll, u32 addr_offset, u32 wdat, int timeout)
+{
+	u32 addr;
+	u32 val;
+
+	addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK);
+
+	val = (CLKMGR_MEM_REQ_SET_MSK | CLKMGR_MEM_WR_SET_MSK |
+	       (wdat << CLKMGR_MEM_WDAT_LSB_OFFSET) | addr);
+
+	if (pll == MEMBUS_MAINPLL)
+		CM_REG_WRITEL(val, CM_MAINPLL_REG_MEM);
+	else
+		CM_REG_WRITEL(val, CM_PERPLL_REG_MEM);
+
+	debug("MEMBUS: Write 0x%08x to addr = 0x%08x\n", wdat, addr);
+
+	return membus_wait_for_req(pll, timeout);
+}
+
+static int membus_read_pll(u32 pll, u32 addr_offset, u32 *rdata, int timeout)
+{
+	u32 addr;
+	u32 val;
+
+	addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK);
+
+	val = ((CLKMGR_MEM_REQ_SET_MSK & ~CLKMGR_MEM_WR_SET_MSK) | addr);
+
+	if (pll == MEMBUS_MAINPLL)
+		CM_REG_WRITEL(val, CM_MAINPLL_REG_MEM);
+	else
+		CM_REG_WRITEL(val, CM_PERPLL_REG_MEM);
+
+	*rdata = 0;
+
+	if (membus_wait_for_req(pll, timeout))
+		return -ETIMEDOUT;
+
+	if (pll == MEMBUS_MAINPLL)
+		*rdata = CM_REG_READL(CM_MAINPLL_REG_MEMSTAT);
+	else
+		*rdata = CM_REG_READL(CM_PERPLL_REG_MEMSTAT);
+
+	debug("MEMBUS: Read 0x%08x from addr = 0x%08x\n", *rdata, addr);
+
+	return 0;
+}
+
+static u32 calc_vocalib_pll(u32 pllm, u32 pllglob)
+{
+	u32 mdiv, refclkdiv, arefclkdiv, drefclkdiv, mscnt, hscnt, vcocalib;
+
+	mdiv = pllm & CLKMGR_PLLM_MDIV_MASK;
+	arefclkdiv = (pllglob >> CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET) &
+		     CLKMGR_PLLGLOB_AREFCLKDIV_MASK;
+	drefclkdiv = (pllglob >> CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET) &
+		     CLKMGR_PLLGLOB_DREFCLKDIV_MASK;
+	refclkdiv = (pllglob >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
+		    CLKMGR_PLLGLOB_REFCLKDIV_MASK;
+	mscnt = CLKMGR_VCOCALIB_MSCNT_CONST / (mdiv * BIT(drefclkdiv));
+	if (!mscnt)
+		mscnt = 1;
+	hscnt = (mdiv * mscnt * BIT(drefclkdiv) / refclkdiv) -
+		CLKMGR_VCOCALIB_HSCNT_CONST;
+	vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
+		   ((mscnt & CLKMGR_VCOCALIB_MSCNT_MASK) <<
+		   CLKMGR_VCOCALIB_MSCNT_OFFSET);
+
+	/* Dump all the pll calibration settings for debug purposes */
+	debug("mdiv          : %d\n", mdiv);
+	debug("arefclkdiv    : %d\n", arefclkdiv);
+	debug("drefclkdiv    : %d\n", drefclkdiv);
+	debug("refclkdiv     : %d\n", refclkdiv);
+	debug("mscnt         : %d\n", mscnt);
+	debug("hscnt         : %d\n", hscnt);
+	debug("vcocalib      : 0x%08x\n", vcocalib);
+
+	return vcocalib;
+}
+
+/*
+ * Setup clocks while making no assumptions about previous state of the clocks.
+ */
+void cm_basic_init(const struct cm_config * const cfg)
+{
+	u32 vcocalib;
+	u32 rdata;
+
+	if (!cfg)
+		return;
+
+	/* Put both PLLs in bypass */
+	cm_write_bypass_mainpll(CLKMGR_BYPASS_MAINPLL_ALL);
+	cm_write_bypass_perpll(CLKMGR_BYPASS_PERPLL_ALL);
+
+	/* Put both PLLs in Reset and Power Down */
+	CM_REG_CLRBITS(CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK,
+		       CM_MAINPLL_REG_PLLGLOB);
+	CM_REG_CLRBITS(CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK,
+		       CM_PERPLL_REG_PLLGLOB);
+
+	/* setup main PLL dividers where calculate the vcocalib value */
+	vcocalib = calc_vocalib_pll(cfg->main_pll_pllm, cfg->main_pll_pllglob);
+	CM_REG_WRITEL(cfg->main_pll_pllglob & ~CLKMGR_PLLGLOB_RST_MASK,
+		      CM_MAINPLL_REG_PLLGLOB);
+	CM_REG_WRITEL(cfg->main_pll_fdbck, CM_MAINPLL_REG_FDBCK);
+	CM_REG_WRITEL(vcocalib, CM_MAINPLL_REG_VCOCALIB);
+	CM_REG_WRITEL(cfg->main_pll_pllc0, CM_MAINPLL_REG_PLLC0);
+	CM_REG_WRITEL(cfg->main_pll_pllc1, CM_MAINPLL_REG_PLLC1);
+	CM_REG_WRITEL(cfg->main_pll_pllc2, CM_MAINPLL_REG_PLLC2);
+	CM_REG_WRITEL(cfg->main_pll_pllc3, CM_MAINPLL_REG_PLLC3);
+	CM_REG_WRITEL(cfg->main_pll_pllm, CM_MAINPLL_REG_PLLM);
+	CM_REG_WRITEL(cfg->main_pll_mpuclk, CM_MAINPLL_REG_MPUCLK);
+	CM_REG_WRITEL(cfg->main_pll_nocclk, CM_MAINPLL_REG_NOCCLK);
+	CM_REG_WRITEL(cfg->main_pll_nocdiv, CM_MAINPLL_REG_NOCDIV);
+
+	/* setup peripheral PLL dividers where calculate the vcocalib value */
+	vcocalib = calc_vocalib_pll(cfg->per_pll_pllm, cfg->per_pll_pllglob);
+	CM_REG_WRITEL(cfg->per_pll_pllglob & ~CLKMGR_PLLGLOB_RST_MASK,
+		      CM_PERPLL_REG_PLLGLOB);
+	CM_REG_WRITEL(cfg->per_pll_fdbck, CM_PERPLL_REG_FDBCK);
+	CM_REG_WRITEL(vcocalib, CM_PERPLL_REG_VCOCALIB);
+	CM_REG_WRITEL(cfg->per_pll_pllc0, CM_PERPLL_REG_PLLC0);
+	CM_REG_WRITEL(cfg->per_pll_pllc1, CM_PERPLL_REG_PLLC1);
+	CM_REG_WRITEL(cfg->per_pll_pllc2, CM_PERPLL_REG_PLLC2);
+	CM_REG_WRITEL(cfg->per_pll_pllc3, CM_PERPLL_REG_PLLC3);
+	CM_REG_WRITEL(cfg->per_pll_pllm, CM_PERPLL_REG_PLLM);
+	CM_REG_WRITEL(cfg->per_pll_emacctl, CM_PERPLL_REG_EMACCTL);
+	CM_REG_WRITEL(cfg->per_pll_gpiodiv, CM_PERPLL_REG_GPIODIV);
+
+	/* Take both PLL out of reset and power up */
+	CM_REG_SETBITS(CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK,
+		       CM_MAINPLL_REG_PLLGLOB);
+	CM_REG_SETBITS(CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK,
+		       CM_PERPLL_REG_PLLGLOB);
+
+	/* Membus programming to set mainpll and perripll to
+	 * source synchronous mode
+	 */
+	membus_read_pll(MEMBUS_MAINPLL, MEMBUS_ADDR_CLKSLICE, &rdata,
+			MEMBUS_TIMEOUT);
+	membus_write_pll(MEMBUS_MAINPLL, MEMBUS_ADDR_CLKSLICE,
+			 (rdata | MEMBUS_CLKSLICE_SYNC_MODE_EN),
+			 MEMBUS_TIMEOUT);
+	membus_read_pll(MEMBUS_PERPLL, MEMBUS_ADDR_CLKSLICE, &rdata,
+			MEMBUS_TIMEOUT);
+	membus_write_pll(MEMBUS_PERPLL, MEMBUS_ADDR_CLKSLICE,
+			 (rdata | MEMBUS_CLKSLICE_SYNC_MODE_EN),
+			 MEMBUS_TIMEOUT);
+
+	cm_wait_for_lock(CLKMGR_STAT_ALLPLL_LOCKED_MASK);
+
+	/* Configure ping pong counters in altera group */
+	CM_REG_WRITEL(cfg->alt_emacactr, CM_ALTERA_REG_EMACACTR);
+	CM_REG_WRITEL(cfg->alt_emacbctr, CM_ALTERA_REG_EMACBCTR);
+	CM_REG_WRITEL(cfg->alt_emacptpctr, CM_ALTERA_REG_EMACPTPCTR);
+	CM_REG_WRITEL(cfg->alt_gpiodbctr, CM_ALTERA_REG_GPIODBCTR);
+	CM_REG_WRITEL(cfg->alt_sdmmcctr, CM_ALTERA_REG_SDMMCCTR);
+	CM_REG_WRITEL(cfg->alt_s2fuser0ctr, CM_ALTERA_REG_S2FUSER0CTR);
+	CM_REG_WRITEL(cfg->alt_s2fuser1ctr, CM_ALTERA_REG_S2FUSER1CTR);
+	CM_REG_WRITEL(cfg->alt_psirefctr, CM_ALTERA_REG_PSIREFCTR);
+
+	/* Take all PLLs out of bypass */
+	cm_write_bypass_mainpll(0);
+	cm_write_bypass_perpll(0);
+
+	/* Clear the loss of lock bits (write 1 to clear) */
+	CM_REG_CLRBITS(CLKMGR_INTER_PERPLLLOST_MASK |
+		       CLKMGR_INTER_MAINPLLLOST_MASK, CM_REG_INTRCLR);
+
+	/* Take all ping pong counters out of reset */
+	CM_REG_CLRBITS(CLKMGR_ALT_EXTCNTRST_ALLCNTRST,
+		       CM_ALTERA_REG_EXTCNTRST);
+
+	/* Out of boot mode */
+	cm_write_ctrl(CM_REG_READL(CM_REG_CTRL) & ~CLKMGR_CTRL_BOOTMODE);
+}
+
+static u64 cm_get_main_vco_clk_hz(void)
+{
+	 u64 fref, arefdiv, mdiv, reg, vco;
+
+	reg = CM_REG_READL(CM_MAINPLL_REG_PLLGLOB);
+
+	fref = (reg >> CLKMGR_PLLGLOB_VCO_PSRC_OFFSET) &
+	       CLKMGR_PLLGLOB_VCO_PSRC_MASK;
+
+	switch (fref) {
+	case CLKMGR_VCO_PSRC_EOSC1:
+		fref = cm_get_osc_clk_hz();
+		break;
+	case CLKMGR_VCO_PSRC_INTOSC:
+		fref = cm_get_intosc_clk_hz();
+		break;
+	case CLKMGR_VCO_PSRC_F2S:
+		fref = cm_get_fpga_clk_hz();
+		break;
+	}
+
+	arefdiv = (reg >> CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET) &
+		  CLKMGR_PLLGLOB_AREFCLKDIV_MASK;
+
+	reg = CM_REG_READL(CM_MAINPLL_REG_PLLM);
+	mdiv = reg & CLKMGR_PLLM_MDIV_MASK;
+
+	vco = fref / arefdiv;
+	vco = vco * mdiv;
+
+	return vco;
+}
+
+static u64 cm_get_per_vco_clk_hz(void)
+{
+	u64 fref, arefdiv, mdiv, reg, vco;
+
+	reg = CM_REG_READL(CM_PERPLL_REG_PLLGLOB);
+
+	fref = (reg >> CLKMGR_PLLGLOB_VCO_PSRC_OFFSET) &
+		CLKMGR_PLLGLOB_VCO_PSRC_MASK;
+	switch (fref) {
+	case CLKMGR_VCO_PSRC_EOSC1:
+		fref = cm_get_osc_clk_hz();
+		break;
+	case CLKMGR_VCO_PSRC_INTOSC:
+		fref = cm_get_intosc_clk_hz();
+		break;
+	case CLKMGR_VCO_PSRC_F2S:
+		fref = cm_get_fpga_clk_hz();
+		break;
+	}
+
+	arefdiv = (reg >> CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET) &
+		 CLKMGR_PLLGLOB_AREFCLKDIV_MASK;
+
+	reg = CM_REG_READL(CM_PERPLL_REG_PLLM);
+	mdiv = reg & CLKMGR_PLLM_MDIV_MASK;
+
+	vco = fref / arefdiv;
+	vco = vco * mdiv;
+
+	return vco;
+}
+
+static u32 cm_get_5_1_clk_src(u64 reg)
+{
+	u32 clksrc = CM_REG_READL(reg);
+
+	return (clksrc >> CLKMGR_CLKSRC_OFFSET) & CLKMGR_CLKSRC_MASK;
+}
+
+u64 cm_get_mpu_clk_hz(void)
+{
+	u64 clock = cm_get_5_1_clk_src(CM_MAINPLL_REG_MPUCLK);
+
+	switch (clock) {
+	case CLKMGR_CLKSRC_MAIN:
+		clock = cm_get_main_vco_clk_hz();
+		clock /= (CM_REG_READL(CM_MAINPLL_REG_PLLC0) &
+			  CLKMGR_CLKCNT_MSK);
+		break;
+
+	case CLKMGR_CLKSRC_PER:
+		clock = cm_get_per_vco_clk_hz();
+		clock /= (CM_REG_READL(CM_PERPLL_REG_PLLC0) &
+			  CLKMGR_CLKCNT_MSK);
+		break;
+
+	case CLKMGR_CLKSRC_OSC1:
+		clock = cm_get_osc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_INTOSC:
+		clock = cm_get_intosc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_FPGA:
+		clock = cm_get_fpga_clk_hz();
+		break;
+	}
+
+	clock /= 1 + (CM_REG_READL(CM_MAINPLL_REG_MPUCLK) &
+		 CLKMGR_CLKCNT_MSK);
+
+	return clock;
+}
+
+static u32 cm_get_l3_main_clk_hz(void)
+{
+	u32 clock = cm_get_5_1_clk_src(CM_MAINPLL_REG_NOCCLK);
+
+	switch (clock) {
+	case CLKMGR_CLKSRC_MAIN:
+		clock = cm_get_main_vco_clk_hz();
+		clock /= (CM_REG_READL(CM_MAINPLL_REG_PLLC1) &
+			  CLKMGR_CLKCNT_MSK);
+		break;
+
+	case CLKMGR_CLKSRC_PER:
+		clock = cm_get_per_vco_clk_hz();
+		clock /= (CM_REG_READL(CM_PERPLL_REG_PLLC1) &
+			  CLKMGR_CLKCNT_MSK);
+		break;
+
+	case CLKMGR_CLKSRC_OSC1:
+		clock = cm_get_osc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_INTOSC:
+		clock = cm_get_intosc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_FPGA:
+		clock = cm_get_fpga_clk_hz();
+		break;
+	}
+
+	return clock;
+}
+
+u32 cm_get_mmc_controller_clk_hz(void)
+{
+	u32 clock = cm_get_5_1_clk_src(CM_ALTERA_REG_SDMMCCTR);
+
+	switch (clock) {
+	case CLKMGR_CLKSRC_MAIN:
+		clock = cm_get_main_vco_clk_hz();
+		clock /= (CM_REG_READL(CM_MAINPLL_REG_PLLC3) &
+			  CLKMGR_CLKCNT_MSK);
+		break;
+
+	case CLKMGR_CLKSRC_PER:
+		clock = cm_get_main_vco_clk_hz();
+		clock /= (CM_REG_READL(CM_PERPLL_REG_PLLC3) &
+			  CLKMGR_CLKCNT_MSK);
+		break;
+
+	case CLKMGR_CLKSRC_OSC1:
+		clock = cm_get_osc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_INTOSC:
+		clock = cm_get_intosc_clk_hz();
+		break;
+
+	case CLKMGR_CLKSRC_FPGA:
+		clock = cm_get_fpga_clk_hz();
+		break;
+	}
+
+	clock /= 1 + (CM_REG_READL(CM_ALTERA_REG_SDMMCCTR) &
+		 CLKMGR_CLKCNT_MSK);
+
+	return clock;
+}
+
+u32 cm_get_l4_sp_clk_hz(void)
+{
+	u32 clock = cm_get_l3_main_clk_hz();
+
+	clock /= BIT((CM_REG_READL(CM_MAINPLL_REG_NOCDIV) >>
+		      CLKMGR_NOCDIV_L4SPCLK_OFFSET) &
+		      CLKMGR_NOCDIV_DIVIDER_MASK);
+
+	return clock;
+}
+
+static u32 cm_get_l4_mp_clk_hz(void)
+{
+	u32 clock = cm_get_l3_main_clk_hz();
+
+	clock /= BIT((CM_REG_READL(CM_MAINPLL_REG_NOCDIV) >>
+		      CLKMGR_NOCDIV_L4MPCLK_OFFSET) &
+		      CLKMGR_NOCDIV_DIVIDER_MASK);
+
+	return clock;
+}
+
+u32 cm_get_qspi_controller_clk_hz(void)
+{
+	return readl(&sysmgr_regs->boot_scratch_cold0);
+}
+
+u32 cm_get_spi_controller_clk_hz(void)
+{
+	u32 clock = cm_get_l3_main_clk_hz();
+
+	clock /= BIT((CM_REG_READL(CM_MAINPLL_REG_NOCDIV) >>
+		      CLKMGR_NOCDIV_L4MAIN_OFFSET) &
+		      CLKMGR_NOCDIV_DIVIDER_MASK);
+
+	return clock;
+}
+
+u32 cm_get_l4_sys_free_clk_hz(void)
+{
+	if (CM_REG_READL(CM_REG_STAT) & CLKMGR_STAT_BOOTMODE)
+		return cm_get_l3_main_clk_hz() / 2;
+
+	return cm_get_l3_main_clk_hz() / 4;
+}
+
+static u32 cm_get_main_mod_clk_hz(void)
+{
+	u32 moddiv = (CM_REG_READL(CM_MAINPLL_REG_PLLGLOB) >>
+		      CLKMGR_PLLGLOB_MODCLKDIV_OFFSET) &
+		     CLKMGR_PLLGLOB_MODCLKDIV_MASK;
+
+	return (u32)cm_get_main_vco_clk_hz() / moddiv;
+}
+
+static u32 cm_get_per_mod_clk_hz(void)
+{
+	u32 moddiv = (CM_REG_READL(CM_PERPLL_REG_PLLGLOB) >>
+		      CLKMGR_PLLGLOB_MODCLKDIV_OFFSET) &
+		     CLKMGR_PLLGLOB_MODCLKDIV_MASK;
+
+	return (u32)cm_get_per_vco_clk_hz() / moddiv;
+}
+
+void cm_print_clock_quick_summary(void)
+{
+	printf("Main VCO    %d kHz\n", (u32)(cm_get_main_vco_clk_hz() / 1000));
+	printf("Per VCO     %d kHz\n", (u32)(cm_get_per_vco_clk_hz() / 1000));
+	printf("Main Mod    %d kHz\n", cm_get_main_mod_clk_hz() / 1000);
+	printf("Per Mod     %d kHz\n", cm_get_per_mod_clk_hz() / 1000);
+	printf("EOSC1       %d kHz\n", cm_get_osc_clk_hz() / 1000);
+	printf("MPU         %d kHz\n", (u32)(cm_get_mpu_clk_hz() / 1000));
+	printf("L3 main     %d kHz\n", cm_get_l3_main_clk_hz() / 1000);
+	printf("L4 MP       %d kHz\n", cm_get_l4_mp_clk_hz() / 1000);
+	printf("HPS MMC     %d kHz\n", cm_get_mmc_controller_clk_hz() / 1000);
+	printf("UART        %d kHz\n", cm_get_l4_sp_clk_hz() / 1000);
+}
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager.h b/arch/arm/mach-socfpga/include/mach/clock_manager.h
index dd80e3a767..a3d5de59d2 100644
--- a/arch/arm/mach-socfpga/include/mach/clock_manager.h
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager.h
@@ -18,6 +18,8 @@ void cm_print_clock_quick_summary(void);
 #include <asm/arch/clock_manager_arria10.h>
 #elif defined(CONFIG_TARGET_SOCFPGA_STRATIX10)
 #include <asm/arch/clock_manager_s10.h>
+#elif defined(CONFIG_TARGET_SOCFPGA_AGILEX)
+#include <asm/arch/clock_manager_agilex.h>
 #endif
 
 #endif /* _CLOCK_MANAGER_H_ */
diff --git a/arch/arm/mach-socfpga/include/mach/clock_manager_agilex.h b/arch/arm/mach-socfpga/include/mach/clock_manager_agilex.h
new file mode 100644
index 0000000000..45e6eafc03
--- /dev/null
+++ b/arch/arm/mach-socfpga/include/mach/clock_manager_agilex.h
@@ -0,0 +1,328 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#ifndef	_CLOCK_MANAGER_AGILEX_
+#define	_CLOCK_MANAGER_AGILEX_
+
+#define CM_REG_READL(reg)			\
+		readl(SOCFPGA_CLKMGR_ADDRESS + (reg))
+
+#define CM_REG_WRITEL(data, reg)		\
+		writel(data, SOCFPGA_CLKMGR_ADDRESS + (reg))
+
+#define CM_REG_CLRBITS(mask, reg)		\
+		clrbits_le32(SOCFPGA_CLKMGR_ADDRESS + (reg), (mask))
+
+#define CM_REG_SETBITS(mask, reg)		\
+		setbits_le32(SOCFPGA_CLKMGR_ADDRESS + (reg), (mask))
+
+#define CM_REG_CLRSETBITS(mask, data, reg)	\
+		clrsetbits_le32(SOCFPGA_CLKMGR_ADDRESS + (reg), (mask), (data))
+
+/* Clock speed accessors */
+u64 cm_get_mpu_clk_hz(void);
+u32 cm_get_l4_sp_clk_hz(void);
+u32 cm_get_mmc_controller_clk_hz(void);
+u32 cm_get_qspi_controller_clk_hz(void);
+u32 cm_get_l4_sys_free_clk_hz(void);
+u32 cm_get_spi_controller_clk_hz(void);
+const unsigned int cm_get_osc_clk_hz(void);
+const unsigned int cm_get_intosc_clk_hz(void);
+const unsigned int cm_get_fpga_clk_hz(void);
+
+#define CLKMGR_EOSC1_HZ		25000000
+#define CLKMGR_INTOSC_HZ	400000000
+#define CLKMGR_FPGA_CLK_HZ	50000000
+
+/* Clock configuration accessors */
+const struct cm_config * const cm_get_default_config(void);
+
+struct cm_config {
+	/* main group */
+	u32 main_pll_mpuclk;
+	u32 main_pll_nocclk;
+	u32 main_pll_nocdiv;
+	u32 main_pll_pllglob;
+	u32 main_pll_fdbck;
+	u32 main_pll_pllc0;
+	u32 main_pll_pllc1;
+	u32 main_pll_pllc2;
+	u32 main_pll_pllc3;
+	u32 main_pll_pllm;
+
+	/* peripheral group */
+	u32 per_pll_emacctl;
+	u32 per_pll_gpiodiv;
+	u32 per_pll_pllglob;
+	u32 per_pll_fdbck;
+	u32 per_pll_pllc0;
+	u32 per_pll_pllc1;
+	u32 per_pll_pllc2;
+	u32 per_pll_pllc3;
+	u32 per_pll_pllm;
+
+	/* altera group */
+	u32 alt_emacactr;
+	u32 alt_emacbctr;
+	u32 alt_emacptpctr;
+	u32 alt_gpiodbctr;
+	u32 alt_sdmmcctr;
+	u32 alt_s2fuser0ctr;
+	u32 alt_s2fuser1ctr;
+	u32 alt_psirefctr;
+
+	/* incoming clock */
+	u32 hps_osc_clk_hz;
+	u32 fpga_clk_hz;
+	u32 spare[3];
+};
+
+void cm_basic_init(const struct cm_config * const cfg);
+
+/* Register access with structure */
+struct socfpga_clock_manager_main_pll {
+	u32	en;
+	u32	ens;
+	u32	enr;
+	u32	bypass;
+	u32	bypasss;
+	u32	bypassr;
+	u32	mpuclk;
+	u32	nocclk;
+	u32	nocdiv;
+	u32	pllglob;
+	u32	fdbck;
+	u32	mem;
+	u32	memstat;
+	u32	pllc0;
+	u32	pllc1;
+	u32	vcocalib;
+	u32	pllc2;
+	u32	pllc3;
+	u32	pllm;
+	u32	fhop;
+	u32	ssc;
+	u32	lostlock;
+};
+
+struct socfpga_clock_manager_per_pll {
+	u32	en;
+	u32	ens;
+	u32	enr;
+	u32	bypass;
+	u32	bypasss;
+	u32	bypassr;
+	u32	emacctl;
+	u32	gpiodiv;
+	u32	pllglob;
+	u32	fdbck;
+	u32	mem;
+	u32	memstat;
+	u32	pllc0;
+	u32	pllc1;
+	u32	vcocalib;
+	u32	pllc2;
+	u32	pllc3;
+	u32	pllm;
+	u32	fhop;
+	u32	ssc;
+	u32	lostlock;
+};
+
+struct socfpga_clock_manager_alt_pll {
+	u32	jtag;
+	u32	emacactr;
+	u32	emacbctr;
+	u32	emacptpctr;
+	u32	gpiodbctr;
+	u32	sdmmcctr;
+	u32	s2fuser0ctr;
+	u32	s2fuser1ctr;
+	u32	psirefctr;
+	u32	extcntrst;
+};
+
+struct socfpga_clock_manager {
+	u32	ctrl;
+	u32	stat;
+	u32	testioctrl;
+	u32	intrgen;
+	u32	intrmsk;
+	u32	intrclr;
+	u32	intrsts;
+	u32	intrstk;
+	u32	intrraw;
+	struct socfpga_clock_manager_main_pll main_pll;
+	struct socfpga_clock_manager_per_pll per_pll;
+	struct socfpga_clock_manager_alt_pll alt_pll;
+};
+
+/* Register access with macro functions */
+/* Clock Manager registers */
+#define CM_REG_CTRL				0
+#define CM_REG_STAT				4
+#define CM_REG_TESTIOCTRL			8
+#define CM_REG_INTRGEN				0x0c
+#define CM_REG_INTRMSK				0x10
+#define CM_REG_INTRCLR				0x14
+#define CM_REG_INTRSTS				0x18
+#define CM_REG_INTRSTK				0x1c
+#define CM_REG_INTRRAW				0x20
+
+/* Clock Manager Main PPL group registers */
+#define CM_MAINPLL_REG_EN			0x24
+#define CM_MAINPLL_REG_ENS			0x28
+#define CM_MAINPLL_REG_ENR			0x2c
+#define CM_MAINPLL_REG_BYPASS			0x30
+#define CM_MAINPLL_REG_BYPASSS			0x34
+#define CM_MAINPLL_REG_BYPASSR			0x38
+#define CM_MAINPLL_REG_MPUCLK			0x3c
+#define CM_MAINPLL_REG_NOCCLK			0x40
+#define CM_MAINPLL_REG_NOCDIV			0x44
+#define CM_MAINPLL_REG_PLLGLOB			0x48
+#define CM_MAINPLL_REG_FDBCK			0x4c
+#define CM_MAINPLL_REG_MEM			0x50
+#define CM_MAINPLL_REG_MEMSTAT			0x54
+#define CM_MAINPLL_REG_PLLC0			0x58
+#define CM_MAINPLL_REG_PLLC1			0x5c
+#define CM_MAINPLL_REG_VCOCALIB			0x60
+#define CM_MAINPLL_REG_PLLC2			0x64
+#define CM_MAINPLL_REG_PLLC3			0x68
+#define CM_MAINPLL_REG_PLLM			0x6c
+#define CM_MAINPLL_REG_FHOP			0x70
+#define CM_MAINPLL_REG_SSC			0x74
+#define CM_MAINPLL_REG_LOSTLOCK			0x78
+
+/* Clock Manager Peripheral PPL group registers */
+#define CM_PERPLL_REG_EN			0x7c
+#define CM_PERPLL_REG_ENS			0x80
+#define CM_PERPLL_REG_ENR			0x84
+#define CM_PERPLL_REG_BYPASS			0x88
+#define CM_PERPLL_REG_BYPASSS			0x8c
+#define CM_PERPLL_REG_BYPASSR			0x90
+#define CM_PERPLL_REG_EMACCTL			0x94
+#define CM_PERPLL_REG_GPIODIV			0x98
+#define CM_PERPLL_REG_PLLGLOB			0x9c
+#define CM_PERPLL_REG_FDBCK			0xa0
+#define CM_PERPLL_REG_MEM			0xa4
+#define CM_PERPLL_REG_MEMSTAT			0xa8
+#define CM_PERPLL_REG_PLLC0			0xac
+#define CM_PERPLL_REG_PLLC1			0xb0
+#define CM_PERPLL_REG_VCOCALIB			0xb4
+#define CM_PERPLL_REG_PLLC2			0xb8
+#define CM_PERPLL_REG_PLLC3			0xbc
+#define CM_PERPLL_REG_PLLM			0xc0
+#define CM_PERPLL_REG_FHOP			0xc4
+#define CM_PERPLL_REG_SSC			0xc8
+#define CM_PERPLL_REG_LOSTLOCK			0xcc
+
+/* Clock Manager Altera group registers */
+#define CM_ALTERA_REG_JTAG			0xd0
+#define CM_ALTERA_REG_EMACACTR			0xd4
+#define CM_ALTERA_REG_EMACBCTR			0xd8
+#define CM_ALTERA_REG_EMACPTPCTR		0xdc
+#define CM_ALTERA_REG_GPIODBCTR			0xe0
+#define CM_ALTERA_REG_SDMMCCTR			0xe4
+#define CM_ALTERA_REG_S2FUSER0CTR		0xe8
+#define CM_ALTERA_REG_S2FUSER1CTR		0xec
+#define CM_ALTERA_REG_PSIREFCTR			0xf0
+#define CM_ALTERA_REG_EXTCNTRST			0xf4
+
+#define CLKMGR_CTRL_BOOTMODE			BIT(0)
+
+#define CLKMGR_STAT_BUSY			BIT(0)
+#define CLKMGR_STAT_MAINPLL_LOCKED		BIT(8)
+#define CLKMGR_STAT_MAIN_TRANS			BIT(9)
+#define CLKMGR_STAT_PERPLL_LOCKED		BIT(16)
+#define CLKMGR_STAT_PERF_TRANS			BIT(17)
+#define CLKMGR_STAT_BOOTMODE			BIT(24)
+#define CLKMGR_STAT_BOOTCLKSRC			BIT(25)
+
+#define CLKMGR_STAT_ALLPLL_LOCKED_MASK		\
+		(CLKMGR_STAT_MAINPLL_LOCKED | CLKMGR_STAT_PERPLL_LOCKED)
+
+#define CLKMGR_INTER_MAINPLLLOCKED_MASK		0x00000001
+#define CLKMGR_INTER_PERPLLLOCKED_MASK		0x00000002
+#define CLKMGR_INTER_MAINPLLLOST_MASK		0x00000004
+#define CLKMGR_INTER_PERPLLLOST_MASK		0x00000008
+
+#define CLKMGR_CLKSRC_MASK			0x7
+#define CLKMGR_CLKSRC_OFFSET			16
+#define CLKMGR_CLKSRC_MAIN			0
+#define CLKMGR_CLKSRC_PER			1
+#define CLKMGR_CLKSRC_OSC1			2
+#define CLKMGR_CLKSRC_INTOSC			3
+#define CLKMGR_CLKSRC_FPGA			4
+#define CLKMGR_CLKCNT_MSK			0x7ff
+
+#define CLKMGR_BYPASS_MAINPLL_ALL		0x7
+#define CLKMGR_BYPASS_PERPLL_ALL		0x7f
+
+#define CLKMGR_NOCDIV_L4MAIN_OFFSET		0
+#define CLKMGR_NOCDIV_L4MPCLK_OFFSET		8
+#define CLKMGR_NOCDIV_L4SPCLK_OFFSET		16
+#define CLKMGR_NOCDIV_CSATCLK_OFFSET		24
+#define CLKMGR_NOCDIV_CSTRACECLK_OFFSET		26
+#define CLKMGR_NOCDIV_CSPDBGCLK_OFFSET		28
+#define CLKMGR_NOCDIV_DIVIDER_MASK		0x3
+
+#define CLKMGR_PLLGLOB_PD_MASK			0x00000001
+#define CLKMGR_PLLGLOB_RST_MASK			0x00000002
+#define CLKMGR_PLLGLOB_AREFCLKDIV_MASK		0xf
+#define CLKMGR_PLLGLOB_DREFCLKDIV_MASK		0x3
+#define CLKMGR_PLLGLOB_REFCLKDIV_MASK		0x3f
+#define CLKMGR_PLLGLOB_MODCLKDIV_MASK		0xf
+#define CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET	8
+#define CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET	12
+#define CLKMGR_PLLGLOB_REFCLKDIV_OFFSET		8
+#define CLKMGR_PLLGLOB_MODCLKDIV_OFFSET		24
+#define CLKMGR_PLLGLOB_VCO_PSRC_MASK		0x3
+#define CLKMGR_PLLGLOB_VCO_PSRC_OFFSET		16
+
+#define CLKMGR_VCO_PSRC_EOSC1			0
+#define CLKMGR_VCO_PSRC_INTOSC			1
+#define CLKMGR_VCO_PSRC_F2S			2
+
+#define CLKMGR_MEM_REQ_SET_MSK			BIT(24)
+#define CLKMGR_MEM_WR_SET_MSK			BIT(25)
+#define CLKMGR_MEM_ERR_MSK			BIT(26)
+#define CLKMGR_MEM_WDAT_LSB_OFFSET		16
+#define CLKMGR_MEM_ADDR_MASK			0xffff
+#define CLKMGR_MEM_ADDR_START			0x00004000
+
+#define CLKMGR_PLLCX_EN_SET_MSK			BIT(27)
+#define CLKMGR_PLLCX_MUTE_SET_MSK		BIT(28)
+
+#define CLKMGR_VCOCALIB_MSCNT_MASK		0xff
+#define CLKMGR_VCOCALIB_MSCNT_OFFSET		16
+#define CLKMGR_VCOCALIB_HSCNT_MASK		0x3ff
+#define CLKMGR_VCOCALIB_MSCNT_CONST		100
+#define CLKMGR_VCOCALIB_HSCNT_CONST		4
+
+#define CLKMGR_PLLM_MDIV_MASK			0x3ff
+
+#define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK	0x00000020
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB	BIT(26)
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB	BIT(27)
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB	BIT(28)
+
+#define CLKMGR_ALT_EXTCNTRST_EMACACNTRST	BIT(0)
+#define CLKMGR_ALT_EXTCNTRST_EMACBCNTRST	BIT(1)
+#define CLKMGR_ALT_EXTCNTRST_EMACPTPCNTRST	BIT(2)
+#define CLKMGR_ALT_EXTCNTRST_GPIODBCNTRST	BIT(3)
+#define CLKMGR_ALT_EXTCNTRST_SDMMCCNTRST	BIT(4)
+#define CLKMGR_ALT_EXTCNTRST_S2FUSER0CNTRST	BIT(5)
+#define CLKMGR_ALT_EXTCNTRST_S2FUSER1CNTRST	BIT(6)
+#define CLKMGR_ALT_EXTCNTRST_PSIREFCNTRST	BIT(7)
+#define CLKMGR_ALT_EXTCNTRST_ALLCNTRST		\
+		(CLKMGR_ALT_EXTCNTRST_EMACACNTRST | \
+		 CLKMGR_ALT_EXTCNTRST_EMACBCNTRST | \
+		 CLKMGR_ALT_EXTCNTRST_EMACPTPCNTRST | \
+		 CLKMGR_ALT_EXTCNTRST_GPIODBCNTRST | \
+		 CLKMGR_ALT_EXTCNTRST_SDMMCCNTRST | \
+		 CLKMGR_ALT_EXTCNTRST_S2FUSER0CNTRST | \
+		 CLKMGR_ALT_EXTCNTRST_S2FUSER1CNTRST | \
+		 CLKMGR_ALT_EXTCNTRST_PSIREFCNTRST)
+#endif /* _CLOCK_MANAGER_AGILEX_ */
-- 
2.19.0



More information about the U-Boot mailing list