forked from lowRISC/opentitan
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dif_spi_host.h
470 lines (440 loc) · 13.9 KB
/
dif_spi_host.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
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
// 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_SPI_HOST_H_
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_SPI_HOST_H_
/**
* @file
* @brief <a href="/hw/ip/spi_host/doc/">SPI Host</a> Device Interface Functions
*/
#include <stdint.h>
#include "sw/device/lib/dif/autogen/dif_spi_host_autogen.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
* Runtime configuration for SPI Host.
*
* This struct describes (SOFTWARE) runtime information for one-time
* configuration of the hardware.
*/
typedef struct dif_spi_host_config {
/** Desired SPI clock frequency (SCK). */
uint32_t spi_clock;
/** Peripheral clock frequency (ie: kClockFreqPeripheralHz). */
uint32_t peripheral_clock_freq_hz;
struct {
/** Minimum idle time between commands in SCK half-cycles. */
uint8_t idle;
/** Chip-select trailing time in SCK half-cycles. */
uint8_t trail;
/** Chip-select leading time in SCK half-cycles. */
uint8_t lead;
} chip_select;
/** Full-cycle sampling mode. */
bool full_cycle;
/** SPI clock phase. */
bool cpha;
/** SPI clock polarity. */
bool cpol;
/** If `EVENT_ENABLE.TXWM` is set, an interrupt will fire when the depth of
* the TX FIFO drops below `TX_WATERMARK` words (32b each). */
size_t tx_watermark;
/** If `EVENT_ENABLE.RXWM` is set, an interrupt will fire when the depth of
* the RX FIFO drops below `RX_WATERMARK` words (32b each). */
size_t rx_watermark;
} dif_spi_host_config_t;
/**
* Width of SPI operations.
*/
typedef enum dif_spi_host_width {
/** Standard SPI mode (single lanes for send and recv). */
kDifSpiHostWidthStandard = 0,
/** Dual SPI mode (use two lanes for send and recv). */
kDifSpiHostWidthDual = 1,
/** Quad SPI mode (use four lanes for send and recv). */
kDifSpiHostWidthQuad = 2,
} dif_spi_host_width_t;
/**
* Direction of SPI operations.
*
* This describes which direction a given SPI operation will use.
*/
typedef enum dif_spi_host_direction {
/** The SPI host neither transmits or receives. */
kDifSpiHostDirectionDummy = 0,
/** The SPI host receives data. */
kDifSpiHostDirectionRx = 1,
/** The SPI host transmits data. */
kDifSpiHostDirectionTx = 2,
/** The SPI host transmits and receives data. */
kDifSpiHostDirectionBidirectional = 3,
} dif_spi_host_direction_t;
/**
* Segment types for segments in a transaction.
*/
typedef enum dif_spi_host_segment_type {
/** The segment is a SPI opcode. */
kDifSpiHostSegmentTypeOpcode,
/** The segment is a SPI address. */
kDifSpiHostSegmentTypeAddress,
/** The segment is a SPI dummy cycle. */
kDifSpiHostSegmentTypeDummy,
/** The segment is a SPI transmit (from a memory buffer). */
kDifSpiHostSegmentTypeTx,
/** The segment is a SPI receive (into a memory buffer). */
kDifSpiHostSegmentTypeRx,
/** The segment is a simultaneous transmit and receieve. */
kDifSpiHostSegmentTypeBidirectional,
} dif_spi_host_segment_type_t;
/**
* Address mode for the address segment in a transaction.
*/
typedef enum dif_spi_host_addr_mode {
/** The address is a 3-byte address. */
kDifSpiHostAddrMode3b,
/** The address is a 4-byte address. */
kDifSpiHostAddrMode4b,
} dif_spi_host_addr_mode_t;
/**
* Segment descriptor for each segment in a transaction.
*
* This struct is a tagged union: the `type` field determines
* which field of the union is relevant.
*/
typedef struct dif_spi_host_segment {
/** The segment type for this segment. */
dif_spi_host_segment_type_t type;
union {
struct {
dif_spi_host_width_t width;
uint8_t opcode;
} opcode;
struct {
dif_spi_host_width_t width;
dif_spi_host_addr_mode_t mode;
uint32_t address;
} address;
struct {
dif_spi_host_width_t width;
size_t length;
} dummy;
struct {
dif_spi_host_width_t width;
const void *buf;
size_t length;
} tx;
struct {
dif_spi_host_width_t width;
void *buf;
size_t length;
} rx;
struct {
dif_spi_host_width_t width;
const void *txbuf;
void *rxbuf;
size_t length;
} bidir;
};
} dif_spi_host_segment_t;
/**
* Configures SPI Host with runtime information.
*
* This function should only need to be called once for the lifetime of
* `handle`.
*
* @param spi_host A SPI Host handle.
* @param config Runtime configuration parameters.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_spi_host_configure(const dif_spi_host_t *spi_host,
dif_spi_host_config_t config);
/**
* Sets the enablement of the SPI host output buffers.
*
* @param spi_host A SPI Host handle.
* @param enabled Enable or disable the output buffers.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_spi_host_output_set_enabled(const dif_spi_host_t *spi_host,
bool enabled);
/**
* Write to the SPI Host transmit FIFO.
*
* @param spi_host A SPI Host handle.
* @param src A pointer to the buffer to transmit.
* @param len The length of the transmit buffer.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_spi_host_fifo_write(const dif_spi_host_t *spi_host,
const void *src, uint16_t len);
/**
* Read from the SPI Host receive FIFO.
*
* @param spi_host A SPI Host handle.
* @param dst A pointer to the buffer to receive the data.
* @param len The length of the receive buffer.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_spi_host_fifo_read(const dif_spi_host_t *spi_host, void *dst,
uint16_t len);
/**
* Begins a SPI Host transaction.
*
* @param spi_host A SPI Host handle.
* @param csid The chip-select ID of the SPI target.
* @param segments The SPI segments to send in this transaction.
* @param length The number of SPI segments in this transaction.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_spi_host_transaction(const dif_spi_host_t *spi_host,
uint32_t csid,
dif_spi_host_segment_t *segments,
size_t length);
typedef enum dif_spi_host_events {
/**
* Enable IRQ to be fired when `STATUS.RXFULL` goes high.
*/
kDifSpiHostEvtRxFull = 1 << 0,
/**
* Enable IRQ to be fired when `STATUS.TXEMPTY` goes high.
*/
kDifSpiHostEvtTxEmpty = 1 << 1,
/**
* Enable IRQ to be fired when the number of 32-bit words in the RX FIFO is
* greater than `CONTROL.RX_WATERMARK`.
*/
kDifSpiHostEvtRxWm = 1 << 2,
/**
* Enable IRQ to be fired when the number of 32-bit words in the TX FIFO is
* greater than `CONTROL.TX_WATERMARK`.
*/
kDifSpiHostEvtTxWm = 1 << 3,
/**
* Enable IRQ to be fired when `STATUS.READY` goes high.
*/
kDifSpiHostEvtReady = 1 << 4,
/**
* Enable IRQ to be fired when `STATUS.ACTIVE` goes low.
*/
kDifSpiHostEvtIdle = 1 << 5,
/**
* All above together.
*/
kDifSpiHostEvtAll = (1 << 6) - 1,
} dif_spi_host_events_code_t;
/**
* Bitmask with the `dif_spi_host_events_code_t` values.
*/
typedef uint32_t dif_spi_host_events_t;
/**
* Set the enable state of the spi host events.
*
* @param spi_host A SPI Host handle.
* @param events A bitmask with the events to be enabled or disabled.
* @param enable True to enable the `events` or false to disable.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_spi_host_event_set_enabled(const dif_spi_host_t *spi_host,
dif_spi_host_events_t events,
bool enable);
/**
* Get the enabled events.
*
* @param spi_host A SPI Host handle.
* @param[out] events A bitmask that will contain all the events that are
* enabled.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_spi_host_event_get_enabled(const dif_spi_host_t *spi_host,
dif_spi_host_events_t *events);
typedef struct dif_spi_host_status {
/**
* Indicates the SPI host is ready to receive commands.
*/
bool ready;
/**
* Indicates the SPI host is processing a previously issued command.
*/
bool active;
/**
* Indicates that the transmit data fifo is full.
*/
bool tx_full;
/**
* Indicates that the transmit data fifo is empty.
*/
bool tx_empty;
/**
* If true, signifies that an ongoing transaction has stalled due to lack of
* data in the`TX FIFO`.
*/
bool tx_stall;
/**
* If true, the amount of data in the `TX FIFO` has fallen below the
* level of `CONTROL.TX_WATERMARK`words (32b each).
*/
bool tx_water_mark;
/**
* Indicates that the receive fifo is full. Any ongoing transactions will
* stall until firmware reads some data from `RXDATA`.
*/
bool rx_full;
/**
* Indicates that the receive fifo is empty. Any reads from `RX FIFO` will
* cause an error interrupt.
*/
bool rx_empty;
/**
* If true, signifies that an ongoing transaction has stalled due to lack of
* available space in the `RX FIFO`.
*/
bool rx_stall;
/**
* If true the least significant bits will be transmitted first.
*/
bool least_significant_first;
/**
* If true, the number of 32-bits in the `RX FIFO` now exceeds the
* `CONTROL.RX_WATERMARK`entries (32b each).
*/
bool rx_water_mark;
/**
* Indicates how many unread 32-bit words are currently in the command
* segment queue.
*/
uint32_t cmd_queue_depth;
/**
* Indicates how many unread 32-bit words are currently in the `RX FIFO`.
* When active, this result may an underestimate due to synchronization
* delays.
*/
uint32_t rx_queue_depth;
/**
* Indicates how many unsent 32-bit words are currently in the`TX FIFO`.
*/
uint32_t tx_queue_depth;
} dif_spi_host_status_t;
/**
* Read the current status of the spi host.
*
* @param spi_host A SPI Host handle.
* @param[out] status The status of the spi.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_spi_host_get_status(const dif_spi_host_t *spi_host,
dif_spi_host_status_t *status);
/**
* Issues a command segment to a spi_host.
*
* @param spi_host A SPI Host handle.
* @param length The number of 1-byte burst for read and write segments, or the
* number of cycles for dummy segments.
* @param speed Which speed the transmission should use.
* @param direction Which direction the operation should use.
* @param last_segment If true the chip select line is raised after the
* transmission, otherwise it is kept low.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_spi_host_write_command(const dif_spi_host_t *spi_host,
uint16_t length,
dif_spi_host_width_t speed,
dif_spi_host_direction_t direction,
bool last_segment);
typedef enum dif_spi_host_error_code {
/**
* Indicates a write to `COMMAND` when `STATUS.READY = 0`.
*/
kDifSpiHostErrorCmdBusy = 1 << 0,
/**
* Indicates that firmware has overflowed the `TX FIFO`.
*/
kDifSpiHostErrorOverflow = 1 << 1,
/**
* Indicates that firmware has attempted to read from `RXDATA` when the `RX
* FIFO` is empty.
*/
kDifSpiHostErrorUnderflow = 1 << 2,
/**
* Indicates an invalid command segment, meaning either an invalid value of
* `COMMAND.SPEED` or a request for bidirectional data transfer at dual or
* quad speed.
*/
kDifSpiHostErrorCmdInval = 1 << 3,
/**
* Indicates a command was attempted with an invalid value for `CSID`.
*/
kDifSpiHostErrorCsIdIval = 1 << 4,
/**
* Indicates that TL-UL attempted to write to `TXDATA` with no bytes enabled.
* Such ‘zero byte’ writes are not supported. Note: This error does not
* generate IRQ.
*/
kDifSpiHostErrorAccessIval = 1 << 5,
/**
* All the errors that can generate an IRQ.
*/
kDifSpiHostIrqErrorAll = (1 << 5) - 1,
/**
* All the errors above together.
*/
kDifSpiHostErrorAll = (1 << 6) - 1,
} dif_spi_host_error_code_t;
/**
* Bitmask with the `dif_spi_host_error_code_t` values.
*/
typedef uint32_t dif_spi_host_errors_t;
/**
* Set the enable state of the spi host errors.
*
* @param spi_host A SPI Host handle.
* @param errors A bitmask with the errors to be enabled or disabled.
* @param enable True to enable the `events` or false to disable.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_spi_host_error_set_enabled(const dif_spi_host_t *spi_host,
dif_spi_host_errors_t errors,
bool enable);
/**
* Get the enabled errors.
*
* @param spi_host A SPI Host handle.
* @param[out] errors A bitmask that will contain all the errors that are
* enabled.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_spi_host_error_get_enabled(const dif_spi_host_t *spi_host,
dif_spi_host_errors_t *errors);
/**
* Read the current error status of the spi host.
*
* @param spi_host A SPI Host handle.
* @param[out] errors The error status of the spi.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_spi_host_get_error(const dif_spi_host_t *spi_host,
dif_spi_host_errors_t *errors);
/**
* Wait until the SPI Host is idle.
*
* @param spi_host A SPI Host handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_spi_host_wait_until_idle(const dif_spi_host_t *spi_host);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_SPI_HOST_H_