summaryrefslogtreecommitdiff
path: root/arch/microblaze/kernel/misc.S
blob: 7cf86498326cc4eafc0db81a8de13ff06bc654bc (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
/*
 * Miscellaneous low-level MMU functions.
 *
 * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
 * Copyright (C) 2008-2009 PetaLogix
 * Copyright (C) 2007 Xilinx, Inc.  All rights reserved.
 *
 * Derived from arch/ppc/kernel/misc.S
 *
 * This file is subject to the terms and conditions of the GNU General
 * Public License. See the file COPYING in the main directory of this
 * archive for more details.
 */

#include <linux/linkage.h>
#include <linux/sys.h>
#include <asm/unistd.h>
#include <linux/errno.h>
#include <asm/mmu.h>
#include <asm/page.h>

	.text
/*
 * Flush MMU TLB
 *
 * We avoid flushing the pinned 0, 1 and possibly 2 entries.
 */
.globl _tlbia;
.type  _tlbia, @function
.align 4;
_tlbia:
	addik	r12, r0, MICROBLAZE_TLB_SIZE - 1 /* flush all entries (63 - 3) */
	/* isync */
_tlbia_1:
	mts	rtlbx, r12
	nop
	mts	rtlbhi, r0 /* flush: ensure V is clear */
	nop
	addik	r11, r12, -2
	bneid	r11, _tlbia_1 /* loop for all entries */
	addik	r12, r12, -1
	/* sync */
	rtsd	r15, 8
	nop
	.size  _tlbia, . - _tlbia

/*
 * Flush MMU TLB for a particular address (in r5)
 */
.globl _tlbie;
.type  _tlbie, @function
.align 4;
_tlbie:
	mts	rtlbsx, r5 /* look up the address in TLB */
	nop
	mfs	r12, rtlbx /* Retrieve index */
	nop
	blti	r12, _tlbie_1 /* Check if found */
	mts	rtlbhi, r0 /* flush: ensure V is clear */
	nop
_tlbie_1:
	rtsd	r15, 8
	nop

	.size  _tlbie, . - _tlbie

/*
 * Allocate TLB entry for early console
 */
.globl early_console_reg_tlb_alloc;
.type  early_console_reg_tlb_alloc, @function
.align 4;
early_console_reg_tlb_alloc:
	/*
	 * Load a TLB entry for the UART, so that microblaze_progress() can use
	 * the UARTs nice and early.  We use a 4k real==virtual mapping.
	 */
	ori	r4, r0, MICROBLAZE_TLB_SIZE - 1
	mts	rtlbx, r4 /* TLB slot 2 */

	or	r4,r5,r0
	andi	r4,r4,0xfffff000
	ori	r4,r4,(TLB_WR|TLB_I|TLB_M|TLB_G)

	andi	r5,r5,0xfffff000
	ori	r5,r5,(TLB_VALID | TLB_PAGESZ(PAGESZ_4K))

	mts	rtlblo,r4 /* Load the data portion of the entry */
	nop
	mts	rtlbhi,r5 /* Load the tag portion of the entry */
	nop
	rtsd	r15, 8
	nop

	.size  early_console_reg_tlb_alloc, . - early_console_reg_tlb_alloc

/*
 * Copy a whole page (4096 bytes).
 */
#define COPY_16_BYTES		\
	lwi	r7, r6, 0;	\
	lwi	r8, r6, 4;	\
	lwi	r9, r6, 8;	\
	lwi	r10, r6, 12;	\
	swi	r7, r5, 0;	\
	swi	r8, r5, 4;	\
	swi	r9, r5, 8;	\
	swi	r10, r5, 12


/* FIXME DCACHE_LINE_BYTES (CONFIG_XILINX_MICROBLAZE0_DCACHE_LINE_LEN * 4)*/
#define DCACHE_LINE_BYTES (4 * 4)

.globl copy_page;
.type  copy_page, @function
.align 4;
copy_page:
	ori	r11, r0, (PAGE_SIZE/DCACHE_LINE_BYTES) - 1
_copy_page_loop:
	COPY_16_BYTES
#if DCACHE_LINE_BYTES >= 32
	COPY_16_BYTES
#endif
	addik	r6, r6, DCACHE_LINE_BYTES
	addik	r5, r5, DCACHE_LINE_BYTES
	bneid	r11, _copy_page_loop
	addik	r11, r11, -1
	rtsd	r15, 8
	nop

	.size  copy_page, . - copy_page