NanoPayload

stage2/cpu.c

216:95be7694d999
2017-06-28 Paul Boddie Employ structure member names to make initialisation clearer.
     1 /*     2  * CPU-specific routines originally from U-Boot.     3  * See: uboot-xburst/files/arch/mips/cpu/xburst/cpu.c     4  * See: u-boot/arch/mips/include/asm/cacheops.h     5  *     6  * Copyright (C) 2000-2009 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>     7  * Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk>     8  *     9  * This program is free software; you can redistribute it and/or    10  * modify it under the terms of the GNU General Public License as    11  * published by the Free Software Foundation; either version 2 of    12  * the License, or (at your option) any later version.    13  *    14  * This program is distributed in the hope that it will be useful,    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    17  * GNU General Public License for more details.    18  *    19  * You should have received a copy of the GNU General Public License    20  * along with this program; if not, write to the Free Software    21  * Foundation, Inc., 51 Franklin Street, Fifth Floor,    22  * Boston, MA  02110-1301, USA    23  */    24     25 #include "cpu.h"    26 #include "cpu_op.h"    27 #include "memory.h"    28 #include "paging.h"    29 #include "sdram.h"    30     31 void flush_icache_all()    32 {    33 	u32 addr;    34     35 	flush_icache_tag();    36     37 	for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_ICACHE_SIZE; addr += CONFIG_SYS_CACHELINE_SIZE)    38 		flush_icache_region(addr);    39     40 	flush_icache_config();    41 }    42     43 void flush_dcache_all()    44 {    45 	u32 addr;    46     47 	for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_DCACHE_SIZE; addr += CONFIG_SYS_CACHELINE_SIZE)    48 		flush_dcache_region(addr);    49     50 	asm volatile ("sync");    51 }    52     53 void flush_cache_all()    54 {    55 	flush_dcache_all();    56 	flush_icache_all();    57 }    58     59 void init_registers(u32 *base, u32 got, void (*function)(), u32 args[], u8 nargs)    60 {    61 	u8 i;    62     63 	/* Provide arguments to the function. */    64     65 	for (i = 0; i < nargs; i++)    66 	{    67 		base[i+4] = args[i];    68 	}    69     70 	/* Store essential data for the function environment. */    71     72 	base[25] = (u32) function - 0x80000000;	/* store the function address as t9 */    73 	base[26] = got - 0x80000000;		/* store the global pointer */    74 	base[29] = (u32) function - 0x80000000;	/* store the function address as EPC (for the handler) */    75 }    76     77 void init_tlb(u8 first_random)    78 {    79 	u32 limit = configure_tlb(first_random), i;    80     81 	/* Reset the mappings. The total number is bits 30..25 of Config1. */    82     83 	for (i = 0; i < ((limit >> 25) & 0x3f); i++)    84 	{    85 		map_page_index(0, 0, 4096, 0, 0, i);    86 	}    87 }    88     89 void init_page_table(u32 page_table, u32 virtual, u32 physical, u32 pagesize, u8 flags, u8 asid)    90 {    91 	u32 lower = ((physical & 0xfffff000) >> 6) | flags;    92 	u32 upper = (((physical + pagesize) & 0xfffff000) >> 6) | flags;    93     94 	/*    95 	With a complete address space mapping involving pairs of 4KB pages    96 	described by two values for each entry, there would be...    97     98 	an address space of 0x100000000 requiring...    99    100 	0x100000000 / (8 * 1024) == 0x100000000 >> 13   101 	== 524288 entries   102 	== 0x80000 entries   103    104 	Thus, each task's entries would require...   105    106 	0x80000 * 8 == 0x400000 bytes   107    108 	The kseg2 region thus permits 256 tasks occupying 0x40000000 bytes.   109    110 	However, for more modest address spaces occupying as much as 32MB there   111 	would be...   112    113 	an address space of 0x02000000 requiring...   114    115 	0x02000000 / (8 * 1024) == 0x02000000 >> 13   116 	== 4096 entries   117 	== 0x1000 entries   118    119 	Thus, each task's entries would only require...   120    121 	0x1000 * 8 == 0x8000 bytes   122 	*/   123    124 	u32 base = page_table + STAGE2_PAGE_TABLE_TASK * asid;   125    126 	/* Each page table entry corresponds to a pair of 4KB pages and holds two values. */   127    128 	u32 entry = ((virtual & 0xffffe000) >> 13) * 8;   129 	u32 *address = (u32 *) (base + entry);   130    131 	/* The page tables should be permanently mapped to avoid hierarchical TLB miss handling. */   132    133 	*address = lower;   134 	*(address + 1) = upper;   135 }   136    137 void map_page(u32 virtual, u32 physical, u32 pagesize, u8 flags, u8 asid)   138 {   139 	u32 start = (virtual & 0xffffe000) | asid; /* VPN2 | ASID*/   140 	u32 lower = ((physical & 0xfffff000) >> 6) | flags;   141 	u32 upper = (((physical + pagesize) & 0xfffff000) >> 6) | flags;   142 	u32 pagemask = ((pagesize - 1) & 0xfffff000) << 1;   143    144 	map_page_op(lower, upper, start, pagemask);   145 }   146    147 void map_page_index(u32 virtual, u32 physical, u32 pagesize, u8 flags, u8 asid, u32 index)   148 {   149 	u32 start = (virtual & 0xffffe000) | asid; /* VPN2 | ASID*/   150 	u32 lower = ((physical & 0xfffff000) >> 6) | flags;   151 	u32 upper = (((physical + pagesize) & 0xfffff000) >> 6) | flags;   152 	u32 pagemask = ((pagesize - 1) & 0xfffff000) << 1;   153    154 	map_page_set_index(index);   155 	map_page_index_op(lower, upper, start, pagemask);   156 }