mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 23:51:33 +00:00
sc520: Move RAM sizing code from asm to C
This commit is contained in:
parent
ed4cba79d6
commit
96cd66426a
10 changed files with 611 additions and 767 deletions
|
@ -33,10 +33,10 @@ LIB := $(obj)lib$(SOC).o
|
|||
|
||||
COBJS-$(CONFIG_SYS_SC520) += sc520.o
|
||||
COBJS-$(CONFIG_PCI) += sc520_pci.o
|
||||
COBJS-$(CONFIG_SYS_SC520) += sc520_sdram.o
|
||||
COBJS-$(CONFIG_SYS_SC520_SSI) += sc520_ssi.o
|
||||
COBJS-$(CONFIG_SYS_SC520_TIMER) += sc520_timer.o
|
||||
|
||||
SOBJS-$(CONFIG_SYS_SC520) += sc520_asm.o
|
||||
SOBJS-$(CONFIG_SYS_SC520) += sc520_car.o
|
||||
|
||||
SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
|
||||
|
|
|
@ -31,13 +31,6 @@
|
|||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* utility functions for boards based on the AMD sc520
|
||||
*
|
||||
* void init_sc520(void)
|
||||
* unsigned long init_sc520_dram(void)
|
||||
*/
|
||||
|
||||
sc520_mmcr_t *sc520_mmcr = (sc520_mmcr_t *)SC520_MMCR_BASE;
|
||||
|
||||
int cpu_init_f(void)
|
||||
|
@ -65,109 +58,6 @@ int cpu_init_f(void)
|
|||
return x86_cpu_init_f();
|
||||
}
|
||||
|
||||
unsigned long init_sc520_dram(void)
|
||||
{
|
||||
bd_t *bd = gd->bd;
|
||||
|
||||
u32 dram_present=0;
|
||||
u32 dram_ctrl;
|
||||
|
||||
#ifdef CONFIG_SYS_SDRAM_DRCTMCTL
|
||||
/* these memory control registers are set up in the assember part,
|
||||
* in sc520_asm.S, during 'mem_init'. If we muck with them here,
|
||||
* after we are running a stack in RAM, we have troubles. Besides,
|
||||
* these refresh and delay values are better ? simply specified
|
||||
* outright in the include/configs/{cfg} file since the HW designer
|
||||
* simply dictates it.
|
||||
*/
|
||||
#else
|
||||
u8 tmp;
|
||||
u8 val;
|
||||
|
||||
int cas_precharge_delay = CONFIG_SYS_SDRAM_PRECHARGE_DELAY;
|
||||
int refresh_rate = CONFIG_SYS_SDRAM_REFRESH_RATE;
|
||||
int ras_cas_delay = CONFIG_SYS_SDRAM_RAS_CAS_DELAY;
|
||||
|
||||
/* set SDRAM speed here */
|
||||
|
||||
refresh_rate /= 78;
|
||||
if (refresh_rate <= 1) {
|
||||
val = 0; /* 7.8us */
|
||||
} else if (refresh_rate == 2) {
|
||||
val = 1; /* 15.6us */
|
||||
} else if (refresh_rate == 3 || refresh_rate == 4) {
|
||||
val = 2; /* 31.2us */
|
||||
} else {
|
||||
val = 3; /* 62.4us */
|
||||
}
|
||||
|
||||
tmp = (readb(&sc520_mmcr->drcctl) & 0xcf) | (val<<4);
|
||||
writeb(tmp, &sc520_mmcr->drcctl);
|
||||
|
||||
val = readb(&sc520_mmcr->drctmctl) & 0xf0;
|
||||
|
||||
if (cas_precharge_delay==3) {
|
||||
val |= 0x04; /* 3T */
|
||||
} else if (cas_precharge_delay==4) {
|
||||
val |= 0x08; /* 4T */
|
||||
} else if (cas_precharge_delay>4) {
|
||||
val |= 0x0c;
|
||||
}
|
||||
|
||||
if (ras_cas_delay > 3) {
|
||||
val |= 2;
|
||||
} else {
|
||||
val |= 1;
|
||||
}
|
||||
writeb(val, &c520_mmcr->drctmctl);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We read-back the configuration of the dram
|
||||
* controller that the assembly code wrote
|
||||
*/
|
||||
dram_ctrl = readl(&sc520_mmcr->drcbendadr);
|
||||
|
||||
bd->bi_dram[0].start = 0;
|
||||
if (dram_ctrl & 0x80) {
|
||||
/* bank 0 enabled */
|
||||
dram_present = bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22;
|
||||
bd->bi_dram[0].size = bd->bi_dram[1].start;
|
||||
} else {
|
||||
bd->bi_dram[0].size = 0;
|
||||
bd->bi_dram[1].start = bd->bi_dram[0].start;
|
||||
}
|
||||
|
||||
if (dram_ctrl & 0x8000) {
|
||||
/* bank 1 enabled */
|
||||
dram_present = bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14;
|
||||
bd->bi_dram[1].size = bd->bi_dram[2].start - bd->bi_dram[1].start;
|
||||
} else {
|
||||
bd->bi_dram[1].size = 0;
|
||||
bd->bi_dram[2].start = bd->bi_dram[1].start;
|
||||
}
|
||||
|
||||
if (dram_ctrl & 0x800000) {
|
||||
/* bank 2 enabled */
|
||||
dram_present = bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6;
|
||||
bd->bi_dram[2].size = bd->bi_dram[3].start - bd->bi_dram[2].start;
|
||||
} else {
|
||||
bd->bi_dram[2].size = 0;
|
||||
bd->bi_dram[3].start = bd->bi_dram[2].start;
|
||||
}
|
||||
|
||||
if (dram_ctrl & 0x80000000) {
|
||||
/* bank 3 enabled */
|
||||
dram_present = (dram_ctrl & 0x7f000000) >> 2;
|
||||
bd->bi_dram[3].size = dram_present - bd->bi_dram[3].start;
|
||||
} else {
|
||||
bd->bi_dram[3].size = 0;
|
||||
}
|
||||
gd->ram_size = dram_present;
|
||||
|
||||
return dram_present;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_SC520_RESET
|
||||
void reset_cpu(ulong addr)
|
||||
{
|
||||
|
|
|
@ -1,608 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* This file is largely based on code obtned from AMD. AMD's original
|
||||
* copyright is included below
|
||||
*/
|
||||
|
||||
/* TITLE SIZER - Aspen DRAM Sizing Routine.
|
||||
* =============================================================================
|
||||
*
|
||||
* Copyright 1999 Advanced Micro Devices, Inc.
|
||||
* You may redistribute this program and/or modify this program 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 program is distributed WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
* THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY
|
||||
* OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT OF
|
||||
* THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
* IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER
|
||||
* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
|
||||
* INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR INABILITY
|
||||
* TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGES. BECAUSE SOME JURSIDICTIONS PROHIBIT THE EXCLUSION OR
|
||||
* LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE
|
||||
* LIMITATION MAY NOT APPLY TO YOU.
|
||||
*
|
||||
* AMD does not assume any responsibility for any errors that may appear in
|
||||
* the Materials nor any responsibility to support or update the Materials.
|
||||
* AMD retains the right to make changes to its test specifications at any
|
||||
* time, without notice.
|
||||
* ==============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* FILE : sizer.asm - SDRAM DIMM Sizing Algorithm
|
||||
*
|
||||
*
|
||||
*
|
||||
* FUNCTIONS : sizemem() - jumped to, not called. To be executed after
|
||||
* reset to determine the size of the SDRAM DIMMs. Initializes
|
||||
* the memory subsystem.
|
||||
*
|
||||
*
|
||||
* AUTHOR : Buddy Fey - Original.
|
||||
*
|
||||
*
|
||||
* DESCRIPTION : Performs sizing on SDRAM DIMMs on ASPEN processor.
|
||||
* NOTE: This is a small memory model version
|
||||
*
|
||||
*
|
||||
* INPUTS : BP contains return address offset
|
||||
* CACHE is assumed to be disabled.
|
||||
* The FS segment limit has already been set to big real mode
|
||||
* (full 32-bit addressing capability)
|
||||
*
|
||||
*
|
||||
* OUTPUTS : None
|
||||
*
|
||||
*
|
||||
* REG USE : ax,bx,cx,dx,di,si,bp, fs
|
||||
*
|
||||
*
|
||||
* REVISION : See PVCS info below
|
||||
*
|
||||
*
|
||||
* TEST PLAN CROSS REFERENCE:
|
||||
*
|
||||
*
|
||||
* $Workfile: $
|
||||
* $Revision: 1.2 $
|
||||
* $Date: 1999/09/22 12:49:33 $
|
||||
* $Author: chipf $
|
||||
* $Log: sizer.asm $
|
||||
* Revision 1.2 1999/09/22 12:49:33 chipf
|
||||
* Add legal header
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* FUNCTIONAL DESCRIPTION:
|
||||
* This routine is called to autodetect the geometry of the DRAM.
|
||||
*
|
||||
* This routine is called to determine the number of column bits for the DRAM
|
||||
* devices in this external bank. This routine assumes that the external bank
|
||||
* has been configured for an 11-bit column and for 4 internal banks. This gives
|
||||
* us the maximum address reach in memory. By writing a test value to the max
|
||||
* address and locating where it aliases to, we can determine the number of valid
|
||||
* column bits.
|
||||
*
|
||||
* This routine is called to determine the number of internal banks each DRAM
|
||||
* device has. The external bank (under test) is configured for maximum reach
|
||||
* with 11-bit columns and 4 internal banks. This routine will write to a max
|
||||
* address (BA1 and BA0 = 1) and then read from an address with BA1=0 to see if
|
||||
* that column is a "don't care". If BA1 does not affect write/read of data,
|
||||
* then this device has only 2 internal banks.
|
||||
*
|
||||
* This routine is called to determine the ending address for this external
|
||||
* bank of SDRAM. We write to a max address with a data value and then disable
|
||||
* row address bits looking for "don't care" locations. Each "don't care" bit
|
||||
* represents a dividing of the maximum density (128M) by 2. By dividing the
|
||||
* maximum of 32 4M chunks in an external bank down by all the "don't care" bits
|
||||
* determined during sizing, we set the proper density.
|
||||
*
|
||||
* WARNINGS.
|
||||
* bp must be preserved because it is used for return linkage.
|
||||
*
|
||||
* EXIT
|
||||
* nothing returned - but the memory subsystem is enabled
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <asm/ic/sc520.h>
|
||||
|
||||
.section .text
|
||||
.equ CACHELINESZ, 0x00000010 /* size of our cache line (read buffer) */
|
||||
.equ COL11_ADR, 0x0e001e00 /* 11 col addrs */
|
||||
.equ COL10_ADR, 0x0e000e00 /* 10 col addrs */
|
||||
.equ COL09_ADR, 0x0e000600 /* 9 col addrs */
|
||||
.equ COL08_ADR, 0x0e000200 /* 8 col addrs */
|
||||
.equ ROW14_ADR, 0x0f000000 /* 14 row addrs */
|
||||
.equ ROW13_ADR, 0x07000000 /* 13 row addrs */
|
||||
.equ ROW12_ADR, 0x03000000 /* 12 row addrs */
|
||||
.equ ROW11_ADR, 0x01000000 /* 11 row addrs/also bank switch */
|
||||
.equ ROW10_ADR, 0x00000000 /* 10 row addrs/also bank switch */
|
||||
.equ COL11_DATA, 0x0b0b0b0b /* 11 col addrs */
|
||||
.equ COL10_DATA, 0x0a0a0a0a /* 10 col data */
|
||||
.equ COL09_DATA, 0x09090909 /* 9 col data */
|
||||
.equ COL08_DATA, 0x08080808 /* 8 col data */
|
||||
.equ ROW14_DATA, 0x3f3f3f3f /* 14 row data (MASK) */
|
||||
.equ ROW13_DATA, 0x1f1f1f1f /* 13 row data (MASK) */
|
||||
.equ ROW12_DATA, 0x0f0f0f0f /* 12 row data (MASK) */
|
||||
.equ ROW11_DATA, 0x07070707 /* 11 row data/also bank switch (MASK) */
|
||||
.equ ROW10_DATA, 0xaaaaaaaa /* 10 row data/also bank switch (MASK) */
|
||||
|
||||
.globl mem_init
|
||||
mem_init:
|
||||
/* Preserve Boot Flags */
|
||||
movl %ebx, %ebp
|
||||
|
||||
/* initialize dram controller registers */
|
||||
xorw %ax, %ax
|
||||
movl $SC520_DBCTL, %edi
|
||||
movb %al, (%edi) /* disable write buffer */
|
||||
|
||||
movl $SC520_ECCCTL, %edi
|
||||
movb %al, (%edi) /* disable ECC */
|
||||
|
||||
movl $SC520_DRCTMCTL, %edi
|
||||
movb $0x1e, %al /* Set SDRAM timing for slowest */
|
||||
movb %al, (%edi)
|
||||
|
||||
/* setup loop to do 4 external banks starting with bank 3 */
|
||||
movl $0xff000000, %eax /* enable last bank and setup */
|
||||
movl $SC520_DRCBENDADR, %edi /* ending address register */
|
||||
movl %eax, (%edi)
|
||||
|
||||
movl $SC520_DRCCFG, %edi /* setup */
|
||||
movw $0xbbbb, %ax /* dram config register for */
|
||||
movw %ax, (%edi)
|
||||
|
||||
/* issue a NOP to all DRAMs */
|
||||
movl $SC520_DRCCTL, %edi /* setup DRAM control register with */
|
||||
movb $0x01, %al /* Disable refresh,disable write buffer */
|
||||
movb %al, (%edi)
|
||||
movl $CACHELINESZ, %esi /* just a dummy address to write for */
|
||||
movw %ax, (%esi)
|
||||
|
||||
/* delay for 100 usec? */
|
||||
movw $100, %cx
|
||||
sizdelay:
|
||||
loop sizdelay
|
||||
|
||||
/* issue all banks precharge */
|
||||
movb $0x02, %al
|
||||
movb %al, (%edi)
|
||||
movw %ax, (%esi)
|
||||
|
||||
/* issue 2 auto refreshes to all banks */
|
||||
movb $0x04, %al /* Auto refresh cmd */
|
||||
movb %al, (%edi)
|
||||
movw $0x02, %cx
|
||||
refresh1:
|
||||
movw %ax, (%esi)
|
||||
loop refresh1
|
||||
|
||||
/* issue LOAD MODE REGISTER command */
|
||||
movb $0x03, %al /* Load mode register cmd */
|
||||
movb %al, (%edi)
|
||||
movw %ax, (%esi)
|
||||
|
||||
/* issue 8 more auto refreshes to all banks */
|
||||
movb $0x04, %al /* Auto refresh cmd */
|
||||
movb %al, (%edi)
|
||||
movw $0x0008, %cx
|
||||
refresh2:
|
||||
movw %ax, (%esi)
|
||||
loop refresh2
|
||||
|
||||
/* set control register to NORMAL mode */
|
||||
movb $0x00, %al /* Normal mode value */
|
||||
movb %al, (%edi)
|
||||
|
||||
/*
|
||||
* size dram starting with external bank 3
|
||||
* moving to external bank 0
|
||||
*/
|
||||
movl $0x3, %ecx /* start with external bank 3 */
|
||||
|
||||
nextbank:
|
||||
|
||||
/* write col 11 wrap adr */
|
||||
movl $COL11_ADR, %esi /* set address to max col (11) wrap addr */
|
||||
movl $COL11_DATA, %eax /* pattern for max supported columns(11) */
|
||||
movl %eax, (%esi) /* write max col pattern at max col adr */
|
||||
movl (%esi), %ebx /* optional read */
|
||||
cmpl %ebx, %eax /* to verify write */
|
||||
jnz bad_ram /* this ram is bad */
|
||||
|
||||
/* write col 10 wrap adr */
|
||||
movl $COL10_ADR, %esi /* set address to 10 col wrap address */
|
||||
movl $COL10_DATA, %eax /* pattern for 10 col wrap */
|
||||
movl %eax, (%esi) /* write 10 col pattern @ 10 col wrap adr */
|
||||
movl (%esi), %ebx /* optional read */
|
||||
cmpl %ebx, %eax /* to verify write */
|
||||
jnz bad_ram /* this ram is bad */
|
||||
|
||||
/* write col 9 wrap adr */
|
||||
movl $COL09_ADR, %esi /* set address to 9 col wrap address */
|
||||
movl $COL09_DATA, %eax /* pattern for 9 col wrap */
|
||||
movl %eax, (%esi) /* write 9 col pattern @ 9 col wrap adr */
|
||||
movl (%esi), %ebx /* optional read */
|
||||
cmpl %ebx, %eax /* to verify write */
|
||||
jnz bad_ram /* this ram is bad */
|
||||
|
||||
/* write col 8 wrap adr */
|
||||
movl $COL08_ADR, %esi /* set address to min(8) col wrap address */
|
||||
movl $COL08_DATA, %eax /* pattern for min (8) col wrap */
|
||||
movl %eax, (%esi) /* write min col pattern @ min col adr */
|
||||
movl (%esi), %ebx /* optional read */
|
||||
cmpl %ebx, %eax /* to verify write */
|
||||
jnz bad_ram /* this ram is bad */
|
||||
|
||||
/* write row 14 wrap adr */
|
||||
movl $ROW14_ADR, %esi /* set address to max row (14) wrap addr */
|
||||
movl $ROW14_DATA, %eax /* pattern for max supported rows(14) */
|
||||
movl %eax, (%esi) /* write max row pattern at max row adr */
|
||||
movl (%esi), %ebx /* optional read */
|
||||
cmpl %ebx, %eax /* to verify write */
|
||||
jnz bad_ram /* this ram is bad */
|
||||
|
||||
/* write row 13 wrap adr */
|
||||
movl $ROW13_ADR, %esi /* set address to 13 row wrap address */
|
||||
movl $ROW13_DATA, %eax /* pattern for 13 row wrap */
|
||||
movl %eax, (%esi) /* write 13 row pattern @ 13 row wrap adr */
|
||||
movl (%esi), %ebx /* optional read */
|
||||
cmpl %ebx, %eax /* to verify write */
|
||||
jnz bad_ram /* this ram is bad */
|
||||
|
||||
/* write row 12 wrap adr */
|
||||
movl $ROW12_ADR, %esi /* set address to 12 row wrap address */
|
||||
movl $ROW12_DATA, %eax /* pattern for 12 row wrap */
|
||||
movl %eax, (%esi) /* write 12 row pattern @ 12 row wrap adr */
|
||||
movl (%esi), %ebx /* optional read */
|
||||
cmpl %ebx, %eax /* to verify write */
|
||||
jnz bad_ram /* this ram is bad */
|
||||
|
||||
/* write row 11 wrap adr */
|
||||
movl $ROW11_ADR, %edi /* set address to 11 row wrap address */
|
||||
movl $ROW11_DATA, %eax /* pattern for 11 row wrap */
|
||||
movl %eax, (%edi) /* write 11 row pattern @ 11 row wrap adr */
|
||||
movl (%edi), %ebx /* optional read */
|
||||
cmpl %ebx, %eax /* to verify write */
|
||||
jnz bad_ram /* this ram is bad */
|
||||
|
||||
/*
|
||||
* write row 10 wrap adr --- this write is really to determine
|
||||
* number of banks
|
||||
*/
|
||||
movl $ROW10_ADR, %edi /* set address to 10 row wrap address */
|
||||
movl $ROW10_DATA, %eax /* pattern for 10 row wrap (AA) */
|
||||
movl %eax, (%edi) /* write 10 row pattern @ 10 row wrap adr */
|
||||
movl (%edi), %ebx /* optional read */
|
||||
cmpl %ebx, %eax /* to verify write */
|
||||
jnz bad_ram /* this ram is bad */
|
||||
|
||||
/*
|
||||
* read data @ row 12 wrap adr to determine * banks,
|
||||
* and read data @ row 14 wrap adr to determine * rows.
|
||||
* if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM.
|
||||
* if data @ row 12 wrap == AA, we only have 2 banks, NOT 4
|
||||
* if data @ row 12 wrap == 11 or 12, we have 4 banks,
|
||||
*/
|
||||
xorw %di, %di /* value for 2 banks in DI */
|
||||
movl (%esi), %ebx /* read from 12 row wrap to check banks */
|
||||
/* (esi is setup from the write to row 12 wrap) */
|
||||
cmpl %ebx, %eax /* check for AA pattern (eax holds the aa pattern) */
|
||||
jz only2 /* if pattern == AA, we only have 2 banks */
|
||||
|
||||
/* 4 banks */
|
||||
|
||||
movw $0x008, %di /* value for 4 banks in DI (BNK_CNT bit) */
|
||||
cmpl $ROW11_DATA, %ebx /* only other legitimate values are 11 */
|
||||
jz only2
|
||||
cmpl $ROW12_DATA, %ebx /* and 12 */
|
||||
jnz bad_ram /* its bad if not 11 or 12! */
|
||||
|
||||
/* fall through */
|
||||
only2:
|
||||
/*
|
||||
* validate row mask
|
||||
*/
|
||||
movl $ROW14_ADR, %esi /* set address back to max row wrap addr */
|
||||
movl (%esi), %eax /* read actual number of rows @ row14 adr */
|
||||
|
||||
cmpl $ROW11_DATA, %eax /* row must be greater than 11 pattern */
|
||||
jb bad_ram
|
||||
|
||||
cmpl $ROW14_DATA, %eax /* and row must be less than 14 pattern */
|
||||
ja bad_ram
|
||||
|
||||
cmpb %ah, %al /* verify all 4 bytes of dword same */
|
||||
jnz bad_ram
|
||||
movl %eax, %ebx
|
||||
shrl $16, %ebx
|
||||
cmpw %bx, %ax
|
||||
jnz bad_ram
|
||||
|
||||
/*
|
||||
* read col 11 wrap adr for real column data value
|
||||
*/
|
||||
movl $COL11_ADR, %esi /* set address to max col (11) wrap addr */
|
||||
movl (%esi), %eax /* read real col number at max col adr */
|
||||
|
||||
/*
|
||||
* validate column data
|
||||
*/
|
||||
cmpl $COL08_DATA, %eax /* col must be greater than 8 pattern */
|
||||
jb bad_ram
|
||||
|
||||
cmpl $COL11_DATA, %eax /* and row must be less than 11 pattern */
|
||||
ja bad_ram
|
||||
|
||||
subl $COL08_DATA, %eax /* normalize column data to zero */
|
||||
jc bad_ram
|
||||
cmpb %ah, %al /* verify all 4 bytes of dword equal */
|
||||
jnz bad_ram
|
||||
movl %eax, %edx
|
||||
shrl $16, %edx
|
||||
cmpw %dx, %ax
|
||||
jnz bad_ram
|
||||
|
||||
/*
|
||||
* merge bank and col data together
|
||||
*/
|
||||
addw %di, %dx /* merge of bank and col info in dl */
|
||||
|
||||
/*
|
||||
* fix ending addr mask based upon col info
|
||||
*/
|
||||
movb $0x03, %al
|
||||
subb %dh, %al /* dh contains the overflow from the bank/col merge */
|
||||
movb %bl, %dh /* bl contains the row mask (aa, 07, 0f, 1f or 3f) */
|
||||
xchgw %cx, %ax /* cx = ax = 3 or 2 depending on 2 or 4 bank device */
|
||||
shrb %cl, %dh
|
||||
incb %dh /* ending addr is 1 greater than real end */
|
||||
xchgw %cx, %ax /* cx is bank number again */
|
||||
|
||||
bad_reint:
|
||||
/*
|
||||
* issue all banks precharge
|
||||
*/
|
||||
movl $SC520_DRCCTL, %esi /* setup DRAM control register with */
|
||||
movb $0x02, %al /* All banks precharge */
|
||||
movb %al, (%esi)
|
||||
movl $CACHELINESZ, %esi /* address to init read buffer */
|
||||
movw %ax, (%esi)
|
||||
|
||||
/*
|
||||
* update ENDING ADDRESS REGISTER
|
||||
*/
|
||||
movl $SC520_DRCBENDADR, %edi /* DRAM ending address register */
|
||||
movl %ecx, %ebx
|
||||
addl %ebx, %edi
|
||||
movb %dh, (%edi)
|
||||
|
||||
/*
|
||||
* update CONFIG REGISTER
|
||||
*/
|
||||
xorb %dh, %dh
|
||||
movw $0x000f, %bx
|
||||
movw %cx, %ax
|
||||
shlw $2, %ax
|
||||
xchgw %cx, %ax
|
||||
shlw %cl, %dx
|
||||
shlw %cl, %bx
|
||||
notw %bx
|
||||
xchgw %cx, %ax
|
||||
movl $SC520_DRCCFG, %edi
|
||||
movw (%edi), %ax
|
||||
andw %bx, %ax
|
||||
orw %dx, %ax
|
||||
movw %ax, (%edi)
|
||||
jcxz cleanup
|
||||
|
||||
decw %cx
|
||||
movl %ecx, %ebx
|
||||
movl $SC520_DRCBENDADR, %edi /* DRAM ending address register */
|
||||
movb $0xff, %al
|
||||
addl %ebx, %edi
|
||||
movb %al, (%edi)
|
||||
|
||||
/*
|
||||
* set control register to NORMAL mode
|
||||
*/
|
||||
movl $SC520_DRCCTL, %esi /* setup DRAM control register with */
|
||||
movb $0x00, %al /* Normal mode value */
|
||||
movb %al, (%esi)
|
||||
movl $CACHELINESZ, %esi /* address to init read buffer */
|
||||
movw %ax, (%esi)
|
||||
jmp nextbank
|
||||
|
||||
cleanup:
|
||||
movl $SC520_DRCBENDADR, %edi /* DRAM ending address register */
|
||||
movw $0x04, %cx
|
||||
xorw %ax, %ax
|
||||
cleanuplp:
|
||||
movb (%edi), %al
|
||||
orb %al, %al
|
||||
jz emptybank
|
||||
|
||||
addb %ah, %al
|
||||
jns nottoomuch
|
||||
|
||||
movb $0x7f, %al
|
||||
nottoomuch:
|
||||
movb %al, %ah
|
||||
orb $0x80, %al
|
||||
movb %al, (%edi)
|
||||
emptybank:
|
||||
incl %edi
|
||||
loop cleanuplp
|
||||
|
||||
#if defined CONFIG_SYS_SDRAM_DRCTMCTL
|
||||
/* just have your hardware desinger _GIVE_ you what you need here! */
|
||||
movl $SC520_DRCTMCTL, %edi
|
||||
movb $CONFIG_SYS_SDRAM_DRCTMCTL, %al
|
||||
movb %al, (%edi)
|
||||
#else
|
||||
#if defined(CONFIG_SYS_SDRAM_CAS_LATENCY_2T) || defined(CONFIG_SYS_SDRAM_CAS_LATENCY_3T)
|
||||
/*
|
||||
* Set the CAS latency now since it is hard to do
|
||||
* when we run from the RAM
|
||||
*/
|
||||
movl $SC520_DRCTMCTL, %edi /* DRAM timing register */
|
||||
movb (%edi), %al
|
||||
#ifdef CONFIG_SYS_SDRAM_CAS_LATENCY_2T
|
||||
andb $0xef, %al
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_SDRAM_CAS_LATENCY_3T
|
||||
orb $0x10, %al
|
||||
#endif
|
||||
movb %al, (%edi)
|
||||
#endif
|
||||
#endif
|
||||
movl $SC520_DRCCTL, %edi /* DRAM Control register */
|
||||
movb $0x03, %al /* Load mode register cmd */
|
||||
movb %al, (%edi)
|
||||
movw %ax, (%esi)
|
||||
|
||||
|
||||
movl $SC520_DRCCTL, %edi /* DRAM Control register */
|
||||
movb $0x18, %al /* Enable refresh and NORMAL mode */
|
||||
movb %al, (%edi)
|
||||
|
||||
jmp dram_done
|
||||
|
||||
bad_ram:
|
||||
xorl %edx, %edx
|
||||
xorl %edi, %edi
|
||||
jmp bad_reint
|
||||
|
||||
dram_done:
|
||||
/* Restore Boot Flags */
|
||||
movl %ebx, %ebp
|
||||
ret
|
||||
|
||||
#if CONFIG_SYS_SDRAM_ECC_ENABLE
|
||||
.globl init_ecc
|
||||
init_ecc:
|
||||
/* A nominal memory test: just a byte at each address line */
|
||||
movl %eax, %ecx
|
||||
shrl $0x1, %ecx
|
||||
movl $0x1, %edi
|
||||
memtest0:
|
||||
movb $0xa5, (%edi)
|
||||
cmpb $0xa5, (%edi)
|
||||
jne out
|
||||
shrl $0x1, %ecx
|
||||
andl %ecx, %ecx
|
||||
jz set_ecc
|
||||
shll $0x1, %edi
|
||||
jmp memtest0
|
||||
|
||||
set_ecc:
|
||||
/* clear all ram with a memset */
|
||||
movl %eax, %ecx
|
||||
xorl %esi, %esi
|
||||
xorl %edi, %edi
|
||||
xorl %eax, %eax
|
||||
shrl $0x2, %ecx
|
||||
cld
|
||||
rep stosl
|
||||
|
||||
/* enable read, write buffers */
|
||||
movb $0x11, %al
|
||||
movl $SC520_DBCTL, %edi
|
||||
movb %al, (%edi)
|
||||
|
||||
/* enable NMI mapping for ECC */
|
||||
movl $SC520_ECCINT, %edi
|
||||
movb $0x10, %al
|
||||
movb %al, (%edi)
|
||||
|
||||
/* Turn on ECC */
|
||||
movl $SC520_ECCCTL, %edi
|
||||
movb $0x05, %al
|
||||
movb %al,(%edi)
|
||||
|
||||
out:
|
||||
ret
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Read and decode the sc520 DRCBENDADR MMCR and return the number of
|
||||
* available ram bytes in %eax
|
||||
*/
|
||||
.globl get_mem_size
|
||||
get_mem_size:
|
||||
movl $SC520_DRCBENDADR, %edi /* DRAM ending address register */
|
||||
|
||||
bank0: movl (%edi), %eax
|
||||
movl %eax, %ecx
|
||||
andl $0x00000080, %ecx
|
||||
jz bank1
|
||||
andl $0x0000007f, %eax
|
||||
shll $22, %eax
|
||||
movl %eax, %edx
|
||||
|
||||
bank1: movl (%edi), %eax
|
||||
movl %eax, %ecx
|
||||
andl $0x00008000, %ecx
|
||||
jz bank2
|
||||
andl $0x00007f00, %eax
|
||||
shll $14, %eax
|
||||
movl %eax, %edx
|
||||
|
||||
bank2: movl (%edi), %eax
|
||||
movl %eax, %ecx
|
||||
andl $0x00800000, %ecx
|
||||
jz bank3
|
||||
andl $0x007f0000, %eax
|
||||
shll $6, %eax
|
||||
movl %eax, %edx
|
||||
|
||||
bank3: movl (%edi), %eax
|
||||
movl %eax, %ecx
|
||||
andl $0x80000000, %ecx
|
||||
jz done
|
||||
andl $0x7f000000, %eax
|
||||
shrl $2, %eax
|
||||
movl %eax, %edx
|
||||
|
||||
done:
|
||||
movl %edx, %eax
|
||||
ret
|
532
arch/i386/cpu/sc520/sc520_sdram.c
Normal file
532
arch/i386/cpu/sc520/sc520_sdram.c
Normal file
|
@ -0,0 +1,532 @@
|
|||
/*
|
||||
* (C) Copyright 2010
|
||||
* Graeme Russ <graeme.russ@gmail.com>.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* 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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/processor-flags.h>
|
||||
#include <asm/ic/sc520.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct sc520_sdram_info {
|
||||
u8 banks;
|
||||
u8 columns;
|
||||
u8 rows;
|
||||
u8 size;
|
||||
};
|
||||
|
||||
static void sc520_sizemem(void);
|
||||
static void sc520_set_dram_timing(void);
|
||||
static void sc520_set_dram_refresh_rate(void);
|
||||
static void sc520_enable_dram_refresh(void);
|
||||
static void sc520_enable_sdram(void);
|
||||
#if CONFIG_SYS_SDRAM_ECC_ENABLE
|
||||
static void sc520_enable_ecc(void)
|
||||
#endif
|
||||
|
||||
int dram_init_f(void)
|
||||
{
|
||||
sc520_sizemem();
|
||||
sc520_set_dram_timing();
|
||||
sc520_set_dram_refresh_rate();
|
||||
sc520_enable_dram_refresh();
|
||||
sc520_enable_sdram();
|
||||
#if CONFIG_SYS_SDRAM_ECC_ENABLE
|
||||
sc520_enable_ecc();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void sc520_dummy_write(void)
|
||||
{
|
||||
writew(0x0000, CACHELINESZ);
|
||||
}
|
||||
static inline void sc520_issue_sdram_op_mode_select(u8 command)
|
||||
{
|
||||
writeb(command, &sc520_mmcr->drcctl);
|
||||
sc520_dummy_write();
|
||||
}
|
||||
|
||||
static inline int check_long(u32 test_long)
|
||||
{
|
||||
u8 i;
|
||||
u8 tmp_byte = (u8)(test_long & 0x000000ff);
|
||||
|
||||
for (i = 1; i < 4; i++) {
|
||||
if ((u8)((test_long >> (i * 8)) & 0x000000ff) != tmp_byte)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int write_and_test(u32 data, u32 address)
|
||||
{
|
||||
writel(data, address);
|
||||
if (readl(address) == data)
|
||||
return 0; /* Good */
|
||||
else
|
||||
return -1; /* Bad */
|
||||
}
|
||||
|
||||
static void sc520_enable_sdram(void)
|
||||
{
|
||||
u32 par_config;
|
||||
|
||||
/* Enable Writes, Caching and Code Execution to SDRAM */
|
||||
par_config = readl(&sc520_mmcr->par[3]);
|
||||
par_config &= ~(SC520_PAR_EXEC_DIS |
|
||||
SC520_PAR_CACHE_DIS |
|
||||
SC520_PAR_WRITE_DIS);
|
||||
writel(par_config, &sc520_mmcr->par[3]);
|
||||
|
||||
par_config = readl(&sc520_mmcr->par[4]);
|
||||
par_config &= ~(SC520_PAR_EXEC_DIS |
|
||||
SC520_PAR_CACHE_DIS |
|
||||
SC520_PAR_WRITE_DIS);
|
||||
writel(par_config, &sc520_mmcr->par[4]);
|
||||
}
|
||||
|
||||
static void sc520_set_dram_timing(void)
|
||||
{
|
||||
u8 drctmctl = 0x00;
|
||||
|
||||
#if defined CONFIG_SYS_SDRAM_DRCTMCTL
|
||||
/* just have your hardware designer _GIVE_ you what you need here! */
|
||||
drctmctl = CONFIG_SYS_SDRAM_DRCTMCTL;
|
||||
#else
|
||||
switch (CONFIG_SYS_SDRAM_RAS_CAS_DELAY) {
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
drctmctl |= 0x01;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
drctmctl |= 0x02;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (CONFIG_SYS_SDRAM_PRECHARGE_DELAY) {
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
drctmctl |= 0x04;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
drctmctl |= 0x08;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
drctmctl |= 0x0c;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (CONFIG_SYS_SDRAM_CAS_LATENCY) {
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
drctmctl |= 0x10;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
writeb(drctmctl, &sc520_mmcr->drctmctl);
|
||||
|
||||
/* Issue load mode register command */
|
||||
sc520_issue_sdram_op_mode_select(0x03);
|
||||
}
|
||||
|
||||
static void sc520_set_dram_refresh_rate(void)
|
||||
{
|
||||
u8 drctl;
|
||||
|
||||
drctl = readb(&sc520_mmcr->drcctl);
|
||||
drctl &= 0xcf;
|
||||
|
||||
switch (CONFIG_SYS_SDRAM_REFRESH_RATE) {
|
||||
case 78:
|
||||
break;
|
||||
case 156:
|
||||
default:
|
||||
drctl |= 0x10;
|
||||
break;
|
||||
case 312:
|
||||
drctl |= 0x20;
|
||||
break;
|
||||
case 624:
|
||||
drctl |= 0x30;
|
||||
break;
|
||||
}
|
||||
|
||||
writeb(drctl, &sc520_mmcr->drcctl);
|
||||
}
|
||||
|
||||
static void sc520_enable_dram_refresh(void)
|
||||
{
|
||||
u8 drctl;
|
||||
|
||||
drctl = readb(&sc520_mmcr->drcctl);
|
||||
drctl &= 0x30; /* keep refresh rate */
|
||||
drctl |= 0x08; /* enable refresh, normal mode */
|
||||
|
||||
writeb(drctl, &sc520_mmcr->drcctl);
|
||||
}
|
||||
|
||||
static void sc520_get_bank_info(int bank, struct sc520_sdram_info *bank_info)
|
||||
{
|
||||
u32 col_data;
|
||||
u32 row_data;
|
||||
|
||||
u32 drcbendadr;
|
||||
u16 drccfg;
|
||||
|
||||
u8 banks = 0x00;
|
||||
u8 columns = 0x00;
|
||||
u8 rows = 0x00;
|
||||
|
||||
bank_info->banks = 0x00;
|
||||
bank_info->columns = 0x00;
|
||||
bank_info->rows = 0x00;
|
||||
bank_info->size = 0x00;
|
||||
|
||||
if ((bank < 0) || (bank > 3)) {
|
||||
printf("Bad Bank ID\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save configuration */
|
||||
drcbendadr = readl(&sc520_mmcr->drcbendadr);
|
||||
drccfg = readw(&sc520_mmcr->drccfg);
|
||||
|
||||
/* Setup SDRAM Bank to largest possible size */
|
||||
writew(0x000b << (bank * 4), &sc520_mmcr->drccfg);
|
||||
|
||||
/* Set ending address for this bank */
|
||||
writel(0x000000ff << (bank * 8), &sc520_mmcr->drcbendadr);
|
||||
|
||||
/* write col 11 wrap adr */
|
||||
if (write_and_test(COL11_DATA, COL11_ADR) != 0)
|
||||
goto restore_and_exit;
|
||||
|
||||
/* write col 10 wrap adr */
|
||||
if (write_and_test(COL10_DATA, COL10_ADR) != 0)
|
||||
goto restore_and_exit;
|
||||
|
||||
/* write col 9 wrap adr */
|
||||
if (write_and_test(COL09_DATA, COL09_ADR) != 0)
|
||||
goto restore_and_exit;
|
||||
|
||||
/* write col 8 wrap adr */
|
||||
if (write_and_test(COL08_DATA, COL08_ADR) != 0)
|
||||
goto restore_and_exit;
|
||||
|
||||
col_data = readl(COL11_ADR);
|
||||
|
||||
/* All four bytes in the read long must be the same */
|
||||
if (check_long(col_data) < 0)
|
||||
goto restore_and_exit;
|
||||
|
||||
if ((col_data >= COL08_DATA) && (col_data <= COL11_DATA))
|
||||
columns = (u8)(col_data & 0x000000ff);
|
||||
else
|
||||
goto restore_and_exit;
|
||||
|
||||
/* write row 14 wrap adr */
|
||||
if (write_and_test(ROW14_DATA, ROW14_ADR) != 0)
|
||||
goto restore_and_exit;
|
||||
|
||||
/* write row 13 wrap adr */
|
||||
if (write_and_test(ROW13_DATA, ROW13_ADR) != 0)
|
||||
goto restore_and_exit;
|
||||
|
||||
/* write row 12 wrap adr */
|
||||
if (write_and_test(ROW12_DATA, ROW12_ADR) != 0)
|
||||
goto restore_and_exit;
|
||||
|
||||
/* write row 11 wrap adr */
|
||||
if (write_and_test(ROW11_DATA, ROW11_ADR) != 0)
|
||||
goto restore_and_exit;
|
||||
|
||||
if (write_and_test(ROW10_DATA, ROW10_ADR) != 0)
|
||||
goto restore_and_exit;
|
||||
|
||||
/*
|
||||
* read data @ row 12 wrap adr to determine number of banks,
|
||||
* and read data @ row 14 wrap adr to determine number of rows.
|
||||
* if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM.
|
||||
* if data @ row 12 wrap == AA, we only have 2 banks, NOT 4
|
||||
* if data @ row 12 wrap == 11 or 12, we have 4 banks,
|
||||
*/
|
||||
row_data = readl(ROW12_ADR);
|
||||
|
||||
/* All four bytes in the read long must be the same */
|
||||
if (check_long(row_data) != 0)
|
||||
goto restore_and_exit;
|
||||
|
||||
switch (row_data) {
|
||||
case ROW10_DATA:
|
||||
banks = 2;
|
||||
break;
|
||||
|
||||
case ROW11_DATA:
|
||||
case ROW12_DATA:
|
||||
banks = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto restore_and_exit;
|
||||
}
|
||||
|
||||
row_data = readl(ROW14_ADR);
|
||||
|
||||
/* All four bytes in the read long must be the same */
|
||||
if (check_long(row_data) != 0)
|
||||
goto restore_and_exit;
|
||||
|
||||
switch (row_data) {
|
||||
case ROW11_DATA:
|
||||
case ROW12_DATA:
|
||||
case ROW13_DATA:
|
||||
case ROW14_DATA:
|
||||
rows = (u8)(row_data & 0x000000ff);
|
||||
break;
|
||||
|
||||
default:
|
||||
goto restore_and_exit;
|
||||
}
|
||||
|
||||
bank_info->banks = banks;
|
||||
bank_info->columns = columns;
|
||||
bank_info->rows = rows;
|
||||
|
||||
if ((bank_info->banks != 0) &&
|
||||
(bank_info->columns != 0) &&
|
||||
(bank_info->rows != 0)) {
|
||||
bank_info->size = bank_info->rows;
|
||||
bank_info->size >>= (11 - bank_info->columns);
|
||||
bank_info->size++;
|
||||
}
|
||||
|
||||
restore_and_exit:
|
||||
/* Restore configuration */
|
||||
writel(drcbendadr, &sc520_mmcr->drcbendadr);
|
||||
writew(drccfg, &sc520_mmcr->drccfg);
|
||||
}
|
||||
|
||||
static void sc520_setup_sizemem(void)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
/* Disable write buffer */
|
||||
writeb(0x00, &sc520_mmcr->dbctl);
|
||||
|
||||
/* Disable ECC */
|
||||
writeb(0x00, &sc520_mmcr->eccctl);
|
||||
|
||||
/* Set slowest SDRAM timing */
|
||||
writeb(0x1e, &sc520_mmcr->drctmctl);
|
||||
|
||||
/* Issue a NOP to all SDRAM banks */
|
||||
sc520_issue_sdram_op_mode_select(0x01);
|
||||
|
||||
/* Delay for 100 microseconds */
|
||||
udelay(100);
|
||||
|
||||
/* Issue 'All Banks Precharge' command */
|
||||
sc520_issue_sdram_op_mode_select(0x02);
|
||||
|
||||
/* Issue 2 'Auto Refresh Enable' command */
|
||||
sc520_issue_sdram_op_mode_select(0x04);
|
||||
sc520_dummy_write();
|
||||
|
||||
/* Issue 'Load Mode Register' command */
|
||||
sc520_issue_sdram_op_mode_select(0x03);
|
||||
|
||||
/* Issue 8 more 'Auto Refresh Enable' commands */
|
||||
sc520_issue_sdram_op_mode_select(0x04);
|
||||
for (i = 0; i < 7; i++)
|
||||
sc520_dummy_write();
|
||||
|
||||
/* Set control register to 'Normal Mode' */
|
||||
writeb(0x00, &sc520_mmcr->drcctl);
|
||||
}
|
||||
|
||||
static void sc520_sizemem(void)
|
||||
{
|
||||
struct sc520_sdram_info sdram_info[4];
|
||||
u8 bank_config = 0x00;
|
||||
u8 end_addr = 0x00;
|
||||
u16 drccfg = 0x0000;
|
||||
u32 drcbendadr = 0x00000000;
|
||||
u8 i;
|
||||
|
||||
/* Use PARs to disable caching of maximum allowable 256MB SDRAM */
|
||||
writel(SC520_SDRAM1_PAR | SC520_PAR_CACHE_DIS, &sc520_mmcr->par[3]);
|
||||
writel(SC520_SDRAM2_PAR | SC520_PAR_CACHE_DIS, &sc520_mmcr->par[4]);
|
||||
|
||||
sc520_setup_sizemem();
|
||||
|
||||
gd->ram_size = 0;
|
||||
|
||||
/* Size each SDRAM bank */
|
||||
for (i = 0; i <= 3; i++) {
|
||||
sc520_get_bank_info(i, &sdram_info[i]);
|
||||
|
||||
if (sdram_info[i].banks != 0) {
|
||||
/* Update Configuration register */
|
||||
bank_config = sdram_info[i].columns - 8;
|
||||
|
||||
if (sdram_info[i].banks == 4)
|
||||
bank_config |= 0x08;
|
||||
|
||||
drccfg |= bank_config << (i * 4);
|
||||
|
||||
/* Update End Address register */
|
||||
end_addr += sdram_info[i].size;
|
||||
drcbendadr |= (end_addr | 0x80) << (i * 8);
|
||||
|
||||
gd->ram_size += sdram_info[i].size << 22;
|
||||
}
|
||||
|
||||
/* Issue 'All Banks Precharge' command */
|
||||
sc520_issue_sdram_op_mode_select(0x02);
|
||||
|
||||
/* Set control register to 'Normal Mode' */
|
||||
writeb(0x00, &sc520_mmcr->drcctl);
|
||||
}
|
||||
|
||||
writel(drcbendadr, &sc520_mmcr->drcbendadr);
|
||||
writew(drccfg, &sc520_mmcr->drccfg);
|
||||
|
||||
/* Clear PARs preventing caching of SDRAM */
|
||||
writel(0x00000000, &sc520_mmcr->par[3]);
|
||||
writel(0x00000000, &sc520_mmcr->par[4]);
|
||||
}
|
||||
|
||||
#if CONFIG_SYS_SDRAM_ECC_ENABLE
|
||||
static void sc520_enable_ecc(void)
|
||||
|
||||
/* A nominal memory test: just a byte at each address line */
|
||||
movl %eax, %ecx
|
||||
shrl $0x1, %ecx
|
||||
movl $0x1, %edi
|
||||
memtest0:
|
||||
movb $0xa5, (%edi)
|
||||
cmpb $0xa5, (%edi)
|
||||
jne out
|
||||
shrl $0x1, %ecx
|
||||
andl %ecx, %ecx
|
||||
jz set_ecc
|
||||
shll $0x1, %edi
|
||||
jmp memtest0
|
||||
|
||||
set_ecc:
|
||||
/* clear all ram with a memset */
|
||||
movl %eax, %ecx
|
||||
xorl %esi, %esi
|
||||
xorl %edi, %edi
|
||||
xorl %eax, %eax
|
||||
shrl $0x2, %ecx
|
||||
cld
|
||||
rep stosl
|
||||
|
||||
/* enable read, write buffers */
|
||||
movb $0x11, %al
|
||||
movl $DBCTL, %edi
|
||||
movb %al, (%edi)
|
||||
|
||||
/* enable NMI mapping for ECC */
|
||||
movl $ECCINT, %edi
|
||||
movb $0x10, %al
|
||||
movb %al, (%edi)
|
||||
|
||||
/* Turn on ECC */
|
||||
movl $ECCCTL, %edi
|
||||
movb $0x05, %al
|
||||
movb %al,(%edi)
|
||||
|
||||
out:
|
||||
jmp init_ecc_ret
|
||||
}
|
||||
#endif
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
ulong dram_ctrl;
|
||||
ulong dram_present = 0x00000000;
|
||||
|
||||
/*
|
||||
* We read-back the configuration of the dram
|
||||
* controller that the assembly code wrote
|
||||
*/
|
||||
dram_ctrl = readl(&sc520_mmcr->drcbendadr);
|
||||
|
||||
gd->bd->bi_dram[0].start = 0;
|
||||
if (dram_ctrl & 0x80) {
|
||||
/* bank 0 enabled */
|
||||
gd->bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22;
|
||||
dram_present = gd->bd->bi_dram[1].start;
|
||||
gd->bd->bi_dram[0].size = gd->bd->bi_dram[1].start;
|
||||
} else {
|
||||
gd->bd->bi_dram[0].size = 0;
|
||||
gd->bd->bi_dram[1].start = gd->bd->bi_dram[0].start;
|
||||
}
|
||||
|
||||
if (dram_ctrl & 0x8000) {
|
||||
/* bank 1 enabled */
|
||||
gd->bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14;
|
||||
dram_present = gd->bd->bi_dram[2].start;
|
||||
gd->bd->bi_dram[1].size = gd->bd->bi_dram[2].start -
|
||||
gd->bd->bi_dram[1].start;
|
||||
} else {
|
||||
gd->bd->bi_dram[1].size = 0;
|
||||
gd->bd->bi_dram[2].start = gd->bd->bi_dram[1].start;
|
||||
}
|
||||
|
||||
if (dram_ctrl & 0x800000) {
|
||||
/* bank 2 enabled */
|
||||
gd->bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6;
|
||||
dram_present = gd->bd->bi_dram[3].start;
|
||||
gd->bd->bi_dram[2].size = gd->bd->bi_dram[3].start -
|
||||
gd->bd->bi_dram[2].start;
|
||||
} else {
|
||||
gd->bd->bi_dram[2].size = 0;
|
||||
gd->bd->bi_dram[3].start = gd->bd->bi_dram[2].start;
|
||||
}
|
||||
|
||||
if (dram_ctrl & 0x80000000) {
|
||||
/* bank 3 enabled */
|
||||
dram_present = (dram_ctrl & 0x7f000000) >> 2;
|
||||
gd->bd->bi_dram[3].size = dram_present -
|
||||
gd->bd->bi_dram[3].start;
|
||||
} else {
|
||||
gd->bd->bi_dram[3].size = 0;
|
||||
}
|
||||
|
||||
gd->ram_size = dram_present;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -82,29 +82,22 @@ car_init_ret:
|
|||
* starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack
|
||||
*/
|
||||
movl $CONFIG_SYS_INIT_SP_ADDR, %esp
|
||||
movl $CONFIG_SYS_INIT_GD_ADDR, %ebp
|
||||
|
||||
/* Skip memory initialization if not starting from cold-reset */
|
||||
movl %ebx, %ecx
|
||||
andl $GD_FLG_COLD_BOOT, %ecx
|
||||
jz skip_mem_init
|
||||
/* Set Boot Flags in Global Data */
|
||||
movl %ebx, (GD_FLAGS * 4)(%ebp)
|
||||
|
||||
/* Determine our load offset (and put in Global Data) */
|
||||
call 1f
|
||||
1: popl %ecx
|
||||
subl $1b, %ecx
|
||||
movl %ecx, (GD_LOAD_OFF * 4)(%ebp)
|
||||
|
||||
/* size memory */
|
||||
call mem_init
|
||||
call dram_init_f
|
||||
|
||||
skip_mem_init:
|
||||
/* fetch memory size (into %eax) */
|
||||
call get_mem_size
|
||||
movl %eax, %esp
|
||||
|
||||
#if CONFIG_SYS_SDRAM_ECC_ENABLE
|
||||
/* Skip ECC initialization if not starting from cold-reset */
|
||||
movl %ebx, %ecx
|
||||
andl $GD_FLG_COLD_BOOT, %ecx
|
||||
jz skip_ecc_init
|
||||
call init_ecc
|
||||
|
||||
skip_init_ecc:
|
||||
#endif
|
||||
/* Setup stack in SDRAM */
|
||||
movl (GD_RAM_SIZE * 4)(%ebp), %esp
|
||||
|
||||
/* Test the stack */
|
||||
pushl $0
|
||||
|
@ -118,21 +111,8 @@ skip_init_ecc:
|
|||
|
||||
wbinvd
|
||||
|
||||
/* Determine our load offset */
|
||||
call 1f
|
||||
1: popl %ecx
|
||||
subl $1b, %ecx
|
||||
|
||||
/* Set the upper memory limit parameter */
|
||||
subl $CONFIG_SYS_STACK_SIZE, %eax
|
||||
|
||||
/* Pointer to temporary global data */
|
||||
movl $CONFIG_SYS_INIT_GD_ADDR, %edx
|
||||
|
||||
/* %edx points to the global data structure */
|
||||
movl %esp, (GD_RAM_SIZE * 4)(%edx)
|
||||
movl %ebx, (GD_FLAGS * 4)(%edx)
|
||||
movl %ecx, (GD_LOAD_OFF * 4)(%edx)
|
||||
/* Set parameter to board_init_f() to boot flags */
|
||||
movl (GD_FLAGS * 4)(%ebp), %eax
|
||||
|
||||
call board_init_f /* Enter, U-boot! */
|
||||
|
||||
|
|
|
@ -285,6 +285,36 @@ extern sc520_mmcr_t *sc520_mmcr;
|
|||
#define SC520_PAR14 (SC520_PAR0 + (0x04 * 14))
|
||||
#define SC520_PAR15 (SC520_PAR0 + (0x04 * 15))
|
||||
|
||||
/*
|
||||
* PARs for maximum allowable 256MB of SDRAM @ 0x00000000
|
||||
* Two PARs are required due to maximum PAR size of 128MB
|
||||
* These are used in the SDRAM sizing code to disable caching
|
||||
*
|
||||
* 111 0 0 0 1 11111111111 00000000000000 }- 0xe3ffc000
|
||||
* 111 0 0 0 1 11111111111 00100000000000 }- 0xe3ffc800
|
||||
* \ / | | | | \----+----/ \-----+------/
|
||||
* | | | | | | +---------- Start at 0x00000000
|
||||
* | | | | | | 0x08000000
|
||||
* | | | | | +----------------------- 128MB Region Size
|
||||
* | | | | | ((2047 + 1) * 64kB)
|
||||
* | | | | +------------------------------ 64kB Page Size
|
||||
* | | | +-------------------------------- Writes Enabled
|
||||
* | | +---------------------------------- Caching Enabled
|
||||
* | +------------------------------------ Execution Enabled
|
||||
* +--------------------------------------- SDRAM
|
||||
*/
|
||||
#define SC520_SDRAM1_PAR 0xe3ffc000
|
||||
#define SC520_SDRAM2_PAR 0xe3ffc800
|
||||
|
||||
#define SC520_PAR_WRITE_DIS 0x04000000
|
||||
#define SC520_PAR_CACHE_DIS 0x08000000
|
||||
#define SC520_PAR_EXEC_DIS 0x10000000
|
||||
|
||||
/*
|
||||
* Programmable Address Regions to cover 256MB SDRAM (Maximum supported)
|
||||
* required for DRAM sizing code
|
||||
*/
|
||||
|
||||
/* MMCR Register bits (not all of them :) ) */
|
||||
|
||||
/* SSI Stuff */
|
||||
|
@ -315,6 +345,33 @@ extern sc520_mmcr_t *sc520_mmcr;
|
|||
#define UART2_DIS 0x02 /* UART2 Disable */
|
||||
#define UART1_DIS 0x01 /* UART1 Disable */
|
||||
|
||||
/*
|
||||
* Defines used for SDRAM Sizing (number of columns and rows)
|
||||
* Refer to section 10.6.4 - SDRAM Sizing Algorithm in the
|
||||
* Elan SC520 Microcontroller User's Manual (Order #22004B)
|
||||
*/
|
||||
#define CACHELINESZ 0x00000010
|
||||
|
||||
#define COL11_ADR 0x0e001e00
|
||||
#define COL10_ADR 0x0e000e00
|
||||
#define COL09_ADR 0x0e000600
|
||||
#define COL08_ADR 0x0e000200
|
||||
#define COL11_DATA 0x0b0b0b0b
|
||||
#define COL10_DATA 0x0a0a0a0a
|
||||
#define COL09_DATA 0x09090909
|
||||
#define COL08_DATA 0x08080808
|
||||
|
||||
#define ROW14_ADR 0x0f000000
|
||||
#define ROW13_ADR 0x07000000
|
||||
#define ROW12_ADR 0x03000000
|
||||
#define ROW11_ADR 0x01000000
|
||||
#define ROW10_ADR 0x00000000
|
||||
#define ROW14_DATA 0x3f3f3f3f
|
||||
#define ROW13_DATA 0x1f1f1f1f
|
||||
#define ROW12_DATA 0x0f0f0f0f
|
||||
#define ROW11_DATA 0x07070707
|
||||
#define ROW10_DATA 0xaaaaaaaa
|
||||
|
||||
/* 0x28000000 - 0x3fffffff is used by the flash banks */
|
||||
|
||||
/* 0x40000000 - 0xffffffff is not adressable by the SC520 */
|
||||
|
|
|
@ -176,7 +176,7 @@ gd_t *gd;
|
|||
/*
|
||||
* Load U-Boot into RAM, initialize BSS, perform relocation adjustments
|
||||
*/
|
||||
void board_init_f(ulong mem_top)
|
||||
void board_init_f(ulong boot_flags)
|
||||
{
|
||||
void *text_start = &__text_start;
|
||||
void *data_end = &__data_end;
|
||||
|
@ -194,8 +194,12 @@ void board_init_f(ulong mem_top)
|
|||
Elf32_Rel *re_src;
|
||||
Elf32_Rel *re_end;
|
||||
|
||||
gd->flags = boot_flags;
|
||||
|
||||
/* Calculate destination RAM Address and relocation offset */
|
||||
dest_addr = (void *)mem_top - (bss_end - text_start);
|
||||
dest_addr = (void *)gd->ram_size;
|
||||
dest_addr -= CONFIG_SYS_STACK_SIZE;
|
||||
dest_addr -= (bss_end - text_start);
|
||||
rel_offset = text_start - dest_addr;
|
||||
|
||||
/* Perform low-level initialization only when cold booted */
|
||||
|
|
|
@ -160,12 +160,6 @@ int board_early_init_r(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
init_sc520_dram();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void show_boot_progress(int val)
|
||||
{
|
||||
uchar led_mask;
|
||||
|
|
|
@ -57,11 +57,6 @@ board_init16:
|
|||
movl $CONFIG_SYS_SC520_LLIO_PAR, %eax
|
||||
movl %eax, (%di)
|
||||
|
||||
/* Disable SDRAM write buffer */
|
||||
movw $(SC520_DBCTL - SC520_MMCR_BASE), %di
|
||||
xorw %ax, %ax
|
||||
movb %al, (%di)
|
||||
|
||||
/* Disabe MMCR alias */
|
||||
movw $0xfffc, %dx
|
||||
movl $0x000000cb, %eax
|
||||
|
|
|
@ -136,11 +136,11 @@
|
|||
* SDRAM Configuration
|
||||
*/
|
||||
#define CONFIG_SYS_SDRAM_DRCTMCTL 0x18
|
||||
#define CONFIG_SYS_SDRAM_REFRESH_RATE 156
|
||||
#define CONFIG_NR_DRAM_BANKS 4
|
||||
|
||||
/* CONFIG_SYS_SDRAM_DRCTMCTL Overrides the following*/
|
||||
#undef CONFIG_SYS_SDRAM_PRECHARGE_DELAY
|
||||
#undef CONFIG_SYS_SDRAM_REFRESH_RATE
|
||||
#undef CONFIG_SYS_SDRAM_RAS_CAS_DELAY
|
||||
#undef CONFIG_SYS_SDRAM_CAS_LATENCY_2T
|
||||
#undef CONFIG_SYS_SDRAM_CAS_LATENCY_3T
|
||||
|
|
Loading…
Reference in a new issue