Software APIs
dif_spi_host.h
Go to the documentation of this file.
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_SPI_HOST_H_
6 #define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_SPI_HOST_H_
7 /**
8  * @file
9  * @brief <a href="/hw/ip/spi_host/doc/">SPI Host</a> Device Interface Functions
10  */
11 
12 #include <stdint.h>
13 
14 #include "sw/device/lib/dif/autogen/dif_spi_host_autogen.h"
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif // __cplusplus
19 
20 /**
21  * Runtime configuration for SPI Host.
22  *
23  * This struct describes (SOFTWARE) runtime information for one-time
24  * configuration of the hardware.
25  */
26 typedef struct dif_spi_host_config {
27  /** Desired SPI clock frequency (SCK). */
28  uint32_t spi_clock;
29  /** Peripheral clock frequency (ie: kClockFreqPeripheralHz). */
31  struct {
32  /** Minimum idle time between commands in SCK half-cycles. */
33  uint8_t idle;
34  /** Chip-select trailing time in SCK half-cycles. */
35  uint8_t trail;
36  /** Chip-select leading time in SCK half-cycles. */
37  uint8_t lead;
38  } chip_select;
39  /** Full-cycle sampling mode. */
40  bool full_cycle;
41  /** SPI clock phase. */
42  bool cpha;
43  /** SPI clock polarity. */
44  bool cpol;
45  /** If `EVENT_ENABLE.TXWM` is set, an interrupt will fire when the depth of
46  * the TX FIFO drops below `TX_WATERMARK` words (32b each). */
47  size_t tx_watermark;
48  /** If `EVENT_ENABLE.RXWM` is set, an interrupt will fire when the depth of
49  * the RX FIFO drops below `RX_WATERMARK` words (32b each). */
50  size_t rx_watermark;
52 
53 /**
54  * Width of SPI operations.
55  */
56 typedef enum dif_spi_host_width {
57  /** Standard SPI mode (single lanes for send and recv). */
59  /** Dual SPI mode (use two lanes for send and recv). */
61  /** Quad SPI mode (use four lanes for send and recv). */
64 
65 /**
66  * Direction of SPI operations.
67  *
68  * This describes which direction a given SPI operation will use.
69  */
70 typedef enum dif_spi_host_direction {
71  /** The SPI host neither transmits or receives. */
73  /** The SPI host receives data. */
75  /** The SPI host transmits data. */
77  /** The SPI host transmits and receives data. */
80 
81 /**
82  * Segment types for segments in a transaction.
83  */
85  /** The segment is a SPI opcode. */
87  /** The segment is a SPI address. */
89  /** The segment is a SPI dummy cycle. */
91  /** The segment is a SPI transmit (from a memory buffer). */
93  /** The segment is a SPI receive (into a memory buffer). */
95  /** The segment is a simultaneous transmit and receieve. */
98 
99 /**
100  * Address mode for the address segment in a transaction.
101  */
103  /** The address is a 3-byte address. */
105  /** The address is a 4-byte address. */
108 
109 /**
110  * Segment descriptor for each segment in a transaction.
111  *
112  * This struct is a tagged union: the `type` field determines
113  * which field of the union is relevant.
114  */
115 typedef struct dif_spi_host_segment {
116  /** The segment type for this segment. */
118  union {
119  struct {
120  dif_spi_host_width_t width;
121  uint8_t opcode;
122  } opcode;
123  struct {
124  dif_spi_host_width_t width;
126  uint32_t address;
127  } address;
128  struct {
129  dif_spi_host_width_t width;
130  size_t length;
131  } dummy;
132  struct {
133  dif_spi_host_width_t width;
134  const void *buf;
135  size_t length;
136  } tx;
137  struct {
138  dif_spi_host_width_t width;
139  void *buf;
140  size_t length;
141  } rx;
142  struct {
143  dif_spi_host_width_t width;
144  const void *txbuf;
145  void *rxbuf;
146  size_t length;
147  } bidir;
148  };
150 
151 /**
152  * Configures SPI Host with runtime information.
153  *
154  * This function should only need to be called once for the lifetime of
155  * `handle`.
156  *
157  * @param spi_host A SPI Host handle.
158  * @param config Runtime configuration parameters.
159  * @return The result of the operation.
160  */
162 dif_result_t dif_spi_host_configure(const dif_spi_host_t *spi_host,
163  dif_spi_host_config_t config);
164 
165 /**
166  * Sets the enablement of the SPI host output buffers.
167  *
168  * @param spi_host A SPI Host handle.
169  * @param enabled Enable or disable the output buffers.
170  * @return The result of the operation.
171  */
173 dif_result_t dif_spi_host_output_set_enabled(const dif_spi_host_t *spi_host,
174  bool enabled);
175 
176 /**
177  * Write to the SPI Host transmit FIFO.
178  *
179  * @param spi_host A SPI Host handle.
180  * @param src A pointer to the buffer to transmit.
181  * @param len The length of the transmit buffer.
182  * @return The result of the operation.
183  */
185 dif_result_t dif_spi_host_fifo_write(const dif_spi_host_t *spi_host,
186  const void *src, uint16_t len);
187 
188 /**
189  * Read from the SPI Host receive FIFO.
190  *
191  * @param spi_host A SPI Host handle.
192  * @param dst A pointer to the buffer to receive the data.
193  * @param len The length of the receive buffer.
194  * @return The result of the operation.
195  */
197 dif_result_t dif_spi_host_fifo_read(const dif_spi_host_t *spi_host, void *dst,
198  uint16_t len);
199 
200 /**
201  * Begins a SPI Host transaction without reading the FIFOs.
202  *
203  * @param spi_host A SPI Host handle.
204  * @param csid The chip-select ID of the SPI target.
205  * @param segments The SPI segments to send in this transaction.
206  * @param length The number of SPI segments in this transaction.
207  * @return The result of the operation.
208  */
210 dif_result_t dif_spi_host_start_transaction(const dif_spi_host_t *spi_host,
211  uint32_t csid,
212  dif_spi_host_segment_t *segments,
213  size_t length);
214 
215 /**
216  * Begins a SPI Host transaction.
217  *
218  * @param spi_host A SPI Host handle.
219  * @param csid The chip-select ID of the SPI target.
220  * @param segments The SPI segments to send in this transaction.
221  * @param length The number of SPI segments in this transaction.
222  * @return The result of the operation.
223  */
225 dif_result_t dif_spi_host_transaction(const dif_spi_host_t *spi_host,
226  uint32_t csid,
227  dif_spi_host_segment_t *segments,
228  size_t length);
229 
230 typedef enum dif_spi_host_events {
231  /**
232  * Enable IRQ to be fired when `STATUS.RXFULL` goes high.
233  */
235  /**
236  * Enable IRQ to be fired when `STATUS.TXEMPTY` goes high.
237  */
239  /**
240  * Enable IRQ to be fired when the number of 32-bit words in the RX FIFO is
241  * greater than `CONTROL.RX_WATERMARK`.
242  */
244  /**
245  * Enable IRQ to be fired when the number of 32-bit words in the TX FIFO is
246  * greater than `CONTROL.TX_WATERMARK`.
247  */
249  /**
250  * Enable IRQ to be fired when `STATUS.READY` goes high.
251  */
253  /**
254  * Enable IRQ to be fired when `STATUS.ACTIVE` goes low.
255  */
257  /**
258  * All above together.
259  */
260  kDifSpiHostEvtAll = (1 << 6) - 1,
261 } dif_spi_host_events_code_t;
262 
263 /**
264  * Bitmask with the `dif_spi_host_events_code_t` values.
265  */
266 typedef uint32_t dif_spi_host_events_t;
267 
268 /**
269  * Set the enable state of the spi host events.
270  *
271  * @param spi_host A SPI Host handle.
272  * @param events A bitmask with the events to be enabled or disabled.
273  * @param enable True to enable the `events` or false to disable.
274  * @return The result of the operation.
275  */
277 dif_result_t dif_spi_host_event_set_enabled(const dif_spi_host_t *spi_host,
278  dif_spi_host_events_t events,
279  bool enable);
280 
281 /**
282  * Get the enabled events.
283  *
284  * @param spi_host A SPI Host handle.
285  * @param[out] events A bitmask that will contain all the events that are
286  * enabled.
287  * @return The result of the operation.
288  */
290 dif_result_t dif_spi_host_event_get_enabled(const dif_spi_host_t *spi_host,
291  dif_spi_host_events_t *events);
292 
293 typedef struct dif_spi_host_status {
294  /**
295  * Indicates the SPI host is ready to receive commands.
296  */
297  bool ready;
298  /**
299  * Indicates the SPI host is processing a previously issued command.
300  */
301  bool active;
302  /**
303  * Indicates that the transmit data fifo is full.
304  */
305  bool tx_full;
306  /**
307  * Indicates that the transmit data fifo is empty.
308  */
309  bool tx_empty;
310  /**
311  * If true, signifies that an ongoing transaction has stalled due to lack of
312  * data in the`TX FIFO`.
313  */
314  bool tx_stall;
315  /**
316  * If true, the amount of data in the `TX FIFO` has fallen below the
317  * level of `CONTROL.TX_WATERMARK`words (32b each).
318  */
320  /**
321  * Indicates that the receive fifo is full. Any ongoing transactions will
322  * stall until firmware reads some data from `RXDATA`.
323  */
324  bool rx_full;
325  /**
326  * Indicates that the receive fifo is empty. Any reads from `RX FIFO` will
327  * cause an error interrupt.
328  */
329  bool rx_empty;
330  /**
331  * If true, signifies that an ongoing transaction has stalled due to lack of
332  * available space in the `RX FIFO`.
333  */
334  bool rx_stall;
335  /**
336  * If true the least significant bits will be transmitted first.
337  */
339  /**
340  * If true, the number of 32-bits in the `RX FIFO` now exceeds the
341  * `CONTROL.RX_WATERMARK`entries (32b each).
342  */
344  /**
345  * Indicates how many unread 32-bit words are currently in the command
346  * segment queue.
347  */
348  uint32_t cmd_queue_depth;
349  /**
350  * Indicates how many unread 32-bit words are currently in the `RX FIFO`.
351  * When active, this result may an underestimate due to synchronization
352  * delays.
353  */
354  uint32_t rx_queue_depth;
355  /**
356  * Indicates how many unsent 32-bit words are currently in the`TX FIFO`.
357  */
358  uint32_t tx_queue_depth;
360 
361 /**
362  * Read the current status of the spi host.
363  *
364  * @param spi_host A SPI Host handle.
365  * @param[out] status The status of the spi.
366  * @return The result of the operation.
367  */
369 dif_result_t dif_spi_host_get_status(const dif_spi_host_t *spi_host,
371 
372 /**
373  * Issues a command segment to a spi_host.
374  *
375  * @param spi_host A SPI Host handle.
376  * @param length The number of 1-byte burst for read and write segments, or the
377  * number of cycles for dummy segments.
378  * @param speed Which speed the transmission should use.
379  * @param direction Which direction the operation should use.
380  * @param last_segment If true the chip select line is raised after the
381  * transmission, otherwise it is kept low.
382  * @return The result of the operation.
383  */
385 dif_result_t dif_spi_host_write_command(const dif_spi_host_t *spi_host,
386  uint16_t length,
387  dif_spi_host_width_t speed,
388  dif_spi_host_direction_t direction,
389  bool last_segment);
390 
392  /**
393  * Indicates a write to `COMMAND` when `STATUS.READY = 0`.
394  */
396  /**
397  * Indicates that firmware has overflowed the `TX FIFO`.
398  */
400  /**
401  * Indicates that firmware has attempted to read from `RXDATA` when the `RX
402  * FIFO` is empty.
403  */
405  /**
406  * Indicates an invalid command segment, meaning either an invalid value of
407  * `COMMAND.SPEED` or a request for bidirectional data transfer at dual or
408  * quad speed.
409  */
411  /**
412  * Indicates a command was attempted with an invalid value for `CSID`.
413  */
415  /**
416  * Indicates that TL-UL attempted to write to `TXDATA` with no bytes enabled.
417  * Such ‘zero byte’ writes are not supported. Note: This error does not
418  * generate IRQ.
419  */
421  /**
422  * All the errors that can generate an IRQ.
423  */
424  kDifSpiHostIrqErrorAll = (1 << 5) - 1,
425  /**
426  * All the errors above together.
427  */
428  kDifSpiHostErrorAll = (1 << 6) - 1,
429 } dif_spi_host_error_code_t;
430 
431 /**
432  * Bitmask with the `dif_spi_host_error_code_t` values.
433  */
434 typedef uint32_t dif_spi_host_errors_t;
435 
436 /**
437  * Set the enable state of the spi host errors.
438  *
439  * @param spi_host A SPI Host handle.
440  * @param errors A bitmask with the errors to be enabled or disabled.
441  * @param enable True to enable the `events` or false to disable.
442  * @return The result of the operation.
443  */
445 dif_result_t dif_spi_host_error_set_enabled(const dif_spi_host_t *spi_host,
446  dif_spi_host_errors_t errors,
447  bool enable);
448 
449 /**
450  * Get the enabled errors.
451  *
452  * @param spi_host A SPI Host handle.
453  * @param[out] errors A bitmask that will contain all the errors that are
454  * enabled.
455  * @return The result of the operation.
456  */
458 dif_result_t dif_spi_host_error_get_enabled(const dif_spi_host_t *spi_host,
459  dif_spi_host_errors_t *errors);
460 
461 /**
462  * Read the current error status of the spi host.
463  *
464  * @param spi_host A SPI Host handle.
465  * @param[out] errors The error status of the spi.
466  * @return The result of the operation.
467  */
469 dif_result_t dif_spi_host_get_error(const dif_spi_host_t *spi_host,
470  dif_spi_host_errors_t *errors);
471 
472 /**
473  * Wait until the SPI Host is idle.
474  *
475  * @param spi_host A SPI Host handle.
476  * @return The result of the operation.
477  */
479 dif_result_t dif_spi_host_wait_until_idle(const dif_spi_host_t *spi_host);
480 
481 #ifdef __cplusplus
482 } // extern "C"
483 #endif // __cplusplus
484 
485 #endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_SPI_HOST_H_