2010-06-18 17:33:51 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Copyright © 2010 by Rafaël Carré
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
#include "config.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
|
|
|
|
#define CACHE_NONE 0
|
|
|
|
#define CACHE_ALL 0x0C
|
|
|
|
#define UNCACHED_ADDR(a) (a + 0x10000000)
|
|
|
|
|
|
|
|
#if defined(SANSA_CLIP) || defined(SANSA_M200V4) || defined(SANSA_C200V2)
|
|
|
|
/* 16 bits external bus, low power SDRAM, 16 Mbits = 2 Mbytes */
|
|
|
|
#define MEMORY_MODEL 0x21
|
|
|
|
|
|
|
|
#elif defined(SANSA_E200V2) || defined(SANSA_FUZE) || defined(SANSA_CLIPV2) \
|
2011-08-27 16:21:19 +00:00
|
|
|
|| defined(SANSA_CLIPPLUS) || defined(SANSA_FUZEV2) \
|
|
|
|
|| defined(SANSA_CLIPZIP)
|
2010-06-18 17:33:51 +00:00
|
|
|
/* 16 bits external bus, high performance SDRAM, 64 Mbits = 8 Mbytes */
|
|
|
|
#define MEMORY_MODEL 0x5
|
|
|
|
|
|
|
|
#else
|
|
|
|
#error "The external memory in your player is unknown"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
.global memory_init
|
|
|
|
.text
|
|
|
|
|
|
|
|
memory_init:
|
|
|
|
|
|
|
|
#ifdef BOOTLOADER
|
|
|
|
|
|
|
|
ldr r2, =0xC80F0014 @ CGU_PERI
|
|
|
|
ldr r1, [r2]
|
|
|
|
orr r1, r1, #(CGU_EXTMEM_CLOCK_ENABLE|CGU_EXTMEMIF_CLOCK_ENABLE)
|
|
|
|
str r1, [r2]
|
|
|
|
|
|
|
|
ldr r3, =0xC6030000 @ MPMC_BASE
|
|
|
|
|
|
|
|
mov r2, #1 @ enable MPMC
|
|
|
|
str r2, [r3] @ MPMC_CONTROL
|
|
|
|
ldr r2, =0x183 @ SDRAM NOP, all clocks high
|
|
|
|
str r2, [r3, #0x20] @ MPMC_DYNAMIC_CONTROL
|
|
|
|
ldr r2, =0x103 @ SDRAM PALL, all clocks high
|
|
|
|
str r2, [r3, #0x20] @ MPMC_DYNAMIC_CONTROL
|
|
|
|
ldr r1, =0x138 @ 0x138 * 16 HCLK ticks between SDRAM refresh cycles
|
|
|
|
str r1, [r3, #0x24] @ MPMC_DYNAMIC_REFRESH
|
|
|
|
mov r2, #0 @ little endian, HCLK:MPMCCLKOUT[3:0] ratio = 1:1
|
|
|
|
str r2, [r3, #8] @ MPMC_CONFIG
|
|
|
|
|
|
|
|
ldr r2, [r3, #0xfe8] @ MPMC_PERIPH_ID2
|
|
|
|
tst r2, #0xf0
|
|
|
|
movne r2, #1 @ command delayed, clock out not delayed
|
|
|
|
strne r2, [r3, #0x28] @ MPMC_DYNAMIC_READ_CONFIG
|
|
|
|
|
|
|
|
mov r1, #2
|
|
|
|
mov r0, #5
|
|
|
|
mov ip, #4
|
|
|
|
mov r2, #0
|
|
|
|
str r1, [r3, #0x30] @ tRP
|
|
|
|
str ip, [r3, #0x34] @ tRAS
|
|
|
|
str r0, [r3, #0x38] @ tSREX
|
|
|
|
str r2, [r3, #0x3c] @ tAPR
|
|
|
|
str ip, [r3, #0x40] @ tDAL
|
|
|
|
str r1, [r3, #0x44] @ tWR
|
|
|
|
str r0, [r3, #0x48] @ tRC
|
|
|
|
str r0, [r3, #0x4c] @ tRFC
|
|
|
|
str r0, [r3, #0x50] @ tXSR
|
|
|
|
str r1, [r3, #0x54] @ tRRD
|
|
|
|
str r1, [r3, #0x58] @ tMRD
|
|
|
|
mov ip, #(MEMORY_MODEL << 7)
|
|
|
|
str ip, [r3, #0x100] @ MPMC_DYNAMIC_CONFIG_CONFIG_0
|
|
|
|
orr r1, r1, #(2<<8) @ CAS & RAS latency = 2 clock cycle
|
|
|
|
str r1, [r3, #0x104] @ MPMC_DYNAMIC_CONFIG_RASCAS_0
|
|
|
|
|
|
|
|
str r2, [r3, #0x120] @ MPMC_DYNAMIC_CONFIG_CONFIG_1
|
|
|
|
str r2, [r3, #0x124] @ MPMC_DYNAMIC_CONFIG_RASCAS_1
|
|
|
|
str r2, [r3, #0x140] @ MPMC_DYNAMIC_CONFIG_CONFIG_2
|
|
|
|
str r2, [r3, #0x144] @ MPMC_DYNAMIC_CONFIG_RASCAS_2
|
|
|
|
str r2, [r3, #0x160] @ MPMC_DYNAMIC_CONFIG_CONFIG_3
|
|
|
|
str r2, [r3, #0x164] @ MPMC_DYNAMIC_CONFIG_RASCAS_3
|
|
|
|
|
|
|
|
mov r1, #0x82 @ SDRAM MODE, MPMCCLKOUT runs continuously
|
|
|
|
str r1, [r3, #0x20] @ MPMC_DYNAMIC_CONTROL
|
|
|
|
|
2011-02-02 17:55:04 +00:00
|
|
|
ldr r1, =DRAM_ORIG+(0x2300*MEMORYSIZE)
|
2010-06-18 17:33:51 +00:00
|
|
|
ldr r1, [r1]
|
|
|
|
|
|
|
|
str r2, [r3, #0x20] @ MPMC_DYNAMIC_CONTROL= SDRAM NORMAL,
|
|
|
|
@ MPMCCLKOUT stopped when SDRAM is idle
|
|
|
|
|
|
|
|
ldr r2, [r3, #0x100] @ MPMC_DYNAMIC_CONFIG_0
|
|
|
|
orr r2, r2, #(1<<19) @ buffer enable
|
|
|
|
str r2, [r3, #0x100]
|
|
|
|
|
|
|
|
#endif /* BOOTLOADER */
|
|
|
|
|
|
|
|
@ XXX: to avoid using the stack, we rely on the fact that:
|
|
|
|
@ - ttb_init
|
|
|
|
@ - map_section
|
|
|
|
@ - enable_mmu
|
|
|
|
@ do not modify ip (r12)
|
|
|
|
mov ip, lr
|
|
|
|
|
|
|
|
/* Setup MMU */
|
|
|
|
|
|
|
|
bl ttb_init
|
|
|
|
|
|
|
|
mov r0, #0 @ physical address
|
|
|
|
mov r1, #0 @ virtual address
|
|
|
|
mov r2, #0x1000 @ size (all memory)
|
|
|
|
mov r3, #CACHE_NONE
|
|
|
|
bl map_section
|
|
|
|
|
|
|
|
mov r0, #0 @ physical address
|
|
|
|
ldr r1, =IRAM_ORIG @ virtual address
|
|
|
|
mov r2, #1 @ size : 1MB
|
|
|
|
mov r3, #CACHE_ALL
|
|
|
|
bl map_section
|
|
|
|
|
|
|
|
mov r0, #0 @ physical address
|
|
|
|
ldr r1, =UNCACHED_ADDR(IRAM_ORIG) @ virtual address
|
|
|
|
mov r2, #1 @ size : 1MB
|
|
|
|
mov r3, #CACHE_NONE
|
|
|
|
bl map_section
|
|
|
|
|
|
|
|
mov r0, #0x30000000 @ physical address
|
|
|
|
mov r1, #DRAM_ORIG @ virtual address
|
|
|
|
mov r2, #MEMORYSIZE @ size
|
|
|
|
mov r3, #CACHE_ALL
|
|
|
|
bl map_section
|
|
|
|
|
|
|
|
mov r0, #0x30000000 @ physical address
|
|
|
|
mov r1, #UNCACHED_ADDR(DRAM_ORIG) @ virtual address
|
|
|
|
mov r2, #MEMORYSIZE @ size
|
|
|
|
mov r3, #CACHE_NONE
|
|
|
|
bl map_section
|
|
|
|
|
|
|
|
/* map 1st mbyte of RAM at 0x0 to have exception vectors available */
|
|
|
|
#ifdef BOOTLOADER
|
|
|
|
mov r0, #0x81000000 @ physical address
|
|
|
|
#else
|
|
|
|
mov r0, #0x30000000 @ physical address
|
|
|
|
#endif
|
|
|
|
mov r1, #0 @ virtual address
|
|
|
|
mov r2, #1 @ size
|
|
|
|
mov r3, #CACHE_ALL
|
|
|
|
bl map_section
|
|
|
|
|
|
|
|
bl enable_mmu
|
|
|
|
|
|
|
|
bx ip
|