aboutsummaryrefslogtreecommitdiff
path: root/src/cpu/amd/model_lx/cache_as_ram.inc
diff options
context:
space:
mode:
authorMarc Jones <marc.jones@amd.com>2007-05-04 18:24:55 +0000
committerStefan Reinauer <stepan@openbios.org>2007-05-04 18:24:55 +0000
commitbc8176c5526ec9124aa99559f9432210be364dfe (patch)
treef4855271c5e16a2b9fba7d558a965c497a60e0cc /src/cpu/amd/model_lx/cache_as_ram.inc
parent5941c25fe8e2118c93ef695ea3b30b65e016cdc1 (diff)
This patch adds support for the AMD Geode LX CPU. (rediffed)
Signed-off-by: Marc Jones <marc.jones@amd.com> Acked-by: Stefan Reinauer <stepan@coresystems.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2628 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/cpu/amd/model_lx/cache_as_ram.inc')
-rw-r--r--src/cpu/amd/model_lx/cache_as_ram.inc370
1 files changed, 370 insertions, 0 deletions
diff --git a/src/cpu/amd/model_lx/cache_as_ram.inc b/src/cpu/amd/model_lx/cache_as_ram.inc
new file mode 100644
index 0000000000..fa90c5bf7f
--- /dev/null
+++ b/src/cpu/amd/model_lx/cache_as_ram.inc
@@ -0,0 +1,370 @@
+/*
+* This file is part of the LinuxBIOS project.
+*
+* Copyright (C) 2007 Advanced Micro Devices
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* 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
+*/
+
+
+#define LX_STACK_BASE DCACHE_RAM_BASE /* this is where the DCache will be mapped and be used as stack, It would be cool if it was the same base as LinuxBIOS normal stack */
+#define LX_STACK_END LX_STACK_BASE+(DCACHE_RAM_SIZE-1)
+
+#define LX_NUM_CACHELINES 0x080 /* there are 128lines per way */
+#define LX_CACHELINE_SIZE 0x020 /* there are 32bytes per line */
+#define LX_CACHEWAY_SIZE (LX_NUM_CACHELINES * LX_CACHELINE_SIZE)
+#define CR0_CD 0x40000000 /* bit 30 = Cache Disable */
+#define CR0_NW 0x20000000 /* bit 29 = Not Write Through */
+#include <cpu/amd/lxdef.h>
+/***************************************************************************
+/**
+/** DCacheSetup
+/**
+/** Setup data cache for use as RAM for a stack.
+/**
+/***************************************************************************/
+DCacheSetup:
+
+ invd
+ /* set cache properties */
+ movl $CPU_RCONF_DEFAULT, %ecx
+ rdmsr
+ movl $0x010010000, %eax /*1MB system memory in write back 1|00100|00 */
+ wrmsr
+
+ /* in LX DCDIS is set after POR which disables the cache..., clear this bit */
+ movl CPU_DM_CONFIG0,%ecx
+ rdmsr
+ andl $(~(DM_CONFIG0_LOWER_DCDIS_SET)), %eax /* TODO: make consistent with i$ init, either whole reg = 0, or just this bit... */
+ wrmsr
+
+ /* get cache timing params from BIOS config data locations and apply */
+ /* fix delay controls for DM and IM arrays */
+ /* 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
+
+ /* startaddress for tag of Way0: ebp will hold the incrementing address. dont destroy! */
+ movl $LX_STACK_BASE, %ebp /* init to start address */
+ orl $1, %ebp /* set valid bit and tag for this Way (B[31:12] : Cache tag value for line/way curr. selected by CPU_DC_INDEX */
+
+ /* start tag Ways 0 with 128 lines with 32bytes each: edi will hold the line counter. dont 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 8bytes = 4 quadWords) */
+ 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 cont. in the next cache line... */
+ xorl %edx, %edx
+ movl %ebp, %eax
+ movl $CPU_DC_TAG, %ecx
+ wrmsr
+
+ /* switch to next line */
+ /* lines are in Bits10: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
+ addl $0x010, %eax /* TODO: prob. would be more elegant to calc. this from counter var edi... */
+ 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
+ andl $0xFFFFF80F, %eax /* lets be sure: reset line index Bits10:4 */
+ 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:
+
+ /* Go do early init and memory setup */
+ call cache_as_ram_main
+
+ /* If you wanted to maintain the stack in memory you would need to set the tags as dirty
+ so the wbinvd would push out the old stack contents to memory */
+ /* Clear the cache, the following code from crt0.S.lb will setup a new stack*/
+ wbinvd
+
+/* the following code is from crt0.S.lb */
+/* This takes the place of the post-CAR funtions that the K8 uses to setup the stack and copy LB low.*/
+
+#ifndef CONSOLE_DEBUG_TX_STRING
+ /* uses: esp, ebx, ax, dx */
+# define __CRT_CONSOLE_TX_STRING(string) \
+ mov string, %ebx ; \
+ CALLSP(crt_console_tx_string)
+
+# if defined(TTYS0_BASE) && (ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG)
+# define CONSOLE_DEBUG_TX_STRING(string) __CRT_CONSOLE_TX_STRING(string)
+# else
+# define CONSOLE_DEBUG_TX_STRING(string)
+# endif
+#endif
+
+ /* clear boot_complete flag */
+ xorl %ebp, %ebp
+__main:
+ CONSOLE_DEBUG_TX_STRING($str_copying_to_ram)
+
+ /*
+ * Copy data into RAM and clear the BSS. Since these segments
+ * isn\'t really that big we just copy/clear using bytes, not
+ * double words.
+ */
+ intel_chip_post_macro(0x11) /* post 11 */
+
+ cld /* clear direction flag */
+
+ /* copy linuxBIOS from it's initial load location to
+ * the location it is compiled to run at.
+ * Normally this is copying from FLASH ROM to RAM.
+ */
+#if !CONFIG_COMPRESS
+ movl $_liseg, %esi
+ movl $_iseg, %edi
+ movl $_eiseg, %ecx
+ subl %edi, %ecx
+ rep movsb
+#else
+ leal 4+_liseg, %esi
+ leal _iseg, %edi
+ movl %ebp, %esp /* preserve %ebp */
+ movl $-1, %ebp /* last_m_off = -1 */
+ jmp dcl1_n2b
+
+/* ------------- DECOMPRESSION -------------
+
+ Input:
+ %esi - source
+ %edi - dest
+ %ebp - -1
+ cld
+
+ Output:
+ %eax - 0
+ %ecx - 0
+*/
+
+.macro getbit bits
+.if \bits == 1
+ addl %ebx, %ebx
+ jnz 1f
+.endif
+ movl (%esi), %ebx
+ subl $-4, %esi /* sets carry flag */
+ adcl %ebx, %ebx
+1:
+.endm
+
+decompr_literals_n2b:
+ movsb
+
+decompr_loop_n2b:
+ addl %ebx, %ebx
+ jnz dcl2_n2b
+dcl1_n2b:
+ getbit 32
+dcl2_n2b:
+ jc decompr_literals_n2b
+ xorl %eax, %eax
+ incl %eax /* m_off = 1 */
+loop1_n2b:
+ getbit 1
+ adcl %eax, %eax /* m_off = m_off*2 + getbit() */
+ getbit 1
+ jnc loop1_n2b /* while(!getbit()) */
+ xorl %ecx, %ecx
+ subl $3, %eax
+ jb decompr_ebpeax_n2b /* if (m_off == 2) goto decompr_ebpeax_n2b ? */
+ shll $8, %eax
+ movb (%esi), %al /* m_off = (m_off - 3)*256 + src[ilen++] */
+ incl %esi
+ xorl $-1, %eax
+ jz decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */
+ movl %eax, %ebp /* last_m_off = m_off ?*/
+decompr_ebpeax_n2b:
+ getbit 1
+ adcl %ecx, %ecx /* m_len = getbit() */
+ getbit 1
+ adcl %ecx, %ecx /* m_len = m_len*2 + getbit()) */
+ jnz decompr_got_mlen_n2b /* if (m_len == 0) goto decompr_got_mlen_n2b */
+ incl %ecx /* m_len++ */
+loop2_n2b:
+ getbit 1
+ adcl %ecx, %ecx /* m_len = m_len*2 + getbit() */
+ getbit 1
+ jnc loop2_n2b /* while(!getbit()) */
+ incl %ecx
+ incl %ecx /* m_len += 2 */
+decompr_got_mlen_n2b:
+ cmpl $-0xd00, %ebp
+ adcl $1, %ecx /* m_len = m_len + 1 + (last_m_off > 0xd00) */
+ movl %esi, %edx
+ leal (%edi,%ebp), %esi /* m_pos = dst + olen + -m_off */
+ rep
+ movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */
+ movl %edx, %esi
+ jmp decompr_loop_n2b
+decompr_end_n2b:
+ intel_chip_post_macro(0x12) /* post 12 */
+
+ movl %esp, %ebp
+#endif
+
+ CONSOLE_DEBUG_TX_STRING($str_pre_main)
+ leal _iseg, %edi
+ jmp *%edi
+
+.Lhlt:
+ intel_chip_post_macro(0xee) /* post fail ee */
+ hlt
+ jmp .Lhlt
+
+#ifdef __CRT_CONSOLE_TX_STRING
+ /* Uses esp, ebx, ax, dx */
+crt_console_tx_string:
+ mov (%ebx), %al
+ inc %ebx
+ cmp $0, %al
+ jne 9f
+ RETSP
+9:
+/* Base Address */
+#ifndef TTYS0_BASE
+#define TTYS0_BASE 0x3f8
+#endif
+/* Data */
+#define TTYS0_RBR (TTYS0_BASE+0x00)
+
+/* Control */
+#define TTYS0_TBR TTYS0_RBR
+#define TTYS0_IER (TTYS0_BASE+0x01)
+#define TTYS0_IIR (TTYS0_BASE+0x02)
+#define TTYS0_FCR TTYS0_IIR
+#define TTYS0_LCR (TTYS0_BASE+0x03)
+#define TTYS0_MCR (TTYS0_BASE+0x04)
+#define TTYS0_DLL TTYS0_RBR
+#define TTYS0_DLM TTYS0_IER
+
+/* Status */
+#define TTYS0_LSR (TTYS0_BASE+0x05)
+#define TTYS0_MSR (TTYS0_BASE+0x06)
+#define TTYS0_SCR (TTYS0_BASE+0x07)
+
+ mov %al, %ah
+10: mov $TTYS0_LSR, %dx
+ inb %dx, %al
+ test $0x20, %al
+ je 10b
+ mov $TTYS0_TBR, %dx
+ mov %ah, %al
+ outb %al, %dx
+
+ jmp crt_console_tx_string
+#endif /* __CRT_CONSOLE_TX_STRING */
+
+#if defined(CONSOLE_DEBUG_TX_STRING) && (ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG)
+.section ".rom.data"
+str_copying_to_ram: .string "Copying LinuxBIOS to ram.\r\n"
+str_pre_main: .string "Jumping to LinuxBIOS.\r\n"
+.previous
+
+#endif /* ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG */