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



-- 
Marc Jones
Senior Software Engineer
(970) 226-9684 Office
mailto:[EMAIL PROTECTED]
http://www.amd.com/embeddedprocessors



-- 
linuxbios mailing list
[email protected]
http://www.linuxbios.org/mailman/listinfo/linuxbios

Reply via email to