[coreboot-gerrit] New patch to review for coreboot: rockchip: rk3399: support basic clock driver

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Sat May 7 08:30:05 CEST 2016


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14706

-gerrit

commit 1d800fbcf067d30eb7b17f94477744b3e0be2de6
Author: Lin Huang <hl at rock-chips.com>
Date:   Wed Mar 9 18:08:20 2016 +0800

    rockchip: rk3399: support basic clock driver
    
    This patch initialize the PLL clocks and add function to
    configure cpu freq. Right now, we set the little cpu freq to 600MHz.
    
    In coreboot, we currently care about these four PLLs,
    o. APLL for cpu clk, where A stands for AXI,
    o. CPLL and GPLL are the generic PLL mainly for peripheral clk,
    o. PPLL is only PMU clk.
    
    For the peripheral clocks, there are thress clocks named as,
     aclk_perihp,
     aclk_perilp0,
     hclk_perilp1,
    where the 'h' and 'l' letters refer to High and Low speed.
    As the diagram below, the aclk_perihp always be the parent of
    more higher speed peripheral devices like pcie, and
    hclk_perilp1 for spi, i2c, aclk_perilp0 for crypto.
    These three clocks can choose parent from GPLL or CPLL freely,
    in this patch, they are all sourced from GPLL.
    
    GPLL(594M)/CPLL(384M)                      APLL(600M for little core)
       |                                           |
       `-- aclk_perihp                             `-- clk_core(600M == APLL)
       |       |                                           |
       |       `-- periph_aclk(148.5M)                     `-- atclk_core(300M)
       |       `-- periph_hclk(148.5M)                     `-- aclkm_core(300M)
       |       `-- periph_pclk(37.125M)                    `-- pclk_dbg_core(100M)
       |
       `-- hclk_perilp1
       |       |
       |       `-- periph_hclk(99M)            PPLL(594M)
       |       `-- periph_pclk(49.5M)              |
       |                                           `-- pmu_pclk(99M)
       `-- aclk_perilp0
               |
               `-- periph_aclk(99M)
               `-- periph_hclk(99M)
               `-- periph_pclk(49.5M)
    
    BRANCH=none
    BUG=chrome-os-partner:51537
    TEST=emerge-kevin coreboot
    
    Change-Id: I1c46ff17e6b466529244afb41d7fd4abbcfd3da4
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: 9f0d31177336a3450577950426f9cc9d56e2254c
    Original-Change-Id: I4ad00df3e406bd0a7576287d6e62b8993a8c2d02
    Original-Signed-off-by: Lin Huang <hl at rock-chips.com>
    Original-Signed-off-by: Shunqian Zheng <zhengsq at rock-chips.com>
    Original-Reviewed-on: https://chromium-review.googlesource.com/332386
    Original-Commit-Ready: Vadim Bendebury <vbendeb at chromium.org>
    Original-Reviewed-by: Vadim Bendebury <vbendeb at chromium.org>
---
 src/soc/rockchip/rk3399/bootblock.c              |   8 +-
 src/soc/rockchip/rk3399/clock.c                  | 335 ++++++++++++++++++++++-
 src/soc/rockchip/rk3399/include/soc/addressmap.h |   1 +
 src/soc/rockchip/rk3399/include/soc/clock.h      |  87 +++++-
 4 files changed, 424 insertions(+), 7 deletions(-)

diff --git a/src/soc/rockchip/rk3399/bootblock.c b/src/soc/rockchip/rk3399/bootblock.c
index ae41a08..d87f967 100644
--- a/src/soc/rockchip/rk3399/bootblock.c
+++ b/src/soc/rockchip/rk3399/bootblock.c
@@ -11,15 +11,13 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
  */
 
-#include <arch/io.h>
-#include <arch/mmu.h>
 #include <bootblock_common.h>
-#include <console/console.h>
-#include <symbols.h>
+#include <soc/clock.h>
 
 void bootblock_soc_init(void)
 {
+	rkclk_init();
+	rkclk_configure_cpu(APLL_L_600_MHZ);
 }
diff --git a/src/soc/rockchip/rk3399/clock.c b/src/soc/rockchip/rk3399/clock.c
index 7bf5df8..7053a37 100644
--- a/src/soc/rockchip/rk3399/clock.c
+++ b/src/soc/rockchip/rk3399/clock.c
@@ -11,11 +11,344 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
  */
 
+#include <assert.h>
+#include <console/console.h>
+#include <delay.h>
+#include <soc/addressmap.h>
 #include <soc/clock.h>
 #include <soc/grf.h>
+#include <soc/soc.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct pll_div {
+	u32 refdiv;
+	u32 fbdiv;
+	u32 postdiv1;
+	u32 postdiv2;
+	u32 frac;
+};
+
+#define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
+	.refdiv = _refdiv,\
+	.fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
+	.postdiv1 = _postdiv1, .postdiv2 = _postdiv2};\
+	_Static_assert(((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ) *\
+			 OSC_HZ / (_refdiv * _postdiv1 * _postdiv2) == hz,\
+			 #hz "Hz cannot be hit with PLL "\
+			 "divisors on line " STRINGIFY(__LINE__))
+
+static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
+static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2, 2);
+static const struct pll_div ppll_init_cfg = PLL_DIVISORS(PPLL_HZ, 2, 2, 1);
+
+static const struct pll_div apll_l_1600_cfg = PLL_DIVISORS(1600*MHz, 3, 1, 1);
+static const struct pll_div apll_l_600_cfg = PLL_DIVISORS(600*MHz, 1, 2, 1);
+
+static const struct pll_div *apll_l_cfgs[] = {
+	[APLL_L_1600_MHZ] = &apll_l_1600_cfg,
+	[APLL_L_600_MHZ] = &apll_l_600_cfg,
+};
+
+enum {
+	/* PLL_CON0 */
+	PLL_FBDIV_MASK			= 0xfff,
+	PLL_FBDIV_SHIFT			= 0,
+
+	/* PLL_CON1 */
+	PLL_POSTDIV2_MASK		= 0x7,
+	PLL_POSTDIV2_SHIFT		= 12,
+	PLL_POSTDIV1_MASK		= 0x7,
+	PLL_POSTDIV1_SHIFT		= 8,
+	PLL_REFDIV_MASK			= 0x3f,
+	PLL_REFDIV_SHIFT		= 0,
+
+	/* PLL_CON2 */
+	PLL_LOCK_STATUS_MASK		= 1,
+	PLL_LOCK_STATUS_SHIFT		= 31,
+	PLL_FRACDIV_MASK		= 0xffffff,
+	PLL_FRACDIV_SHIFT		= 0,
+
+	/* PLL_CON3 */
+	PLL_MODE_MASK			= 3,
+	PLL_MODE_SHIFT			= 8,
+	PLL_MODE_SLOW			= 0,
+	PLL_MODE_NORM,
+	PLL_MODE_DEEP,
+	PLL_DSMPD_MASK			= 1,
+	PLL_DSMPD_SHIFT			= 3,
+	PLL_INTEGER_MODE		= 1,
+
+	/* PMUCRU_CLKSEL_CON0 */
+	PMU_PCLK_DIV_CON_MASK		= 0x1f,
+	PMU_PCLK_DIV_CON_SHIFT		= 0,
+
+	/* CLKSEL_CON0 */
+	ACLKM_CORE_L_DIV_CON_MASK	= 0x1f,
+	ACLKM_CORE_L_DIV_CON_SHIFT	= 8,
+	CLK_CORE_L_PLL_SEL_MASK		= 3,
+	CLK_CORE_L_PLL_SEL_SHIFT	= 6,
+	CLK_CORE_L_PLL_SEL_ALPLL	= 0x0,
+	CLK_CORE_L_PLL_SEL_ABPLL	= 0x1,
+	CLK_CORE_L_PLL_SEL_DPLL		= 0x10,
+	CLK_CORE_L_PLL_SEL_GPLL		= 0x11,
+	CLK_CORE_L_DIV_MASK		= 0x1f,
+	CLK_CORE_L_DIV_SHIFT		= 0,
+
+	/* CLKSEL_CON1 */
+	PCLK_DBG_L_DIV_MASK		= 0x1f,
+	PCLK_DBG_L_DIV_SHIFT		= 0x8,
+	ATCLK_CORE_L_DIV_MASK		= 0x1f,
+	ATCLK_CORE_L_DIV_SHIFT		= 0,
+
+	/* CLKSEL_CON14 */
+	PCLK_PERIHP_DIV_CON_MASK	= 0x7,
+	PCLK_PERIHP_DIV_CON_SHIFT	= 12,
+	HCLK_PERIHP_DIV_CON_MASK	= 3,
+	HCLK_PERIHP_DIV_CON_SHIFT	= 8,
+	ACLK_PERIHP_PLL_SEL_MASK	= 1,
+	ACLK_PERIHP_PLL_SEL_SHIFT	= 7,
+	ACLK_PERIHP_PLL_SEL_CPLL	= 0,
+	ACLK_PERIHP_PLL_SEL_GPLL	= 1,
+	ACLK_PERIHP_DIV_CON_MASK	= 0x1f,
+	ACLK_PERIHP_DIV_CON_SHIFT	= 0,
+
+	/* CLKSEL_CON23 */
+	PCLK_PERILP0_DIV_CON_MASK	= 0x7,
+	PCLK_PERILP0_DIV_CON_SHIFT	= 12,
+	HCLK_PERILP0_DIV_CON_MASK	= 3,
+	HCLK_PERILP0_DIV_CON_SHIFT	= 8,
+	ACLK_PERILP0_PLL_SEL_MASK	= 1,
+	ACLK_PERILP0_PLL_SEL_SHIFT	= 7,
+	ACLK_PERILP0_PLL_SEL_CPLL	= 0,
+	ACLK_PERILP0_PLL_SEL_GPLL	= 1,
+	ACLK_PERILP0_DIV_CON_MASK	= 0x1f,
+	ACLK_PERILP0_DIV_CON_SHIFT	= 0,
+
+	/* CLKSEL_CON25 */
+	PCLK_PERILP1_DIV_CON_MASK	= 0x7,
+	PCLK_PERILP1_DIV_CON_SHIFT	= 8,
+	HCLK_PERILP1_PLL_SEL_MASK	= 1,
+	HCLK_PERILP1_PLL_SEL_SHIFT	= 7,
+	HCLK_PERILP1_PLL_SEL_CPLL	= 0,
+	HCLK_PERILP1_PLL_SEL_GPLL	= 1,
+	HCLK_PERILP1_DIV_CON_MASK	= 0x1f,
+	HCLK_PERILP1_DIV_CON_SHIFT	= 0,
+};
+
+#define VCO_MAX_KHZ	(3200 * (MHz / KHz))
+#define VCO_MIN_KHZ	(800 * (MHz / KHz))
+#define OUTPUT_MAX_KHZ	(3200 * (MHz / KHz))
+#define OUTPUT_MIN_KHZ	(16 * (MHz / KHz))
+
+/* the div restrictions of pll in integer mode,
+ * these are defined in * CRU_*PLL_CON0 or PMUCRU_*PLL_CON0
+ */
+#define PLL_DIV_MIN	16
+#define PLL_DIV_MAX	3200
+
+/* How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
+ * Formulas also embedded within the Fractional PLL Verilog model:
+ * If DSMPD = 1 (DSM is disabled, "integer mode")
+ * FOUTVCO = FREF / REFDIV * FBDIV
+ * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
+ * Where:
+ * FOUTVCO = Fractional PLL non-divided output frequency
+ * FOUTPOSTDIV = Fractional PLL divided output frequency
+ *               (output of second post divider)
+ * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
+ * REFDIV = Fractional PLL input reference clock divider
+ * FBDIV = Integer value programmed into feedback divide
+ *
+ */
+static void rkclk_set_pll(u32 *pll_con, const struct pll_div *div)
+{
+	/* All 8 PLLs have same VCO and output frequency range restrictions. */
+	u32 vco_khz = OSC_HZ / 1000 * div->fbdiv / div->refdiv;
+	u32 output_khz = vco_khz / div->postdiv1 / div->postdiv2;
+
+	printk(BIOS_DEBUG, "PLL at %p: fbdiv=%d, refdiv=%d, postdiv1=%d, "
+			   "postdiv2=%d, vco=%u khz, output=%u khz\n",
+			   pll_con, div->fbdiv, div->refdiv, div->postdiv1,
+			   div->postdiv2, vco_khz, output_khz);
+	assert(vco_khz >= VCO_MIN_KHZ && vco_khz <= VCO_MAX_KHZ &&
+	       output_khz >= OUTPUT_MIN_KHZ && output_khz <= OUTPUT_MAX_KHZ &&
+	       div->fbdiv >= PLL_DIV_MIN && div->fbdiv <= PLL_DIV_MAX);
+
+	/* When power on or changing PLL setting,
+	 * we must force PLL into slow mode to ensure output stable clock.
+	 */
+	write32(&pll_con[3], RK_CLRSETBITS(PLL_MODE_MASK << PLL_MODE_SHIFT,
+					   PLL_MODE_SLOW << PLL_MODE_SHIFT));
+
+	/* use integer mode */
+	write32(&pll_con[3],
+		RK_CLRSETBITS(PLL_DSMPD_MASK << PLL_DSMPD_SHIFT,
+			      PLL_INTEGER_MODE << PLL_DSMPD_SHIFT));
+
+	write32(&pll_con[0], RK_CLRSETBITS(PLL_FBDIV_MASK << PLL_FBDIV_SHIFT,
+					   div->fbdiv << PLL_FBDIV_SHIFT));
+	write32(&pll_con[1],
+		RK_CLRSETBITS(PLL_POSTDIV2_MASK << PLL_POSTDIV2_SHIFT |
+			      PLL_POSTDIV1_MASK << PLL_POSTDIV1_SHIFT |
+			      PLL_REFDIV_MASK | PLL_REFDIV_SHIFT,
+			      (div->postdiv2 << PLL_POSTDIV2_SHIFT) |
+			      (div->postdiv1 << PLL_POSTDIV1_SHIFT) |
+			      (div->refdiv << PLL_REFDIV_SHIFT)));
+
+	/* waiting for pll lock */
+	while (!(read32(&pll_con[2]) & (1 << PLL_LOCK_STATUS_SHIFT)))
+		udelay(1);
+
+	/* pll enter normal mode */
+	write32(&pll_con[3], RK_CLRSETBITS(PLL_MODE_MASK << PLL_MODE_SHIFT,
+					   PLL_MODE_NORM << PLL_MODE_SHIFT));
+}
+
+void rkclk_init(void)
+{
+	u32 aclk_div;
+	u32 hclk_div;
+	u32 pclk_div;
+
+	/* some cru registers changed by bootrom, we'd better reset them to
+	 * reset/default values described in TRM to avoid confusion in kernel.
+	 * Please consider these threee lines as a fix of bootrom bug.
+	 */
+	write32(&cru_ptr->clksel_con[12], 0xffff4101);
+	write32(&cru_ptr->clksel_con[19], 0xffff033f);
+	write32(&cru_ptr->clksel_con[56], 0x00030003);
+
+	/* configure pmu pll(ppll) */
+	rkclk_set_pll(&pmucru_ptr->ppll_con[0], &ppll_init_cfg);
+
+	/* configure pmu pclk */
+	pclk_div = PPLL_HZ / PMU_PCLK_HZ - 1;
+	assert((pclk_div + 1) * PMU_PCLK_HZ == PPLL_HZ && pclk_div < 0x1f);
+	write32(&pmucru_ptr->pmucru_clksel[0],
+		RK_CLRSETBITS(PMU_PCLK_DIV_CON_MASK << PMU_PCLK_DIV_CON_SHIFT,
+			      pclk_div << PMU_PCLK_DIV_CON_SHIFT));
+
+	/* configure gpll cpll */
+	rkclk_set_pll(&cru_ptr->gpll_con[0], &gpll_init_cfg);
+	rkclk_set_pll(&cru_ptr->cpll_con[0], &cpll_init_cfg);
+
+	/* configure perihp aclk, hclk, pclk */
+	aclk_div = GPLL_HZ / PERIHP_ACLK_HZ - 1;
+	assert((aclk_div + 1) * PERIHP_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
+
+	hclk_div = PERIHP_ACLK_HZ / PERIHP_HCLK_HZ - 1;
+	assert((hclk_div + 1) * PERIHP_HCLK_HZ ==
+	       PERIHP_ACLK_HZ && (hclk_div < 0x4));
+
+	pclk_div = PERIHP_ACLK_HZ / PERIHP_PCLK_HZ - 1;
+	assert((pclk_div + 1) * PERIHP_PCLK_HZ ==
+	       PERIHP_ACLK_HZ && (pclk_div < 0x7));
+
+	write32(&cru_ptr->clksel_con[14],
+		RK_CLRSETBITS(PCLK_PERIHP_DIV_CON_MASK <<
+						PCLK_PERIHP_DIV_CON_SHIFT |
+			      HCLK_PERIHP_DIV_CON_MASK <<
+						HCLK_PERIHP_DIV_CON_SHIFT |
+			      ACLK_PERIHP_PLL_SEL_MASK <<
+						ACLK_PERIHP_PLL_SEL_SHIFT |
+			      ACLK_PERIHP_DIV_CON_MASK <<
+						ACLK_PERIHP_DIV_CON_SHIFT,
+			      pclk_div << PCLK_PERIHP_DIV_CON_SHIFT |
+			      hclk_div << HCLK_PERIHP_DIV_CON_SHIFT |
+			      ACLK_PERIHP_PLL_SEL_GPLL <<
+						ACLK_PERIHP_PLL_SEL_SHIFT |
+			      aclk_div << ACLK_PERIHP_DIV_CON_SHIFT));
+
+	/* configure perilp0 aclk, hclk, pclk */
+	aclk_div = GPLL_HZ / PERILP0_ACLK_HZ - 1;
+	assert((aclk_div + 1) * PERILP0_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
+
+	hclk_div = PERILP0_ACLK_HZ / PERILP0_HCLK_HZ - 1;
+	assert((hclk_div + 1) * PERILP0_HCLK_HZ ==
+	       PERILP0_ACLK_HZ && (hclk_div < 0x4));
+
+	pclk_div = PERILP0_ACLK_HZ / PERILP0_PCLK_HZ - 1;
+	assert((pclk_div + 1) * PERILP0_PCLK_HZ ==
+	       PERILP0_ACLK_HZ && (pclk_div < 0x7));
+
+	write32(&cru_ptr->clksel_con[23],
+		RK_CLRSETBITS(PCLK_PERILP0_DIV_CON_MASK <<
+						PCLK_PERILP0_DIV_CON_SHIFT |
+			      HCLK_PERILP0_DIV_CON_MASK <<
+						HCLK_PERILP0_DIV_CON_SHIFT |
+			      ACLK_PERILP0_PLL_SEL_MASK <<
+						ACLK_PERILP0_PLL_SEL_SHIFT |
+			      ACLK_PERILP0_DIV_CON_MASK <<
+						ACLK_PERILP0_DIV_CON_SHIFT,
+			      pclk_div << PCLK_PERILP0_DIV_CON_SHIFT |
+			      hclk_div << HCLK_PERILP0_DIV_CON_SHIFT |
+			      ACLK_PERILP0_PLL_SEL_GPLL <<
+						ACLK_PERILP0_PLL_SEL_SHIFT |
+			      aclk_div << ACLK_PERILP0_DIV_CON_SHIFT));
+
+	/* perilp1 hclk select gpll as source */
+	hclk_div = GPLL_HZ / PERILP1_HCLK_HZ - 1;
+	assert((hclk_div + 1) * PERILP1_HCLK_HZ ==
+	       GPLL_HZ && (hclk_div < 0x1f));
+
+	pclk_div = PERILP1_HCLK_HZ / PERILP1_HCLK_HZ - 1;
+	assert((pclk_div + 1) * PERILP1_HCLK_HZ ==
+	       PERILP1_HCLK_HZ && (hclk_div < 0x7));
+
+	write32(&cru_ptr->clksel_con[25],
+		RK_CLRSETBITS(PCLK_PERILP1_DIV_CON_MASK <<
+						PCLK_PERILP1_DIV_CON_SHIFT |
+			      HCLK_PERILP1_DIV_CON_MASK <<
+						HCLK_PERILP1_DIV_CON_SHIFT |
+			      HCLK_PERILP1_PLL_SEL_MASK <<
+						HCLK_PERILP1_PLL_SEL_SHIFT,
+			      pclk_div << PCLK_PERILP1_DIV_CON_SHIFT |
+			      hclk_div << HCLK_PERILP1_DIV_CON_SHIFT |
+			      HCLK_PERILP1_PLL_SEL_GPLL <<
+						HCLK_PERILP1_PLL_SEL_SHIFT));
+}
+
+void rkclk_configure_cpu(enum apll_l_frequencies apll_l_freq)
+{
+	u32 aclkm_div;
+	u32 pclk_dbg_div;
+	u32 atclk_div;
+
+	rkclk_set_pll(&cru_ptr->apll_l_con[0], apll_l_cfgs[apll_l_freq]);
+
+	aclkm_div = APLL_HZ / ACLKM_CORE_HZ - 1;
+	assert((aclkm_div + 1) * ACLKM_CORE_HZ == APLL_HZ &&
+	       aclkm_div < 0x1f);
+
+	pclk_dbg_div = APLL_HZ / PCLK_DBG_HZ - 1;
+	assert((pclk_dbg_div + 1) * PCLK_DBG_HZ == APLL_HZ &&
+	       pclk_dbg_div < 0x1f);
+
+	atclk_div = APLL_HZ / ATCLK_CORE_HZ - 1;
+	assert((atclk_div + 1) * ATCLK_CORE_HZ == APLL_HZ &&
+	       atclk_div < 0x1f);
+
+	write32(&cru_ptr->clksel_con[0],
+		RK_CLRSETBITS(ACLKM_CORE_L_DIV_CON_MASK <<
+						ACLKM_CORE_L_DIV_CON_SHIFT |
+			      CLK_CORE_L_PLL_SEL_MASK <<
+						CLK_CORE_L_PLL_SEL_SHIFT |
+			      CLK_CORE_L_DIV_MASK << CLK_CORE_L_DIV_SHIFT,
+			      aclkm_div << ACLKM_CORE_L_DIV_CON_SHIFT |
+			      CLK_CORE_L_PLL_SEL_ALPLL <<
+						CLK_CORE_L_PLL_SEL_SHIFT |
+			      0 << CLK_CORE_L_DIV_SHIFT));
+
+	write32(&cru_ptr->clksel_con[1],
+		RK_CLRSETBITS(PCLK_DBG_L_DIV_MASK << PCLK_DBG_L_DIV_SHIFT |
+			      ATCLK_CORE_L_DIV_MASK << ATCLK_CORE_L_DIV_SHIFT,
+			      pclk_dbg_div << PCLK_DBG_L_DIV_SHIFT |
+			      atclk_div << ATCLK_CORE_L_DIV_SHIFT));
+}
 
 void rkclk_configure_spi(unsigned int bus, unsigned int hz)
 {
diff --git a/src/soc/rockchip/rk3399/include/soc/addressmap.h b/src/soc/rockchip/rk3399/include/soc/addressmap.h
index 377256e..427122c 100644
--- a/src/soc/rockchip/rk3399/include/soc/addressmap.h
+++ b/src/soc/rockchip/rk3399/include/soc/addressmap.h
@@ -18,6 +18,7 @@
 
 #define PMUGRF_BASE		0xff320000
 #define PMUSGRF_BASE		0xff330000
+#define PMUCRU_BASE		0xff750000
 #define CRU_BASE		0xff760000
 #define GRF_BASE		0xff770000
 #define TIMER0_BASE		0xff850000
diff --git a/src/soc/rockchip/rk3399/include/soc/clock.h b/src/soc/rockchip/rk3399/include/soc/clock.h
index c0ba52c..9b54799 100644
--- a/src/soc/rockchip/rk3399/include/soc/clock.h
+++ b/src/soc/rockchip/rk3399/include/soc/clock.h
@@ -16,6 +16,91 @@
 #ifndef __SOC_ROCKCHIP_RK3399_CLOCK_H__
 #define __SOC_ROCKCHIP_RK3399_CLOCK_H__
 
-void rkclk_configure_spi(unsigned int bus, unsigned int hz);
+#include <soc/addressmap.h>
+#include <types.h>
+
+struct rk3399_pmucru_reg {
+	u32 ppll_con[6];
+	u32 reserved[0x1a];
+	u32 pmucru_clksel[6];
+	u32 pmucru_clkfrac_con[2];
+	u32 reserved2[0x18];
+	u32 pmucru_clkgate_con[3];
+	u32 reserved3;
+	u32 pmucru_softrst_con[2];
+	u32 reserved4[2];
+	u32 pmucru_rstnhold_con[2];
+	u32 reserved5[2];
+	u32 pmucru_gatedis_con[2];
+};
+check_member(rk3399_pmucru_reg, pmucru_gatedis_con[1], 0x134);
+
+struct rk3399_cru_reg {
+	u32 apll_l_con[6];
+	u32 reserved[2];
+	u32 apll_b_con[6];
+	u32 reserved1[2];
+	u32 dpll_con[6];
+	u32 reserved2[2];
+	u32 cpll_con[6];
+	u32 reserved3[2];
+	u32 gpll_con[6];
+	u32 reserved4[2];
+	u32 npll_con[6];
+	u32 reserved5[2];
+	u32 vpll_con[6];
+	u32 reserved6[0x0a];
+	u32 clksel_con[108];
+	u32 reserved7[0x14];
+	u32 clkgate_con[35];
+	u32 reserved8[0x1d];
+	u32 softrst_con[21];
+	u32 reserved9[0x2b];
+	u32 glb_srst_fst_value;
+	u32 glb_srst_snd_value;
+	u32 glb_cnt_th;
+	u32 misc_con;
+	u32 glb_rst_con;
+	u32 glb_rst_st;
+	u32 reserved10[0x1a];
+	u32 sdmmc_con[2];
+	u32 sdio0_con[2];
+	u32 sdio1_con[2];
+};
+check_member(rk3399_cru_reg, sdio1_con[1], 0x594);
+
+static struct rk3399_pmucru_reg * const pmucru_ptr = (void *)PMUCRU_BASE;
+static struct rk3399_cru_reg * const cru_ptr = (void *)CRU_BASE;
+
+#define OSC_HZ		(24*MHz)
+#define APLL_HZ		(600*MHz)
+#define GPLL_HZ		(594*MHz)
+#define CPLL_HZ		(384*MHz)
+#define PPLL_HZ		(594*MHz)
+
+#define PMU_PCLK_HZ	(99*MHz)
 
+#define ACLKM_CORE_HZ	(300*MHz)
+#define ATCLK_CORE_HZ	(300*MHz)
+#define PCLK_DBG_HZ	(100*MHz)
+
+#define PERIHP_ACLK_HZ	(148500*KHz)
+#define PERIHP_HCLK_HZ	(148500*KHz)
+#define PERIHP_PCLK_HZ	(37125*KHz)
+
+#define PERILP0_ACLK_HZ	(99000*KHz)
+#define PERILP0_HCLK_HZ	(99000*KHz)
+#define PERILP0_PCLK_HZ	(49500*KHz)
+
+#define PERILP1_HCLK_HZ	(99000*KHz)
+#define PERILP1_PCLK_HZ	(49500*KHz)
+
+enum apll_l_frequencies {
+	APLL_L_1600_MHZ,
+	APLL_L_600_MHZ,
+};
+
+void rkclk_init(void);
+void rkclk_configure_cpu(enum apll_l_frequencies apll_l_freq);
+void rkclk_configure_spi(unsigned int bus, unsigned int hz);
 #endif	/* __SOC_ROCKCHIP_RK3399_CLOCK_H__ */



More information about the coreboot-gerrit mailing list