blob: 9a146a2fbfe10eb8f06267744996748f152e4e79 [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"
15
Andrew Scull877ae4b2019-07-02 12:52:33 +010016#include "hf/check.h"
Andrew Sculle22b32f2019-05-13 14:46:02 +010017
18/* Opaque types for different sized fields of memory mapped IO. */
19
20typedef struct {
21 volatile uint8_t *ptr;
22} io8_t;
23
24typedef struct {
25 volatile uint16_t *ptr;
26} io16_t;
27
28typedef struct {
29 volatile uint32_t *ptr;
30} io32_t;
31
32typedef struct {
33 volatile uint64_t *ptr;
34} io64_t;
35
36typedef struct {
37 volatile uint8_t *base;
38 size_t count;
39} io8_array_t;
40
41typedef struct {
42 volatile uint16_t *base;
43 size_t count;
44} io16_array_t;
45
46typedef struct {
47 volatile uint32_t *base;
48 size_t count;
49} io32_array_t;
50
51typedef struct {
52 volatile uint64_t *base;
53 size_t count;
54} io64_array_t;
55
56/* Contructors for literals. */
57
58#define IO8_C(addr) ((io8_t){.ptr = (volatile uint8_t *)(addr)})
59#define IO16_C(addr) ((io16_t){.ptr = (volatile uint16_t *)(addr)})
60#define IO32_C(addr) ((io32_t){.ptr = (volatile uint32_t *)(addr)})
61#define IO64_C(addr) ((io64_t){.ptr = (volatile uint64_t *)(addr)})
62
63#define IO8_ARRAY_C(addr, cnt) \
64 ((io8_array_t){.base = (volatile uint8_t *)(addr), .count = (cnt)})
65#define IO16_ARRAY_C(addr, cnt) \
66 ((io16_array_t){.base = (volatile uint16_t *)(addr), .count = (cnt)})
67#define IO32_ARRAY_C(addr, cnt) \
68 ((io32_array_t){.base = (volatile uint32_t *)(addr), .count = (cnt)})
69#define IO64_ARRAY_C(addr, cnt) \
70 ((io64_array_t){.base = (volatile uint64_t *)(addr), .count = (cnt)})
71
72/** Read from memory-mapped IO. */
73
74static inline uint8_t io_read8(io8_t io)
75{
76 return *io.ptr;
77}
78
79static inline uint16_t io_read16(io16_t io)
80{
81 return *io.ptr;
82}
83
84static inline uint32_t io_read32(io32_t io)
85{
86 return *io.ptr;
87}
88
89static inline uint64_t io_read64(io64_t io)
90{
91 return *io.ptr;
92}
93
94static inline uint8_t io_read8_array(io8_array_t io, size_t n)
95{
Andrew Scull877ae4b2019-07-02 12:52:33 +010096 CHECK(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +010097 return io.base[n];
98}
99
100static inline uint16_t io_read16_array(io16_array_t io, size_t n)
101{
Andrew Scull877ae4b2019-07-02 12:52:33 +0100102 CHECK(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100103 return io.base[n];
104}
105
106static inline uint32_t io_read32_array(io32_array_t io, size_t n)
107{
Andrew Scull877ae4b2019-07-02 12:52:33 +0100108 CHECK(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100109 return io.base[n];
110}
111
112static inline uint64_t io_read64_array(io64_array_t io, size_t n)
113{
Andrew Scull877ae4b2019-07-02 12:52:33 +0100114 CHECK(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100115 return io.base[n];
116}
117
118/**
119 * Read from memory-mapped IO with memory barrier.
120 *
121 * The read is ordered before subsequent memory accesses.
122 */
123
124static inline uint8_t io_read8_mb(io8_t io)
125{
126 uint8_t v = io_read8(io);
127
David Brazdil851948e2019-08-09 12:02:12 +0100128 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100129 return v;
130}
131
132static inline uint16_t io_read16_mb(io16_t io)
133{
134 uint16_t v = io_read16(io);
135
David Brazdil851948e2019-08-09 12:02:12 +0100136 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100137 return v;
138}
139
140static inline uint32_t io_read32_mb(io32_t io)
141{
142 uint32_t v = io_read32(io);
143
David Brazdil851948e2019-08-09 12:02:12 +0100144 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100145 return v;
146}
147
148static inline uint64_t io_read64_mb(io64_t io)
149{
150 uint64_t v = io_read64(io);
151
David Brazdil851948e2019-08-09 12:02:12 +0100152 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100153 return v;
154}
155
156static inline uint8_t io_read8_array_mb(io8_array_t io, size_t n)
157{
158 uint8_t v = io_read8_array(io, n);
159
David Brazdil851948e2019-08-09 12:02:12 +0100160 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100161 return v;
162}
163
164static inline uint16_t io_read16_array_mb(io16_array_t io, size_t n)
165{
166 uint16_t v = io_read16_array(io, n);
167
David Brazdil851948e2019-08-09 12:02:12 +0100168 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100169 return v;
170}
171
172static inline uint32_t io_read32_array_mb(io32_array_t io, size_t n)
173{
174 uint32_t v = io_read32_array(io, n);
175
David Brazdil851948e2019-08-09 12:02:12 +0100176 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100177 return v;
178}
179
180static inline uint64_t io_read64_array_mb(io64_array_t io, size_t n)
181{
182 uint64_t v = io_read64_array(io, n);
183
David Brazdil851948e2019-08-09 12:02:12 +0100184 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100185 return v;
186}
187
188/* Write to memory-mapped IO. */
189
190static inline void io_write8(io8_t io, uint8_t v)
191{
192 *io.ptr = v;
193}
194
195static inline void io_write16(io16_t io, uint16_t v)
196{
197 *io.ptr = v;
198}
199
200static inline void io_write32(io32_t io, uint32_t v)
201{
202 *io.ptr = v;
203}
204
205static inline void io_write64(io64_t io, uint64_t v)
206{
207 *io.ptr = v;
208}
209
Madhukar Pappireddy2b86c0d2021-08-03 09:19:59 -0500210static inline void io_clrbits32(io32_t io, uint32_t clear)
211{
212 io_write32(io, io_read32(io) & ~clear);
213}
214
215static inline void io_setbits32(io32_t io, uint32_t set)
216{
217 io_write32(io, io_read32(io) | set);
218}
219
220static inline void io_clrsetbits32(io32_t io, uint32_t clear, uint32_t set)
221{
222 io_write32(io, (io_read32(io) & ~clear) | set);
223}
224
Andrew Sculle22b32f2019-05-13 14:46:02 +0100225static inline void io_write8_array(io8_array_t io, size_t n, uint8_t v)
226{
Andrew Scull877ae4b2019-07-02 12:52:33 +0100227 CHECK(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100228 io.base[n] = v;
229}
230
231static inline void io_write16_array(io16_array_t io, size_t n, uint16_t v)
232{
Andrew Scull877ae4b2019-07-02 12:52:33 +0100233 CHECK(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100234 io.base[n] = v;
235}
236
237static inline void io_write32_array(io32_array_t io, size_t n, uint32_t v)
238{
Andrew Scull877ae4b2019-07-02 12:52:33 +0100239 CHECK(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100240 io.base[n] = v;
241}
242
243static inline void io_write64_array(io64_array_t io, size_t n, uint64_t v)
244{
Andrew Scull877ae4b2019-07-02 12:52:33 +0100245 CHECK(n < io.count);
Andrew Sculle22b32f2019-05-13 14:46:02 +0100246 io.base[n] = v;
247}
248
249/*
250 * Write to memory-mapped IO with memory barrier.
251 *
252 * The write is ordered after previous memory accesses.
253 */
254
255static inline void io_write8_mb(io8_t io, uint8_t v)
256{
David Brazdil851948e2019-08-09 12:02:12 +0100257 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100258 io_write8(io, v);
259}
260
261static inline void io_write16_mb(io16_t io, uint16_t v)
262{
David Brazdil851948e2019-08-09 12:02:12 +0100263 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100264 io_write16(io, v);
265}
266
267static inline void io_write32_mb(io32_t io, uint32_t v)
268{
David Brazdil851948e2019-08-09 12:02:12 +0100269 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100270 io_write32(io, v);
271}
272
273static inline void io_write64_mb(io64_t io, uint64_t v)
274{
David Brazdil851948e2019-08-09 12:02:12 +0100275 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100276 io_write64(io, v);
277}
278
279static inline void io_write8_array_mb(io8_array_t io, size_t n, uint8_t v)
280{
David Brazdil851948e2019-08-09 12:02:12 +0100281 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100282 io_write8_array(io, n, v);
283}
284
285static inline void io_write16_array_mb(io16_array_t io, size_t n, uint16_t v)
286{
David Brazdil851948e2019-08-09 12:02:12 +0100287 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100288 io_write16_array(io, n, v);
289}
290
291static inline void io_write32_array_mb(io32_array_t io, size_t n, uint32_t v)
292{
David Brazdil851948e2019-08-09 12:02:12 +0100293 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100294 io_write32_array(io, n, v);
295}
296
297static inline void io_write64_array_mb(io64_array_t io, size_t n, uint64_t v)
298{
David Brazdil851948e2019-08-09 12:02:12 +0100299 data_sync_barrier();
Andrew Sculle22b32f2019-05-13 14:46:02 +0100300 io_write64_array(io, n, v);
301}