summaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/mm-rpc.c
blob: f789b8f7970a29e28551d6e81fe730e9b92f4f8c (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
/*
 * arch/arm/mm/mm-rpc.c
 *
 * Extra MM routines for RiscPC architecture
 *
 * Copyright (C) 1998 Russell King
 */

#include <linux/sched.h>
#include <linux/slab.h>

#include <asm/pgtable.h>
#include <asm/setup.h>
#include <asm/io.h>
#include <asm/proc/mm-init.h>
#include <asm/arch/mm-init.h>

#define NR_DRAM_BANKS	4
#define NR_VRAM_BANKS	1

#define NR_BANKS	(NR_DRAM_BANKS + NR_VRAM_BANKS)

#define FIRST_BANK	0
#define FIRST_DRAM_BANK	0
#define FIRST_VRAM_BANK	NR_DRAM_BANKS

#define BANK_SHIFT	26
#define FIRST_DRAM_ADDR	0x10000000

#define PHYS_TO_BANK(x)	(((x) >> BANK_SHIFT) & (NR_DRAM_BANKS - 1))
#define BANK_TO_PHYS(x)	((FIRST_DRAM_ADDR) + \
			    (((x) - FIRST_DRAM_BANK) << BANK_SHIFT))

struct ram_bank {
	unsigned int virt_addr;		/* virtual address of the *end* of this bank + 1 */
	  signed int phys_offset;	/* offset to physical address of this bank */
};

static struct ram_bank rambank[NR_BANKS];

/*
 * Return the physical (0x10000000 -> 0x20000000) address of
 * the virtual (0xc0000000 -> 0xd0000000) address
 */
unsigned long __virt_to_phys(unsigned long vpage)
{
	unsigned int bank = FIRST_BANK;

	while (vpage >= rambank[bank].virt_addr && bank < NR_BANKS)
		bank ++;

	return vpage - rambank[bank].phys_offset;
}

/*
 * Return the virtual (0xc0000000 -> 0xd0000000) address of
 * the physical (0x10000000 -> 0x20000000) address
 */
unsigned long __phys_to_virt(unsigned long phys)
{
	unsigned int bank;

	if (phys > FIRST_DRAM_ADDR)
		bank = PHYS_TO_BANK(phys);
	else
		bank = FIRST_VRAM_BANK;

	return phys + rambank[bank].phys_offset;
}

void init_dram_banks(struct param_struct *params)
{
	unsigned int bank;
	unsigned int bytes = 0;

	for (bank = FIRST_DRAM_BANK; bank < NR_DRAM_BANKS; bank++) {
		rambank[bank].phys_offset = PAGE_OFFSET + bytes
						- BANK_TO_PHYS(bank);

		bytes += params->u1.s.pages_in_bank[bank - FIRST_DRAM_BANK] * PAGE_SIZE;

		rambank[bank].virt_addr   = PAGE_OFFSET + bytes;
	}

	rambank[FIRST_VRAM_BANK].phys_offset = 0xd6000000;
	rambank[FIRST_VRAM_BANK].virt_addr   = 0xd8000000;

	current->tss.memmap = __virt_to_phys((unsigned long)swapper_pg_dir);
}

static struct mapping {
	unsigned long virtual;
	unsigned long physical;
	unsigned long length;
} io_mapping[] = {
	{ SCREEN2_BASE,	SCREEN_START,	2*1048576	},	/* VRAM		*/
	{ IO_BASE,	IO_START,	IO_SIZE		}	/* IO space	*/
};

#define SIZEOFIO (sizeof(io_mapping) / sizeof(io_mapping[0]))

/* map in IO */
unsigned long setup_io_pagetables(unsigned long start_mem)
{
	struct mapping *mp;
	int i;

	for (i = 0, mp = io_mapping; i < SIZEOFIO; i++, mp++) {
		while ((mp->virtual & 1048575 || mp->physical & 1048575) && mp->length >= PAGE_SIZE) {
			alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
					PTE_AP_WRITE);

			mp->length -= PAGE_SIZE;
			mp->virtual += PAGE_SIZE;
			mp->physical += PAGE_SIZE;
		}

		while (mp->length >= 1048576) {
			alloc_init_section(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
					   PMD_SECT_AP_WRITE);
			mp->length -= 1048576;
			mp->virtual += 1048576;
			mp->physical += 1048576;
		}

		while (mp->length >= PAGE_SIZE) {
			alloc_init_page(&start_mem, mp->virtual, mp->physical, DOMAIN_IO,
					PTE_AP_WRITE);

			mp->length -= PAGE_SIZE;
			mp->virtual += PAGE_SIZE;
			mp->physical += PAGE_SIZE;
		}
	}

	return start_mem;
}