-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy patharm-mcr.h
209 lines (175 loc) · 4.38 KB
/
arm-mcr.h
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/** \file
* ARM control registers
*/
/*
* Copyright (C) 2009 Trammell Hudson <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef _arm_mcr_h_
#define _arm_mcr_h_
#include <stdint.h>
#include <limits.h>
#include <sys/types.h>
#include "compiler.h"
typedef void (*thunk)(void);
#if 0
typedef signed long int32_t;
typedef unsigned long uint32_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef uint32_t size_t;
typedef int32_t ssize_t;
#endif
static inline uint32_t
read_lr( void )
{
uint32_t lr;
asm( "mov %0, lr" : "=r"(lr) );
return lr;
}
static inline void
select_normal_vectors( void )
{
uint32_t reg;
asm(
"mrc p15, 0, %0, c1, c0\n"
"bic %0, %0, #0x2000\n"
"mcr p15, 0, %0, c1, c0\n"
: "=r"(reg)
);
}
static inline void
flush_caches( void )
{
uint32_t reg = 0;
asm(
"mov %0, #0\n"
"mcr p15, 0, %0, c7, c5, 0\n" // entire I cache
"mov %0, #0\n"
"mcr p15, 0, %0, c7, c6, 0\n" // entire D cache
"mcr p15, 0, %0, c7, c10, 4\n" // drain write buffer
: : "r"(reg)
);
}
static inline void
clean_d_cache( void )
{
uint32_t segment = 0;
do {
uint32_t line = 0;
for( ; line != 0x400 ; line += 0x20 )
{
asm(
"mcr p15, 0, %0, c7, c14, 2"
: : "r"( line | segment )
);
}
} while( segment += 0x40000000 );
}
// This must be a macro
#define setup_memory_region( region, value ) \
asm __volatile__ ( "mcr p15, 0, %0, c6, c" #region "\n" : : "r"(value) )
#define set_d_cache_regions( value ) \
asm __volatile__ ( "mcr p15, 0, %0, c2, c0\n" : : "r"(value) )
#define set_i_cache_regions( value ) \
asm __volatile__ ( "mcr p15, 0, %0, c2, c0, 1\n" : : "r"(value) )
#define set_d_buffer_regions( value ) \
asm __volatile__ ( "mcr p15, 0, %0, c3, c0\n" : : "r"(value) )
#define set_d_rw_regions( value ) \
asm __volatile__ ( "mcr p15, 0, %0, c5, c0, 0\n" : : "r"(value) )
#define set_i_rw_regions( value ) \
asm __volatile__ ( "mcr p15, 0, %0, c5, c0, 1\n" : : "r"(value) )
static inline void
set_control_reg( uint32_t value )
{
asm __volatile__ ( "mcr p15, 0, %0, c3, c0\n" : : "r"(value) );
}
static inline uint32_t
read_control_reg( void )
{
uint32_t value;
asm __volatile__ ( "mrc p15, 0, %0, c3, c0\n" : "=r"(value) );
return value;
}
static inline void
set_d_tcm( uint32_t value )
{
asm( "mcr p15, 0, %0, c9, c1, 0\n" : : "r"(value) );
}
static inline void
set_i_tcm( uint32_t value )
{
asm( "mcr p15, 0, %0, c9, c1, 1\n" : : "r"(value) );
}
/** Routines to enable / disable interrupts */
static inline uint32_t
cli(void)
{
uint32_t old_cpsr;
uint32_t new_cpsr;
asm __volatile__ (
"mrs %0, CPSR\n"
"orr %1, %0, #0x80\n" // set I flag to disable IRQ
"msr CPSR_c, %1\n"
: "=r"(old_cpsr)
: "r"(new_cpsr)
);
return old_cpsr & 0x80; // return true if the flags are set
}
static inline void
sei( uint32_t old_cpsr )
{
uint32_t new_cpsr;
asm __volatile__ (
"mrs %0, CPSR\n"
"bic %0, %0, #0x80\n"
"orr %0, %0, %1\n"
"msr CPSR_c, %0" : : "r"(new_cpsr), "r"(old_cpsr) );
}
/**
* Some common instructions.
*/
#define RET_INSTR 0xe12fff1e // bx lr
#define FAR_CALL_INSTR 0xe51ff004 // ldr pc, [pc,#-4]
#define LOOP_INSTR 0xeafffffe // 1: b 1b
#define NOP_INSTR 0xe1a00000 // mov r0, r0
#define BL_INSTR(pc,dest) \
( 0xEB000000 \
| ((( ((uint32_t)dest) - ((uint32_t)pc) - 8 ) >> 2) & 0x00FFFFFF) \
)
/** Simple boot loader memcpy.
*
* \note This is not general purpose; len must be > 0 and must be % 4
*/
static inline void
blob_memcpy(
void * dest_v,
const void * src_v,
const void * end
)
{
uint32_t * dest = dest_v;
const uint32_t * src = src_v;
const uint32_t len = ((const uint32_t*) end) - src;
uint32_t i;
for( i=0 ; i<len ; i++ )
dest[i] = src[i];
}
#endif