Nils Jacobs | 7a4952a | 2010-07-27 00:30:42 +0000 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the coreboot project. |
| 3 | * |
| 4 | * Copyright (C) 2007 Advanced Micro Devices, Inc. |
| 5 | * Copyright (C) 2010 Nils Jacobs |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License version 2 as |
| 9 | * published by the Free Software Foundation. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
Nils Jacobs | 7a4952a | 2010-07-27 00:30:42 +0000 | [diff] [blame] | 15 | */ |
| 16 | |
| 17 | #define GX2_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 */ |
| 18 | #define GX2_STACK_END GX2_STACK_BASE+(CONFIG_DCACHE_RAM_SIZE-1) |
| 19 | |
| 20 | #define GX2_NUM_CACHELINES 0x080 /* there are 128lines per way */ |
| 21 | #define GX2_CACHELINE_SIZE 0x020 /* there are 32bytes per line */ |
| 22 | #define GX2_CACHEWAY_SIZE (GX2_NUM_CACHELINES * GX2_CACHELINE_SIZE) |
| 23 | #define CR0_CD 0x40000000 /* bit 30 = Cache Disable */ |
| 24 | #define CR0_NW 0x20000000 /* bit 29 = Not Write Through */ |
Edward O'Callaghan | efe2435 | 2014-06-28 19:07:33 +1000 | [diff] [blame] | 25 | |
Nils Jacobs | 7a4952a | 2010-07-27 00:30:42 +0000 | [diff] [blame] | 26 | #include <cpu/amd/gx2def.h> |
Alexandru Gagniuc | 5005bb06 | 2011-04-11 20:17:22 +0000 | [diff] [blame] | 27 | #include <cpu/x86/post_code.h> |
Edward O'Callaghan | efe2435 | 2014-06-28 19:07:33 +1000 | [diff] [blame] | 28 | |
| 29 | /* |
| 30 | * DCacheSetup |
| 31 | * |
| 32 | * Setup data cache for use as RAM for a stack. |
| 33 | * |
| 34 | * Max. size data cache =0x4000 (16KB) |
| 35 | */ |
Nils Jacobs | 7a4952a | 2010-07-27 00:30:42 +0000 | [diff] [blame] | 36 | DCacheSetup: |
| 37 | /* Save the BIST result */ |
| 38 | movl %eax, %ebx |
| 39 | |
| 40 | invd |
| 41 | /* set cache properties */ |
| 42 | movl $CPU_RCONF_DEFAULT, %ecx |
| 43 | rdmsr |
| 44 | movl $0x010010000, %eax /*1MB system memory in write back 1|00100|00 */ |
| 45 | wrmsr |
| 46 | |
| 47 | /* in GX2 DCDIS is set after POR which disables the cache..., clear this bit */ |
| 48 | movl $CPU_DM_CONFIG0, %ecx |
| 49 | rdmsr |
| 50 | andl $(~(DM_CONFIG0_LOWER_DCDIS_SET)), %eax /* TODO: make consistent with i$ init, either whole reg = 0, or just this bit... */ |
| 51 | wrmsr |
| 52 | |
| 53 | /* Get cleaned up. */ |
| 54 | xorl %edi, %edi |
| 55 | xorl %esi, %esi |
| 56 | xorl %ebp, %ebp |
| 57 | |
| 58 | /* DCache Ways0 through Ways3 will be tagged for GX2_STACK_BASE + CONFIG_DCACHE_RAM_SIZE for holding stack */ |
| 59 | /* remember, there is NO stack yet... */ |
| 60 | |
| 61 | /* Tell cache we want to fill WAY 0 starting at the top */ |
| 62 | xorl %edx, %edx |
| 63 | xorl %eax, %eax |
| 64 | movl $CPU_DC_INDEX, %ecx |
| 65 | wrmsr |
| 66 | |
| 67 | /* startaddress for tag of Way0: ebp will hold the incrementing address. dont destroy! */ |
| 68 | movl $GX2_STACK_BASE, %ebp /* init to start address */ |
| 69 | 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 */ |
| 70 | |
| 71 | /* start tag Ways 0 with 128 lines with 32bytes each: edi will hold the line counter. dont destroy! */ |
| 72 | movl $GX2_NUM_CACHELINES, %edi |
| 73 | DCacheSetupFillWay: |
| 74 | |
| 75 | /* fill with dummy data: zero it so we can tell it from PCI memory space (returns FFs). */ |
| 76 | /* We will now store a line (32 bytes = 4 x 8bytes = 4 quadWords) */ |
| 77 | movw $0x04, %si |
| 78 | xorl %edx, %edx |
| 79 | xorl %eax, %eax |
| 80 | movl $CPU_DC_DATA, %ecx |
| 81 | DCacheSetup_quadWordLoop: |
| 82 | wrmsr |
| 83 | decw %si |
| 84 | jnz DCacheSetup_quadWordLoop |
| 85 | |
| 86 | /* Set the tag for this line,need to do this for every new cache line to validate it! */ |
| 87 | /* accessing CPU_DC_TAG_I makes the LINE field in CPU_DC_INDEX increment and thus cont. in the next cache line... */ |
| 88 | xorl %edx, %edx |
| 89 | movl %ebp, %eax |
| 90 | movl $CPU_DC_TAG, %ecx |
| 91 | wrmsr |
| 92 | |
| 93 | /* switch to next line */ |
| 94 | /* lines are in Bits8:2 */ |
| 95 | /* when index is crossing 0x7F -> 0x80 writing a RSVD bit as 0x80 is not a valid CL anymore! */ |
| 96 | movl $CPU_DC_INDEX, %ecx |
| 97 | rdmsr |
| 98 | addl $0x04, %eax /* inc DC_LINE. TODO: prob. would be more elegant to calc. this from counter var edi... */ |
| 99 | wrmsr |
| 100 | |
| 101 | decl %edi |
| 102 | jnz DCacheSetupFillWay |
| 103 | |
| 104 | /* 1 Way has been filled, forward start address for next Way, terminate if we have reached end of desired address range */ |
| 105 | addl $GX2_CACHEWAY_SIZE, %ebp |
| 106 | cmpl $GX2_STACK_END, %ebp |
| 107 | jge leave_DCacheSetup |
| 108 | movl $GX2_NUM_CACHELINES, %edi |
| 109 | |
| 110 | /* switch to next way */ |
| 111 | movl $CPU_DC_INDEX, %ecx |
| 112 | rdmsr |
| 113 | addl $0x01, %eax |
| 114 | andl $0xFFFFFE03, %eax /* lets be sure: reset line index Bits8:2 */ |
| 115 | wrmsr |
| 116 | |
| 117 | jmp DCacheSetupFillWay |
| 118 | |
| 119 | leave_DCacheSetup: |
| 120 | xorl %edi, %edi |
| 121 | xorl %esi, %esi |
| 122 | xorl %ebp, %ebp |
| 123 | |
| 124 | /* Disable the cache, but ... DO NOT INVALIDATE the tags. */ |
| 125 | /* Memory reads and writes will all hit in the cache. */ |
| 126 | /* Cache updates and memory write-backs will not occur ! */ |
| 127 | movl %cr0, %eax |
| 128 | orl $(CR0_CD + CR0_NW), %eax /* set the CD and NW bits */ |
| 129 | movl %eax, %cr0 |
| 130 | |
| 131 | /* Now point sp to the cached stack. */ |
| 132 | /* The stack will be fully functional at this location. No system memory is required at all ! */ |
| 133 | /* set up the stack pointer */ |
| 134 | movl $GX2_STACK_END, %eax |
| 135 | movl %eax, %esp |
| 136 | |
| 137 | /* test the stack*/ |
| 138 | movl $0x0F0F05A5A, %edx |
| 139 | pushl %edx |
| 140 | popl %ecx |
| 141 | cmpl %ecx, %edx |
| 142 | je DCacheSetupGood |
| 143 | |
| 144 | post_code(0xc5) |
| 145 | DCacheSetupBad: |
| 146 | hlt /* issues */ |
| 147 | jmp DCacheSetupBad |
| 148 | DCacheSetupGood: |
| 149 | /* Go do early init and memory setup */ |
| 150 | |
| 151 | /* Restore the BIST result */ |
| 152 | movl %ebx, %eax |
| 153 | movl %esp, %ebp |
| 154 | pushl %eax |
| 155 | |
| 156 | post_code(0x23) |
| 157 | |
| 158 | /* Call romstage.c main function */ |
| 159 | call main |
| 160 | done_cache_as_ram_main: |
| 161 | |
| 162 | /* We now run over the stack-in-cache, copying it back to itself to invalidate the cache */ |
| 163 | |
| 164 | push %edi |
Stefan Reinauer | 4a45ec4 | 2015-07-07 00:54:05 +0200 | [diff] [blame] | 165 | mov $(CONFIG_DCACHE_RAM_SIZE >> 2),%ecx |
Nils Jacobs | 7a4952a | 2010-07-27 00:30:42 +0000 | [diff] [blame] | 166 | push %esi |
| 167 | mov $(CONFIG_DCACHE_RAM_BASE),%edi |
| 168 | mov %edi,%esi |
| 169 | cld |
| 170 | rep movsl %ds:(%esi),%es:(%edi) |
| 171 | pop %esi |
| 172 | pop %edi |
| 173 | |
| 174 | /* Clear the cache out to ram */ |
| 175 | wbinvd |
| 176 | /* re-enable the cache */ |
| 177 | movl %cr0, %eax |
| 178 | xorl $(CR0_CD + CR0_NW), %eax /* clear the CD and NW bits */ |
| 179 | movl %eax, %cr0 |
| 180 | |
Nils Jacobs | 7a4952a | 2010-07-27 00:30:42 +0000 | [diff] [blame] | 181 | __main: |
Alexandru Gagniuc | 5005bb06 | 2011-04-11 20:17:22 +0000 | [diff] [blame] | 182 | post_code(POST_PREPARE_RAMSTAGE) |
Nils Jacobs | 7a4952a | 2010-07-27 00:30:42 +0000 | [diff] [blame] | 183 | |
| 184 | /* TODO For suspend/resume the cache will have to live between |
| 185 | * CONFIG_RAMBASE and CONFIG_RAMTOP |
| 186 | */ |
| 187 | |
| 188 | cld /* clear direction flag */ |
| 189 | |
| 190 | /* copy coreboot from it's initial load location to |
| 191 | * the location it is compiled to run at. |
| 192 | * Normally this is copying from FLASH ROM to RAM. |
| 193 | */ |
Nils Jacobs | 7a4952a | 2010-07-27 00:30:42 +0000 | [diff] [blame] | 194 | call copy_and_run |
| 195 | |
| 196 | .Lhlt: |
Alexandru Gagniuc | 5005bb06 | 2011-04-11 20:17:22 +0000 | [diff] [blame] | 197 | post_code(POST_DEAD_CODE) |
Nils Jacobs | 7a4952a | 2010-07-27 00:30:42 +0000 | [diff] [blame] | 198 | hlt |
| 199 | jmp .Lhlt |