Hi,
is anybody working on a Cache-as-RAM implementation for the GX1 and GX2? Or does the LX code work for those, too? If not, how much work would it be to port that code?
Thanks, Uwe.
On Monday 07 May 2007 03:03, Uwe Hermann wrote:
is anybody working on a Cache-as-RAM implementation for the GX1 and GX2? Or does the LX code work for those, too? If not, how much work would it be to port that code?
I could provide some code to map the Geode GX1 cache anywhere you like. It simply uses the tr3, tr4 and tr5 registers to map each cache line to a physical address. I'm currently using it to map the scratch pad RAM to enable and use the video acceleration. Its written in C, but its very easy to rewrite it in assembler. Maybe it achieves LinuxBIOS's requirements, but I'm not sure.
Juergen
On Mon, May 07, 2007 at 09:43:06AM +0200, Juergen Beisert wrote:
I could provide some code to map the Geode GX1 cache anywhere you like. It simply uses the tr3, tr4 and tr5 registers to map each cache line to a physical address. I'm currently using it to map the scratch pad RAM to enable and use the video acceleration. Its written in C, but its very easy to rewrite it in assembler. Maybe it achieves LinuxBIOS's requirements, but I'm not sure.
I would love to see the code.
If we can keep it in C that's a lot better than rewriting it in assembly, too!
//Peter
Hi Peter,
On Monday 07 May 2007 15:41, Peter Stuge wrote:
On Mon, May 07, 2007 at 09:43:06AM +0200, Juergen Beisert wrote:
I could provide some code to map the Geode GX1 cache anywhere you like. It simply uses the tr3, tr4 and tr5 registers to map each cache line to a physical address. I'm currently using it to map the scratch pad RAM to enable and use the video acceleration. Its written in C, but its very easy to rewrite it in assembler. Maybe it achieves LinuxBIOS's requirements, but I'm not sure.
I would love to see the code.
If we can keep it in C that's a lot better than rewriting it in assembly, too!
Hmmm, I think we must rewrite it in Assembler as I think it should prepare some RAM to be used to setup the SDRAM in C. Or am I wrong?
Here is the code. Runs on my Geode GX1 based system to map a part of the cache to a specific address. It maps always the set 0 of the cache due to this part can be used as Scratch Pad RAM. But it should be not a big problem to expand it, to map all sets of the cache (16 kiB in this case).
/* ---------------------------------------------------------- */
static inline void write_tr3(u32 tr3) { asm volatile ("movl %0, %%tr3" : : "r" (tr3)); }
static inline void write_tr4(u32 tr4) { asm volatile ("movl %0, %%tr4" : : "r" (tr4)); }
static inline void write_tr5(u32 tr5) { asm volatile ("movl %0, %%tr5" : : "r" (tr5)); }
#define invalidate_cache() __asm__ __volatile__ ("invd": : :"memory")
/* * Disable and write back the cache * * Call this function with interrupts disabled! */ static void disable_cache(void) { unsigned long cr0;
wbinvd(); cr0 = read_cr0(); cr0 |= 0x40000000; write_cr0(cr0); wbinvd(); }
/* * Enable the cache * * Call this function with interrupts disabled! */ static void enable_cache(void) { unsigned long cr0;
cr0 = read_cr0(); cr0 &= 0x9fffffff; write_cr0(cr0); }
/* * write 16 bytes into cache' fill buffer * * This data will be cacheline's content after mapping */ static void setup_fill_buffer(u32 value) { write_tr5(0x0); write_tr3(value); write_tr5(0x4); write_tr3(value); write_tr5(0x8); write_tr3(value); write_tr5(0xc); write_tr3(value); }
/* * map_cache_line - map a cachline of set 0 to a specific address * @mapping_address: physical address to map this line to * * Always set 0 will be mapped due to this set is used * as a scratch pad ram only * * Note: Call this function only when cache is disabled */ static void map_cache_line(u32 mapping_address) { write_tr4((mapping_address & 0xFFFFF000) | 0x400); write_tr5((mapping_address & 0xFF0) | 0x00 << 2 | 0x1); }
/* * init_scratch_pad_size * @info hardware info * @size: new size of the scratch pad ram * * Note: Called with size = 0 will disable the scratch pad ram. */ static int geode_gx1_init_scratch_pad_size(struct geode_gx1_info * info,u32 size) { int i; u32 base; unsigned long flags;
if (size > 4096) return -1;
if ((size != 0) && (size < 2048)) return -1;
if (size < 3072) size=2048; else if (size < 4096) size=3072; /* * The mapping uses always the base * address of the internal chipset * registers */ info->scratch_pad_phys = info->physical_base; base = info->physical_base+(4096-size);
spin_lock_irqsave(&geode_gx1_memory_lock, flags); /* * first disable and invalidate the remaining cache */ disable_cache(); invalidate_cache(); /* * now free the _whole_ RAM for cache and invalidate * it again to unmap currently used scratch pad ram */ set_scratch_pad_size(info,0); invalidate_cache(); /* * remap the cache lines again */ for (i=0; i<size; i+=16,base+=16) { setup_fill_buffer(0xdeadbeef); map_cache_line(base); } /* * freeze the mapped cache lines */ set_scratch_pad_size(info,size); /* * and again use the remaining * cache lines as usual */ enable_cache();
spin_unlock_irqrestore(&geode_gx1_memory_lock, flags);
return 0; }
/* ---------------------------------------------------------- */
setup_fill_buffer() and map_cache_line() are the most important functions and map_cache_line() must be extended to also support the other three cache sets -> ...| 0x00 << 2 |... stands for set 0, ...| 0x01 << 2 |... would be set 1 and so on.
The functions above do their work in my LinuxBIOS based Geode GX1 system, with a special Xorg driver and graphics acceleration.
Hope it helps,
Juergen
Juergen Beisert wrote:
Hi Peter,
On Monday 07 May 2007 15:41, Peter Stuge wrote:
On Mon, May 07, 2007 at 09:43:06AM +0200, Juergen Beisert wrote:
I could provide some code to map the Geode GX1 cache anywhere you like. It simply uses the tr3, tr4 and tr5 registers to map each cache line to a physical address. I'm currently using it to map the scratch pad RAM to enable and use the video acceleration. Its written in C, but its very easy to rewrite it in assembler. Maybe it achieves LinuxBIOS's requirements, but I'm not sure.
I would love to see the code.
If we can keep it in C that's a lot better than rewriting it in assembly, too!
Hmmm, I think we must rewrite it in Assembler as I think it should prepare some RAM to be used to setup the SDRAM in C. Or am I wrong?
Here is the code. Runs on my Geode GX1 based system to map a part of the cache to a specific address. It maps always the set 0 of the cache due to this part can be used as Scratch Pad RAM. But it should be not a big problem to expand it, to map all sets of the cache (16 kiB in this case).
/* ---------------------------------------------------------- */
static inline void write_tr3(u32 tr3) { asm volatile ("movl %0, %%tr3" : : "r" (tr3)); }
static inline void write_tr4(u32 tr4) { asm volatile ("movl %0, %%tr4" : : "r" (tr4)); }
static inline void write_tr5(u32 tr5) { asm volatile ("movl %0, %%tr5" : : "r" (tr5)); }
#define invalidate_cache() __asm__ __volatile__ ("invd": : :"memory")
/*
- Disable and write back the cache
- Call this function with interrupts disabled!
*/ static void disable_cache(void) { unsigned long cr0;
wbinvd(); cr0 = read_cr0(); cr0 |= 0x40000000; write_cr0(cr0); wbinvd(); }
/*
- Enable the cache
- Call this function with interrupts disabled!
*/ static void enable_cache(void) { unsigned long cr0;
cr0 = read_cr0(); cr0 &= 0x9fffffff; write_cr0(cr0); }
/*
- write 16 bytes into cache' fill buffer
- This data will be cacheline's content after mapping
*/ static void setup_fill_buffer(u32 value) { write_tr5(0x0); write_tr3(value); write_tr5(0x4); write_tr3(value); write_tr5(0x8); write_tr3(value); write_tr5(0xc); write_tr3(value); }
/*
- map_cache_line - map a cachline of set 0 to a specific address
- @mapping_address: physical address to map this line to
- Always set 0 will be mapped due to this set is used
- as a scratch pad ram only
- Note: Call this function only when cache is disabled
*/ static void map_cache_line(u32 mapping_address) { write_tr4((mapping_address & 0xFFFFF000) | 0x400); write_tr5((mapping_address & 0xFF0) | 0x00 << 2 | 0x1); }
/*
- init_scratch_pad_size
- @info hardware info
- @size: new size of the scratch pad ram
- Note: Called with size = 0 will disable the scratch pad ram.
*/ static int geode_gx1_init_scratch_pad_size(struct geode_gx1_info * info,u32 size) { int i; u32 base; unsigned long flags;
if (size > 4096) return -1;
if ((size != 0) && (size < 2048)) return -1;
if (size < 3072) size=2048; else if (size < 4096) size=3072; /* * The mapping uses always the base * address of the internal chipset * registers */ info->scratch_pad_phys = info->physical_base; base = info->physical_base+(4096-size);
spin_lock_irqsave(&geode_gx1_memory_lock, flags); /* * first disable and invalidate the remaining cache */ disable_cache(); invalidate_cache(); /* * now free the _whole_ RAM for cache and invalidate * it again to unmap currently used scratch pad ram */ set_scratch_pad_size(info,0); invalidate_cache(); /* * remap the cache lines again */ for (i=0; i<size; i+=16,base+=16) { setup_fill_buffer(0xdeadbeef); map_cache_line(base); } /* * freeze the mapped cache lines */ set_scratch_pad_size(info,size); /* * and again use the remaining * cache lines as usual */ enable_cache();
spin_unlock_irqrestore(&geode_gx1_memory_lock, flags);
return 0; }
/* ---------------------------------------------------------- */
setup_fill_buffer() and map_cache_line() are the most important functions and map_cache_line() must be extended to also support the other three cache sets -> ...| 0x00 << 2 |... stands for set 0, ...| 0x01 << 2 |... would be set 1 and so on.
The functions above do their work in my LinuxBIOS based Geode GX1 system, with a special Xorg driver and graphics acceleration.
Hope it helps,
Juergen
This looks like a good example of scratchpad setup. The only part I thought missing is the size setting of the GCR register.
(from the GX1 databook) Bit Name Description Index B8h GCR Register (R/W) Default Value = 00h 7:4 RSVD Reserved: Set to 0. 3:2 SP Scratchpad Size: Specifies the size of the scratchpad cache. 00 = 0 KB; Graphics instruction disabled (see Section 5.1.5 "Display Driver Instructions" on page 97). 01 = 2 KB 10 = 3 KB 11 = 4 KB 1:0 GX GX1 Base Address: Specifies the physical address for the base (GX_BASE) of the scratchpad RAM, the graphics memory (frame buffer, compression buffer, etc.) and the other memory mapped registers. 00 = Scratchpad RAM, Graphics Subsystem, and memory-mapped configuration registers are disabled. 01 = Scratchpad RAM and control registers start at GX_BASE = 40000000h. 10 = Scratchpad RAM and control registers start at GX_BASE = 80000000h. 11 = Scratchpad RAM and control registers start at GX_BASE = C0000000h.
(intel asm) GXM_GCR EQU 0B8h SCRATCHPAD_SIZE EQU 0Ch ; GCR[3:2]
mov al, GXM_GCR ; Set ScratchPad size out 22h, al in al, 23h or al, SCRATCHPAD_SIZE out 23h, al
Marc
Hi Marc,
On Monday 07 May 2007 21:37, Marc Jones wrote:
This looks like a good example of scratchpad setup. The only part I thought missing is the size setting of the GCR register.
Sorry, I thought it was not important. Its only important to use set 0 as a scratch pad RAM (very Geode GX1 special case for video acceleration). To use the whole cache as regular RAM it is not important. You only have to setup the the cache lines itself to let them visible to the CPU.
Juergen
Juergen,
You might be right. I hadn't thought through the exact needs. I only mentioned it for completeness.
Marc
Juergen Beisert wrote:
Hi Marc,
On Monday 07 May 2007 21:37, Marc Jones wrote:
This looks like a good example of scratchpad setup. The only part I thought missing is the size setting of the GCR register.
Sorry, I thought it was not important. Its only important to use set 0 as a scratch pad RAM (very Geode GX1 special case for video acceleration). To use the whole cache as regular RAM it is not important. You only have to setup the the cache lines itself to let them visible to the CPU.
Juergen
Marc,
On Monday 07 May 2007 21:37, Marc Jones wrote:
This looks like a good example of scratchpad setup. The only part I thought missing is the size setting of the GCR register.
To be complete, here comes the missed function.
/* * set_scratch_pad_size - configure a new size * @info: hardware info * @size: new size in bytes * * Note: Call this function with the lock held! * Note: Called with size = 0 will disable the scratch pad ram */ static void set_scratch_pad_size(struct geode_gx1_info * info,u32 size) { u8 ccr3,new_size;
ccr3 = getCx86(CX86_CCR3); setCx86(CX86_CCR3, (ccr3 & 0x0F) | 0x10); /* enable MAPEN */ new_size=getCx86(CX86_GCR) & 0x03; switch (size) { case 0: break; case 2048: new_size |= 0x04; break; case 3072: new_size |= 0x08; break; default: new_size |= 0x0C; break; } setCx86(CX86_GCR,new_size); /* setup the new size */ setCx86(CX86_CCR3, ccr3); }
Juergen
Hi Folks,
I was chatting on this group a little while ago.
We have a custom GeodeLX board that I would like to get linux-bios running on.
I have seen a lot of chatter regarding the GeodeLX linux bios.
Where is the current release version/patch list for the GeodeLX bios.
Can we help out in the testing/qualification?
Thanks
Steve Spano, President Finger Lakes Engineering
* Steve Spano steve@fl-eng.com [070507 15:58]:
I have seen a lot of chatter regarding the GeodeLX linux bios.
Where is the current release version/patch list for the GeodeLX bios.
All required code is in the current development tree. See http://www.linuxbios.org/Download_LinuxBIOS on how to get it.
Can we help out in the testing/qualification?
Yes, definitely. The first goal would be to get your board up and running with LinuxBIOSv2. I suggest cloning an existing Geode LX board (AMD Norwich for example) and modifying it to suit the requirements of your board.
We have a test system which is described here: http://www.linuxbios.org/Distributed_and_Automated_Testsystem This allows running a comprehensive set of regression tests on the supported boards.
Stefan
Uwe Hermann wrote:
Hi,
is anybody working on a Cache-as-RAM implementation for the GX1 and GX2? Or does the LX code work for those, too? If not, how much work would it be to port that code?
Thanks, Uwe.
GX1 is entirely different and requires the setup of the scratchpad (a locked tag cache region typically used by graphics).
GX2 should be very similar to LX (if not exactly the same). There might be some slight differences in the cache MSRs.
Marc