summaryrefslogtreecommitdiff
path: root/arch/arm/cpu/arm926ejs/lpc32xx
diff options
context:
space:
mode:
authorAlbert ARIBAUD \(3ADEV\) <albert.aribaud@3adev.fr>2015-03-31 11:40:51 +0200
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>2015-04-10 14:23:39 +0200
commit412ae53aadb53cd63e754d638bafe6e426aeafee (patch)
tree0bbf46fef21d002cc1a37b8f478e4b7a26c200d4 /arch/arm/cpu/arm926ejs/lpc32xx
parent8c80eb3b533c73a4b4a505fbaf925cdaafe0b5d2 (diff)
downloadu-boot-412ae53aadb53cd63e754d638bafe6e426aeafee.tar.gz
lpc32xx: add support for board work_92105
Work_92105 from Work Microwave is an LPC3250- based board with the following features: - 64MB or 128MB SDR DRAM - 1 GB SLC NAND, managed through MLC controller. - Ethernet - Ethernet + PHY SMSC8710 - I2C: - EEPROM (24M01-compatible) - RTC (DS1374-compatible) - Temperature sensor (DS620) - DACs (2 x MAX518) - SPI (through SSP interface) - Port expander MAX6957 - LCD display (HD44780-compatible), controlled through the port expander and DACs This board has SPL support, and uses the LPC32XX boot image format. Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Diffstat (limited to 'arch/arm/cpu/arm926ejs/lpc32xx')
-rw-r--r--arch/arm/cpu/arm926ejs/lpc32xx/Makefile2
-rw-r--r--arch/arm/cpu/arm926ejs/lpc32xx/clk.c34
-rw-r--r--arch/arm/cpu/arm926ejs/lpc32xx/cpu.c1
-rw-r--r--arch/arm/cpu/arm926ejs/lpc32xx/dram.c77
-rw-r--r--arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S45
5 files changed, 159 insertions, 0 deletions
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/Makefile b/arch/arm/cpu/arm926ejs/lpc32xx/Makefile
index 314f004eba..48373776ff 100644
--- a/arch/arm/cpu/arm926ejs/lpc32xx/Makefile
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/Makefile
@@ -6,3 +6,5 @@
#
obj-y = cpu.o clk.o devices.o timer.o
+
+obj-$(CONFIG_SPL_BUILD) += dram.o lowlevel_init.o
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/clk.c b/arch/arm/cpu/arm926ejs/lpc32xx/clk.c
index b7a44d59da..1ef8a36669 100644
--- a/arch/arm/cpu/arm926ejs/lpc32xx/clk.c
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/clk.c
@@ -98,6 +98,40 @@ unsigned int get_periph_clk_rate(void)
return get_hclk_pll_rate() / get_periph_clk_div();
}
+unsigned int get_sdram_clk_rate(void)
+{
+ unsigned int src_clk;
+
+ if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN))
+ return get_sys_clk_rate();
+
+ src_clk = get_hclk_pll_rate();
+
+ if (readl(&clk->sdramclk_ctrl) & CLK_SDRAM_DDR_SEL) {
+ /* using DDR */
+ switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_DDRAM_MASK) {
+ case CLK_HCLK_DDRAM_HALF:
+ return src_clk/2;
+ case CLK_HCLK_DDRAM_NOMINAL:
+ return src_clk;
+ default:
+ return 0;
+ }
+ } else {
+ /* using SDR */
+ switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK) {
+ case CLK_HCLK_ARM_PLL_DIV_4:
+ return src_clk/4;
+ case CLK_HCLK_ARM_PLL_DIV_2:
+ return src_clk/2;
+ case CLK_HCLK_ARM_PLL_DIV_1:
+ return src_clk;
+ default:
+ return 0;
+ }
+ }
+}
+
int get_serial_clock(void)
{
return get_periph_clk_rate();
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c b/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c
index eec4d9e880..f757474076 100644
--- a/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c
@@ -9,6 +9,7 @@
#include <asm/arch/cpu.h>
#include <asm/arch/clk.h>
#include <asm/arch/wdt.h>
+#include <asm/arch/sys_proto.h>
#include <asm/io.h>
static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/dram.c b/arch/arm/cpu/arm926ejs/lpc32xx/dram.c
new file mode 100644
index 0000000000..1eea8e2bbf
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/dram.c
@@ -0,0 +1,77 @@
+/*
+ * LPC32xx dram init
+ *
+ * (C) Copyright 2014 DENX Software Engineering GmbH
+ * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
+ *
+ * This is called by SPL to gain access to the SDR DRAM.
+ *
+ * This code runs from SRAM.
+ *
+ * Actual CONFIG_LPC32XX_SDRAM_* parameters must be provided
+ * by the board configuration file.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <netdev.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/wdt.h>
+#include <asm/arch/emc.h>
+#include <asm/io.h>
+
+static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
+static struct emc_regs *emc = (struct emc_regs *)EMC_BASE;
+
+void ddr_init(struct emc_dram_settings *dram)
+{
+ uint32_t ck;
+
+ /* Enable EMC interface and choose little endian mode */
+ writel(1, &emc->ctrl);
+ writel(0, &emc->config);
+ /* Select maximum EMC Dynamic Memory Refresh Time */
+ writel(0x7FF, &emc->refresh);
+ /* Determine CLK */
+ ck = get_sdram_clk_rate();
+ /* Configure SDRAM */
+ writel(dram->cmddelay, &clk->sdramclk_ctrl);
+ writel(dram->config0, &emc->config0);
+ writel(dram->rascas0, &emc->rascas0);
+ writel(dram->rdconfig, &emc->read_config);
+ /* Set timings */
+ writel((ck / dram->trp) & 0x0000000F, &emc->t_rp);
+ writel((ck / dram->tras) & 0x0000000F, &emc->t_ras);
+ writel((ck / dram->tsrex) & 0x0000007F, &emc->t_srex);
+ writel((ck / dram->twr) & 0x0000000F, &emc->t_wr);
+ writel((ck / dram->trc) & 0x0000001F, &emc->t_rc);
+ writel((ck / dram->trfc) & 0x0000001F, &emc->t_rfc);
+ writel((ck / dram->txsr) & 0x000000FF, &emc->t_xsr);
+ writel(dram->trrd, &emc->t_rrd);
+ writel(dram->tmrd, &emc->t_mrd);
+ writel(dram->tcdlr, &emc->t_cdlr);
+ /* Dynamic refresh */
+ writel((((ck / dram->refresh) >> 4) & 0x7FF), &emc->refresh);
+ udelay(10);
+ /* Force all clocks, enable inverted ck, issue NOP command */
+ writel(0x00000193, &emc->control);
+ udelay(100);
+ /* Keep all clocks enabled, issue a PRECHARGE ALL command */
+ writel(0x00000113, &emc->control);
+ /* Fast dynamic refresh for at least a few SDRAM ck cycles */
+ writel((((128) >> 4) & 0x7FF), &emc->refresh);
+ udelay(10);
+ /* set correct dynamic refresh timing */
+ writel((((ck / dram->refresh) >> 4) & 0x7FF), &emc->refresh);
+ udelay(10);
+ /* set normal mode to CAS=3 */
+ writel(0x00000093, &emc->control);
+ readl(EMC_DYCS0_BASE | dram->mode);
+ /* set extended mode to all zeroes */
+ writel(0x00000093, &emc->control);
+ readl(EMC_DYCS0_BASE | dram->emode);
+ /* stop forcing clocks, keep inverted clock, issue normal mode */
+ writel(0x00000010, &emc->control);
+}
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S b/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S
new file mode 100644
index 0000000000..4b8053e3f9
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S
@@ -0,0 +1,45 @@
+/*
+ * WORK Microwave work_92105 board low level init
+ *
+ * (C) Copyright 2014 DENX Software Engineering GmbH
+ * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
+ *
+ * Low level init is called from SPL to set up the clocks.
+ * On entry, the LPC3250 is in Direct Run mode with all clocks
+ * running at 13 MHz; on exit, ARM clock is 208 MHz, HCLK is
+ * 104 MHz and PCLK is 13 MHz.
+ *
+ * This code must run from SRAM so that the clock changes do
+ * not prevent it from executing.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+.globl lowlevel_init
+
+lowlevel_init:
+
+ /* Set ARM, HCLK, PCLK dividers for normal mode */
+ ldr r0, =0x0000003D
+ ldr r1, =0x40004040
+ str r0, [r1]
+
+ /* Start HCLK PLL for 208 MHz */
+ ldr r0, =0x0001401E
+ ldr r1, =0x40004058
+ str r0, [r1]
+
+ /* wait for HCLK PLL to lock */
+1:
+ ldr r0, [r1]
+ ands r0, r0, #1
+ beq 1b
+
+ /* switch to normal mode */
+ ldr r1, =0x40004044
+ ldr r0, [r1]
+ orr r0, #0x00000004
+ str r0, [r1]
+
+ /* Return to U-boot via saved link register */
+ mov pc, lr