Please bear with me - another rename checkin. This qualifies as trivial, no
[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           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)
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 + 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(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 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.
219          */
220 #if !CONFIG_COMPRESS
221         movl    $_liseg, %esi
222         movl    $_iseg,  %edi
223         movl    $_eiseg, %ecx
224         subl    %edi, %ecx
225         rep     movsb
226 #else
227         leal    4+_liseg, %esi
228         leal    _iseg, %edi
229         movl    %ebp, %esp      /* preserve %ebp */
230         movl    $-1, %ebp       /* last_m_off = -1 */
231         jmp     dcl1_n2b
232
233 /* ------------- DECOMPRESSION -------------
234
235  Input:
236    %esi - source
237    %edi - dest
238    %ebp - -1
239    cld
240
241  Output:
242    %eax - 0
243    %ecx - 0
244 */
245
246 .macro getbit bits
247 .if     \bits == 1
248         addl    %ebx, %ebx
249         jnz     1f
250 .endif
251         movl    (%esi), %ebx
252         subl    $-4, %esi       /* sets carry flag */
253         adcl    %ebx, %ebx
254 1:
255 .endm
256
257 decompr_literals_n2b:
258         movsb
259
260 decompr_loop_n2b:
261         addl    %ebx, %ebx
262         jnz     dcl2_n2b
263 dcl1_n2b:
264         getbit  32
265 dcl2_n2b:
266         jc      decompr_literals_n2b
267         xorl    %eax, %eax
268         incl    %eax            /* m_off = 1 */
269 loop1_n2b:
270         getbit  1
271         adcl    %eax, %eax      /* m_off = m_off*2 + getbit() */
272         getbit  1
273         jnc     loop1_n2b       /* while(!getbit()) */
274         xorl    %ecx, %ecx
275         subl    $3, %eax
276         jb      decompr_ebpeax_n2b      /* if (m_off == 2) goto decompr_ebpeax_n2b ? */
277         shll    $8, %eax
278         movb    (%esi), %al     /* m_off = (m_off - 3)*256 + src[ilen++] */
279         incl    %esi
280         xorl    $-1, %eax
281         jz      decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */
282         movl    %eax, %ebp      /* last_m_off = m_off ?*/
283 decompr_ebpeax_n2b:
284         getbit  1
285         adcl    %ecx, %ecx      /* m_len = getbit() */
286         getbit  1
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++ */
290 loop2_n2b:
291         getbit  1
292         adcl    %ecx, %ecx      /* m_len = m_len*2 + getbit() */
293         getbit  1
294         jnc     loop2_n2b       /* while(!getbit()) */
295         incl    %ecx
296         incl    %ecx            /* m_len += 2 */
297 decompr_got_mlen_n2b:
298         cmpl    $-0xd00, %ebp
299         adcl    $1, %ecx        /* m_len = m_len + 1 + (last_m_off > 0xd00) */
300         movl    %esi, %edx
301         leal    (%edi,%ebp), %esi       /* m_pos = dst + olen + -m_off  */
302         rep
303         movsb                   /* dst[olen++] = *m_pos++ while(m_len > 0) */
304         movl    %edx, %esi
305         jmp     decompr_loop_n2b
306 decompr_end_n2b:
307         intel_chip_post_macro(0x12)             /* post 12 */
308
309         movl    %esp, %ebp
310 #endif
311
312         CONSOLE_DEBUG_TX_STRING($str_pre_main)
313         leal    _iseg, %edi
314         jmp     *%edi
315
316 .Lhlt:
317         intel_chip_post_macro(0xee)     /* post fail ee */
318         hlt
319         jmp     .Lhlt
320
321 #ifdef __CRT_CONSOLE_TX_STRING
322         /* Uses esp, ebx, ax, dx  */
323 crt_console_tx_string:
324         mov     (%ebx), %al
325         inc     %ebx
326         cmp     $0, %al
327         jne     9f
328         RETSP
329 9:
330 /* Base Address */
331 #ifndef TTYS0_BASE
332 #define TTYS0_BASE      0x3f8
333 #endif
334 /* Data */
335 #define TTYS0_RBR (TTYS0_BASE+0x00)
336
337 /* Control */
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
346
347 /* Status */
348 #define TTYS0_LSR (TTYS0_BASE+0x05)
349 #define TTYS0_MSR (TTYS0_BASE+0x06)
350 #define TTYS0_SCR (TTYS0_BASE+0x07)
351
352         mov     %al, %ah
353 10:     mov     $TTYS0_LSR, %dx
354         inb     %dx, %al
355         test    $0x20, %al
356         je      10b
357         mov     $TTYS0_TBR, %dx
358         mov     %ah, %al
359         outb    %al, %dx
360
361         jmp crt_console_tx_string
362 #endif /* __CRT_CONSOLE_TX_STRING */
363
364 #if defined(CONSOLE_DEBUG_TX_STRING) && (ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG)
365 .section ".rom.data"
366 str_copying_to_ram:  .string "Copying LinuxBIOS to ram.\r\n"
367 str_pre_main:        .string "Jumping to LinuxBIOS.\r\n"
368 .previous
369
370 #endif /* ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG */