c9e538ad931da26332ba016100e6f6d473ed9cd7
[coreboot.git] / src / cpu / amd / model_lx / cache_as_ram.inc
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2007 Advanced Micro Devices, Inc.
5  *
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.
9  *
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.
14  *
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
18  */
19
20 #define LX_STACK_BASE           CONFIG_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 coreboot normal stack */
21 #define LX_STACK_END            LX_STACK_BASE+(CONFIG_DCACHE_RAM_SIZE-1)
22
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 /***************************************************************************
30 /**
31 /**     DCacheSetup
32 /**
33 /**     Setup data cache for  use as RAM for a stack.
34 /**
35 /***************************************************************************/
36 DCacheSetup:
37
38         invd
39         /* set cache properties */
40         movl    $CPU_RCONF_DEFAULT, %ecx
41         rdmsr
42         movl    $0x010010000, %eax              /*1MB system memory in write back 1|00100|00 */
43         wrmsr
44
45         /* in LX DCDIS is set after POR which disables the cache..., clear this bit */
46         movl    CPU_DM_CONFIG0,%ecx
47         rdmsr
48         andl    $(~(DM_CONFIG0_LOWER_DCDIS_SET)), %eax  /* TODO: make consistent with i$ init,  either whole reg = 0,  or just this bit... */
49         wrmsr
50
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
55         xorl    %edx, %edx
56         movl    $0x2814D352, %eax
57         wrmsr
58
59         movl    $CPU_BC_MSS_ARRAY_CTL1, %ecx
60         xorl    %edx, %edx
61         movl    $0x1068334D, %eax
62         wrmsr
63
64         movl    $CPU_BC_MSS_ARRAY_CTL2, %ecx
65         movl    $0x00000106, %edx
66         movl    $0x83104104, %eax
67         wrmsr
68
69         movl    $GLCP_FIFOCTL, %ecx
70         rdmsr
71         movl    $0x00000005, %edx
72         wrmsr
73
74         /* Enable setting */
75         movl    $CPU_BC_MSS_ARRAY_CTL_ENA, %ecx
76         xorl    %edx, %edx
77         movl    $0x01, %eax
78         wrmsr
79
80         /* Get cleaned up. */
81         xorl    %edi, %edi
82         xorl    %esi, %esi
83         xorl    %ebp, %ebp
84
85         /* DCache Ways0 through Ways7 will be tagged for LX_STACK_BASE + CONFIG_DCACHE_RAM_SIZE for holding stack */
86         /* remember,  there is NO stack yet... */
87
88         /* Tell cache we want to fill WAY 0 starting at the top */
89         xorl    %edx, %edx
90         xorl    %eax, %eax
91         movl    $CPU_DC_INDEX, %ecx
92         wrmsr
93
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 */
97
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
100 DCacheSetupFillWay:
101
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) */
104         movw    $0x04, %si
105         xorl    %edx, %edx
106         xorl    %eax, %eax
107         movl    $CPU_DC_DATA, %ecx
108 DCacheSetup_quadWordLoop:
109         wrmsr
110         decw    %si
111         jnz     DCacheSetup_quadWordLoop
112
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... */
115         xorl    %edx, %edx
116         movl    %ebp, %eax
117         movl    $CPU_DC_TAG, %ecx
118         wrmsr
119
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
124         rdmsr
125         addl    $0x010, %eax /* TODO: prob. would be more elegant to calc. this from counter var edi... */
126         wrmsr
127
128         decl    %edi
129         jnz     DCacheSetupFillWay
130
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
136
137         /* switch to next way */
138         movl    $CPU_DC_INDEX, %ecx
139         rdmsr
140         addl    $0x01, %eax
141         andl    $0xFFFFF80F, %eax /* lets be sure: reset line index Bits10:4 */
142         wrmsr
143
144         jmp     DCacheSetupFillWay
145
146 leave_DCacheSetup:
147         xorl    %edi, %edi
148         xorl    %esi, %esi
149         xorl    %ebp, %ebp
150
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 ! */
154         movl    %cr0, %eax
155         orl             $(CR0_CD + CR0_NW), %eax        /* set the CD and NW bits */
156         movl    %eax, %cr0
157
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
162         movl    %eax, %esp
163
164         /* test the stack*/
165         movl    $0x0F0F05A5A, %edx
166         pushl   %edx
167         popl    %ecx
168         cmpl    %ecx, %edx
169         je      DCacheSetupGood
170         movb    $0xC5, %al
171         outb    %al, $0x80
172 DCacheSetupBad:
173         hlt             /* issues */
174         jmp DCacheSetupBad
175 DCacheSetupGood:
176
177         /* Go do early init and memory setup */
178         call    cache_as_ram_main
179 done_cache_as_ram_main:
180
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*/
184         wbinvd
185
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.*/
188
189 #ifndef CONSOLE_DEBUG_TX_STRING
190         /* uses:         esp, ebx, ax, dx */
191 # define __CRT_CONSOLE_TX_STRING(string) \
192         mov     string, %ebx    ; \
193         CALLSP(crt_console_tx_string)
194
195 # if defined(CONFIG_TTYS0_BASE) && (ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG)
196 #  define CONSOLE_DEBUG_TX_STRING(string)        __CRT_CONSOLE_TX_STRING(string)
197 # else
198 #  define CONSOLE_DEBUG_TX_STRING(string)
199 # endif
200 #endif
201
202         /* clear boot_complete flag */
203         xorl    %ebp, %ebp
204 __main:
205         CONSOLE_DEBUG_TX_STRING($str_copying_to_ram)
206
207         /*
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
210          *      double words.
211          */
212         intel_chip_post_macro(0x11)             /* post 11 */
213
214         cld                             /* clear direction flag */
215
216         /* copy coreboot 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.
219          */
220 #if !CONFIG_COMPRESS
221         movl    $_liseg, %esi
222         movl    $_iseg,  %edi
223         movl    $_eiseg, %ecx
224         subl    %edi, %ecx
225         movb    %cl, %al
226         shrl    $2, %ecx
227         andb    $3, %al
228         rep     movsl
229         movb    %al, %cl
230         rep     movsb
231 #else
232         leal    4+_liseg, %esi
233         leal    _iseg, %edi
234         movl    %ebp, %esp      /* preserve %ebp */
235         movl    $-1, %ebp       /* last_m_off = -1 */
236         jmp     dcl1_n2b
237
238 /* ------------- DECOMPRESSION -------------
239
240  Input:
241    %esi - source
242    %edi - dest
243    %ebp - -1
244    cld
245
246  Output:
247    %eax - 0
248    %ecx - 0
249 */
250
251 .macro getbit bits
252 .if     \bits == 1
253         addl    %ebx, %ebx
254         jnz     1f
255 .endif
256         movl    (%esi), %ebx
257         subl    $-4, %esi       /* sets carry flag */
258         adcl    %ebx, %ebx
259 1:
260 .endm
261
262 decompr_literals_n2b:
263         movsb
264
265 decompr_loop_n2b:
266         addl    %ebx, %ebx
267         jnz     dcl2_n2b
268 dcl1_n2b:
269         getbit  32
270 dcl2_n2b:
271         jc      decompr_literals_n2b
272         xorl    %eax, %eax
273         incl    %eax            /* m_off = 1 */
274 loop1_n2b:
275         getbit  1
276         adcl    %eax, %eax      /* m_off = m_off*2 + getbit() */
277         getbit  1
278         jnc     loop1_n2b       /* while(!getbit()) */
279         xorl    %ecx, %ecx
280         subl    $3, %eax
281         jb      decompr_ebpeax_n2b      /* if (m_off == 2) goto decompr_ebpeax_n2b ? */
282         shll    $8, %eax
283         movb    (%esi), %al     /* m_off = (m_off - 3)*256 + src[ilen++] */
284         incl    %esi
285         xorl    $-1, %eax
286         jz      decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */
287         movl    %eax, %ebp      /* last_m_off = m_off ?*/
288 decompr_ebpeax_n2b:
289         getbit  1
290         adcl    %ecx, %ecx      /* m_len = getbit() */
291         getbit  1
292         adcl    %ecx, %ecx      /* m_len = m_len*2 + getbit()) */
293         jnz     decompr_got_mlen_n2b    /* if (m_len == 0) goto decompr_got_mlen_n2b */
294         incl    %ecx            /* m_len++ */
295 loop2_n2b:
296         getbit  1
297         adcl    %ecx, %ecx      /* m_len = m_len*2 + getbit() */
298         getbit  1
299         jnc     loop2_n2b       /* while(!getbit()) */
300         incl    %ecx
301         incl    %ecx            /* m_len += 2 */
302 decompr_got_mlen_n2b:
303         cmpl    $-0xd00, %ebp
304         adcl    $1, %ecx        /* m_len = m_len + 1 + (last_m_off > 0xd00) */
305         movl    %esi, %edx
306         leal    (%edi,%ebp), %esi       /* m_pos = dst + olen + -m_off  */
307         rep
308         movsb                   /* dst[olen++] = *m_pos++ while(m_len > 0) */
309         movl    %edx, %esi
310         jmp     decompr_loop_n2b
311 decompr_end_n2b:
312         intel_chip_post_macro(0x12)             /* post 12 */
313
314         movl    %esp, %ebp
315 #endif
316
317         CONSOLE_DEBUG_TX_STRING($str_pre_main)
318         leal    _iseg, %edi
319         jmp     *%edi
320
321 .Lhlt:
322         intel_chip_post_macro(0xee)     /* post fail ee */
323         hlt
324         jmp     .Lhlt
325
326 #ifdef __CRT_CONSOLE_TX_STRING
327         /* Uses esp, ebx, ax, dx  */
328 crt_console_tx_string:
329         mov     (%ebx), %al
330         inc     %ebx
331         cmp     $0, %al
332         jne     9f
333         RETSP
334 9:
335 /* Base Address */
336 #ifndef CONFIG_TTYS0_BASE
337 #define CONFIG_TTYS0_BASE       0x3f8
338 #endif
339 /* Data */
340 #define TTYS0_RBR (CONFIG_TTYS0_BASE+0x00)
341
342 /* Control */
343 #define TTYS0_TBR TTYS0_RBR
344 #define TTYS0_IER (CONFIG_TTYS0_BASE+0x01)
345 #define TTYS0_IIR (CONFIG_TTYS0_BASE+0x02)
346 #define TTYS0_FCR TTYS0_IIR
347 #define TTYS0_LCR (CONFIG_TTYS0_BASE+0x03)
348 #define TTYS0_MCR (CONFIG_TTYS0_BASE+0x04)
349 #define TTYS0_DLL TTYS0_RBR
350 #define TTYS0_DLM TTYS0_IER
351
352 /* Status */
353 #define TTYS0_LSR (CONFIG_TTYS0_BASE+0x05)
354 #define TTYS0_MSR (CONFIG_TTYS0_BASE+0x06)
355 #define TTYS0_SCR (CONFIG_TTYS0_BASE+0x07)
356
357         mov     %al, %ah
358 10:     mov     $TTYS0_LSR, %dx
359         inb     %dx, %al
360         test    $0x20, %al
361         je      10b
362         mov     $TTYS0_TBR, %dx
363         mov     %ah, %al
364         outb    %al, %dx
365
366         jmp crt_console_tx_string
367 #endif /* __CRT_CONSOLE_TX_STRING */
368
369 #if defined(CONSOLE_DEBUG_TX_STRING) && (ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG)
370 .section ".rom.data"
371 #if CONFIG_COMPRESS
372 str_copying_to_ram:  .string "Uncompressing coreboot to ram.\r\n"
373 #else
374 str_copying_to_ram:  .string "Copying coreboot to ram.\r\n"
375 #endif
376 str_pre_main:        .string "Jumping to coreboot.\r\n"
377 .previous
378
379 #endif /* ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG */