openmv/lib/alif/Alif_CMSIS/Source/Driver_OSPI.c
iabdalkader daf2bb30da misc: Restructure repo.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-04-13 08:28:34 +02:00

1293 lines
36 KiB
C

/* Copyright (C) 2022 Alif Semiconductor - All Rights Reserved.
* Use, distribution and modification of this code is permitted under the
* terms stated in the Alif Semiconductor Software License Agreement
*
* You should have received a copy of the Alif Semiconductor Software
* License Agreement with this file. If not, please write to:
* contact@alifsemi.com, or visit: https://alifsemi.com/license
*
*/
/**************************************************************************//**
* @file Driver_OSPI.c
* @author Khushboo Singh
* @email khushboo.singh@alifsemi.com
* @version V1.0.0
* @date 21-Oct-2022
* @brief CMSIS-Driver for OSPI derived from CMSIS SPI driver.
* @bug None.
* @Note None
******************************************************************************/
#include "Driver_OSPI_Private.h"
#if !( (RTE_OSPI0) || (RTE_OSPI1) )
#error "OSPI is not enabled in the RTE_Device.h"
#endif
#if !defined(RTE_Drivers_OSPI)
#error "OSPI is not enabled in the RTE_Components.h"
#endif
#define ARM_OSPI_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1, 0) /* driver version */
/* Driver Version */
static const ARM_DRIVER_VERSION DriverVersion = {
ARM_OSPI_API_VERSION,
ARM_OSPI_DRV_VERSION
};
/* Driver Capabilities */
static const ARM_OSPI_CAPABILITIES DriverCapabilities = {
0, /* Simplex Mode (Master and Slave) Deprecated: Reserved (must be zero)*/
0, /* TI Synchronous Serial Interface */
0, /* Microwire Interface */
0, /* Signal Mode Fault event: \ref ARM_OSPI_EVENT_MODE_FAULT */
0 /* Reserved, must be zero */
};
/**
* @fn ARM_DRIVER_VERSION ARM_OSPI_GetVersion(void)
* @brief get ospi version
* @note none
* @param none
* @retval driver version
*/
static ARM_DRIVER_VERSION ARM_OSPI_GetVersion(void)
{
return DriverVersion;
}
/**
* @fn ARM_OSPI_CAPABILITIES ARM_OSPI_GetCapabilities(void)
* @brief get ospi capabilities
* @note none
* @param none
* @retval driver capabilities
*/
static ARM_OSPI_CAPABILITIES ARM_OSPI_GetCapabilities(void)
{
return DriverCapabilities;
}
/**
* @fn void OSPI_IRQHandler(OSPI_RESOURCES *OSPI)
* @brief OSPI interrupt handler
* @note none
* @param OSPI : Pointer to ospi resources structure
* @retval none
*/
static void OSPI_IRQHandler(OSPI_RESOURCES *OSPI)
{
ospi_transfer_t *transfer = &(OSPI->transfer);
ospi_irq_handler(OSPI->regs, transfer);
if (transfer->status == SPI_TRANSFER_STATUS_COMPLETE)
{
transfer->status = SPI_TRANSFER_STATUS_NONE;
OSPI->status.busy = 0;
OSPI->cb_event(ARM_OSPI_EVENT_TRANSFER_COMPLETE);
}
if (transfer->status == SPI_TRANSFER_STATUS_OVERFLOW)
{
transfer->status = SPI_TRANSFER_STATUS_NONE;
OSPI->status.busy = 0;
OSPI->status.data_lost = 1;
OSPI->cb_event(ARM_OSPI_EVENT_DATA_LOST);
}
}
#if OSPI_DMA_ENABLE
/**
\fn static void OSPI_DMACallback(uint32_t event, int8_t peri_num,
OSPI_RESOURCES *OSPI)
\brief Callback function from DMA for OSPI
\param[in] event Event from DMA
\param[in] peri_num Peripheral number
\param[in] OSPI Pointer to OSPI resources
*/
static void OSPI_DMACallback(uint32_t event, int8_t peri_num,
OSPI_RESOURCES *OSPI)
{
if (!OSPI->cb_event)
return;
if (event & ARM_DMA_EVENT_COMPLETE)
{
switch (peri_num)
{
case OSPI0_DMA_RX_PERIPH_REQ:
case OSPI1_DMA_RX_PERIPH_REQ:
OSPI->status.busy = 0;
OSPI->cb_event(ARM_OSPI_EVENT_TRANSFER_COMPLETE);
break;
case OSPI0_DMA_TX_PERIPH_REQ:
case OSPI1_DMA_TX_PERIPH_REQ:
if (OSPI->transfer.mode == SPI_TMOD_TX)
{
OSPI->status.busy = 0;
OSPI->cb_event(ARM_OSPI_EVENT_TRANSFER_COMPLETE);
}
break;
default:
break;
}
}
if (event & ARM_DMA_EVENT_ABORT)
{
OSPI->status.busy = 0;
OSPI->cb_event(ARM_OSPI_EVENT_DATA_LOST);
}
}
/**
\fn int32_t OSPI_DMA_Initialize(DMA_PERIPHERAL_CONFIG *dma_periph)
\brief Initialize DMA for OSPI
\param[in] dma_periph Pointer to DMA resources
\return \ref execution_status
*/
__STATIC_INLINE int32_t OSPI_DMA_Initialize(DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
status = dma_drv->Initialize();
if (status)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t OSPI_DMA_PowerControl(ARM_POWER_STATE state, DMA_PERIPHERAL_CONFIG *dma_periph)
\brief PowerControl DMA for OSPI
\param[in] state Power state
\param[in] dma_periph Pointer to DMA resources
\return \ref execution_status
*/
__STATIC_INLINE int32_t OSPI_DMA_PowerControl(ARM_POWER_STATE state, DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
status = dma_drv->PowerControl(state);
if (status)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t OSPI_DMA_Allocate(DMA_PERIPHERAL_CONFIG *dma_periph)
\brief Allocate a channel for OSPI
\param[in] dma_periph Pointer to DMA resources
\return \ref execution_status
*/
__STATIC_INLINE int32_t OSPI_DMA_Allocate(DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Allocate handle for peripheral */
status = dma_drv->Allocate(&dma_periph->dma_handle);
if (status)
{
return ARM_DRIVER_ERROR;
}
/* Enable the channel in the Event Router */
if (dma_periph->evtrtr_cfg.instance == 0)
{
evtrtr0_enable_dma_channel(dma_periph->evtrtr_cfg.channel,
dma_periph->evtrtr_cfg.group,
DMA_ACK_COMPLETION_PERIPHERAL);
evtrtr0_enable_dma_handshake(dma_periph->evtrtr_cfg.channel,
dma_periph->evtrtr_cfg.group);
}
else
{
evtrtrlocal_enable_dma_channel(dma_periph->evtrtr_cfg.channel,
DMA_ACK_COMPLETION_PERIPHERAL);
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t OSPI_DMA_DeAllocate(DMA_PERIPHERAL_CONFIG *dma_periph)
\brief De-allocate channel of OSPI
\param[in] dma_periph Pointer to DMA resources
\return \ref execution_status
*/
__STATIC_INLINE int32_t OSPI_DMA_DeAllocate(DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* De-Allocate handle */
status = dma_drv->DeAllocate(&dma_periph->dma_handle);
if (status)
{
return ARM_DRIVER_ERROR;
}
/* Disable the channel in the Event Router */
if (dma_periph->evtrtr_cfg.instance == 0)
{
evtrtr0_disable_dma_channel(dma_periph->evtrtr_cfg.channel);
evtrtr0_disable_dma_handshake(dma_periph->evtrtr_cfg.channel,
dma_periph->evtrtr_cfg.group);
}
else
{
evtrtrlocal_disable_dma_channel(dma_periph->evtrtr_cfg.channel);
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t OSPI_DMA_Start(DMA_PERIPHERAL_CONFIG *dma_periph,
ARM_DMA_PARAMS *dma_params)
\brief Start OSPI DMA transfer
\param[in] dma_periph Pointer to DMA resources
\param[in] dma_params Pointer to DMA parameters
\return \ref execution_status
*/
__STATIC_INLINE int32_t OSPI_DMA_Start(DMA_PERIPHERAL_CONFIG *dma_periph,
ARM_DMA_PARAMS *dma_params)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Start transfer */
status = dma_drv->Start(&dma_periph->dma_handle, dma_params);
if (status)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t OSPI_DMA_Stop(DMA_PERIPHERAL_CONFIG *dma_periph)
\brief Stop OSPI DMA transfer
\param[in] dma_periph Pointer to DMA resources
\return \ref execution_status
*/
__STATIC_INLINE int32_t OSPI_DMA_Stop(DMA_PERIPHERAL_CONFIG *dma_periph)
{
int32_t status;
ARM_DRIVER_DMA *dma_drv = dma_periph->dma_drv;
/* Stop transfer */
status = dma_drv->Stop(&dma_periph->dma_handle);
if (status)
{
return ARM_DRIVER_ERROR;
}
return ARM_DRIVER_OK;
}
#endif
/**
* @fn int32_t ARM_OSPI_Initialize(OSPI_RESOURCES *OSPI, ARM_OSPI_SignalEvent_t cb_event).
* @brief Initialize the Spi for communication.
* @note none.
* @param OSPI : Pointer to spi resources structure.
* @param cb_event : Pointer to user callback function.
* @retval \ref execution_status
*/
static int32_t ARM_OSPI_Initialize(OSPI_RESOURCES *OSPI, ARM_OSPI_SignalEvent_t cb_event)
{
if (OSPI->state.initialized == 1)
{
return ARM_DRIVER_OK;
}
if (cb_event == NULL)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if ((OSPI->tx_fifo_threshold > OSPI_TX_FIFO_DEPTH) || (OSPI->tx_fifo_start_level > OSPI_TX_FIFO_DEPTH))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if (OSPI->rx_fifo_threshold > OSPI_RX_FIFO_DEPTH)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
OSPI->transfer.addr_len = 0;
OSPI->transfer.dummy_cycle = 0;
OSPI->transfer.tx_buff = NULL;
OSPI->transfer.rx_buff = NULL;
OSPI->transfer.tx_default_val = 0;
OSPI->transfer.tx_default_enable = 0;
OSPI->transfer.tx_total_cnt = 0;
OSPI->transfer.rx_total_cnt = 0;
OSPI->transfer.tx_current_cnt = 0;
OSPI->transfer.rx_current_cnt = 0;
OSPI->cb_event = cb_event;
#if OSPI_DMA_ENABLE
if (OSPI->dma_enable)
{
OSPI->dma_config->dma_rx.dma_handle = -1;
OSPI->dma_config->dma_tx.dma_handle = -1;
/* Initialize DMA for OSPI-Tx */
if (OSPI_DMA_Initialize(&OSPI->dma_config->dma_tx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
/* Initialize DMA for OSPI-Rx */
if (OSPI_DMA_Initialize(&OSPI->dma_config->dma_rx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
}
#endif
OSPI->state.initialized = 1;
return ARM_DRIVER_OK;
}
/**
* @fn int32_t ARM_OSPI_Uninitialize(OSPI_RESOURCES *OSPI).
* @brief Un-Initialize the Spi.
* @note none.
* @param OSPI : Pointer to spi resources structure.
* @retval \ref execution_status
*/
static int32_t ARM_OSPI_Uninitialize(OSPI_RESOURCES *OSPI)
{
if (OSPI->state.initialized == 0)
{
return ARM_DRIVER_OK;
}
if (OSPI->state.powered == 1)
{
return ARM_DRIVER_ERROR;
}
OSPI->transfer.tx_buff = NULL;
OSPI->transfer.rx_buff = NULL;
OSPI->transfer.tx_default_val = 0;
OSPI->transfer.tx_default_enable = 0;
OSPI->transfer.tx_total_cnt = 0;
OSPI->transfer.rx_total_cnt = 0;
OSPI->transfer.tx_current_cnt = 0;
OSPI->transfer.rx_current_cnt = 0;
OSPI->cb_event = NULL;
OSPI->state.initialized = 0;
return ARM_DRIVER_OK;
}
/**
* @fn int32_t ARM_OSPI_PowerControl(OSPI_RESOURCES *OSPI, ARM_POWER_STATE state).
* @brief Handles the spi power.
* @note none.
* @param OSPI : Pointer to spi resources structure.
* @param state : power state.
* @retval \ref execution_status
*/
static int32_t ARM_OSPI_PowerControl(OSPI_RESOURCES *OSPI, ARM_POWER_STATE state)
{
if (OSPI->state.initialized == 0)
{
return ARM_DRIVER_ERROR;
}
switch (state)
{
case ARM_POWER_OFF:
{
if (OSPI->state.powered == 0)
{
return ARM_DRIVER_OK;
}
if (ospi_busy(OSPI->regs))
{
return ARM_DRIVER_ERROR_BUSY;
}
ospi_mask_interrupts(OSPI->regs);
NVIC_ClearPendingIRQ(OSPI->irq);
NVIC_DisableIRQ(OSPI->irq);
ospi_disable(OSPI->regs);
#if OSPI_DMA_ENABLE
if (OSPI->dma_enable)
{
ospi_disable_tx_dma(OSPI->regs);
ospi_disable_rx_dma(OSPI->regs);
if (OSPI_DMA_DeAllocate(&OSPI->dma_config->dma_tx) == ARM_DRIVER_ERROR)
{
return ARM_DRIVER_ERROR;
}
if (OSPI_DMA_DeAllocate(&OSPI->dma_config->dma_rx) == ARM_DRIVER_ERROR)
{
return ARM_DRIVER_ERROR;
}
}
#endif
OSPI->state.powered = 0;
break;
}
case ARM_POWER_FULL:
{
if (OSPI->state.powered == 1)
{
return ARM_DRIVER_OK;
}
ospi_set_tx_threshold(OSPI->regs, OSPI->tx_fifo_threshold);
ospi_set_rx_threshold(OSPI->regs, OSPI->rx_fifo_threshold);
ospi_set_rx_sample_delay(OSPI->regs, OSPI->rx_sample_delay);
ospi_set_ddr_drive_edge(OSPI->regs, OSPI->ddr_drive_edge);
aes_set_rxds_delay(OSPI->aes_regs, OSPI->rxds_delay);
ospi_mask_interrupts(OSPI->regs);
#if OSPI_DMA_ENABLE
if (OSPI->dma_enable)
{
ospi_set_rx_dma_data_level(OSPI->regs, OSPI->rx_dma_data_level);
ospi_set_tx_dma_data_level(OSPI->regs, OSPI->tx_dma_data_level);
}
#endif
NVIC_ClearPendingIRQ(OSPI->irq);
NVIC_SetPriority(OSPI->irq, OSPI->irq_priority);
NVIC_EnableIRQ(OSPI->irq);
OSPI->state.powered = 1;
break;
}
case ARM_POWER_LOW:
default :
{
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
}
#if OSPI_DMA_ENABLE
if (OSPI->dma_enable)
{
/* Power Control DMA for OSPI-Tx */
if (OSPI_DMA_PowerControl (state, &OSPI->dma_config->dma_tx) != ARM_DRIVER_OK)
{
OSPI->state.powered = 0;
return ARM_DRIVER_ERROR;
}
/* Power Control DMA for OSPI-Rx */
if (OSPI_DMA_PowerControl (state, &OSPI->dma_config->dma_rx) != ARM_DRIVER_OK)
{
OSPI->state.powered = 0;
return ARM_DRIVER_ERROR;
}
if (state == ARM_POWER_FULL)
{
/* Try to allocate a DMA channel for Tx */
if (OSPI_DMA_Allocate(&OSPI->dma_config->dma_tx) == ARM_DRIVER_ERROR)
{
OSPI->state.powered = 0;
return ARM_DRIVER_ERROR;
}
/* Try to allocate a DMA channel for Rx */
if (OSPI_DMA_Allocate(&OSPI->dma_config->dma_rx) == ARM_DRIVER_ERROR)
{
OSPI->state.powered = 0;
return ARM_DRIVER_ERROR;
}
}
}
#endif
return ARM_DRIVER_OK;
}
/**
* @fn int32_t ARM_OSPI_Send(OSPI_RESOURCES *OSPI, const void *data, uint32_t num).
* @brief Used to send through spi.
* @note none.
* @param OSPI : Pointer to spi resources structure.
* @param data : Pointer to the data to send.
* @param num : Number of data byte to send.
* @retval \ref execution_status
*/
static int32_t ARM_OSPI_Send(OSPI_RESOURCES *OSPI, const void *data, uint32_t num)
{
#if OSPI_DMA_ENABLE
int32_t status;
#endif
if (OSPI->state.powered == 0)
{
return ARM_DRIVER_ERROR;
}
if (ospi_busy(OSPI->regs))
{
return ARM_DRIVER_ERROR_BUSY;
}
if ((data == NULL) && (OSPI->transfer.tx_default_enable == false))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if (num == 0)
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if (OSPI->status.busy)
{
return ARM_DRIVER_ERROR_BUSY;
}
OSPI->status.busy = 1;
OSPI->transfer.tx_total_cnt = num;
OSPI->transfer.mode = SPI_TMOD_TX;
#if OSPI_DMA_ENABLE
ARM_DMA_PARAMS dma_params;
if (OSPI->dma_enable && (ospi_get_dfs(OSPI->regs) > 8))
{
dma_params.peri_reqno = OSPI->dma_config->dma_tx.dma_periph_req;
dma_params.dir = ARM_DMA_MEM_TO_DEV;
dma_params.cb_event = OSPI->dma_cb;
dma_params.src_addr = (void *) data;
dma_params.dst_addr = (void *) ospi_get_dma_addr(OSPI->regs);
dma_params.num_bytes = num * 4;
dma_params.irq_priority = OSPI->dma_irq_priority;
dma_params.burst_size = BS_BYTE_4;
dma_params.burst_len = 16;
ospi_dma_send(OSPI->regs, &(OSPI->transfer));
/* Start DMA transfer */
status = OSPI_DMA_Start(&OSPI->dma_config->dma_tx, &dma_params);
if (status)
{
OSPI->status.busy = 0;
return ARM_DRIVER_ERROR;
}
}
else
#endif
{
OSPI->transfer.tx_buff = data;
OSPI->transfer.tx_current_cnt = 0;
OSPI->transfer.status = SPI_TRANSFER_STATUS_NONE;
ospi_send(OSPI->regs, &(OSPI->transfer));
}
return ARM_DRIVER_OK;
}
/**
* @fn int32_t ARM_OSPI_Receive(OSPI_RESOURCES *OSPI, void *data, uint32_t num).
* @brief Used to receive data through spi.
* @note none.
* @param OSPI : Pointer to spi resources structure.
* @param data : Pointer to the data received.
* @param num : Number of data byte to receive.
* @retval \ref execution_status
*/
static int32_t ARM_OSPI_Receive(OSPI_RESOURCES *OSPI, void *data, uint32_t num)
{
if (OSPI->state.powered == 0)
{
return ARM_DRIVER_ERROR;
}
if (ospi_busy(OSPI->regs))
{
return ARM_DRIVER_ERROR_BUSY;
}
if ((data == NULL) || (num == 0))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if (OSPI->status.busy)
{
return ARM_DRIVER_ERROR_BUSY;
}
OSPI->status.busy = 1;
OSPI->transfer.rx_buff = (uint8_t *) data;
OSPI->transfer.rx_current_cnt = 0;
OSPI->transfer.rx_total_cnt = num;
OSPI->transfer.mode = SPI_TMOD_RX;
OSPI->transfer.status = SPI_TRANSFER_STATUS_NONE;
ospi_receive(OSPI->regs, &(OSPI->transfer));
return ARM_DRIVER_OK;
}
/**
* @fn int32_t ARM_OSPI_Transfer(OSPI_RESOURCES *OSPI, const void *data_out, void *data_in, uint32_t num).
* @brief Used to Transfer and Receive data through spi.
* @note none.
* @param OSPI : Pointer to spi resources structure.
* @param data_out : Pointer to the data send.
* @param data_in : Pointer to the data received.
* @param num : Number of data byte to receive.
* @retval \ref execution_status
*/
static int32_t ARM_OSPI_Transfer(OSPI_RESOURCES *OSPI, const void *data_out, void *data_in, uint32_t num)
{
#if OSPI_DMA_ENABLE
int32_t status;
#endif
if (OSPI->state.powered == 0)
{
return ARM_DRIVER_ERROR;
}
if (ospi_busy(OSPI->regs))
{
return ARM_DRIVER_ERROR_BUSY;
}
if ((OSPI->transfer.tx_default_enable == 0) && (data_out == NULL))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if ((data_out == NULL) || (data_in == NULL) || (num == 0))
{
return ARM_DRIVER_ERROR_PARAMETER;
}
if (OSPI->status.busy)
{
return ARM_DRIVER_ERROR_BUSY;
}
OSPI->status.busy = 1;
OSPI->transfer.rx_total_cnt = num;
OSPI->transfer.mode = SPI_TMOD_TX_AND_RX;
/* Tx total count based on address length */
if (OSPI->transfer.addr_len == ARM_OSPI_ADDR_LENGTH_0_BITS)
OSPI->transfer.tx_total_cnt = 1;
else if (OSPI->transfer.addr_len == ARM_OSPI_ADDR_LENGTH_24_BITS)
OSPI->transfer.tx_total_cnt = 4;
else if (OSPI->transfer.addr_len == ARM_OSPI_ADDR_LENGTH_32_BITS)
OSPI->transfer.tx_total_cnt = 2;
#if OSPI_DMA_ENABLE
ARM_DMA_PARAMS tx_dma_params, rx_dma_params;
/*
* DMA transfers with 8 bit DFS are not supported because of the
* h/w limitation on 8bit reception
*/
uint8_t dfs = ospi_get_dfs(OSPI->regs);
if (OSPI->dma_enable && dfs > 8)
{
tx_dma_params.peri_reqno = OSPI->dma_config->dma_tx.dma_periph_req;
tx_dma_params.dir = ARM_DMA_MEM_TO_DEV;
tx_dma_params.cb_event = OSPI->dma_cb;
tx_dma_params.src_addr = (void *) data_out;
tx_dma_params.dst_addr = (void *) ospi_get_dma_addr(OSPI->regs);
tx_dma_params.num_bytes = OSPI->transfer.tx_total_cnt * 4;
tx_dma_params.irq_priority = OSPI->dma_irq_priority;
tx_dma_params.burst_size = BS_BYTE_4;
tx_dma_params.burst_len = 16;
rx_dma_params.peri_reqno = OSPI->dma_config->dma_rx.dma_periph_req;
rx_dma_params.dir = ARM_DMA_DEV_TO_MEM;
rx_dma_params.cb_event = OSPI->dma_cb;
rx_dma_params.src_addr = (void *) ospi_get_dma_addr(OSPI->regs);
rx_dma_params.dst_addr = data_in;
rx_dma_params.irq_priority = OSPI->dma_irq_priority;
rx_dma_params.burst_len = 16;
if (dfs == 16)
{
rx_dma_params.num_bytes = num * 2;
rx_dma_params.burst_size = BS_BYTE_2;
}
else if (dfs == 32)
{
rx_dma_params.num_bytes = num * 4;
rx_dma_params.burst_size = BS_BYTE_4;
}
ospi_dma_transfer(OSPI->regs, &(OSPI->transfer));
/* Start DMA transfers */
status = OSPI_DMA_Start(&OSPI->dma_config->dma_rx, &rx_dma_params);
if (status)
{
OSPI->status.busy = 0;
return ARM_DRIVER_ERROR;
}
status = OSPI_DMA_Start(&OSPI->dma_config->dma_tx, &tx_dma_params);
if (status)
{
OSPI->status.busy = 0;
return ARM_DRIVER_ERROR;
}
}
else
#endif
{
OSPI->transfer.tx_buff = data_out;
OSPI->transfer.rx_buff = data_in;
OSPI->transfer.tx_current_cnt = 0;
OSPI->transfer.rx_current_cnt = 0;
OSPI->transfer.status = SPI_TRANSFER_STATUS_NONE;
ospi_transfer(OSPI->regs, &(OSPI->transfer));
}
return ARM_DRIVER_OK;
}
/**
* @fn int32_t ARM_OSPI_GetDataCount(OSPI_RESOURCES *OSPI).
* @brief Used to get the data count on spi transfer.
* @note none.
* @param OSPI : Pointer to spi resources structure.
* @retval \ref data count
*/
static uint32_t ARM_OSPI_GetDataCount(OSPI_RESOURCES *OSPI)
{
if (OSPI->transfer.mode == SPI_TMOD_TX)
return OSPI->transfer.tx_current_cnt;
else
return OSPI->transfer.rx_current_cnt;
}
/**
* @fn int32_t ARM_OSPI_Control(OSPI_RESOURCES *OSPI, uint32_t control, uint32_t arg).
* @brief Used to configure spi.
* @note none.
* @param OSPI : Pointer to spi resources structure.
* @param control : control code.
* @param arg : argument.
* @retval \ref execution_status
*/
static int32_t ARM_OSPI_Control(OSPI_RESOURCES *OSPI, uint32_t control, uint32_t arg)
{
int32_t ret = ARM_DRIVER_OK;
uint32_t clk;
if (ospi_busy(OSPI->regs))
{
return ARM_DRIVER_ERROR_BUSY;
}
switch (control & ARM_OSPI_CONTROL_MSK)
{
case ARM_OSPI_MODE_INACTIVE:
{
if (control == 0)
{
ospi_disable(OSPI->regs);
return ARM_DRIVER_OK;
}
break;
}
case ARM_OSPI_MODE_MASTER:
{
ospi_mode_master(OSPI->regs);
clk = getOSPICoreClock();
ospi_set_bus_speed(OSPI->regs, arg, clk);
break;
}
case ARM_OSPI_SET_BUS_SPEED:
{
clk = getOSPICoreClock();
ospi_set_bus_speed(OSPI->regs, arg, clk);
return ARM_DRIVER_OK;
}
case ARM_OSPI_GET_BUS_SPEED:
{
clk = getOSPICoreClock();
return (int32_t) ospi_get_bus_speed(OSPI->regs, clk);
}
case ARM_OSPI_SET_DEFAULT_TX_VALUE:
{
OSPI->transfer.tx_default_val = arg;
OSPI->transfer.tx_default_enable = true;
return ARM_DRIVER_OK;
}
case ARM_OSPI_CONTROL_SS:
{
if (arg == 1)
{
ospi_control_ss(OSPI->regs, OSPI->chip_selection_pin, SPI_SS_STATE_ENABLE);
}
else if (arg == 0)
{
ospi_control_ss(OSPI->regs, OSPI->chip_selection_pin, SPI_SS_STATE_DISABLE);
}
else
{
return ARM_DRIVER_ERROR_PARAMETER;
}
return ARM_DRIVER_OK;
}
case ARM_OSPI_ABORT_TRANSFER:
{
#if OSPI_DMA_ENABLE
if (OSPI->dma_enable)
{
if (OSPI->transfer.mode == SPI_TMOD_TX)
{
if (OSPI_DMA_Stop(&OSPI->dma_config->dma_tx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
}
else if (OSPI->transfer.mode == SPI_TMOD_TX_AND_RX)
{
if (OSPI_DMA_Stop(&OSPI->dma_config->dma_tx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
if (OSPI_DMA_Stop(&OSPI->dma_config->dma_rx) != ARM_DRIVER_OK)
{
return ARM_DRIVER_ERROR;
}
}
}
#endif
ospi_mask_interrupts(OSPI->regs);
ospi_disable(OSPI->regs);
ospi_enable(OSPI->regs);
OSPI->transfer.tx_buff = NULL;
OSPI->transfer.rx_buff = NULL;
OSPI->transfer.tx_default_val = 0;
OSPI->transfer.tx_default_enable = 0;
OSPI->transfer.tx_total_cnt = 0;
OSPI->transfer.rx_total_cnt = 0;
OSPI->transfer.tx_current_cnt = 0;
OSPI->transfer.rx_current_cnt = 0;
OSPI->status.busy = 0;
return ARM_DRIVER_OK;
}
case ARM_OSPI_SET_ADDR_LENGTH_WAIT_CYCLE:
{
OSPI->transfer.addr_len = 0xF & arg;
OSPI->transfer.dummy_cycle = 0xFF & (arg >> ARM_OSPI_WAIT_CYCLE_POS);
break;
}
case ARM_OSPI_SET_FRAME_FORMAT:
{
OSPI->transfer.spi_frf = arg;
break;
}
case ARM_OSPI_SET_DDR_MODE:
{
OSPI->transfer.ddr = arg;
break;
}
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
switch (control & ARM_OSPI_FRAME_FORMAT_MSK)
{
case ARM_OSPI_CPOL0_CPHA0:
{
ospi_set_mode(OSPI->regs, SPI_MODE_0);
break;
}
case ARM_OSPI_CPOL0_CPHA1:
{
ospi_set_mode(OSPI->regs, SPI_MODE_1);
break;
}
case ARM_OSPI_CPOL1_CPHA0:
{
ospi_set_mode(OSPI->regs, SPI_MODE_2);
break;
}
case ARM_OSPI_CPOL1_CPHA1:
{
ospi_set_mode(OSPI->regs, SPI_MODE_3);
break;
}
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
if (control & ARM_OSPI_DATA_BITS_MSK)
{
ospi_set_dfs(OSPI->regs, ((control & ARM_OSPI_DATA_BITS_MSK) >> ARM_OSPI_DATA_BITS_POS));
}
switch (control & ARM_OSPI_BIT_ORDER_MSK)
{
case ARM_OSPI_MSB_LSB:
{
break;
}
case ARM_OSPI_LSB_MSB:
{
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
}
switch (control & ARM_OSPI_SS_MASTER_MODE_MSK)
{
case ARM_OSPI_SS_MASTER_UNUSED:
{
ospi_control_ss(OSPI->regs, 0xF, SPI_SS_STATE_DISABLE);
break;
}
case ARM_OSPI_SS_MASTER_SW:
{
if ((control & ARM_OSPI_CONTROL_MSK) == ARM_OSPI_MODE_MASTER)
{
return ARM_DRIVER_OK;
}
return ARM_DRIVER_ERROR;
}
case ARM_OSPI_SS_MASTER_HW_OUTPUT:
{
/* This is the default state in the IP, No need to configure */
return ARM_DRIVER_OK;
}
case ARM_OSPI_SS_MASTER_HW_INPUT:
{
break;
}
}
return ret;
}
/**
* @fn uint32_t ARM_OSPI_GetStatus(OSPI_RESOURCES *OSPI)
* @brief Used to get spi status.
* @note none.
* @param OSPI : Pointer to spi resources structure.
* @retval \ref spi driver status.
*/
static ARM_OSPI_STATUS ARM_OSPI_GetStatus(OSPI_RESOURCES *OSPI)
{
return OSPI->status;
}
/* OSPI0 driver instance */
#if RTE_OSPI0
#if RTE_OSPI0_DMA_ENABLE
static void OSPI0_DMACallback (uint32_t event, int8_t peri_num);
static OSPI_DMA_HW_CONFIG OSPI0_DMA_HW_CONFIG = {
.dma_rx =
{
.dma_drv = &ARM_Driver_DMA_(OSPI0_DMA),
.dma_periph_req = OSPI0_DMA_RX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = OSPI0_DMA,
.group = OSPI0_DMA_GROUP,
.channel = OSPI0_DMA_RX_PERIPH_REQ,
.enable_handshake = OSPI0_DMA_HANDSHAKE_ENABLE,
},
},
.dma_tx =
{
.dma_drv = &ARM_Driver_DMA_(OSPI0_DMA),
.dma_periph_req = OSPI0_DMA_TX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = OSPI0_DMA,
.group = OSPI0_DMA_GROUP,
.channel = OSPI0_DMA_TX_PERIPH_REQ,
.enable_handshake = OSPI0_DMA_HANDSHAKE_ENABLE,
},
},
};
#endif
OSPI_RESOURCES OSPI0_RES = {
.regs = (OSPI_Type *) OSPI0_BASE,
.aes_regs = (AES_Type *) AES0_BASE,
.irq = OSPI0_IRQ_IRQn,
.cb_event = NULL,
.irq_priority = RTE_OSPI0_IRQ_PRIORITY,
.drv_instance = OSPI_INSTANCE_0,
.chip_selection_pin = RTE_OSPI0_CHIP_SELECTION_PIN,
.transfer.spi_frf = RTE_OSPI0_SPI_FRAME_FORMAT,
.tx_fifo_threshold = RTE_OSPI0_TX_FIFO_THRESHOLD,
.tx_fifo_start_level = RTE_OSPI0_TX_FIFO_LEVEL_TO_START_TRANSFER,
.rx_fifo_threshold = RTE_OSPI0_RX_FIFO_THRESHOLD,
#if RTE_OSPI0_DMA_ENABLE
.dma_cb = OSPI0_DMACallback,
.dma_config = &OSPI0_DMA_HW_CONFIG,
.dma_enable = RTE_OSPI0_DMA_ENABLE,
.dma_irq_priority = RTE_OSPI0_DMA_IRQ_PRIORITY,
.rx_dma_data_level = RTE_OSPI0_RX_DMA_DATA_LEVEL,
.tx_dma_data_level = RTE_OSPI0_TX_DMA_DATA_LEVEL,
#endif
.ddr_drive_edge = RTE_OSPI0_DDR_DRIVE_EDGE,
.rx_sample_delay = RTE_OSPI0_RX_SAMPLE_DELAY,
.rxds_delay = RTE_OSPI0_RXDS_DELAY
};
void OSPI0_IRQHandler(void)
{
OSPI_IRQHandler(&OSPI0_RES);
}
#if RTE_OSPI0_DMA_ENABLE
static void OSPI0_DMACallback(uint32_t event, int8_t peri_num)
{
OSPI_DMACallback(event, peri_num, &OSPI0_RES);
}
#endif
static int32_t ARM_OSPI0_Initialize(ARM_OSPI_SignalEvent_t cb_event)
{
return ARM_OSPI_Initialize(&OSPI0_RES, cb_event);
}
static int32_t ARM_OSPI0_Uninitialize(void)
{
return ARM_OSPI_Uninitialize(&OSPI0_RES);
}
static int32_t ARM_OSPI0_PowerControl(ARM_POWER_STATE state)
{
return ARM_OSPI_PowerControl(&OSPI0_RES, state);
}
static int32_t ARM_OSPI0_Send(const void *data, uint32_t num)
{
return ARM_OSPI_Send(&OSPI0_RES, data, num);
}
static int32_t ARM_OSPI0_Receive(void *data, uint32_t num)
{
return ARM_OSPI_Receive(&OSPI0_RES, data, num);
}
static int32_t ARM_OSPI0_Transfer(const void *data_out, void *data_in, uint32_t num)
{
return ARM_OSPI_Transfer(&OSPI0_RES, data_out, data_in, num);
}
static uint32_t ARM_OSPI0_GetDataCount(void)
{
return ARM_OSPI_GetDataCount(&OSPI0_RES);
}
static int32_t ARM_OSPI0_Control(uint32_t control, uint32_t arg)
{
return ARM_OSPI_Control(&OSPI0_RES, control, arg);
}
static ARM_OSPI_STATUS ARM_OSPI0_GetStatus(void)
{
return ARM_OSPI_GetStatus(&OSPI0_RES);
}
extern ARM_DRIVER_OSPI Driver_OSPI0;
ARM_DRIVER_OSPI Driver_OSPI0 = {
ARM_OSPI_GetVersion,
ARM_OSPI_GetCapabilities,
ARM_OSPI0_Initialize,
ARM_OSPI0_Uninitialize,
ARM_OSPI0_PowerControl,
ARM_OSPI0_Send,
ARM_OSPI0_Receive,
ARM_OSPI0_Transfer,
ARM_OSPI0_GetDataCount,
ARM_OSPI0_Control,
ARM_OSPI0_GetStatus
};
#endif /* RTE_OSPI0 */
/* OSPI1 driver instance */
#if RTE_OSPI1
#if RTE_OSPI1_DMA_ENABLE
static void OSPI1_DMACallback(uint32_t event, int8_t peri_num);
static OSPI_DMA_HW_CONFIG OSPI1_DMA_HW_CONFIG = {
.dma_rx =
{
.dma_drv = &ARM_Driver_DMA_(OSPI1_DMA),
.dma_periph_req = OSPI1_DMA_RX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = OSPI1_DMA,
.group = OSPI1_DMA_GROUP,
.channel = OSPI1_DMA_RX_PERIPH_REQ,
.enable_handshake = OSPI1_DMA_HANDSHAKE_ENABLE,
},
},
.dma_tx =
{
.dma_drv = &ARM_Driver_DMA_(OSPI1_DMA),
.dma_periph_req = OSPI1_DMA_TX_PERIPH_REQ,
.evtrtr_cfg =
{
.instance = OSPI1_DMA,
.group = OSPI1_DMA_GROUP,
.channel = OSPI1_DMA_TX_PERIPH_REQ,
.enable_handshake = OSPI1_DMA_HANDSHAKE_ENABLE,
},
},
};
#endif
OSPI_RESOURCES OSPI1_RES = {
.regs = (OSPI_Type *) OSPI1_BASE,
.aes_regs = (AES_Type *) AES1_BASE,
.irq = OSPI1_IRQ_IRQn,
.cb_event = NULL,
.irq_priority = RTE_OSPI1_IRQ_PRIORITY,
.drv_instance = OSPI_INSTANCE_1,
.chip_selection_pin = RTE_OSPI1_CHIP_SELECTION_PIN,
.transfer.spi_frf = RTE_OSPI1_SPI_FRAME_FORMAT,
.tx_fifo_threshold = RTE_OSPI1_TX_FIFO_THRESHOLD,
.tx_fifo_start_level = RTE_OSPI1_TX_FIFO_LEVEL_TO_START_TRANSFER,
.rx_fifo_threshold = RTE_OSPI1_RX_FIFO_THRESHOLD,
#if RTE_OSPI1_DMA_ENABLE
.dma_cb = OSPI1_DMACallback,
.dma_config = &OSPI1_DMA_HW_CONFIG,
.dma_irq_priority = RTE_OSPI1_DMA_IRQ_PRIORITY,
.dma_enable = RTE_OSPI1_DMA_ENABLE,
.rx_dma_data_level = RTE_OSPI1_RX_DMA_DATA_LEVEL,
.tx_dma_data_level = RTE_OSPI1_TX_DMA_DATA_LEVEL,
#endif
.ddr_drive_edge = RTE_OSPI1_DDR_DRIVE_EDGE,
.rx_sample_delay = RTE_OSPI1_RX_SAMPLE_DELAY,
.rxds_delay = RTE_OSPI1_RXDS_DELAY
};
void OSPI1_IRQHandler(void)
{
OSPI_IRQHandler(&OSPI1_RES);
}
#if RTE_OSPI1_DMA_ENABLE
static void OSPI1_DMACallback(uint32_t event, int8_t peri_num)
{
OSPI_DMACallback(event, peri_num, &OSPI1_RES);
}
#endif
static int32_t ARM_OSPI1_Initialize(ARM_OSPI_SignalEvent_t cb_event)
{
return ARM_OSPI_Initialize(&OSPI1_RES, cb_event);
}
static int32_t ARM_OSPI1_Uninitialize(void)
{
return ARM_OSPI_Uninitialize(&OSPI1_RES);
}
static int32_t ARM_OSPI1_PowerControl(ARM_POWER_STATE state)
{
return ARM_OSPI_PowerControl(&OSPI1_RES, state);
}
static int32_t ARM_OSPI1_Send(const void *data, uint32_t num)
{
return ARM_OSPI_Send(&OSPI1_RES, data, num);
}
static int32_t ARM_OSPI1_Receive(void *data, uint32_t num)
{
return ARM_OSPI_Receive(&OSPI1_RES, data, num);
}
static int32_t ARM_OSPI1_Transfer(const void *data_out, void *data_in, uint32_t num)
{
return ARM_OSPI_Transfer(&OSPI1_RES, data_out, data_in, num);
}
static uint32_t ARM_OSPI1_GetDataCount(void)
{
return ARM_OSPI_GetDataCount(&OSPI1_RES);
}
static int32_t ARM_OSPI1_Control(uint32_t control, uint32_t arg)
{
return ARM_OSPI_Control(&OSPI1_RES, control, arg);
}
static ARM_OSPI_STATUS ARM_OSPI1_GetStatus(void)
{
return ARM_OSPI_GetStatus(&OSPI1_RES);
}
extern ARM_DRIVER_OSPI Driver_OSPI1;
ARM_DRIVER_OSPI Driver_OSPI1 = {
ARM_OSPI_GetVersion,
ARM_OSPI_GetCapabilities,
ARM_OSPI1_Initialize,
ARM_OSPI1_Uninitialize,
ARM_OSPI1_PowerControl,
ARM_OSPI1_Send,
ARM_OSPI1_Receive,
ARM_OSPI1_Transfer,
ARM_OSPI1_GetDataCount,
ARM_OSPI1_Control,
ARM_OSPI1_GetStatus
};
#endif /* RTE_OSPI1 */