summaryrefslogtreecommitdiff
path: root/include/asm-arm/arch-s3c24x0/memory.h
blob: 5e254d2356aab28c6c0eec7231d9366294998b52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
 * linux/include/asm-arm/arch-s3c2400/memory.h by gj@denx.de
 * based on
 * linux/include/asm-arm/arch-sa1100/memory.h
 *
 * Copyright (c) 1999 Nicolas Pitre <nico@visuaide.com>
 */

#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H


/*
 * Task size: 3GB
 */
#define TASK_SIZE       (0xc0000000UL)
#define TASK_SIZE_26	(0x04000000UL)

/*
 * This decides where the kernel will search for a free chunk of vm
 * space during mmap's.
 */
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)

/*
 * Page offset: 3GB
 */
#define PAGE_OFFSET     (0xc0000000UL)

/*
 * Physical DRAM offset is 0x0c000000 on the S3C2400
 */
#define PHYS_OFFSET	(0x0c000000UL)

#include <linux/config.h>


/* Modified for S3C2400, by chc, 20010509 */
#define RAM_IN_BANK_0  32*1024*1024
#define RAM_IN_BANK_1  0
#define RAM_IN_BANK_2  0
#define RAM_IN_BANK_3  0

#define MEM_SIZE  (RAM_IN_BANK_0+RAM_IN_BANK_1+RAM_IN_BANK_2+RAM_IN_BANK_3)


/* translation macros */
#define __virt_to_phys__is_a_macro
#define __phys_to_virt__is_a_macro

#if (RAM_IN_BANK_1 + RAM_IN_BANK_2 + RAM_IN_BANK_3 == 0)

#define __virt_to_phys(x) ( (x) - PAGE_OFFSET + 0x0c000000 )
#define __phys_to_virt(x) ( (x) - 0x0c000000 + PAGE_OFFSET )

#elif (RAM_IN_BANK_0 == RAM_IN_BANK_1) && \
      (RAM_IN_BANK_2 + RAM_IN_BANK_3 == 0)

/* Two identical banks */
#define __virt_to_phys(x) \
	  ( ((x) < PAGE_OFFSET+RAM_IN_BANK_0) ? \
	    ((x) - PAGE_OFFSET + _DRAMBnk0) : \
	    ((x) - PAGE_OFFSET - RAM_IN_BANK_0 + _DRAMBnk1) )
#define __phys_to_virt(x) \
	  ( ((x)&0x07ffffff) + \
	    (((x)&0x08000000) ? PAGE_OFFSET+RAM_IN_BANK_0 : PAGE_OFFSET) )
#else

/* It's more efficient for all other cases to use the function call */
#undef __virt_to_phys__is_a_macro
#undef __phys_to_virt__is_a_macro
extern unsigned long __virt_to_phys(unsigned long vpage);
extern unsigned long __phys_to_virt(unsigned long ppage);

#endif

/*
 * Virtual view <-> DMA view memory address translations
 * virt_to_bus: Used to translate the virtual address to an
 *              address suitable to be passed to set_dma_addr
 * bus_to_virt: Used to convert an address for DMA operations
 *              to an address that the kernel can use.
 *
 * On the SA1100, bus addresses are equivalent to physical addresses.
 */
#define __virt_to_bus__is_a_macro
#define __virt_to_bus(x)        __virt_to_phys(x)
#define __bus_to_virt__is_a_macro
#define __bus_to_virt(x)        __phys_to_virt(x)


#ifdef CONFIG_DISCONTIGMEM
#error "CONFIG_DISCONTIGMEM will not work on S3C2400"
/*
 * Because of the wide memory address space between physical RAM banks on the
 * SA1100, it's much more convenient to use Linux's NUMA support to implement
 * our memory map representation.  Assuming all memory nodes have equal access
 * characteristics, we then have generic discontiguous memory support.
 *
 * Of course, all this isn't mandatory for SA1100 implementations with only
 * one used memory bank.  For those, simply undefine CONFIG_DISCONTIGMEM.
 *
 * The nodes are matched with the physical memory bank addresses which are
 * incidentally the same as virtual addresses.
 *
 *	node 0:  0xc0000000 - 0xc7ffffff
 *	node 1:  0xc8000000 - 0xcfffffff
 *	node 2:  0xd0000000 - 0xd7ffffff
 *	node 3:  0xd8000000 - 0xdfffffff
 */

#define NR_NODES	4

/*
 * Given a kernel address, find the home node of the underlying memory.
 */
#define KVADDR_TO_NID(addr) \
		(((unsigned long)(addr) - 0xc0000000) >> 27)

/*
 * Given a physical address, convert it to a node id.
 */
#define PHYS_TO_NID(addr) KVADDR_TO_NID(__phys_to_virt(addr))

/*
 * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
 * and returns the mem_map of that node.
 */
#define ADDR_TO_MAPBASE(kaddr) \
			NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))

/*
 * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
 * and returns the index corresponding to the appropriate page in the
 * node's mem_map.
 */
#define LOCAL_MAP_NR(kvaddr) \
	(((unsigned long)(kvaddr) & 0x07ffffff) >> PAGE_SHIFT)

/*
 * Given a kaddr, virt_to_page returns a pointer to the corresponding
 * mem_map entry.
 */
#define virt_to_page(kaddr) \
	(ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))

/*
 * VALID_PAGE returns a non-zero value if given page pointer is valid.
 * This assumes all node's mem_maps are stored within the node they refer to.
 */
#define VALID_PAGE(page) \
({ unsigned int node = KVADDR_TO_NID(page); \
   ( (node < NR_NODES) && \
     ((unsigned)((page) - NODE_MEM_MAP(node)) < NODE_DATA(node)->node_size) ); \
})

#else

#define PHYS_TO_NID(addr)	(0)

#endif
#endif /* __ASM_ARCH_MEMORY_H */