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/4599
-gerrit
commit 51df3d29968e9a20faf0cbe1df5e23c34703aeee
Author: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
Date: Thu Jan 2 03:59:24 2014 -0500
cpu/allwinner/a10: Add functions for driving GPIO pins
Change-Id: I9473a6e574c3af02d154a7e30245f0dc0b238300
Signed-off-by: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
---
src/cpu/allwinner/a10/Makefile.inc | 1 +
src/cpu/allwinner/a10/gpio.c | 98 ++++++++++++++++++++++++++++++++++++++
src/cpu/allwinner/a10/gpio.h | 8 ++++
3 files changed, 107 insertions(+)
diff --git a/src/cpu/allwinner/a10/Makefile.inc b/src/cpu/allwinner/a10/Makefile.inc
index 6865529..8e743a2 100644
--- a/src/cpu/allwinner/a10/Makefile.inc
+++ b/src/cpu/allwinner/a10/Makefile.inc
@@ -1,4 +1,5 @@
bootblock-y += clock.c
+bootblock-y += gpio.c
bootblock-y += pinmux.c
bootblock-y += bootblock_media.c
bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c
diff --git a/src/cpu/allwinner/a10/gpio.c b/src/cpu/allwinner/a10/gpio.c
new file mode 100644
index 0000000..24c7f22
--- /dev/null
+++ b/src/cpu/allwinner/a10/gpio.c
@@ -0,0 +1,98 @@
+/*
+ * Basic GPIO helpers for Allwinner CPUs
+ *
+ * Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
+ * Subject to the GNU GPL v2, or (at your option) any later version.
+ */
+
+#include "gpio.h"
+
+#include <arch/io.h>
+
+static struct a10_gpio *const gpio = (void *)GPIO_BASE;
+
+/**
+ * \brief Set a single output pin
+ *
+ * @param[in] port GPIO port of the pin (GPA -> GPS)
+ * @param[in] pin the pin number in the given port (1 -> 31)
+ */
+void gpio_set(u8 port, u8 pin)
+{
+ u32 reg32;
+
+ if ((port > GPS))
+ return;
+
+ reg32 = gpio_read(port);
+ reg32 |= (1 << pin);
+ gpio_write(port, reg32);
+}
+
+/**
+ * \brief Clear a single output pin
+ *
+ * @param[in] port GPIO port of the pin (GPA -> GPS)
+ * @param[in] pin the pin number in the given port (1 -> 31)
+ */
+void gpio_clear(u8 port, u8 pin)
+{
+ u32 reg32;
+ if ((port > GPS))
+ return;
+
+ reg32 = gpio_read(port);
+ reg32 &= ~(1 << pin);
+ gpio_write(port, reg32);
+}
+
+/**
+ * \brief Get the status of a single input pin
+ *
+ * @param[in] port GPIO port of the pin (GPA -> GPS)
+ * @param[in] pin the pin number in the given port (1 -> 31)
+ * @return 1 if the pin is high, or 0 if the pin is low
+ */
+int gpio_get(u8 port, u8 pin)
+{
+ if ((port > GPS))
+ return 0;
+
+ return (gpio_read(port) & (1 << pin)) ? 1 : 0;
+}
+
+/**
+ * \brief Write to a GPIO port
+ *
+ * Write the state of all output pins in the GPIO port. This only affects pins
+ * configured as output pins.
+ *
+ * @param[in] port GPIO port of the pin (GPA -> GPS)
+ * @param[in] value 32-bit mask indicating which pins to set. For a set bit, the
+ * corresponding pin will be set. Otherwise, it will be cleared
+ */
+void gpio_write(u8 port, u32 val)
+{
+ if ((port > GPS))
+ return;
+
+ write32(val, &gpio->port[port].dat);
+}
+
+/**
+ * \brief Write to a GPIO port
+ *
+ * Read the state of all input pins in the GPIO port.
+ *
+ * @param[in] port GPIO port of the pin (GPA -> GPS)
+ * @return 32-bit mask indicating which are high. For each set bit, the
+ * corresponding pin is high. The value of bits corresponding to pins
+ * which are not configured as inputs is undefined.
+ */
+u32 gpio_read(u8 port)
+{
+ if ((port > GPS))
+ return 0;
+
+ return read32(&gpio->port[port].dat);
+}
diff --git a/src/cpu/allwinner/a10/gpio.h b/src/cpu/allwinner/a10/gpio.h
index e4b24ea..b20d759 100644
--- a/src/cpu/allwinner/a10/gpio.h
+++ b/src/cpu/allwinner/a10/gpio.h
@@ -50,6 +50,14 @@ struct a10_gpio {
u32 sdr_pad_pul;
} __attribute__ ((packed));
+/* gpio.c */
+void gpio_set(u8 port, u8 pin);
+void gpio_clear(u8 port, u8 pin);
+int gpio_get(u8 port, u8 pin);
+void gpio_write(u8 port, u32 val);
+u32 gpio_read(u8 port);
+
+/* pinmux.c */
void gpio_set_pin_func(u8 port, u8 pin, u8 pad_func);
void gpio_set_multipin_func(u8 port, u32 pin_mask, u8 pad_func);
Paul Menzel (paulepanter(a)users.sourceforge.net) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4594
-gerrit
commit b2ca25b3780e9b312aa6cc1564d5aec7a8ca1969
Author: Paul Menzel <paulepanter(a)users.sourceforge.net>
Date: Wed Jan 1 14:37:33 2014 +0100
cpu/samsung/exynos5250/cpu.c: Remove unused variable `ret`
CC cpu/samsung/exynos5250/cpu.ramstage.o
src/cpu/samsung/exynos5250/cpu.c: In function 'exynos_displayport_init':
src/cpu/samsung/exynos5250/cpu.c:88:6: error: variable 'ret' set but not used [-Werror=unused-but-set-variable]
cc1: all warnings being treated as errors
Change-Id: I72a5a802aef0a75b0277eaac6ca6c24793812d98
Signed-off-by: Paul Menzel <paulepanter(a)users.sourceforge.net>
---
src/cpu/samsung/exynos5250/cpu.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/cpu/samsung/exynos5250/cpu.c b/src/cpu/samsung/exynos5250/cpu.c
index 61f937b..c663d38 100644
--- a/src/cpu/samsung/exynos5250/cpu.c
+++ b/src/cpu/samsung/exynos5250/cpu.c
@@ -64,7 +64,6 @@ static void set_cpu_id(void)
*/
static void exynos_displayport_init(device_t dev)
{
- int ret;
struct cpu_samsung_exynos5250_config *conf = dev->chip_info;
/* put these on the stack. If, at some point, we want to move
* this code to a pre-ram stage, it will be much easier.
@@ -117,7 +116,7 @@ static void exynos_displayport_init(device_t dev)
mmio_resource(dev, 1, lcdbase/KiB, (fb_size + KiB - 1)/KiB);
printk(BIOS_DEBUG,
"Initializing Exynos VGA, base %p\n", (void *)lcdbase);
- ret = lcd_ctrl_init(fb_size, &panel, (void *)lcdbase);
+ lcd_ctrl_init(fb_size, &panel, (void *)lcdbase);
}
static void cpu_enable(device_t dev)
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 3fc8d1795e63aaa551502f8e7c4e1ea61faa6b6b
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 bc78743..0fc2698 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 give 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 */