summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuergen Beisert <juergen@kreuzholzen.de>2009-10-27 19:57:36 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2009-10-28 09:44:42 +0100
commit8a7f83735549d4edd49f608c922780e03cadc062 (patch)
treeefbefa770eeb259cc0d9b7a9835e2bc08b5eb0e0
parent07d6c14898606c1b41ac43213ad5c59f8c120339 (diff)
downloadbarebox-8a7f83735549d4edd49f608c922780e03cadc062.tar.gz
barebox-8a7f83735549d4edd49f608c922780e03cadc062.tar.xz
A9M2440: Use external GPIO settings to setup the SDRAM
The generic A9M2440 comes in many SDRAM variantes. Two GPIO pins describing the populated SDRAM devices. This patch adds some code to query the setting and setup a correct SDRAM configuration out of four possible variants. Due to the lack of hardware the 16 MiB and 128 MiB case is untested yet. Due to the 32 MiB configuration we must link the u-boot-v2 always to address 0x31fc0000. Even for the 64 MiB and 128 MiB configuration. Signed-off-by: Juergen Beisert <juergen@kreuzholzen.de>
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/configs/a9m2440_defconfig4
-rw-r--r--board/a9m2440/a9m2440.c64
-rw-r--r--board/a9m2440/config.h52
-rw-r--r--board/a9m2440/lowlevel_init.S205
5 files changed, 254 insertions, 74 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2a6546ba11..e859b88bda 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -18,7 +18,7 @@ config ARCH_TEXT_BASE
default 0x87f00000 if MACH_FREESCALE_MX25_3STACK
default 0x87f00000 if MACH_PCM043
default 0xa7f00000 if MACH_PCA100
- default 0x33fc0000 if MACH_A9M2440
+ default 0x31fc0000 if MACH_A9M2440
default 0x23f00000 if MACH_MMCCPU
default 0xa0000000 if MACH_EUKREA_CPUIMX27
@@ -229,7 +229,6 @@ config MACH_A9M2440
select CPU_S3C2440
select MACH_HAS_LOWLEVEL_INIT
select S3C24XX_PLL_INIT
- select S3C24XX_SDRAM_INIT
help
Say Y here if you are using Digi's Connect Core 9M equipped
with a Samsung S3C2440 Processor
diff --git a/arch/arm/configs/a9m2440_defconfig b/arch/arm/configs/a9m2440_defconfig
index 5d8a39861f..5d4d2bd355 100644
--- a/arch/arm/configs/a9m2440_defconfig
+++ b/arch/arm/configs/a9m2440_defconfig
@@ -3,7 +3,7 @@
# U-Boot version: 2.0.0-rc9
# Wed Jul 1 14:23:41 2009
#
-CONFIG_ARCH_TEXT_BASE=0x33fc0000
+CONFIG_ARCH_TEXT_BASE=0x31fc0000
CONFIG_BOARDINFO="Digi A9M2440"
# CONFIG_BOARD_LINKER_SCRIPT is not set
CONFIG_GENERIC_LINKER_SCRIPT=y
@@ -63,7 +63,7 @@ CONFIG_LOCALVERSION_AUTO=y
# memory layout
#
CONFIG_HAVE_CONFIGURABLE_TEXT_BASE=y
-CONFIG_TEXT_BASE=0x33fc0000
+CONFIG_TEXT_BASE=0x31fc0000
CONFIG_HAVE_CONFIGURABLE_MEMORY_LAYOUT=y
CONFIG_MEMORY_LAYOUT_DEFAULT=y
# CONFIG_MEMORY_LAYOUT_FIXED is not set
diff --git a/board/a9m2440/a9m2440.c b/board/a9m2440/a9m2440.c
index e1f1156904..1156b198f9 100644
--- a/board/a9m2440/a9m2440.c
+++ b/board/a9m2440/a9m2440.c
@@ -34,6 +34,7 @@
#include <asm/io.h>
#include <asm/arch/s3c24x0-iomap.h>
#include <asm/arch/s3c24x0-nand.h>
+#include <asm/arch/s3c24xx-generic.h>
static struct memory_platform_data ram_pdata = {
.name = "ram0",
@@ -67,41 +68,70 @@ static struct device_d network_dev = {
.size = 16,
};
+static int a9m2440_check_for_ram(uint32_t addr)
+{
+ uint32_t tmp1, tmp2;
+ int rc = 0;
+
+ tmp1 = readl(addr);
+ tmp2 = readl(addr + sizeof(uint32_t));
+
+ writel(0xaaaaaaaa, addr);
+ writel(0x55555555, addr + sizeof(uint32_t));
+ if ((readl(addr) != 0xaaaaaaaa) || (readl(addr + sizeof(uint32_t)) != 0x55555555))
+ rc = 1; /* seems no RAM */
+
+ writel(0x55555555, addr);
+ writel(0xaaaaaaaa, addr + sizeof(uint32_t));
+ if ((readl(addr) != 0x55555555) || (readl(addr + sizeof(uint32_t)) != 0xaaaaaaaa))
+ rc = 1; /* seems no RAM */
+
+ writel(tmp1, addr);
+ writel(tmp2, addr + sizeof(uint32_t));
+
+ return rc;
+}
+
+static void a9m2440_disable_second_sdram_bank(void)
+{
+ writel(readl(BANKCON7) & ~(0x3 << 15),BANKCON7);
+ writel(readl(MISCCR) | (1 << 18), MISCCR); /* disable clock */
+}
+
static int a9m2440_devices_init(void)
{
uint32_t reg;
/*
- * detect the current memory size
+ * The special SDRAM setup code for this machine will always enable
+ * both SDRAM banks. But the second SDRAM device may not exists!
+ * So we must check here, if the second bank is populated to get the
+ * correct RAM size.
*/
- reg = readl(BANKSIZE);
-
- switch (reg &= 0x7) {
+ switch (readl(BANKSIZE) & 0x7) {
case 0:
- sdram_dev.size = 32 * 1024 * 1024;
+ if (a9m2440_check_for_ram(S3C24X0_SDRAM_BASE + 32 * 1024 * 1024))
+ a9m2440_disable_second_sdram_bank();
break;
case 1:
- sdram_dev.size = 64 * 1024 * 1024;
+ if (a9m2440_check_for_ram(S3C24X0_SDRAM_BASE + 64 * 1024 * 1024))
+ a9m2440_disable_second_sdram_bank();
break;
case 2:
- sdram_dev.size = 128 * 1024 * 1024;
+ if (a9m2440_check_for_ram(S3C24X0_SDRAM_BASE + 128 * 1024 * 1024))
+ a9m2440_disable_second_sdram_bank();
break;
case 4:
- sdram_dev.size = 2 * 1024 * 1024;
- break;
case 5:
- sdram_dev.size = 4 * 1024 * 1024;
- break;
- case 6:
- sdram_dev.size = 8 * 1024 * 1024;
+ case 6: /* not supported on this machine */
break;
- case 7:
- sdram_dev.size = 16 * 1024 * 1024;
+ default:
+ if (a9m2440_check_for_ram(S3C24X0_SDRAM_BASE + 16 * 1024 * 1024))
+ a9m2440_disable_second_sdram_bank();
break;
}
- /* both banks are present */
- sdram_dev.size <<= 1;
+ sdram_dev.size = s3c24x0_get_memory_size();
/* ---------- configure the GPIOs ------------- */
writel(0x007FFFFF, GPACON);
diff --git a/board/a9m2440/config.h b/board/a9m2440/config.h
index c815521aa4..43cb6ab934 100644
--- a/board/a9m2440/config.h
+++ b/board/a9m2440/config.h
@@ -49,58 +49,6 @@
#define BOARD_SPECIFIC_UPLL ((0x3c << 12) + (4 << 4) + 2)
/*
- * SDRAM configuration for Samsung K4M563233E
- * - 2M x 32Bit x 4 Banks Mobile SDRAM
- * - 90 pin FBGA
- * - CL2@100MHz
- */
-/*
- * SDRAM uses 32bit width
- */
-#define BOARD_SPECIFIC_BWSCON ((0x02 << 24) + (0x02 << 28))
-/*
- * 32MiB SDRAM in bank6
- * - MT = 11 (= sync dram type)
- * - Trcd = 00 (= CL2)
- * - SCAN = 01 (= 9 bit collumns)
- */
-#define BOARD_SPECIFIC_BANKCON6 ((0x3 << 15) + (0x0 << 2) + 0x1)
-/*
- * 32MiB SDRAM in bank7
- * - MT = 11 (= sync dram type)
- * - Trcd = 00 (= CL2)
- * - SCAN = 01 (= 9 bit collumns)
- */
-#define BOARD_SPECIFIC_BANKCON7 ((0x3 << 15) + (0x0 << 2) + 0x1)
-/*
- * SDRAM refresh settings
- * - REFEN = 1 (= refresh enabled)
- * - TREFMD = 0 (= auto refresh)
- * - Trp = 00 (= 2 RAS precharge clocks)
- * - Tsrc = 01 (= 5 clocks -> row cycle time @100MHz 2+5=7 -> 70ns)
- * - Refrsh = 2^11 + 1 - 100 * 15.6 = 2049 - 1560 = 489
- */
-#define BOARD_SPECIFIC_REFRESH ((0x1 << 23) + (0x0 << 22) + (0x0 << 20) + (0x1 << 18) + 489)
-/*
- * SDRAM banksize
- * - BURST_EN = 1 (= burst mode enabled)
- * - SCKE_EN = 1 (= SDRAM SCKE enabled)
- * - SCLK_EN = 1 (= clock active only during accesses)
- * - BK67MAP = 000 (= 32MiB)
- */
-#define BOARD_SPECIFIC_BANKSIZE ((1 << 7) + (1 << 5) + (1 << 4) + 0)
-/*
- * SDRAM mode register bank6
- * CL = 010 (= 2 clocks)
- */
-#define BOARD_SPECIFIC_MRSRB6 (0x2 << 4)
-/*
- * SDRAM mode register bank7
- * CL = 010 (= 2 clocks)
- */
-#define BOARD_SPECIFIC_MRSRB7 (0x2 << 4)
-
-/*
* Flash access timings
* Tacls = 0ns (but 20ns data setup time)
* Twrph0 = 25ns (write) 35ns (read)
diff --git a/board/a9m2440/lowlevel_init.S b/board/a9m2440/lowlevel_init.S
index 1af42ddcd1..ff8ef07aa9 100644
--- a/board/a9m2440/lowlevel_init.S
+++ b/board/a9m2440/lowlevel_init.S
@@ -7,6 +7,209 @@
.section ".text_bare_init.board_init_lowlevel","ax"
+/*
+ * To be able to setup the SDRAM interface correctly, we need some
+ * external information about the connected SDRAM devices.
+ *
+ * When we set GPH8, we can read at GPB:
+ * Bit 0..1: Memory device size -> 00=16M, 01=64M, 10=32M, 11=128M
+ * Bit 2: CL setting
+ *
+ * Some remarks: The CL setting seems useless. It always signals a CL3
+ * requirement, but the SDRAM types I found on the cards are supporting
+ * CL2 @ 100 MHz. But also these SDRAM types are only support 105 MHz max.
+ * So, we never need CL3 because we can't run the CPU at 533 MHz (which
+ * implies an 133 MHz SDRAM clock).
+ * All devices are connected via 32 bit databus
+ *
+ * Note: I was able to check the 32 MiB and 64 MiB configuration only. I didn't
+ * had access to a 16 MiB nor 128 MiB config.
+ *
+ */
+
+sdram_init:
+ /*
+ * Read the configuration. After reset until any GPIO port is
+ * configured yet, these pins show external settings, to detect
+ * the SDRAM size.
+ */
+ ldr r1, =GPBDAT
+ ldr r4, [r1]
+ and r4, r4, #0x3
+
+ ldr r1, =S3C24X0_MEMCTL_BASE
+ /* configure both SDRAM areas with 32 bit data bus width */
+ ldr r0, =((0x2 << 24) + (0x2 << 28))
+ str r0, [r1], #0x1c /* post add register offset for bank6 */
+
+ /*
+ * With the configuration we simply need to calculate an offset into
+ * our table with the predefined SDRAM settings
+ */
+ adr r0, SDRAMDATA
+ mov r2, #6*4 /* # of bytes per table entry */
+ mul r3, r4, r2
+ add r0, r0, r3 /* start address of the entry */
+
+ /*
+ * store the table entry data into the registers
+ */
+1:
+ ldr r3, [r0], #4
+ str r3, [r1], #4
+ subs r2, r2, #4
+ bne 1b
+
+/* TODO: Check if the second bank is populated, and switch it off if not */
+
+ mov pc, lr
+
+/*
+ * we need 4 sets of memory settings per main CPU clock speed
+ *
+ * 400MHz main speed:
+ * - 16 MiB in the first bank, maybe 16 MiB in the second bank (untested!)
+ * - 32 MiB in the first bank, maybe 32 MiB in the second bank (CL=2)
+ * - 64 MiB in the first bank, maybe 64 MiB in the second bank (CL=2)
+ * - 128 MiB in the first bank, maybe 128 MiB in the second bank (untested!)
+ *
+ * Note: SDRAM clock runs at 100MHz
+ */
+
+SDRAMDATA:
+/* --------------------------- 16 MiB @ 100MHz --------------------------- */
+ /*
+ * - MT = 11 (= sync dram type)
+ * - Trcd = 01 (= CL3)
+ * - SCAN = 00 (= 8 bit collumns)
+ */
+ .word ((0x3 << 15) + (0x1 << 2) + (0x0))
+ .word ((0x3 << 15) + (0x1 << 2) + (0x0))
+ /*
+ * SDRAM refresh settings
+ * - REFEN = 1 (= refresh enabled)
+ * - TREFMD = 0 (= auto refresh)
+ * - Trp = 00 (= 2 RAS precharge clocks)
+ * - Tsrc = 11 (= 7 clocks -> row cycle time @100MHz 2+5=7 -> 70ns)
+ * - Refrsh = 2^11 + 1 - 100 * 15.6 = 2049 - 1560 = FIXME
+ */
+ .word ((0x1 << 23) + (0x0 << 22) + (0x0 << 20) + (0x3 << 18) + 468)
+ /*
+ * SDRAM banksize
+ * - BURST_EN = 0 (= burst mode disabled)
+ * - SCKE_EN = 1 (= SDRAM SCKE enabled)
+ * - SCLK_EN = 1 (= clock active only during accesses)
+ * - BK67MAP = 010 (= 128MiB) FIXME?????
+ */
+ .word ((0 << 7) + (1 << 5) + (1 << 4) + 2)
+ /*
+ * SDRAM mode register
+ * CL = 010 (= 2 clocks)
+ */
+ .word (0x2 << 4)
+ .word (0x2 << 4)
+
+/* ------------- one or two banks with 64 MiB @ 100MHz -------------------- */
+
+ /*
+ * - MT = 11 (= sync dram type)
+ * - Trcd = 00 (= CL2)
+ * - SCAN = 01 (= 9 bit collumns)
+ */
+ .word ((0x3 << 15) + (0x0 << 2) + (0x1))
+ .word ((0x3 << 15) + (0x0 << 2) + (0x1))
+ /*
+ * SDRAM refresh settings
+ * - REFEN = 1 (= refresh enabled)
+ * - TREFMD = 0 (= auto refresh)
+ * - Trp = 00 (= 2 RAS precharge clocks)
+ * - Tsrc = 01 (= 5 clocks -> row cycle time @100MHz 2+5=7 -> 70ns)
+ * - Refrsh = 2^11 + 1 - 100 * 15.6 = 2049 - 1560 = 489
+ */
+ .word ((0x1 << 23) + (0x0 << 22) + (0x0 << 20) + (0x1 << 18) + 489)
+ /*
+ * SDRAM banksize
+ * - BURST_EN = 1 (= burst mode enabled)
+ * - SCKE_EN = 1 (= SDRAM SCKE enabled)
+ * - SCLK_EN = 1 (= clock active only during accesses)
+ * - BK67MAP = 001 (= 64 MiB)
+ */
+ .word ((1 << 7) + (1 << 5) + (1 << 4) + 1)
+ /*
+ * SDRAM mode register
+ * CL = 010 (= 2 clocks)
+ */
+ .word (0x2 << 4)
+ .word (0x2 << 4)
+
+/* ------------- one or two banks with 32 MiB @ 100MHz -------------------- */
+
+ /*
+ * - MT = 11 (= sync dram type)
+ * - Trcd = 00 (= CL2)
+ * - SCAN = 01 (= 9 bit collumns)
+ */
+ .word ((0x3 << 15) + (0x0 << 2) + (0x1))
+ .word ((0x3 << 15) + (0x0 << 2) + (0x1))
+ /*
+ * SDRAM refresh settings
+ * - REFEN = 1 (= refresh enabled)
+ * - TREFMD = 0 (= auto refresh)
+ * - Trp = 00 (= 2 RAS precharge clocks)
+ * - Tsrc = 01 (= 5 clocks -> row cycle time @100MHz 2+5=7 -> 70ns)
+ * - Refrsh = 2^11 + 1 - 100 * 15.6 = 2049 - 1560 = 489
+ */
+ .word ((0x1 << 23) + (0x0 << 22) + (0x0 << 20) + (0x1 << 18) + 489)
+ /*
+ * SDRAM banksize
+ * - BURST_EN = 1 (= burst mode enabled)
+ * - SCKE_EN = 1 (= SDRAM SCKE enabled)
+ * - SCLK_EN = 1 (= clock active only during accesses)
+ * - BK67MAP = 000 (= 32 MiB)
+ */
+ .word ((1 << 7) + (1 << 5) + (1 << 4) + 0)
+ /*
+ * SDRAM mode register
+ * CL = 010 (= 2 clocks)
+ */
+ .word (0x2 << 4)
+ .word (0x2 << 4)
+
+/* ------------ one or two banks with 128 MiB @ 100MHz -------------------- */
+
+ /*
+ * - MT = 11 (= sync dram type)
+ * - Trcd = 00 (= CL2)
+ * - SCAN = 01 (= 9 bit collumns)
+ */
+ .word ((0x3 << 15) + (0x0 << 2) + (0x1))
+ .word ((0x3 << 15) + (0x0 << 2) + (0x1))
+ /*
+ * SDRAM refresh settings
+ * - REFEN = 1 (= refresh enabled)
+ * - TREFMD = 0 (= auto refresh)
+ * - Trp = 00 (= 2 RAS precharge clocks)
+ * - Tsrc = 01 (= 5 clocks -> row cycle time @100MHz 2+5=7 -> 70ns)
+ * - Refrsh = 2^11 + 1 - 100 * 7.5 = 2049 - FIXME = 1259
+ */
+ .word ((0x1 << 23) + (0x0 << 22) + (0x1 << 20) + (0x3 << 18) + 1259)
+ /*
+ * SDRAM banksize
+ * - BURST_EN = 0 (= burst mode disabled)
+ * - SCKE_EN = 1 (= SDRAM SCKE enabled)
+ * - SCLK_EN = 1 (= clock active only during accesses)
+ * - BK67MAP = 010 (= 128MiB)
+ */
+ .word (0x32)
+ /*
+ * SDRAM mode register
+ * CL = 010 (= 2 clocks)
+ */
+ .word (0x2 << 4)
+ .word (0x2 << 4)
+
+/* ------------------------------------------------------------------------ */
+
.globl board_init_lowlevel
board_init_lowlevel:
@@ -26,7 +229,7 @@ board_init_lowlevel:
1:
bl s3c24x0_pll_init
- bl s3c24x0_sdram_init
+ bl sdram_init
#ifdef CONFIG_S3C24XX_NAND_BOOT
mov lr, r10 /* restore the link register */