wdenk | bb2d927 | 2003-06-25 22:26:29 +0000 | [diff] [blame] | 1 | /* |
Detlev Zundel | f1b3f2b | 2009-05-13 10:54:10 +0200 | [diff] [blame] | 2 | * linux/include/asm-arm/arch-s3c2400/memory.h by garyj@denx.de |
wdenk | bb2d927 | 2003-06-25 22:26:29 +0000 | [diff] [blame] | 3 | * based on |
| 4 | * linux/include/asm-arm/arch-sa1100/memory.h |
| 5 | * |
| 6 | * Copyright (c) 1999 Nicolas Pitre <nico@visuaide.com> |
| 7 | */ |
| 8 | |
| 9 | #ifndef __ASM_ARCH_MEMORY_H |
| 10 | #define __ASM_ARCH_MEMORY_H |
| 11 | |
| 12 | |
| 13 | /* |
| 14 | * Task size: 3GB |
| 15 | */ |
| 16 | #define TASK_SIZE (0xc0000000UL) |
| 17 | #define TASK_SIZE_26 (0x04000000UL) |
| 18 | |
| 19 | /* |
| 20 | * This decides where the kernel will search for a free chunk of vm |
| 21 | * space during mmap's. |
| 22 | */ |
| 23 | #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) |
| 24 | |
| 25 | /* |
| 26 | * Page offset: 3GB |
| 27 | */ |
| 28 | #define PAGE_OFFSET (0xc0000000UL) |
| 29 | |
| 30 | /* |
| 31 | * Physical DRAM offset is 0x0c000000 on the S3C2400 |
| 32 | */ |
| 33 | #define PHYS_OFFSET (0x0c000000UL) |
| 34 | |
wdenk | bb2d927 | 2003-06-25 22:26:29 +0000 | [diff] [blame] | 35 | /* Modified for S3C2400, by chc, 20010509 */ |
| 36 | #define RAM_IN_BANK_0 32*1024*1024 |
| 37 | #define RAM_IN_BANK_1 0 |
| 38 | #define RAM_IN_BANK_2 0 |
| 39 | #define RAM_IN_BANK_3 0 |
| 40 | |
| 41 | #define MEM_SIZE (RAM_IN_BANK_0+RAM_IN_BANK_1+RAM_IN_BANK_2+RAM_IN_BANK_3) |
| 42 | |
| 43 | |
| 44 | /* translation macros */ |
| 45 | #define __virt_to_phys__is_a_macro |
| 46 | #define __phys_to_virt__is_a_macro |
| 47 | |
| 48 | #if (RAM_IN_BANK_1 + RAM_IN_BANK_2 + RAM_IN_BANK_3 == 0) |
| 49 | |
| 50 | #define __virt_to_phys(x) ( (x) - PAGE_OFFSET + 0x0c000000 ) |
| 51 | #define __phys_to_virt(x) ( (x) - 0x0c000000 + PAGE_OFFSET ) |
| 52 | |
| 53 | #elif (RAM_IN_BANK_0 == RAM_IN_BANK_1) && \ |
| 54 | (RAM_IN_BANK_2 + RAM_IN_BANK_3 == 0) |
| 55 | |
| 56 | /* Two identical banks */ |
| 57 | #define __virt_to_phys(x) \ |
| 58 | ( ((x) < PAGE_OFFSET+RAM_IN_BANK_0) ? \ |
| 59 | ((x) - PAGE_OFFSET + _DRAMBnk0) : \ |
| 60 | ((x) - PAGE_OFFSET - RAM_IN_BANK_0 + _DRAMBnk1) ) |
| 61 | #define __phys_to_virt(x) \ |
| 62 | ( ((x)&0x07ffffff) + \ |
| 63 | (((x)&0x08000000) ? PAGE_OFFSET+RAM_IN_BANK_0 : PAGE_OFFSET) ) |
| 64 | #else |
| 65 | |
| 66 | /* It's more efficient for all other cases to use the function call */ |
| 67 | #undef __virt_to_phys__is_a_macro |
| 68 | #undef __phys_to_virt__is_a_macro |
| 69 | extern unsigned long __virt_to_phys(unsigned long vpage); |
| 70 | extern unsigned long __phys_to_virt(unsigned long ppage); |
| 71 | |
| 72 | #endif |
| 73 | |
| 74 | /* |
| 75 | * Virtual view <-> DMA view memory address translations |
| 76 | * virt_to_bus: Used to translate the virtual address to an |
| 77 | * address suitable to be passed to set_dma_addr |
| 78 | * bus_to_virt: Used to convert an address for DMA operations |
| 79 | * to an address that the kernel can use. |
| 80 | * |
| 81 | * On the SA1100, bus addresses are equivalent to physical addresses. |
| 82 | */ |
| 83 | #define __virt_to_bus__is_a_macro |
| 84 | #define __virt_to_bus(x) __virt_to_phys(x) |
| 85 | #define __bus_to_virt__is_a_macro |
| 86 | #define __bus_to_virt(x) __phys_to_virt(x) |
| 87 | |
| 88 | |
| 89 | #ifdef CONFIG_DISCONTIGMEM |
| 90 | #error "CONFIG_DISCONTIGMEM will not work on S3C2400" |
| 91 | /* |
wdenk | 57b2d80 | 2003-06-27 21:31:46 +0000 | [diff] [blame] | 92 | * Because of the wide memory address space between physical RAM banks on the |
wdenk | bb2d927 | 2003-06-25 22:26:29 +0000 | [diff] [blame] | 93 | * SA1100, it's much more convenient to use Linux's NUMA support to implement |
wdenk | 57b2d80 | 2003-06-27 21:31:46 +0000 | [diff] [blame] | 94 | * our memory map representation. Assuming all memory nodes have equal access |
wdenk | bb2d927 | 2003-06-25 22:26:29 +0000 | [diff] [blame] | 95 | * characteristics, we then have generic discontiguous memory support. |
| 96 | * |
| 97 | * Of course, all this isn't mandatory for SA1100 implementations with only |
| 98 | * one used memory bank. For those, simply undefine CONFIG_DISCONTIGMEM. |
| 99 | * |
wdenk | 57b2d80 | 2003-06-27 21:31:46 +0000 | [diff] [blame] | 100 | * The nodes are matched with the physical memory bank addresses which are |
wdenk | bb2d927 | 2003-06-25 22:26:29 +0000 | [diff] [blame] | 101 | * incidentally the same as virtual addresses. |
wdenk | 57b2d80 | 2003-06-27 21:31:46 +0000 | [diff] [blame] | 102 | * |
Wolfgang Denk | a1be476 | 2008-05-20 16:00:29 +0200 | [diff] [blame] | 103 | * node 0: 0xc0000000 - 0xc7ffffff |
| 104 | * node 1: 0xc8000000 - 0xcfffffff |
| 105 | * node 2: 0xd0000000 - 0xd7ffffff |
| 106 | * node 3: 0xd8000000 - 0xdfffffff |
wdenk | bb2d927 | 2003-06-25 22:26:29 +0000 | [diff] [blame] | 107 | */ |
| 108 | |
| 109 | #define NR_NODES 4 |
| 110 | |
| 111 | /* |
| 112 | * Given a kernel address, find the home node of the underlying memory. |
| 113 | */ |
| 114 | #define KVADDR_TO_NID(addr) \ |
| 115 | (((unsigned long)(addr) - 0xc0000000) >> 27) |
| 116 | |
| 117 | /* |
| 118 | * Given a physical address, convert it to a node id. |
| 119 | */ |
| 120 | #define PHYS_TO_NID(addr) KVADDR_TO_NID(__phys_to_virt(addr)) |
| 121 | |
| 122 | /* |
| 123 | * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory |
| 124 | * and returns the mem_map of that node. |
| 125 | */ |
| 126 | #define ADDR_TO_MAPBASE(kaddr) \ |
| 127 | NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr))) |
| 128 | |
| 129 | /* |
| 130 | * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory |
| 131 | * and returns the index corresponding to the appropriate page in the |
| 132 | * node's mem_map. |
| 133 | */ |
| 134 | #define LOCAL_MAP_NR(kvaddr) \ |
| 135 | (((unsigned long)(kvaddr) & 0x07ffffff) >> PAGE_SHIFT) |
| 136 | |
| 137 | /* |
wdenk | 57b2d80 | 2003-06-27 21:31:46 +0000 | [diff] [blame] | 138 | * Given a kaddr, virt_to_page returns a pointer to the corresponding |
wdenk | bb2d927 | 2003-06-25 22:26:29 +0000 | [diff] [blame] | 139 | * mem_map entry. |
| 140 | */ |
| 141 | #define virt_to_page(kaddr) \ |
| 142 | (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr)) |
| 143 | |
| 144 | /* |
| 145 | * VALID_PAGE returns a non-zero value if given page pointer is valid. |
| 146 | * This assumes all node's mem_maps are stored within the node they refer to. |
| 147 | */ |
| 148 | #define VALID_PAGE(page) \ |
| 149 | ({ unsigned int node = KVADDR_TO_NID(page); \ |
| 150 | ( (node < NR_NODES) && \ |
| 151 | ((unsigned)((page) - NODE_MEM_MAP(node)) < NODE_DATA(node)->node_size) ); \ |
| 152 | }) |
| 153 | |
| 154 | #else |
| 155 | |
| 156 | #define PHYS_TO_NID(addr) (0) |
| 157 | |
| 158 | #endif |
| 159 | #endif /* __ASM_ARCH_MEMORY_H */ |