www.pudn.com > mizi_vivi.rar > mmu.c
/* * Copyright (C) 2002 MIZI Reserach, Inc. * * Author: Janghoon Lyu* Date : $Date: 2002/08/29 03:04:55 $ * * $Revision: 1.6 $ * * We just set up a linear virtual -> physical mapping * After evacuating the vivi from Flash, we will use * the fourth to last 1MB of DRAM to hold a cache-enabled image * of the first 1MB Flash * * Note: * - mmu_init()¿¡¼ putstr()°ú °°Àº Ãâ·Â¹®À» »ç¿ëÇÏÁö ¸¶¼¼¿ä. * * History * * 2002-06-19: Janghoon Lyu * - Based on linux/arch/arm/mm/proc-sa110.S * - Based on bootldr/mmu_strongarm.c * * 2002-07-12: Janghoon Lyu * - cpu_sa1100_cache_clean_invalidate_all() »õ·Î ÀÛ¼º. ¸Â³ª ¸ð¸£°Ú³×¿ä. * */ #include "config.h" #include "machine.h" #include "mmu.h" #include "vivi_string.h" static unsigned long *mmu_tlb_base = (unsigned long *)MMU_TABLE_BASE; #define DCACHELINESIZE 32 #define FLUSH_OFFSET 32768 #define FLUSH_BASE 0x08000000 #define FLUSH_BASE_MINICACHE 0x08800000 /* * cpu_sa110_cache_clean_invalidate_all (void) * * clean and invalidate all cache lines * * Note: * 1. we should preserve r0 at all times */ static inline void cpu_sa1100_cache_clean_invalidate_all(void) { unsigned long a0 = FLUSH_BASE; unsigned long a1 = FLUSH_BASE_MINICACHE; __asm__( "mov r0, %0\n" /* load flush base address */ "add r1, r0, #8192\n" /* only necessary for 8k */ "1001: ldr r2, [r0], #32\n" /* Dcache line size = 32 bytes */ "teq r1, r0\n" "bne 1001b\n" "mov r0, %1\n" /* load mini cache flush base address */ "add r1, r0, #512\n" /* only necessary for 512 bytes */ "1002: ldr r2, [r0], #32\n" /* Dcache line size = 32 bytes */ "teq r1, r0\n" "bne 1002b\n" "mov r0, #0\n" "mcr p15, 0, r0, c7, c5, 0\n" /* invalidate I cache */ "mcr p15, 0, r1, c9, c0, 0\n" /* invalidate RB */ "mcr p15, 0, r0, c7, c10, 4\n" /* drain WB */ : /* no outputs */ : "r" (a0), "r" (a1) ); } void cache_clean_invalidate(void) { cpu_sa1100_cache_clean_invalidate_all(); } /* * cpu_sa110_tlb_invalidate_all() * * Invalidate all TLB entries */ static inline void cpu_sa1100_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_sa1100_tlb_invalidate_all(); } static inline void sa1100_setup(void) { unsigned long ttb = MMU_TABLE_BASE; __asm__( /* Invalidate caches */ "mov r10, #0\n" "mcr p15, 0, r10, c7, c7\n" /* invalidate I,D caches on v4 */ "mcr p15, 0, r10, c7, c10, 4\n" /* drain write buffer on v4 */ "mcr p15, 0, r10, c8, c7\n" /* invalidate I,D TLBs on v4 */ /* Load page table pointer */ "mov r4, %0\n" "mcr p15, 0, r4, c2, c0\n" /* load page table pointer */ /* Write cp15_r3, domain id */ "mvn r10, #0\n" /* Domains 0, 1 = client */ "mcr p15, 0, r10, c3, c0\n" /* load domain access register */ /* Set control register v4 */ "mrc p15, 0, r0, c1, c0\n" /* get control register v4 */ /* Clear out 'unwantd bits (then put them in if we need them) */ "bic r0, r0, #0x0e00\n" /* ..VI --RS BLDP WCAM */ "bic r0, r0, #0x000f\n" /* .... 000. .... 0000 */ "bic r0, r0, #0x3000\n" /* ..00 000. .... 0000 */ /* Turn on what we want */ "orr r0, r0, #0x0170\n" /* .... ...1 .111 .... */ #ifdef CONFIG_CPU_D_CACHE_ON "orr r0, r0, #0x000c\n" /* .... .... .... 11.. */ #endif #ifdef CONFIG_CPU_I_CACHE_ON "orr r0, r0, #0x1000\n" /* ...1 .... .... .... */ #endif "orr r0, r0, #0x0001\n" /* .... .... .... ...1 */ "mcr p15, 0, r0, c1, c0, 0\n" /* write ctrl register */ : : "r" (ttb) ); } void mmu_init(void) { sa1100_setup(); } 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 += offset; uncached_addr += offset; *(mmu_tlb_base + (cached_addr >> 20)) = \ (cached_addr | MMU_SECDESC | MMU_CACHEABLE); *(mmu_tlb_base + (uncached_addr >> 20)) = \ (cached_addr | MMU_SECDESC); } } static 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 DRAM */ #if 0 *(mmu_tlb_base + (FLASH_UNCACHED_BASE >> 20)) = \ (VIVI_ROM_BASE | MMU_SECDESC); #endif *(mmu_tlb_base + (VIVI_ROM_BASE >> 20)) = \ (VIVI_RAM_BASE | MMU_SECDESC | MMU_CACHEABLE); } 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); } void mem_map_init(void) { copy_vivi_to_ram(); mem_mapping_linear(); nor_flash_mapping(); nor_flash_remapping(); cache_clean_invalidate(); tlb_invalidate(); }