2 * This file is part of the LinuxBIOS project.
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #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 */
21 #define LX_STACK_END LX_STACK_BASE+(DCACHE_RAM_SIZE-1)
23 #define LX_NUM_CACHELINES 0x080 /* there are 128lines per way */
24 #define LX_CACHELINE_SIZE 0x020 /* there are 32bytes per line */
25 #define LX_CACHEWAY_SIZE (LX_NUM_CACHELINES * LX_CACHELINE_SIZE)
26 #define CR0_CD 0x40000000 /* bit 30 = Cache Disable */
27 #define CR0_NW 0x20000000 /* bit 29 = Not Write Through */
28 #include <cpu/amd/lxdef.h>
29 /***************************************************************************
33 /** Setup data cache for use as RAM for a stack.
35 /***************************************************************************/
39 /* set cache properties */
40 movl $CPU_RCONF_DEFAULT, %ecx
42 movl $0x010010000, %eax /*1MB system memory in write back 1|00100|00 */
45 /* in LX DCDIS is set after POR which disables the cache..., clear this bit */
46 movl CPU_DM_CONFIG0,%ecx
48 andl $(~(DM_CONFIG0_LOWER_DCDIS_SET)), %eax /* TODO: make consistent with i$ init, either whole reg = 0, or just this bit... */
51 /* get cache timing params from BIOS config data locations and apply */
52 /* fix delay controls for DM and IM arrays */
53 /* fix delay controls for DM and IM arrays */
54 movl $CPU_BC_MSS_ARRAY_CTL0, %ecx
56 movl $0x2814D352, %eax
59 movl $CPU_BC_MSS_ARRAY_CTL1, %ecx
61 movl $0x1068334D, %eax
64 movl $CPU_BC_MSS_ARRAY_CTL2, %ecx
65 movl $0x00000106, %edx
66 movl $0x83104104, %eax
69 movl $GLCP_FIFOCTL, %ecx
71 movl $0x00000005, %edx
75 movl $CPU_BC_MSS_ARRAY_CTL_ENA, %ecx
85 /* DCache Ways0 through Ways7 will be tagged for LX_STACK_BASE + DCACHE_RAM_SIZE for holding stack */
86 /* remember, there is NO stack yet... */
88 /* Tell cache we want to fill WAY 0 starting at the top */
91 movl $CPU_DC_INDEX, %ecx
94 /* startaddress for tag of Way0: ebp will hold the incrementing address. dont destroy! */
95 movl $LX_STACK_BASE, %ebp /* init to start address */
96 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 */
98 /* start tag Ways 0 with 128 lines with 32bytes each: edi will hold the line counter. dont destroy! */
99 movl $LX_NUM_CACHELINES, %edi
102 /* fill with dummy data: zero it so we can tell it from PCI memory space (returns FFs). */
103 /* We will now store a line (32 bytes = 4 x 8bytes = 4 quadWords) */
107 movl $CPU_DC_DATA, %ecx
108 DCacheSetup_quadWordLoop:
111 jnz DCacheSetup_quadWordLoop
113 /* Set the tag for this line, need to do this for every new cache line to validate it! */
114 /* accessing CPU_DC_TAG_I makes the LINE field in CPU_DC_INDEX increment and thus cont. in the next cache line... */
117 movl $CPU_DC_TAG, %ecx
120 /* switch to next line */
121 /* lines are in Bits10:4 */
122 /* when index is crossing 0x7F -> 0x80 writing a RSVD bit as 0x80 is not a valid CL anymore! */
123 movl $CPU_DC_INDEX, %ecx
125 addl $0x010, %eax /* TODO: prob. would be more elegant to calc. this from counter var edi... */
129 jnz DCacheSetupFillWay
131 /* 1 Way has been filled, forward start address for next Way, terminate if we have reached end of desired address range */
132 addl $LX_CACHEWAY_SIZE, %ebp
133 cmpl $LX_STACK_END, %ebp
134 jge leave_DCacheSetup
135 movl $LX_NUM_CACHELINES, %edi
137 /* switch to next way */
138 movl $CPU_DC_INDEX, %ecx
141 andl $0xFFFFF80F, %eax /* lets be sure: reset line index Bits10:4 */
144 jmp DCacheSetupFillWay
151 /* Disable the cache, but ... DO NOT INVALIDATE the tags. */
152 /* Memory reads and writes will all hit in the cache. */
153 /* Cache updates and memory write-backs will not occur ! */
155 orl $(CR0_CD + CR0_NW), %eax /* set the CD and NW bits */
158 /* Now point sp to the cached stack. */
159 /* The stack will be fully functional at this location. No system memory is required at all ! */
160 /* set up the stack pointer */
161 movl $LX_STACK_END, %eax
165 movl $0x0F0F05A5A, %edx
177 /* Go do early init and memory setup */
178 call cache_as_ram_main
179 done_cache_as_ram_main:
181 /* If you wanted to maintain the stack in memory you would need to set the tags as dirty
182 so the wbinvd would push out the old stack contents to memory */
183 /* Clear the cache, the following code from crt0.S.lb will setup a new stack*/
186 /* the following code is from crt0.S.lb */
187 /* This takes the place of the post-CAR funtions that the K8 uses to setup the stack and copy LB low.*/
189 #ifndef CONSOLE_DEBUG_TX_STRING
190 /* uses: esp, ebx, ax, dx */
191 # define __CRT_CONSOLE_TX_STRING(string) \
193 CALLSP(crt_console_tx_string)
195 # if defined(TTYS0_BASE) && (ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG)
196 # define CONSOLE_DEBUG_TX_STRING(string) __CRT_CONSOLE_TX_STRING(string)
198 # define CONSOLE_DEBUG_TX_STRING(string)
202 /* clear boot_complete flag */
205 CONSOLE_DEBUG_TX_STRING($str_copying_to_ram)
208 * Copy data into RAM and clear the BSS. Since these segments
209 * isn\'t really that big we just copy/clear using bytes, not
212 intel_chip_post_macro(0x11) /* post 11 */
214 cld /* clear direction flag */
216 /* copy linuxBIOS from it's initial load location to
217 * the location it is compiled to run at.
218 * Normally this is copying from FLASH ROM to RAM.
229 movl %ebp, %esp /* preserve %ebp */
230 movl $-1, %ebp /* last_m_off = -1 */
233 /* ------------- DECOMPRESSION -------------
252 subl $-4, %esi /* sets carry flag */
257 decompr_literals_n2b:
266 jc decompr_literals_n2b
268 incl %eax /* m_off = 1 */
271 adcl %eax, %eax /* m_off = m_off*2 + getbit() */
273 jnc loop1_n2b /* while(!getbit()) */
276 jb decompr_ebpeax_n2b /* if (m_off == 2) goto decompr_ebpeax_n2b ? */
278 movb (%esi), %al /* m_off = (m_off - 3)*256 + src[ilen++] */
281 jz decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */
282 movl %eax, %ebp /* last_m_off = m_off ?*/
285 adcl %ecx, %ecx /* m_len = getbit() */
287 adcl %ecx, %ecx /* m_len = m_len*2 + getbit()) */
288 jnz decompr_got_mlen_n2b /* if (m_len == 0) goto decompr_got_mlen_n2b */
289 incl %ecx /* m_len++ */
292 adcl %ecx, %ecx /* m_len = m_len*2 + getbit() */
294 jnc loop2_n2b /* while(!getbit()) */
296 incl %ecx /* m_len += 2 */
297 decompr_got_mlen_n2b:
299 adcl $1, %ecx /* m_len = m_len + 1 + (last_m_off > 0xd00) */
301 leal (%edi,%ebp), %esi /* m_pos = dst + olen + -m_off */
303 movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */
307 intel_chip_post_macro(0x12) /* post 12 */
312 CONSOLE_DEBUG_TX_STRING($str_pre_main)
317 intel_chip_post_macro(0xee) /* post fail ee */
321 #ifdef __CRT_CONSOLE_TX_STRING
322 /* Uses esp, ebx, ax, dx */
323 crt_console_tx_string:
332 #define TTYS0_BASE 0x3f8
335 #define TTYS0_RBR (TTYS0_BASE+0x00)
338 #define TTYS0_TBR TTYS0_RBR
339 #define TTYS0_IER (TTYS0_BASE+0x01)
340 #define TTYS0_IIR (TTYS0_BASE+0x02)
341 #define TTYS0_FCR TTYS0_IIR
342 #define TTYS0_LCR (TTYS0_BASE+0x03)
343 #define TTYS0_MCR (TTYS0_BASE+0x04)
344 #define TTYS0_DLL TTYS0_RBR
345 #define TTYS0_DLM TTYS0_IER
348 #define TTYS0_LSR (TTYS0_BASE+0x05)
349 #define TTYS0_MSR (TTYS0_BASE+0x06)
350 #define TTYS0_SCR (TTYS0_BASE+0x07)
353 10: mov $TTYS0_LSR, %dx
361 jmp crt_console_tx_string
362 #endif /* __CRT_CONSOLE_TX_STRING */
364 #if defined(CONSOLE_DEBUG_TX_STRING) && (ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG)
366 str_copying_to_ram: .string "Copying LinuxBIOS to ram.\r\n"
367 str_pre_main: .string "Jumping to LinuxBIOS.\r\n"
370 #endif /* ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG */