blob: 195b7c5f6f29c21d1451689bd4e8694865cda09e [file] [log] [blame]
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
* Copyright (C) 2005 Eswar Nallusamy, LANL
* Copyright (C) 2005 Tyan
* (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
* Copyright (C) 2007 coresystems GmbH
* (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
* Copyright (C) 2007 Advanced Micro Devices, Inc.
*
* 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; version 2 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* Init code - Switch CPU to protected mode and enable Cache-as-Ram (CAR). */
#include <macros.h>
#include <amd_geodelx.h>
/* When we come here we are in protected mode. We expand the stack
* and copy the data segment from ROM to the memory.
*
* After that, we call the chipset bootstrap routine that
* does what is left of the chipset initialization.
*
* NOTE: Aligned to 4 so that we are sure that the prefetch
* cache will be reloaded.
*/
.align 4
.globl protected_stage0
protected_stage0:
/* This code was used by v2. TODO. */
lgdt %cs:gdtptr
ljmp $ROM_CODE_SEG, $__protected_stage0
.globl __protected_stage0
__protected_stage0:
/* Save the BIST result. */
movl %eax, %ebp
port80_post(0x01)
movw $ROM_DATA_SEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw %ax, %fs
movw %ax, %gs
/* Restore the BIST value to %eax. */
movl %ebp, %eax
.align 4
/* Here begins CAR support. */
/* This particular code is straight from coreboot v2. */
/* DCacheSetup: Setup data cache for use as RAM for a stack. */
DCacheSetup:
invd
/* Set cache properties. */
movl $CPU_RCONF_DEFAULT, %ecx
rdmsr
/* 1MB system memory in write back 1|00100|00. */
movl $0x010010000, %eax
wrmsr
/* In LX DCDIS is set after POR which disables the cache..., clear
* this bit.
*/
movl $CPU_DM_CONFIG0,%ecx
rdmsr
/* TODO: Make consistent with i$ init, either whole reg = 0, or just
* this bit...
*/
andl $(~(DM_CONFIG0_LOWER_DCDIS_SET)), %eax
wrmsr
/* Get cache timing params from BIOS config data locations and apply. */
/* Fix delay controls for DM and IM arrays. */
movl $CPU_BC_MSS_ARRAY_CTL0, %ecx
xorl %edx, %edx
movl $0x2814D352, %eax
wrmsr
movl $CPU_BC_MSS_ARRAY_CTL1, %ecx
xorl %edx, %edx
movl $0x1068334D, %eax
wrmsr
movl $CPU_BC_MSS_ARRAY_CTL2, %ecx
movl $0x00000106, %edx
movl $0x83104104, %eax
wrmsr
movl $GLCP_FIFOCTL, %ecx
rdmsr
movl $0x00000005, %edx
wrmsr
/* Enable setting. */
movl $CPU_BC_MSS_ARRAY_CTL_ENA, %ecx
xorl %edx, %edx
movl $0x01, %eax
wrmsr
/* Get cleaned up. */
xorl %edi, %edi
xorl %esi, %esi
xorl %ebp, %ebp
/* DCache Ways0 through Ways7 will be tagged for
* LX_STACK_BASE + DCACHE_RAM_SIZE for holding stack.
*/
/* Remember, there is NO stack yet... */
/* Tell cache we want to fill Way 0 starting at the top. */
xorl %edx, %edx
xorl %eax, %eax
movl $CPU_DC_INDEX, %ecx
wrmsr
/* Start address for tag of Way0: ebp will hold the incrementing
* address. Don't destroy!
*/
movl $LX_STACK_BASE, %ebp /* Init to start address. */
/* Set valid bit and tag for this Way (B[31:12]: Cache tag value for
* line/way curr. selected by CPU_DC_INDEX.
*/
orl $1, %ebp
/* Start tag Ways 0 with 128 lines with 32 bytes each: edi will hold
* the line counter. Don't destroy!
*/
movl $LX_NUM_CACHELINES, %edi
DCacheSetupFillWay:
/* Fill with dummy data: zero it so we can tell it from PCI memory
* space (returns FFs).
*/
/* We will now store a line (32 bytes = 4 x 8 bytes = 4 quad-words). */
movw $0x04, %si
xorl %edx, %edx
xorl %eax, %eax
movl $CPU_DC_DATA, %ecx
DCacheSetup_quadWordLoop:
wrmsr
decw %si
jnz DCacheSetup_quadWordLoop
/* Set the tag for this line, need to do this for every new cache
* line to validate it!
*/
/* Accessing CPU_DC_TAG_I makes the LINE field in CPU_DC_INDEX
* increment and thus continue in the next cache line...
*/
xorl %edx, %edx
movl %ebp, %eax
movl $CPU_DC_TAG, %ecx
wrmsr
/* Switch to next line. Lines are in bits 10:4. */
/* When index is crossing 0x7F -> 0x80 writing a RSVD bit as 0x80 is
* not a valid CL anymore!
*/
movl $CPU_DC_INDEX, %ecx
rdmsr
/* TODO: Probably would be more elegant to calculate this from
* counter var edi...
*/
addl $0x010, %eax
wrmsr
decl %edi
jnz DCacheSetupFillWay
/* 1 Way has been filled, forward start address for next Way,
* terminate if we have reached end of desired address range.
*/
addl $LX_CACHEWAY_SIZE, %ebp
cmpl $LX_STACK_END, %ebp
jge leave_DCacheSetup
movl $LX_NUM_CACHELINES, %edi
/* Switch to next way. */
movl $CPU_DC_INDEX, %ecx
rdmsr
addl $0x01, %eax
/* Let's be sure: reset line index bits 10:4. */
andl $0xFFFFF80F, %eax
wrmsr
jmp DCacheSetupFillWay
leave_DCacheSetup:
xorl %edi, %edi
xorl %esi, %esi
xorl %ebp, %ebp
/* Disable the cache, but... DO NOT INVALIDATE the tags. */
/* Memory reads and writes will all hit in the cache. */
/* Cache updates and memory write-backs will not occur! */
movl %cr0, %eax
orl $(CR0_CD + CR0_NW), %eax /* Set the CD and NW bits. */
movl %eax, %cr0
/* Now point sp to the cached stack. */
/* The stack will be fully functional at this location. No system
* memory is required at all!
*/
/* Set up the stack pointer. */
movl $LX_STACK_END, %eax
movl %eax, %esp
/* Test the stack. */
movl $0x0F0F05A5A, %edx
pushl %edx
popl %ecx
cmpl %ecx, %edx
je DCacheSetupGood
movb $0xC5, %al
outb %al, $0x80
DCacheSetupBad:
hlt /* Issues */
jmp DCacheSetupBad
DCacheSetupGood:
/* At this point, CAR should be working. */
movl $(LX_STACK_END), %eax
movl %eax, %esp
/* Load a different set of data segments. */
movw $CACHE_RAM_DATA_SEG, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
lout:
/* Store zero for the pointer to the global variables. */
movl $0, %eax
pushl %eax
/* Restore the BIST result. */
movl %ebp, %eax
/* We need to set ebp? No need. */
movl %esp, %ebp
/* Third parameter: cpu #: 0 == BSP all other are APs.
* Always 0 for Geode.
*/
pushl $0
/* Second parameter: init_detected */
/* Store zero for the unused init_detected parameter. */
pushl $0
/* First parameter: bist */
pushl %eax
call stage1_phase1
/* We will not go back. */
#include "../stage0_common.S"