www.pudn.com > mizi_vivi.rar > mmu.c


/*
 * vivi/arch/s3c2400/mmu.c: Simple MMU management
 *
 * Copyright (C) 2001,2002 MIZI Research, Inc.
 *
 * Author: Janghoon Lyu 
 * Date  : $Date: 2002/08/02 03:24:43 $
 *
 * $Revision: 1.5 $
 *
 * Note:
 *   - mmu_init()¿¡¼­´Â putstr()°ú °°Àº Ãâ·Â¹®À» »ç¿ëÇÏÁö ¸¶¼¼¿ä.
 *
 *
 * History
 *
 * 2001-10-04: Janghoon Lyu 
 *    - Initial code
 *
 * 2002-01-26: Janghoon Lyu 
 *    - Cleaned up header files
 * 
 * 2002-07-23: Janghoon Lyu 
 *   - ¿Õâ »õ·Î °íħ
 */

#include "config.h"
#include "machine.h"
#include "mmu.h"
#include "vivi_string.h"

static unsigned long *mmu_tlb_base = (unsigned long *)MMU_TABLE_BASE;

/*
 * cpu_arm920_cache_clean_invalidate_all()
 *
 * clean and invalidate all cache lines
 */
static inline void cpu_arm920_cache_clean_invalidate_all(void)
{
__asm__(
        "	mov     r1, #0\n"
        "	mov     r1, #7 << 5\n"          /* 8 segments */
        "1:     orr     r3, r1, #63 << 26\n"    /* 64 entries */
        "2:     mcr     p15, 0, r3, c7, c14, 2\n" /* clean & invalidate D index */
        "       subs    r3, r3, #1 << 26\n"
        "       bcs     2b\n"                   /* entries 63 to 0 */
        "       subs    r1, r1, #1 << 5\n"
        "       bcs     1b\n"                   /* segments 7 to 0 */
        "       mcr	p15, 0, r1, c7, c5, 0\n" /* invalidate I cache */
        "       mcr     p15, 0, r1, c7, c10, 4\n" /* drain WB */
        );
}

void cache_clean_invalidate(void)
{
	cpu_arm920_cache_clean_invalidate_all();
}

/*
 * cpu_arm920_tlb_invalidate_all()
 *
 * invalidate all TLB entries
 */
static inline void cpu_arm920_tlb_invalidate_all(void)
{
__asm__(
	"mov    r0, #0\n"
	"mcr    p15, 0, r0, c7, c10, 4\n"	/* drain WB */
	"mcr    p15, 0, r0, c8, c7, 0\n"	/* invalidate I & D TLBs */
	);
}


void tlb_invalidate(void)
{
	cpu_arm920_tlb_invalidate_all();
}

static inline void arm920_setup(void)
{
	unsigned long ttb = MMU_TABLE_BASE;

__asm__(
	/* Invalidate caches */
	"mov	r0, #0\n"
	"mcr	p15, 0, r0, c7, c7, 0\n"	/* invalidate I,D caches on v4 */
	"mcr	p15, 0, r0, c7, c10, 4\n"	/* drain write buffer on v4 */
	"mcr	p15, 0, r0, c8, c7, 0\n"	/* invalidate I,D TLBs on v4 */
	/* Load page table pointer */
	"mov	r4, %0\n"
	"mcr	p15, 0, r4, c2, c0, 0\n"	/* load page table pointer */
	/* Write domain id (cp15_r3) */
	"mvn	r0, #0\n"			/* Domains 0, 1 = client */
	"mcr	p15, 0, r0, c3, c0, 0\n"	/* load domain access register */
	/* Set control register v4 */
	"mrc	p15, 0, r0, c1, c0, 0\n"	/* get control register v4 */
	/* Clear out 'unwanted' bits (then put them in if we need them) */
						/* .RVI ..RS B... .CAM */ 
	"bic	r0, r0, #0x3000\n"		/* ..11 .... .... .... */
	"bic	r0, r0, #0x0300\n"		/* .... ..11 .... .... */
	"bic	r0, r0, #0x0087\n"		/* .... .... 1... .111 */
	/* Turn on what we want */
	/* Fault checking enabled */
	"orr	r0, r0, #0x0002\n"		/* .... .... .... ..1. */
#ifdef CONFIG_CPU_D_CACHE_ON
	"orr	r0, r0, #0x0004\n"		/* .... .... .... .1.. */
#endif  
#ifdef CONFIG_CPU_I_CACHE_ON 
	"orr	r0, r0, #0x1000\n"		/* ...1 .... .... .... */
#endif  
	/* MMU enabled */
	"orr	r0, r0, #0x0001\n"		/* .... .... .... ...1 */
	"mcr	p15, 0, r0, c1, c0, 0\n"	/* write control register */
	: /* no outputs */
	: "r" (ttb) );
}

void mmu_init(void)
{
	arm920_setup();
}

static void copy_vivi_to_ram(void)
{
	putstr_hex("Evacuating 1MB of flash to ram at 0x", VIVI_RAM_BASE);
	memcpy((void *)VIVI_RAM_BASE, (void *)VIVI_ROM_BASE, VIVI_RAM_SIZE);
}

static inline void mem_mapping_linear(void)
{
	unsigned long pageoffset, sectionNumber;

	putstr_hex("MMU table base address = 0x", (unsigned long)mmu_tlb_base);
	/* 4G ¿µ¿ªÀ» 1:1·Î ¸ÅÇÎ. not cacacheable, not bufferable */
	for (sectionNumber = 0; sectionNumber < 4096; sectionNumber++) {
		pageoffset = (sectionNumber << 20);
		*(mmu_tlb_base + (pageoffset >> 20)) = pageoffset | MMU_SECDESC;
	}

	/* make dram cacheable */
	for (pageoffset = DRAM_BASE; pageoffset < (DRAM_BASE+DRAM_SIZE); pageoffset += SZ_1M) {
		//DPRINTK(3, "Make DRAM section cacheable: 0x%08lx\n", pageoffset);
		*(mmu_tlb_base + (pageoffset >> 20)) = pageoffset | MMU_SECDESC | MMU_CACHEABLE; 
	}
}

static inline void nor_flash_mapping(void)
{
	unsigned long offset, cached_addr, uncached_addr;

	cached_addr = FLASH_BASE;
	uncached_addr = FLASH_UNCACHED_BASE;

	for (offset = 0; offset < FLASH_SIZE; offset += MMU_SECTION_SIZE) { 
		cached_addr += MMU_SECTION_SIZE;
		uncached_addr += MMU_SECTION_SIZE;
		*(mmu_tlb_base + (cached_addr >> 20)) = \
				(cached_addr | MMU_SECDESC | MMU_CACHEABLE);
		*(mmu_tlb_base + (uncached_addr >> 20)) = \
				(cached_addr | MMU_SECDESC);
	}
}

static inline void nor_flash_remapping(void)
{
	putstr_hex("Map flash virtual section to DRAM at 0x", VIVI_RAM_BASE);
	/* point first 1MB of flash virtual addresses to its cacheable image in RAM */
/* 
 * ³­µðÀÇ ²ôÀû°Å¸² :
 * °ú¿¬ Çʿ䰡 Àִ°¡? ¾î¶² ÀǹÌÀΰ¡? º° Àǹ̾ø´Â ¾²·¹±â ÄÚµå ÀÎ °Í °°´Ù.
 */
#if 0
#ifndef CONFIG_S3C2400_GAMEPARK_ON_RAM
	*(mmu_tlb_base + (FLASH_UNCACHED_BASE >> 20)) =  \
				(VIVI_ROM_BASE | MMU_SECDESC);
#endif
#endif
	*(mmu_tlb_base + (VIVI_ROM_BASE >> 20)) = \
				(VIVI_RAM_BASE | MMU_SECDESC | MMU_CACHEABLE);
}


void mem_map_init(void)
{
	copy_vivi_to_ram();
	mem_mapping_linear();
	nor_flash_mapping();
	nor_flash_remapping();
	cache_clean_invalidate();
	tlb_invalidate();
}