blob: 3a4818a4ecd25dc5e2ceb8569ce7386fb9183ed5 [file] [log] [blame]
Andrew Sculle22b32f2019-05-13 14:46:02 +01001/*
2 * Copyright 2019 The Hafnium Authors.
3 *
Andrew Walbrane959ec12020-06-17 15:01:09 +01004 * Use of this source code is governed by a BSD-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/BSD-3-Clause.
Andrew Sculle22b32f2019-05-13 14:46:02 +01007 */
8
9#pragma once
10
11#include <stddef.h>
12#include <stdint.h>
13
14#include "hf/arch/barriers.h"
Olivier Deprezf5ad66a2021-10-18 10:35:41 +010015#include "hf/arch/types.h"
Andrew Sculle22b32f2019-05-13 14:46:02 +010016
Daniel Boulbyb74d2682021-11-26 13:54:50 +000017#include "hf/assert.h"
Andrew Sculle22b32f2019-05-13 14:46:02 +010018
19/* Opaque types for different sized fields of memory mapped IO. */
20
21typedef struct {
22 volatile uint8_t *ptr;
23} io8_t;
24
25typedef struct {
26 volatile uint16_t *ptr;
27} io16_t;
28
29typedef struct {
30 volatile uint32_t *ptr;
31} io32_t;
32
33typedef struct {
34 volatile uint64_t *ptr;
35} io64_t;
36
37typedef struct {
38 volatile uint8_t *base;
39 size_t count;
40} io8_array_t;
41
42typedef struct {
43 volatile uint16_t *base;
44 size_t count;
45} io16_array_t;
46
47typedef struct {
48 volatile uint32_t *base;
49 size_t count;
50} io32_array_t;
51
52typedef struct {
53 volatile uint64_t *base;
54 size_t count;
55} io64_array_t;
56
57/* Contructors for literals. */
58
Olivier Deprezf5ad66a2021-10-18 10:35:41 +010059static inline io8_t io8_c(uintpaddr_t addr, uintpaddr_t offset)
60{
61 return (io8_t){.ptr = (volatile uint8_t *)(addr + offset)};
62}
Andrew Sculle22b32f2019-05-13 14:46:02 +010063
Olivier Deprezf5ad66a2021-10-18 10:35:41 +010064static inline io8_array_t io8_array_c(uintpaddr_t addr, uintpaddr_t offset,
65 uint32_t count)
66{
67 return (io8_array_t){.base = (volatile uint8_t *)addr, .count = count};
68}
69
70static inline io16_t io16_c(uintpaddr_t addr, uintpaddr_t offset)
71{
72 return (io16_t){.ptr = (volatile uint16_t *)(addr + offset)};
73}
74
75static inline io16_array_t io16_array_c(uintpaddr_t addr, uintpaddr_t offset,
76 uint32_t count)
77{
78 return (io16_array_t){.base = (volatile uint16_t *)addr,
79 .count = count};
80}
81
82static inline io32_t io32_c(uintpaddr_t addr, uintpaddr_t offset)
83{
84 return (io32_t){.ptr = (volatile uint32_t *)(addr + offset)};
85}
86
87static inline io32_array_t io32_array_c(uintpaddr_t addr, uintpaddr_t offset,
88 uint32_t count)
89{
90 return (io32_array_t){.base = (volatile uint32_t *)addr,
91 .count = count};
92}
93
94static inline io64_t io64_c(uintpaddr_t addr, uintpaddr_t offset)
95{
96 return (io64_t){.ptr = (volatile uint64_t *)(addr + offset)};
97}
98
99static inline io64_array_t io64_array_c(uintpaddr_t addr, uintpaddr_t offset,
100 uint32_t count)
101{
102 return (io64_array_t){.base = (volatile uint64_t *)addr,
103 .count = count};
104}
105
106#define IO8_C(addr) io8_c((addr), 0)
107#define IO16_C(addr) io16_c((addr), 0)
108#define IO32_C(addr) io32_c((addr), 0)
109#define IO64_C(addr) io64_c((addr), 0)
110
111#define IO8_ARRAY_C(addr, cnt) io8_array_c((addr), 0, cnt)
112#define IO16_ARRAY_C(addr, cnt) io16_array_c((addr), 0, cnt)
113#define IO32_ARRAY_C(addr, cnt) io32_array_c((addr), 0, cnt)
114#define IO64_ARRAY_C(addr, cnt) io64_array_c((addr), 0, cnt)
Andrew Sculle22b32f2019-05-13 14:46:02 +0100115
116/** Read from memory-mapped IO. */
117
118static inline uint8_t io_read8(io8_t io)
119{
120 return *io.ptr;
121}
122
123static inline uint16_t io_read16(io16_t io)
124{
125 return *io.ptr;
126}
127
128static inline uint32_t io_read32(io32_t io)
129{
130 return *io.ptr;
131}
132
133static inline uint64_t io_read64(io64_t io)
134{
135 return *io.ptr;
136}
137
138static inline uint8_t io_read8_array(io8_array_t io, size_t n)
139{
Daniel Boulbyb74d2682021-11-26 13:54:50 +0000140 assert(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100141 return io.base[n];
142}
143
144static inline uint16_t io_read16_array(io16_array_t io, size_t n)
145{
Daniel Boulbyb74d2682021-11-26 13:54:50 +0000146 assert(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100147 return io.base[n];
148}
149
150static inline uint32_t io_read32_array(io32_array_t io, size_t n)
151{
Daniel Boulbyb74d2682021-11-26 13:54:50 +0000152 assert(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100153 return io.base[n];
154}
155
156static inline uint64_t io_read64_array(io64_array_t io, size_t n)
157{
Daniel Boulbyb74d2682021-11-26 13:54:50 +0000158 assert(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100159 return io.base[n];
160}
161
162/**
163 * Read from memory-mapped IO with memory barrier.
164 *
165 * The read is ordered before subsequent memory accesses.
166 */
167
168static inline uint8_t io_read8_mb(io8_t io)
169{
170 uint8_t v = io_read8(io);
171
David Brazdil851948e2019-08-09 12:02:12 +0100172 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100173 return v;
174}
175
176static inline uint16_t io_read16_mb(io16_t io)
177{
178 uint16_t v = io_read16(io);
179
David Brazdil851948e2019-08-09 12:02:12 +0100180 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100181 return v;
182}
183
184static inline uint32_t io_read32_mb(io32_t io)
185{
186 uint32_t v = io_read32(io);
187
David Brazdil851948e2019-08-09 12:02:12 +0100188 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100189 return v;
190}
191
192static inline uint64_t io_read64_mb(io64_t io)
193{
194 uint64_t v = io_read64(io);
195
David Brazdil851948e2019-08-09 12:02:12 +0100196 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100197 return v;
198}
199
200static inline uint8_t io_read8_array_mb(io8_array_t io, size_t n)
201{
202 uint8_t v = io_read8_array(io, n);
203
David Brazdil851948e2019-08-09 12:02:12 +0100204 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100205 return v;
206}
207
208static inline uint16_t io_read16_array_mb(io16_array_t io, size_t n)
209{
210 uint16_t v = io_read16_array(io, n);
211
David Brazdil851948e2019-08-09 12:02:12 +0100212 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100213 return v;
214}
215
216static inline uint32_t io_read32_array_mb(io32_array_t io, size_t n)
217{
218 uint32_t v = io_read32_array(io, n);
219
David Brazdil851948e2019-08-09 12:02:12 +0100220 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100221 return v;
222}
223
224static inline uint64_t io_read64_array_mb(io64_array_t io, size_t n)
225{
226 uint64_t v = io_read64_array(io, n);
227
David Brazdil851948e2019-08-09 12:02:12 +0100228 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100229 return v;
230}
231
232/* Write to memory-mapped IO. */
233
234static inline void io_write8(io8_t io, uint8_t v)
235{
236 *io.ptr = v;
237}
238
239static inline void io_write16(io16_t io, uint16_t v)
240{
241 *io.ptr = v;
242}
243
244static inline void io_write32(io32_t io, uint32_t v)
245{
246 *io.ptr = v;
247}
248
249static inline void io_write64(io64_t io, uint64_t v)
250{
251 *io.ptr = v;
252}
253
Madhukar Pappireddy2b86c0d2021-08-03 09:19:59 -0500254static inline void io_clrbits32(io32_t io, uint32_t clear)
255{
256 io_write32(io, io_read32(io) & ~clear);
257}
258
259static inline void io_setbits32(io32_t io, uint32_t set)
260{
261 io_write32(io, io_read32(io) | set);
262}
263
264static inline void io_clrsetbits32(io32_t io, uint32_t clear, uint32_t set)
265{
266 io_write32(io, (io_read32(io) & ~clear) | set);
267}
268
Andrew Sculle22b32f2019-05-13 14:46:02 +0100269static inline void io_write8_array(io8_array_t io, size_t n, uint8_t v)
270{
Daniel Boulbyb74d2682021-11-26 13:54:50 +0000271 assert(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100272 io.base[n] = v;
273}
274
275static inline void io_write16_array(io16_array_t io, size_t n, uint16_t v)
276{
Daniel Boulbyb74d2682021-11-26 13:54:50 +0000277 assert(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100278 io.base[n] = v;
279}
280
281static inline void io_write32_array(io32_array_t io, size_t n, uint32_t v)
282{
Daniel Boulbyb74d2682021-11-26 13:54:50 +0000283 assert(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100284 io.base[n] = v;
285}
286
287static inline void io_write64_array(io64_array_t io, size_t n, uint64_t v)
288{
Daniel Boulbyb74d2682021-11-26 13:54:50 +0000289 assert(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100290 io.base[n] = v;
291}
292
293/*
294 * Write to memory-mapped IO with memory barrier.
295 *
296 * The write is ordered after previous memory accesses.
297 */
298
299static inline void io_write8_mb(io8_t io, uint8_t v)
300{
David Brazdil851948e2019-08-09 12:02:12 +0100301 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100302 io_write8(io, v);
303}
304
305static inline void io_write16_mb(io16_t io, uint16_t v)
306{
David Brazdil851948e2019-08-09 12:02:12 +0100307 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100308 io_write16(io, v);
309}
310
311static inline void io_write32_mb(io32_t io, uint32_t v)
312{
David Brazdil851948e2019-08-09 12:02:12 +0100313 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100314 io_write32(io, v);
315}
316
317static inline void io_write64_mb(io64_t io, uint64_t v)
318{
David Brazdil851948e2019-08-09 12:02:12 +0100319 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100320 io_write64(io, v);
321}
322
323static inline void io_write8_array_mb(io8_array_t io, size_t n, uint8_t v)
324{
David Brazdil851948e2019-08-09 12:02:12 +0100325 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100326 io_write8_array(io, n, v);
327}
328
329static inline void io_write16_array_mb(io16_array_t io, size_t n, uint16_t v)
330{
David Brazdil851948e2019-08-09 12:02:12 +0100331 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100332 io_write16_array(io, n, v);
333}
334
335static inline void io_write32_array_mb(io32_array_t io, size_t n, uint32_t v)
336{
David Brazdil851948e2019-08-09 12:02:12 +0100337 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100338 io_write32_array(io, n, v);
339}
340
341static inline void io_write64_array_mb(io64_array_t io, size_t n, uint64_t v)
342{
David Brazdil851948e2019-08-09 12:02:12 +0100343 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100344 io_write64_array(io, n, v);
345}