blob: 12bc4405bcf1a85472172576e433ccc8f3f4bf87 [file] [log] [blame]
Andrew Sculle22b32f2019-05-13 14:46:02 +01001/*
2 * Copyright 2019 The Hafnium Authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <stddef.h>
20#include <stdint.h>
21
22#include "hf/arch/barriers.h"
23
24#include "hf/assert.h"
25
26/* Opaque types for different sized fields of memory mapped IO. */
27
28typedef struct {
29 volatile uint8_t *ptr;
30} io8_t;
31
32typedef struct {
33 volatile uint16_t *ptr;
34} io16_t;
35
36typedef struct {
37 volatile uint32_t *ptr;
38} io32_t;
39
40typedef struct {
41 volatile uint64_t *ptr;
42} io64_t;
43
44typedef struct {
45 volatile uint8_t *base;
46 size_t count;
47} io8_array_t;
48
49typedef struct {
50 volatile uint16_t *base;
51 size_t count;
52} io16_array_t;
53
54typedef struct {
55 volatile uint32_t *base;
56 size_t count;
57} io32_array_t;
58
59typedef struct {
60 volatile uint64_t *base;
61 size_t count;
62} io64_array_t;
63
64/* Contructors for literals. */
65
66#define IO8_C(addr) ((io8_t){.ptr = (volatile uint8_t *)(addr)})
67#define IO16_C(addr) ((io16_t){.ptr = (volatile uint16_t *)(addr)})
68#define IO32_C(addr) ((io32_t){.ptr = (volatile uint32_t *)(addr)})
69#define IO64_C(addr) ((io64_t){.ptr = (volatile uint64_t *)(addr)})
70
71#define IO8_ARRAY_C(addr, cnt) \
72 ((io8_array_t){.base = (volatile uint8_t *)(addr), .count = (cnt)})
73#define IO16_ARRAY_C(addr, cnt) \
74 ((io16_array_t){.base = (volatile uint16_t *)(addr), .count = (cnt)})
75#define IO32_ARRAY_C(addr, cnt) \
76 ((io32_array_t){.base = (volatile uint32_t *)(addr), .count = (cnt)})
77#define IO64_ARRAY_C(addr, cnt) \
78 ((io64_array_t){.base = (volatile uint64_t *)(addr), .count = (cnt)})
79
80/** Read from memory-mapped IO. */
81
82static inline uint8_t io_read8(io8_t io)
83{
84 return *io.ptr;
85}
86
87static inline uint16_t io_read16(io16_t io)
88{
89 return *io.ptr;
90}
91
92static inline uint32_t io_read32(io32_t io)
93{
94 return *io.ptr;
95}
96
97static inline uint64_t io_read64(io64_t io)
98{
99 return *io.ptr;
100}
101
102static inline uint8_t io_read8_array(io8_array_t io, size_t n)
103{
104 assert(n < io.count);
105 return io.base[n];
106}
107
108static inline uint16_t io_read16_array(io16_array_t io, size_t n)
109{
110 assert(n < io.count);
111 return io.base[n];
112}
113
114static inline uint32_t io_read32_array(io32_array_t io, size_t n)
115{
116 assert(n < io.count);
117 return io.base[n];
118}
119
120static inline uint64_t io_read64_array(io64_array_t io, size_t n)
121{
122 assert(n < io.count);
123 return io.base[n];
124}
125
126/**
127 * Read from memory-mapped IO with memory barrier.
128 *
129 * The read is ordered before subsequent memory accesses.
130 */
131
132static inline uint8_t io_read8_mb(io8_t io)
133{
134 uint8_t v = io_read8(io);
135
136 dsb();
137 return v;
138}
139
140static inline uint16_t io_read16_mb(io16_t io)
141{
142 uint16_t v = io_read16(io);
143
144 dsb();
145 return v;
146}
147
148static inline uint32_t io_read32_mb(io32_t io)
149{
150 uint32_t v = io_read32(io);
151
152 dsb();
153 return v;
154}
155
156static inline uint64_t io_read64_mb(io64_t io)
157{
158 uint64_t v = io_read64(io);
159
160 dsb();
161 return v;
162}
163
164static inline uint8_t io_read8_array_mb(io8_array_t io, size_t n)
165{
166 uint8_t v = io_read8_array(io, n);
167
168 dsb();
169 return v;
170}
171
172static inline uint16_t io_read16_array_mb(io16_array_t io, size_t n)
173{
174 uint16_t v = io_read16_array(io, n);
175
176 dsb();
177 return v;
178}
179
180static inline uint32_t io_read32_array_mb(io32_array_t io, size_t n)
181{
182 uint32_t v = io_read32_array(io, n);
183
184 dsb();
185 return v;
186}
187
188static inline uint64_t io_read64_array_mb(io64_array_t io, size_t n)
189{
190 uint64_t v = io_read64_array(io, n);
191
192 dsb();
193 return v;
194}
195
196/* Write to memory-mapped IO. */
197
198static inline void io_write8(io8_t io, uint8_t v)
199{
200 *io.ptr = v;
201}
202
203static inline void io_write16(io16_t io, uint16_t v)
204{
205 *io.ptr = v;
206}
207
208static inline void io_write32(io32_t io, uint32_t v)
209{
210 *io.ptr = v;
211}
212
213static inline void io_write64(io64_t io, uint64_t v)
214{
215 *io.ptr = v;
216}
217
218static inline void io_write8_array(io8_array_t io, size_t n, uint8_t v)
219{
220 assert(n < io.count);
221 io.base[n] = v;
222}
223
224static inline void io_write16_array(io16_array_t io, size_t n, uint16_t v)
225{
226 assert(n < io.count);
227 io.base[n] = v;
228}
229
230static inline void io_write32_array(io32_array_t io, size_t n, uint32_t v)
231{
232 assert(n < io.count);
233 io.base[n] = v;
234}
235
236static inline void io_write64_array(io64_array_t io, size_t n, uint64_t v)
237{
238 assert(n < io.count);
239 io.base[n] = v;
240}
241
242/*
243 * Write to memory-mapped IO with memory barrier.
244 *
245 * The write is ordered after previous memory accesses.
246 */
247
248static inline void io_write8_mb(io8_t io, uint8_t v)
249{
250 dsb();
251 io_write8(io, v);
252}
253
254static inline void io_write16_mb(io16_t io, uint16_t v)
255{
256 dsb();
257 io_write16(io, v);
258}
259
260static inline void io_write32_mb(io32_t io, uint32_t v)
261{
262 dsb();
263 io_write32(io, v);
264}
265
266static inline void io_write64_mb(io64_t io, uint64_t v)
267{
268 dsb();
269 io_write64(io, v);
270}
271
272static inline void io_write8_array_mb(io8_array_t io, size_t n, uint8_t v)
273{
274 dsb();
275 io_write8_array(io, n, v);
276}
277
278static inline void io_write16_array_mb(io16_array_t io, size_t n, uint16_t v)
279{
280 dsb();
281 io_write16_array(io, n, v);
282}
283
284static inline void io_write32_array_mb(io32_array_t io, size_t n, uint32_t v)
285{
286 dsb();
287 io_write32_array(io, n, v);
288}
289
290static inline void io_write64_array_mb(io64_array_t io, size_t n, uint64_t v)
291{
292 dsb();
293 io_write64_array(io, n, v);
294}