forked from lowRISC/opentitan
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdif_dma.h
410 lines (370 loc) · 12.5 KB
/
dif_dma.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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_DMA_H_
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_DMA_H_
/**
* @file
* @brief <a href="/hw/ip/dma/doc/">DMA Controller</a> Device Interface
* Functions
*/
#include <stdint.h>
#include "dma_regs.h" // Generated.
#include "sw/device/lib/dif/autogen/dif_dma_autogen.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// Target Address space that the source address pointer refers to.
typedef enum dif_dma_address_space_id {
/* OpenTitan 32 bit internal bus. */
kDifDmaOpentitanInternalBus = 0x07,
/* SoC control register address bus using 32 bit (or 64 bits if configured by
an SoC) CTN port .*/
kDifDmaSoCControlRegisterBus = 0x0a,
/* SoC system address bus using 64 bit SYS port. */
kDifDmaSoCSystemBus = 0x09,
} dif_dma_address_space_id_t;
/* Supported transaction widths by the DMA */
typedef enum dif_dma_transaction_width {
/* Transfer 1 byte at a time.*/
kDifDmaTransWidth1Byte = 0x00,
/* Transfer 2 byte at a time.*/
kDifDmaTransWidth2Bytes = 0x01,
/* Transfer 4 byte at a time.*/
kDifDmaTransWidth4Bytes = 0x02,
} dif_dma_transaction_width_t;
/* Supported Opcodes by the DMA */
typedef enum dif_dma_transaction_opcode {
/* Simple copy from source to destination.*/
kDifDmaCopyOpcode = 0x00,
/* Inline hashing with SHA2-256.*/
kDifDmaSha256Opcode = 0x01,
/* Inline hashing with SHA2-384.*/
kDifDmaSha384Opcode = 0x02,
/* Inline hashing with SHA2-512.*/
kDifDmaSha512Opcode = 0x03,
} dif_dma_transaction_opcode_t;
/**
* Define the transaction address space.
*/
typedef struct dif_dma_transaction_address {
uint64_t address;
dif_dma_address_space_id_t asid;
} dif_dma_transaction_address_t;
/**
* Addressing configuration.
*/
typedef struct dif_dma_address_config {
/* Address wraps after each chunk, so chunks overlap */
bool wrap;
/* Increment after each (partial-)word transfer */
bool increment;
} dif_dma_address_config_t;
/**
* Parameters for a DMA Controller transaction.
*/
typedef struct dif_dma_transaction {
dif_dma_transaction_address_t source;
dif_dma_transaction_address_t destination;
dif_dma_address_config_t src_config;
dif_dma_address_config_t dst_config;
/* Chunk size (in bytes) of the data object to transferred.*/
size_t chunk_size;
/* Total size (in bytes) of the data object to transferred.*/
size_t total_size;
/* Iteration width.*/
dif_dma_transaction_width_t width;
} dif_dma_transaction_t;
/**
* Configures DMA Controller for a transaction.
*
* This function should be called every time before `dif_dma_start`.
*
* @param dma A DMA Controller handle.
* @param config Transaction configuration parameters.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_configure(const dif_dma_t *dma,
dif_dma_transaction_t transaction);
/**
* Configures DMA Controller hardware handshake mode.
*
* This function should be called before `dif_dma_start`.
*
* Hardware handshake mode is used to push / pop FIFOs to / from low speed IO
* peripherals receiving data e.g. I3C receive buffer.
*
* @param dma A DMA Controller handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_handshake_enable(const dif_dma_t *dma);
/**
* Disable DMA Controller hardware handshake mode.
*
* @param dma A DMA Controller handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_handshake_disable(const dif_dma_t *dma);
/**
* Begins a DMA Controller transaction.
*
* Before this function the DMA transaction shall be configured by calling the
* function `dif_dma_configure` and optionally `dif_dma_handshake_enable` can be
* called.
*
* @param dma A DMA Controller handle.
* @param opcode Transaction opcode.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_start(const dif_dma_t *dma,
dif_dma_transaction_opcode_t opcode);
/**
* Abort the DMA Controller transaction in execution.
*
* @param dma A DMA Controller handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_abort(const dif_dma_t *dma);
/**
* Set the DMA enabled memory range within the OT internal memory space.
*
* @param dma A DMA Controller handle.
* @param address Base address.
* @param size The range size.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_memory_range_set(const dif_dma_t *dma, uint32_t address,
size_t size);
/**
* Get the DMA enabled memory range within the OT internal memory space.
*
* @param dma A DMA Controller handle.
* @param[out] address Out-param for the base address.
* @param[out] size Out-param for the range size.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_memory_range_get(const dif_dma_t *dma, uint32_t *address,
size_t *size);
/**
* Locks out the DMA memory range register.
*
* This function is reentrant: calling it while functionality is locked will
* have no effect and return `kDifOk`.
*
* @param dma A DMA Controller handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_memory_range_lock(const dif_dma_t *dma);
/**
* Checks whether the DMA memory range is locked.
*
* @param dma A DMA Controller handle.
* @param[out] is_locked Out-param for the locked state.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_is_memory_range_locked(const dif_dma_t *dma,
bool *is_locked);
/**
* Checks whether the DMA memory range is valid.
*
* @param dma A DMA Controller handle.
* @param[out] is_valid Out-param for the valid state.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_is_memory_range_valid(const dif_dma_t *dma,
bool *is_valid);
typedef enum dif_dma_status_code {
// DMA operation is active.
kDifDmaStatusBusy = 0x01 << DMA_STATUS_BUSY_BIT,
// Configured DMA operation is complete.
kDifDmaStatusDone = 0x01 << DMA_STATUS_DONE_BIT,
// Set once aborted operation drains.
kDifDmaStatusAborted = 0x01 << DMA_STATUS_ABORTED_BIT,
// Error occurred during the operation.
// Check the error_code for information about the source of the error.
kDifDmaStatusError = 0x01 << DMA_STATUS_ERROR_BIT,
// Set once the SHA2 digest is valid after finishing a transfer
kDifDmaStatusSha2DigestValid = 0x01 << DMA_STATUS_SHA2_DIGEST_VALID_BIT,
// Transfer of a single chunk is complete.
kDifDmaStatusChunkDone = 0x01 << DMA_STATUS_CHUNK_DONE_BIT,
} dif_dma_status_code_t;
/**
* Bitmask with the `dif_dma_status_code_t` values.
*/
typedef uint32_t dif_dma_status_t;
/**
* Reads the DMA status.
*
* @param dma A DMA Controller handle.
* @param[out] status Out-param for the status.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_status_get(const dif_dma_t *dma, dif_dma_status_t *status);
/**
* Writes the DMA status register and clears the corrsponding status bits.
*
* @param dma A DMA Controller handle.
* @param status Status bits to be cleared.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_status_write(const dif_dma_t *dma,
dif_dma_status_t status);
/**
* Clear all status bits of the status register.
*
* @param dma A DMA Controller handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_status_clear(const dif_dma_t *dma);
/**
* Poll the DMA status util a given flag in the register is set.
*
* @param dma A DMA Controller handle.
* @param flag The status that needs to bet set.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_status_poll(const dif_dma_t *dma,
dif_dma_status_code_t flag);
typedef enum dif_dma_error_code {
// Source address error.
kDifDmaErrorNone = 0x00,
// Source address error.
kDifDmaErrorSourceAddress = 0x01 << 0,
// Destination address error.
kDifDmaErrorDestinationAddress = 0x01 << 1,
// Opcode error.
kDifDmaErrorOpcode = 0x01 << 2,
// Size error.
kDifDmaErrorSize = 0x01 << 3,
// Bus transaction error.
kDifDmaErrorBus = 0x01 << 4,
// DMA enable memory config error.
kDifDmaErrorEnableMemoryConfig = 0x01 << 5,
// Register range valid error.
kDifDmaErrorRangeValid = 0x01 << 6,
// Invalid ASID error.
kDifDmaErrorInvalidAsid = 0x01 << 7,
} dif_dma_error_code_t;
/**
* Reads the DMA error code.
*
* @param dma A DMA Controller handle.
* @param[out] error Out-param for the error code.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_error_code_get(const dif_dma_t *dma,
dif_dma_error_code_t *error);
/**
* Return the digest length given a DMA opcode.
*
* @param opcode A DMA opcode.
* @param digest_len The digest length.
* @return The result of the operation.
*/
dif_result_t dif_dma_get_digest_length(dif_dma_transaction_opcode_t opcode,
uint32_t *digest_len);
/**
* Read out the SHA2 digest
*
* @param dma A DMA Controller handle.
* @param opcode The opcode to select the length of the read digest.
* @param[out] digest Pointer to the digest, to store the read values.
* @return The result of the operation.
*/
dif_result_t dif_dma_sha2_digest_get(const dif_dma_t *dma,
dif_dma_transaction_opcode_t opcode,
uint32_t digest[]);
/**
* Enable DMA controller handshake interrupt.
*
* @param dma A DMA Controller handle.
* @param enable_state Enable state. The bit position corresponds to the IRQ
* index.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_handshake_irq_enable(const dif_dma_t *dma,
uint32_t enable_state);
/**
* Enable the corresponding DME handshake interrupt clearing mechanism.
*
* @param dma A DMA Controller handle.
* @param clear_state Enable interrupt clearing mechanism. The bit position
* corresponds to the IRQ index.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_handshake_clear_irq(const dif_dma_t *dma,
uint32_t clear_state);
/**
* Select the bus interface for the interrupt clearing mechanism.
* 0: CTN/System fabric
* 1: OT-internal crossbar
*
* @param dma A DMA Controller handle.
* @param clear_irq_bus Bus selection for the clearing mechanism. The bit
* position corresponds to the IRQ index.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_handshake_clear_irq_bus(const dif_dma_t *dma,
uint32_t clear_irq_bus);
/**
* Address index for every interrupt. Used to configure the write address and
* write value for the interrupt clearing mechanism.
*/
typedef enum dif_dma_intr_idx {
kDifDmaIntrClearIdx0 = 0x0,
kDifDmaIntrClearIdx1 = 0x4,
kDifDmaIntrClearIdx2 = 0x8,
kDifDmaIntrClearIdx3 = 0xC,
kDifDmaIntrClearIdx4 = 0x10,
kDifDmaIntrClearIdx5 = 0x14,
kDifDmaIntrClearIdx6 = 0x18,
kDifDmaIntrClearIdx7 = 0x1C,
kDifDmaIntrClearIdx8 = 0x20,
kDifDmaIntrClearIdx9 = 0x24,
kDifDmaIntrClearIdx10 = 0x28,
} dif_dma_intr_idx_t;
/**
* Set the write address for the interrupt clearing mechanism.
*
* @param dma A DMA Controller handle.
* @param idx Index of the selected interrupt.
* @param intr_src_addr Address to write the interrupt clearing value to.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_intr_src_addr(const dif_dma_t *dma, dif_dma_intr_idx_t idx,
uint32_t intr_src_addr);
/**
* Set the write value for the interrupt clearing mechanism.
*
* @param dma A DMA Controller handle.
* @param idx Index of the selected interrupt.
* @param intr_src_value Value to write the interrupt clearing value to.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_dma_intr_write_value(const dif_dma_t *dma,
dif_dma_intr_idx_t idx,
uint32_t intr_src_value);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_DMA_H_