Hi,
find below my CAR implementation for the Geode GX1 processor. Tested on my Geode GX1 system. Comments are welcome.
Juergen
/* * Copyright (C) 2007 Juergen Beisert juergen@kreuzholzen.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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 */ /** * This function pins the cache to a fixed address, to be used as an SRAM * until system memory is available. It will be done with the help of the * cache debug and test registers tr3, tr4 and tr5 * * Your hardware must fulfil these qualifications: * - support of the tr3, tr4 and tr5 registers * - size of one cache line must be 16 bytes * - your CAR area must be pinned to an address space where it * also would work in a regular way (do not pin it to an I/O space) * * Mapping of the cache happens from _sstage0_1 as startaddress up to * (_sstage0_1 + _car_size) as endaddress * * Note: This function uses some symbols created by the linker withing the * linker script file. This ensures future compatibility and keeps all layout * configuring into the linker script file. * * _sstage0_1: * contains the physical start address of the CAR area * _car_size: * size of the whole CAR area (in bytes) -> means cache size */ .code32 .section ".bright_side", "ax" .extern pre_c_stage .extern _sstage0_1 .extern _car_size
.globl CacheAsRam CacheAsRam: /* Save the BIST value */ movl %eax, %ebp
movl $_sstage0_1, %edi movl $_car_size, %ecx
next_cache_line: movl $0xdeadbeef, %eax /* value for each byte in the CAR */
/* Fill up cache fill buffer (one cache line = 16 bytes) */ xorl %ebx, %ebx /* entry 0 */ movl %ebx, %tr5 movl %eax, %tr3 /* value for entry 0 */
addl $0x04, %ebx /* entry 1 (at offset 4) */ movl %ebx, %tr5 movl %eax, %tr3 /* value for entry 1 */
addl $0x04, %ebx /* entry 2 (at offset 8) */ movl %ebx, %tr5 movl %eax, %tr3 /* value for entry 2 */
addl $0x04, %ebx /* entry 3 (at offset 12) */ movl %ebx, %tr5 movl %eax, %tr3 /* value for entry 3 */
/* pin this cache line to a fixed address */ movl %edi, %eax andl $0xFFFFF000, %eax /* upper 20 bit of the physical address */ orl $0x00000400, %eax /* mark this entry valid */ movl %eax, %tr4 /* setup correct cache set and cache line */ movl %edi, %eax andl $0x00000FF0, %eax /* calculate cache line from physical address bit [11:4] */ movl %edi, %ebx andl $0x00003000, %ebx /* calculate cache set from physical address bit [13:12] */ shrl $0xA, %ebx orl %ebx, %eax orl $0x01, %eax /* add write buffer command */ movl %eax, %tr5 /* do it */
/* loop until full cache is mapped */ addl $0x10, %edi subl $0x10, %ecx jnz next_cache_line
/* Restore the BIST value to %eax */ movl %ebp, %eax
/* prepare to run C code */ jmp pre_c_stage