[LinuxBIOS] CAR for Geode GX1 / GX2

Marc Jones marc.jones at amd.com
Mon May 7 21:37:56 CEST 2007



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:Marc.Jones at amd.com
http://www.amd.com/embeddedprocessors






More information about the coreboot mailing list