the following patch was just integrated into master:
commit 974e79b64b05f9dffae8459455f751ae1d069bdd
Author: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
Date: Wed Dec 25 03:00:39 2013 -0500
cpu/allwinner/a10: Import raminit code from uboot
The memory initialization code is a work in progress for uboot, so we
only import the bits needed to get RAM up and running. Any refactoring
is cosmetic, and any functional refactoring should be done in separate
patches, and preferably, in coordination with the sunxi team.
Since it's not yet determined if we should initialize memory during
the bootblock or romstage, we don't add raminit to the build just yet.
Change-Id: I2ec1821942c6970150a02fa3806a257da649e1c9
Signed-off-by: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
See http://review.coreboot.org/4597 for details.
-gerrit
the following patch was just integrated into master:
commit 3229b6cc7a372bb99f0857a9bd737819ba7d4dce
Author: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
Date: Tue Dec 31 13:20:27 2013 -0500
cpu/allwinner/a10: Add low-level helpers for DRAM clock control
PLL5 is special in that it controls the DRAM clock, and requires a
fine-grained low-level control which will be needed by raminit code.
This change also brings functionality which will be needed by
raminit.
Change-Id: I25ecc91aa2154e504ceebb9003a5e5728d47f4a3
Signed-off-by: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
See http://review.coreboot.org/4593 for details.
-gerrit
the following patch was just integrated into master:
commit f93a7fc6c21479b7a72619bdcc7b032c340929e8
Author: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
Date: Tue Dec 31 00:57:30 2013 -0500
cubieboard: Initialize memory in bootblock
Even though the Allwinner A10 is limited to a 24KiB bootblock, the
memory initialization takes only about 3KiB and leaves enough room for
an MMC or NAND driver, so init the memory early on. The advantage is
that we can eliminate complicated logistics of where to cache CBFS and
where to load the ramstage in SRAM.
Change-Id: Id549552ed509434e831db60deaef28e04d62417f
Signed-off-by: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
See http://review.coreboot.org/4630 for details.
-gerrit
Alexandru Gagniuc (mr.nuke.me(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4593
-gerrit
commit 3229b6cc7a372bb99f0857a9bd737819ba7d4dce
Author: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
Date: Tue Dec 31 13:20:27 2013 -0500
cpu/allwinner/a10: Add low-level helpers for DRAM clock control
PLL5 is special in that it controls the DRAM clock, and requires a
fine-grained low-level control which will be needed by raminit code.
This change also brings functionality which will be needed by
raminit.
Change-Id: I25ecc91aa2154e504ceebb9003a5e5728d47f4a3
Signed-off-by: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
---
src/cpu/allwinner/a10/clock.c | 81 +++++++++++++++++++++++++++++++++++++++++++
src/cpu/allwinner/a10/clock.h | 28 +++++++++++++++
2 files changed, 109 insertions(+)
diff --git a/src/cpu/allwinner/a10/clock.c b/src/cpu/allwinner/a10/clock.c
index 87a3574..0401a72 100644
--- a/src/cpu/allwinner/a10/clock.c
+++ b/src/cpu/allwinner/a10/clock.c
@@ -9,6 +9,8 @@
#include <arch/io.h>
+static struct a10_ccm *const ccm = (void *)A1X_CCM_BASE;
+
/**
* \brief Enable the clock source for the peripheral
*
@@ -40,3 +42,82 @@ void a1x_periph_clock_disable(enum a1x_clken periph)
reg32 &= ~(1 << (periph & 0x1f));
write32(reg32, addr);
}
+
+/**
+ * \brief Configure PLL5 factors
+ *
+ * This is a low-level accessor to configure the divisors and multipliers of
+ * PLL5. PLL5 uses two factors to multiply the 24MHz oscillator clock to
+ * generate a pre-clock. The pre-divided clock is then divided by one of two
+ * independent divisors, one for DRAM, and another for peripherals clocked from
+ * this PLL. If the PLL was previously disabled, this function will enable it.
+ * Other than that, this function only modifies these factors, and leaves the
+ * other settings unchanged.
+ *
+ * The output clocks are given by the following formulas:
+ *
+ * Pre-clock = (24 MHz * N * K) <- Must be between 240MHz and 2GHz
+ * DRAM clock = pre / M
+ * Other module = pre / P
+ *
+ * It is the caller's responsibility to make sure the pre-divided clock falls
+ * within the operational range of the PLL, and that the divisors and
+ * multipliers are within their ranges.
+ *
+ * @param[in] mul_n Multiplier N, between 0 and 32
+ * @param[in] mul_k Multiplier K, between 1 and 4
+ * @param[in] div_m DRAM clock divisor, between 1 and 4
+ * @param[in] exp_div_p Peripheral clock divisor exponent, between 0 and 3
+ * (P = 1/2/4/8, respectively)
+ */
+void a1x_pll5_configure(u8 mul_n, u8 mul_k, u8 div_m, u8 exp_div_p)
+{
+ u32 reg32;
+
+ reg32 = read32(&ccm->pll5_cfg);
+ reg32 &= ~(PLL5_FACTOR_M_MASK | PLL5_FACTOR_N_MASK |
+ PLL5_FACTOR_K_MASK | PLL5_DIV_EXP_P_MASK);
+ /* The M1 factor is not documented in the datasheet, and the reference
+ * raminit code does not use it. Whether this is a fractional divisor,
+ * or an additional divisor is unknown, so don't use it for now */
+ reg32 &= ~PLL5_FACTOR_M1_MASK;
+ reg32 |= (PLL5_FACTOR_M(div_m) | PLL5_FACTOR_N(mul_n) |
+ PLL5_FACTOR_K(mul_k) | PLL5_DIV_EXP_P(exp_div_p));
+ reg32 |= PLL5_PLL_ENABLE;
+ write32(reg32, &ccm->pll5_cfg);
+}
+
+/**
+ * \brief Enable the clock output to DRAM chips
+ *
+ * This enables the DRAM clock to be sent to DRAM chips. This should normally be
+ * done after PLL5 is configured and locked. Note that the clock may be gated,
+ * and also needs to be ungated in order to reach the DDR chips.
+ * Also see @ref clock_ungate_dram_clk_output
+ */
+void a1x_pll5_enable_dram_clock_output(void)
+{
+ setbits_le32(&ccm->pll5_cfg, PLL5_DDR_CLK_OUT_EN);
+}
+
+/**
+ * \brief Ungate the clock to DRAM chips
+ *
+ * Although the DRAM clock output may be enabled, it is by default gated. It
+ * needs to be ungated before reaching DRAM.
+ */
+void a1x_ungate_dram_clock_output(void)
+{
+ setbits_le32(&ccm->dram_clk_cfg, DRAM_CTRL_DCLK_OUT);
+}
+
+/**
+ * \brief Gate the clock to DRAM chips
+ *
+ * Disable the clock to DRAM without altering PLL configuration, by closing the
+ * DRAM clock gate.
+ */
+void a1x_gate_dram_clock_output(void)
+{
+ clrbits_le32(&ccm->dram_clk_cfg, DRAM_CTRL_DCLK_OUT);
+}
diff --git a/src/cpu/allwinner/a10/clock.h b/src/cpu/allwinner/a10/clock.h
index 9656469..41400ab 100644
--- a/src/cpu/allwinner/a10/clock.h
+++ b/src/cpu/allwinner/a10/clock.h
@@ -43,6 +43,29 @@
#define APB1_RAT_M_MASK 0x1f << 0)
#define APB1_RAT_M(n) (((n) & 0x1f) << 0)
+/* PLL5_CFG values */
+#define PLL5_PLL_ENABLE (1 << 31)
+#define PLL5_OUT_BYPASS_EN (1 << 30)
+#define PLL5_DDR_CLK_OUT_EN (1 << 29)
+#define PLL5_DIV_EXP_P_MASK (0x3 << 16)
+#define PLL5_DIV_EXP_P(ep) ((ep << 16) & PLL5_DIV_EXP_P_MASK)
+#define PLL5_DIV_P_1 (0x0 << 16)
+#define PLL5_DIV_P_2 (0x1 << 16)
+#define PLL5_DIV_P_4 (0x2 << 16)
+#define PLL5_DIV_P_8 (0x3 << 16)
+#define PLL5_FACTOR_N_MASK (0x1f << 8)
+#define PLL5_FACTOR_N(n) ((n << 8) & PLL5_FACTOR_N_MASK)
+#define PLL5_LDO_EN (1 << 7)
+#define PLL5_FACTOR_K_MASK (0x3 << 4)
+#define PLL5_FACTOR_K(k) ((((k) - 1) << 4) & PLL5_FACTOR_K_MASK)
+#define PLL5_FACTOR_M1_MASK (0x3 << 2)
+#define PLL5_FACTOR_M1(m1) (((m1) << 2) & PLL5_FACTOR_M1_MASK)
+#define PLL5_FACTOR_M_MASK (0x3 << 0)
+#define PLL5_FACTOR_M(m) ((((m) - 1) << 0) & PLL5_FACTOR_M_MASK)
+
+/* DRAM_CLK values*/
+#define DRAM_CTRL_DCLK_OUT (1 << 15)
+
/**
* \brief Clock gating definitions
*
@@ -228,4 +251,9 @@ struct a10_ccm {
void a1x_periph_clock_enable(enum a1x_clken periph);
void a1x_periph_clock_disable(enum a1x_clken periph);
+void a1x_pll5_configure(u8 mul_n, u8 mul_k, u8 div_m, u8 exp_div_p);
+void a1x_pll5_enable_dram_clock_output(void);
+void a1x_ungate_dram_clock_output(void);
+void a1x_gate_dram_clock_output(void);
+
#endif /* CPU_ALLWINNER_A10_CLOCK_H */