blob: d27b1a29f5626b0a184d8d3fd489288cca234272 [file] [log] [blame]
// Copyright lowRISC contributors.
// 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;
} 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 {
uint8_t 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);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_SPI_HOST_H_