[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