summaryrefslogtreecommitdiffstats
path: root/src/arch/arm/include/ipxe/arm_io.h
blob: 046cbdb06bb764c0912c922b73912f73ecd8fc0d (plain) (blame)
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
#ifndef _IPXE_ARM_IO_H
#define _IPXE_ARM_IO_H

/** @file
 *
 * iPXE I/O API for ARM
 *
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );

#ifdef IOAPI_ARM
#define IOAPI_PREFIX_arm
#else
#define IOAPI_PREFIX_arm __arm_
#endif

/*
 * Memory space mappings
 *
 */

/*
 * Physical<->Bus address mappings
 *
 */

static inline __always_inline unsigned long
IOAPI_INLINE ( arm, phys_to_bus ) ( unsigned long phys_addr ) {
	return phys_addr;
}

static inline __always_inline unsigned long
IOAPI_INLINE ( arm, bus_to_phys ) ( unsigned long bus_addr ) {
	return bus_addr;
}

/*
 * MMIO reads and writes up to native word size
 *
 */

#define ARM_READX( _suffix, _type, _insn_suffix, _reg_prefix )		      \
static inline __always_inline _type					      \
IOAPI_INLINE ( arm, read ## _suffix ) ( volatile _type *io_addr ) {	      \
	_type data;							      \
	__asm__ __volatile__ ( "ldr" _insn_suffix " %" _reg_prefix "0, %1"    \
			       : "=r" ( data ) : "Qo" ( *io_addr ) );	      \
	return data;							      \
}
#ifdef __aarch64__
ARM_READX ( b, uint8_t, "b", "w" );
ARM_READX ( w, uint16_t, "h", "w" );
ARM_READX ( l, uint32_t, "", "w" );
ARM_READX ( q, uint64_t, "", "" );
#else
ARM_READX ( b, uint8_t, "b", "" );
ARM_READX ( w, uint16_t, "h", "" );
ARM_READX ( l, uint32_t, "", "" );
#endif

#define ARM_WRITEX( _suffix, _type, _insn_suffix, _reg_prefix )		      \
static inline __always_inline void					      \
IOAPI_INLINE ( arm, write ## _suffix ) ( _type data,			      \
					 volatile _type *io_addr ) {	      \
	__asm__ __volatile__ ( "str" _insn_suffix " %" _reg_prefix "0, %1"    \
			       : : "r" ( data ), "Qo" ( *io_addr ) );	      \
}
#ifdef __aarch64__
ARM_WRITEX ( b, uint8_t, "b", "w" );
ARM_WRITEX ( w, uint16_t, "h", "w" );
ARM_WRITEX ( l, uint32_t, "", "w" );
ARM_WRITEX ( q, uint64_t, "", "" );
#else
ARM_WRITEX ( b, uint8_t, "b", "" );
ARM_WRITEX ( w, uint16_t, "h", "" );
ARM_WRITEX ( l, uint32_t, "", "" );
#endif

/*
 * Dummy PIO reads and writes up to 32 bits
 *
 * There is no common standard for I/O-space access for ARM, and
 * non-MMIO peripherals are vanishingly rare.  Provide dummy
 * implementations that will allow code to link and should cause
 * drivers to simply fail to detect hardware at runtime.
 *
 */

#define ARM_INX( _suffix, _type )					      \
static inline __always_inline _type					      \
IOAPI_INLINE ( arm, in ## _suffix ) ( volatile _type *io_addr __unused) {     \
	return ~( (_type) 0 );						      \
}									      \
static inline __always_inline void					      \
IOAPI_INLINE ( arm, ins ## _suffix ) ( volatile _type *io_addr __unused,      \
				       _type *data, unsigned int count ) {    \
	memset ( data, 0xff, count * sizeof ( *data ) );		      \
}
ARM_INX ( b, uint8_t );
ARM_INX ( w, uint16_t );
ARM_INX ( l, uint32_t );

#define ARM_OUTX( _suffix, _type )					      \
static inline __always_inline void					      \
IOAPI_INLINE ( arm, out ## _suffix ) ( _type data __unused,		      \
				       volatile _type *io_addr __unused ) {   \
	/* Do nothing */						      \
}									      \
static inline __always_inline void					      \
IOAPI_INLINE ( arm, outs ## _suffix ) ( volatile _type *io_addr __unused,     \
					const _type *data __unused,	      \
					unsigned int count __unused ) {	      \
	/* Do nothing */						      \
}
ARM_OUTX ( b, uint8_t );
ARM_OUTX ( w, uint16_t );
ARM_OUTX ( l, uint32_t );

/*
 * Slow down I/O
 *
 */
static inline __always_inline void
IOAPI_INLINE ( arm, iodelay ) ( void ) {
	/* Nothing to do */
}

/*
 * Memory barrier
 *
 */
static inline __always_inline void
IOAPI_INLINE ( arm, mb ) ( void ) {

#ifdef __aarch64__
	__asm__ __volatile__ ( "dmb sy" );
#else
	__asm__ __volatile__ ( "dmb" );
#endif
}

#endif /* _IPXE_ARM_IO_H */