1733 lines
42 KiB
C
1733 lines
42 KiB
C
|
/***************************************************************************
|
||
|
*
|
||
|
* Copyright 2015-2019 BES.
|
||
|
* All rights reserved. All unpublished rights reserved.
|
||
|
*
|
||
|
* No part of this work may be used or reproduced in any form or by any
|
||
|
* means, or stored in a database or retrieval system, without prior written
|
||
|
* permission of BES.
|
||
|
*
|
||
|
* Use of this work is governed by a license granted by BES.
|
||
|
* This work contains confidential and proprietary information of
|
||
|
* BES. which is protected by copyright, trade secret,
|
||
|
* trademark and other intellectual property rights.
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
#include "plat_addr_map.h"
|
||
|
#include "cmsis.h"
|
||
|
#include "hal_cmu.h"
|
||
|
#include "hal_dma.h"
|
||
|
#include "hal_location.h"
|
||
|
#include "hal_spi.h"
|
||
|
#include "hal_trace.h"
|
||
|
#include "reg_spi.h"
|
||
|
#include "string.h"
|
||
|
|
||
|
// TODO:
|
||
|
// 1) Add transfer timeout control
|
||
|
|
||
|
#ifdef SPI_ROM_ONLY
|
||
|
#define SPI_ASSERT(c, ...) ASSERT_NODUMP(c)
|
||
|
#else
|
||
|
#define SPI_ASSERT(c, ...) ASSERT(c, ##__VA_ARGS__)
|
||
|
#endif
|
||
|
|
||
|
enum HAL_SPI_ID_T {
|
||
|
HAL_SPI_ID_INTERNAL,
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
HAL_SPI_ID_0,
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
HAL_SPI_ID_SLCD,
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPIPHY
|
||
|
HAL_SPI_ID_PHY,
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPIDPD
|
||
|
HAL_SPI_ID_DPD,
|
||
|
#endif
|
||
|
|
||
|
HAL_SPI_ID_QTY
|
||
|
};
|
||
|
|
||
|
enum HAL_SPI_CS_T {
|
||
|
HAL_SPI_CS_0,
|
||
|
#if (CHIP_SPI_VER >= 2)
|
||
|
HAL_SPI_CS_1,
|
||
|
HAL_SPI_CS_2,
|
||
|
#if (CHIP_SPI_VER >= 3)
|
||
|
HAL_SPI_CS_3,
|
||
|
#if (CHIP_SPI_VER >= 4)
|
||
|
//HAL_SPI_CS_4,
|
||
|
#endif
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
HAL_SPI_CS_QTY
|
||
|
};
|
||
|
|
||
|
enum HAL_SPI_XFER_TYPE_T {
|
||
|
HAL_SPI_XFER_TYPE_SEND,
|
||
|
HAL_SPI_XFER_TYPE_RECV,
|
||
|
|
||
|
HAL_SPI_XFER_TYPE_QTY
|
||
|
};
|
||
|
|
||
|
struct HAL_SPI_MOD_NAME_T {
|
||
|
enum HAL_CMU_MOD_ID_T mod;
|
||
|
enum HAL_CMU_MOD_ID_T apb;
|
||
|
};
|
||
|
|
||
|
static struct SPI_T * const spi[HAL_SPI_ID_QTY] = {
|
||
|
(struct SPI_T *)ISPI_BASE,
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
(struct SPI_T *)SPI_BASE,
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
(struct SPI_T *)SPILCD_BASE,
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPIPHY
|
||
|
(struct SPI_T *)SPIPHY_BASE,
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPIDPD
|
||
|
(struct SPI_T *)SPIDPD_BASE,
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
static const struct HAL_SPI_MOD_NAME_T spi_mod[HAL_SPI_ID_QTY] = {
|
||
|
{
|
||
|
.mod = HAL_CMU_MOD_O_SPI_ITN,
|
||
|
.apb = HAL_CMU_MOD_P_SPI_ITN,
|
||
|
},
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
{
|
||
|
.mod = HAL_CMU_MOD_O_SPI,
|
||
|
.apb = HAL_CMU_MOD_P_SPI,
|
||
|
},
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
{
|
||
|
.mod = HAL_CMU_MOD_O_SLCD,
|
||
|
.apb = HAL_CMU_MOD_P_SLCD,
|
||
|
},
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPIPHY
|
||
|
{
|
||
|
.mod = HAL_CMU_MOD_O_SPI_PHY,
|
||
|
.apb = HAL_CMU_MOD_P_SPI_PHY,
|
||
|
},
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPIDPD
|
||
|
{
|
||
|
.mod = HAL_CMU_MOD_O_SPI_DPD,
|
||
|
.apb = HAL_CMU_MOD_P_SPI_DPD,
|
||
|
},
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
#ifndef SPI_ROM_ONLY
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
static struct HAL_SPI_CTRL_T spi0_ctrl[HAL_SPI_CS_QTY];
|
||
|
#if (CHIP_SPI_VER >= 2)
|
||
|
static enum HAL_SPI_CS_T spi0_cs = HAL_SPI_CS_0;
|
||
|
#else
|
||
|
static const enum HAL_SPI_CS_T spi0_cs = HAL_SPI_CS_0;
|
||
|
#endif
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
static struct HAL_SPI_CTRL_T spilcd_ctrl[HAL_SPI_CS_QTY];
|
||
|
#if (CHIP_SPI_VER >= 2)
|
||
|
static enum HAL_SPI_CS_T spilcd_cs = HAL_SPI_CS_0;
|
||
|
#else
|
||
|
static const enum HAL_SPI_CS_T spilcd_cs = HAL_SPI_CS_0;
|
||
|
#endif
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPIDPD
|
||
|
static struct HAL_SPI_CTRL_T spidpd_ctrl;
|
||
|
#endif
|
||
|
|
||
|
static uint8_t BOOT_BSS_LOC spi_cs_map[HAL_SPI_ID_QTY];
|
||
|
STATIC_ASSERT(sizeof(spi_cs_map[0]) * 8 >= HAL_SPI_CS_QTY, "spi_cs_map size too small");
|
||
|
|
||
|
static bool BOOT_BSS_LOC in_use[HAL_SPI_ID_QTY] = { false, };
|
||
|
|
||
|
static HAL_SPI_DMA_HANDLER_T BOOT_BSS_LOC spi_txdma_handler[HAL_SPI_ID_QTY];
|
||
|
static HAL_SPI_DMA_HANDLER_T BOOT_BSS_LOC spi_rxdma_handler[HAL_SPI_ID_QTY];
|
||
|
static uint8_t BOOT_BSS_LOC spi_txdma_chan[HAL_SPI_ID_QTY];
|
||
|
static uint8_t BOOT_BSS_LOC spi_rxdma_chan[HAL_SPI_ID_QTY];
|
||
|
|
||
|
static enum HAL_SPI_MOD_CLK_SEL_T clk_sel[HAL_SPI_ID_QTY];
|
||
|
|
||
|
static bool BOOT_BSS_LOC spi_init_done = false;
|
||
|
|
||
|
static int hal_spi_activate_cs_id(enum HAL_SPI_ID_T id, uint32_t cs);
|
||
|
#endif
|
||
|
|
||
|
//static const char *invalid_id = "Invalid SPI ID: %d";
|
||
|
|
||
|
static inline uint8_t get_frame_bytes(enum HAL_SPI_ID_T id)
|
||
|
{
|
||
|
uint8_t bits, cnt;
|
||
|
|
||
|
bits = GET_BITFIELD(spi[id]->SSPCR0, SPI_SSPCR0_DSS) + 1;
|
||
|
if (bits <= 8) {
|
||
|
cnt = 1;
|
||
|
} else if (bits <= 16) {
|
||
|
cnt = 2;
|
||
|
} else {
|
||
|
cnt = 4;
|
||
|
}
|
||
|
|
||
|
return cnt;
|
||
|
}
|
||
|
|
||
|
static inline void copy_frame_from_bytes(uint32_t *val, const uint8_t *data, uint8_t cnt)
|
||
|
{
|
||
|
#ifdef UNALIGNED_ACCESS
|
||
|
if (cnt == 1) {
|
||
|
*val = *(const uint8_t *)data;
|
||
|
} else if (cnt == 2) {
|
||
|
*val = *(const uint16_t *)data;
|
||
|
} else {
|
||
|
*val = *(const uint32_t *)data;
|
||
|
}
|
||
|
#else
|
||
|
if (cnt == 1) {
|
||
|
*val = data[0];
|
||
|
} else if (cnt == 2) {
|
||
|
*val = data[0] | (data[1] << 8);
|
||
|
} else {
|
||
|
*val = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static inline void copy_bytes_from_frame(uint8_t *data, uint32_t val, uint8_t cnt)
|
||
|
{
|
||
|
#ifdef UNALIGNED_ACCESS
|
||
|
if (cnt == 1) {
|
||
|
*(uint8_t *)data = (uint8_t)val;
|
||
|
} else if (cnt == 2) {
|
||
|
*(uint16_t *)data = (uint16_t)val;
|
||
|
} else {
|
||
|
*(uint32_t *)data = (uint32_t)val;
|
||
|
}
|
||
|
#else
|
||
|
data[0] = (uint8_t)val;
|
||
|
if (cnt == 1) {
|
||
|
return;
|
||
|
} else if (cnt == 2) {
|
||
|
data[1] = (uint8_t)(val >> 8);
|
||
|
} else {
|
||
|
data[1] = (uint8_t)(val >> 8);
|
||
|
data[2] = (uint8_t)(val >> 16);
|
||
|
data[3] = (uint8_t)(val >> 24);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int hal_spi_init_ctrl(const struct HAL_SPI_CFG_T *cfg, struct HAL_SPI_CTRL_T *ctrl)
|
||
|
{
|
||
|
uint32_t div;
|
||
|
uint16_t cpsdvsr, scr;
|
||
|
uint32_t mod_clk;
|
||
|
|
||
|
#ifdef SPI_ROM_ONLY
|
||
|
// Assume default crystal -- Never access global versatile data to ensure reentrance
|
||
|
mod_clk = HAL_CMU_DEFAULT_CRYSTAL_FREQ;
|
||
|
#else // !SPI_ROM_ONLY
|
||
|
mod_clk = 0;
|
||
|
#ifdef PERIPH_PLL_FREQ
|
||
|
if (PERIPH_PLL_FREQ / 2 > 2 * hal_cmu_get_crystal_freq()) {
|
||
|
// Init to OSC_X2
|
||
|
mod_clk = 2 * hal_cmu_get_crystal_freq();
|
||
|
if (cfg->rate * 2 > mod_clk) {
|
||
|
mod_clk = PERIPH_PLL_FREQ / 2;
|
||
|
ctrl->clk_sel = HAL_SPI_MOD_CLK_SEL_PLL;
|
||
|
} else {
|
||
|
mod_clk = 0;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
if (mod_clk == 0) {
|
||
|
// Init to OSC
|
||
|
mod_clk = hal_cmu_get_crystal_freq();
|
||
|
if (cfg->rate * 2 > mod_clk) {
|
||
|
mod_clk *= 2;
|
||
|
ctrl->clk_sel = HAL_SPI_MOD_CLK_SEL_OSC_X2;
|
||
|
} else {
|
||
|
ctrl->clk_sel = HAL_SPI_MOD_CLK_SEL_OSC;
|
||
|
}
|
||
|
}
|
||
|
#endif // !SPI_ROM_ONLY
|
||
|
|
||
|
SPI_ASSERT(cfg->rate <= mod_clk / (MIN_CPSDVSR * (1 + MIN_SCR)), "SPI rate too large: %u", cfg->rate);
|
||
|
SPI_ASSERT(cfg->rate >= mod_clk / (MAX_CPSDVSR * (1 + MAX_SCR)), "SPI rate too small: %u", cfg->rate);
|
||
|
SPI_ASSERT(cfg->tx_bits <= MAX_DATA_BITS && cfg->tx_bits >= MIN_DATA_BITS, "Invalid SPI TX bits: %d", cfg->tx_bits);
|
||
|
SPI_ASSERT(cfg->rx_bits <= MAX_DATA_BITS && cfg->rx_bits >= MIN_DATA_BITS, "Invalid SPI RX bits: %d", cfg->rx_bits);
|
||
|
SPI_ASSERT(cfg->rx_frame_bits <= MAX_DATA_BITS && (cfg->rx_frame_bits == 0 || cfg->rx_frame_bits > cfg->rx_bits),
|
||
|
"Invalid SPI RX FRAME bits: %d", cfg->rx_frame_bits);
|
||
|
SPI_ASSERT(cfg->cs < HAL_SPI_CS_QTY, "SPI cs bad: %d", cfg->cs);
|
||
|
|
||
|
div = (mod_clk + cfg->rate - 1) / cfg->rate;
|
||
|
cpsdvsr = (div + MAX_SCR) / (MAX_SCR + 1);
|
||
|
if (cpsdvsr < 2) {
|
||
|
cpsdvsr = 2;
|
||
|
} else {
|
||
|
if (cpsdvsr & 0x1) {
|
||
|
cpsdvsr += 1;
|
||
|
}
|
||
|
if (cpsdvsr > MAX_CPSDVSR) {
|
||
|
cpsdvsr = MAX_CPSDVSR;
|
||
|
}
|
||
|
}
|
||
|
scr = (div + cpsdvsr - 1) / cpsdvsr;
|
||
|
if (scr > 0) {
|
||
|
scr -= 1;
|
||
|
}
|
||
|
if (scr > MAX_SCR) {
|
||
|
scr = MAX_SCR;
|
||
|
}
|
||
|
|
||
|
ctrl->sspcr0_tx = SPI_SSPCR0_SCR(scr) |
|
||
|
(cfg->clk_delay_half ? SPI_SSPCR0_SPH : 0) |
|
||
|
(cfg->clk_polarity ? SPI_SSPCR0_SPO : 0) |
|
||
|
SPI_SSPCR0_FRF(0) | // Only support Motorola SPI frame format
|
||
|
SPI_SSPCR0_DSS(cfg->tx_bits - 1);
|
||
|
ctrl->sspcr1 = (cfg->rx_sep_line ? SPI_RX_SEL_EN : 0) |
|
||
|
SPI_SLAVE_ID(cfg->cs) |
|
||
|
SPI_SSPCR1_SOD |
|
||
|
(cfg->slave ? SPI_SSPCR1_MS : 0) |
|
||
|
SPI_SSPCR1_SSE;
|
||
|
ctrl->sspcpsr = SPI_SSPCPSR_CPSDVSR(cpsdvsr);
|
||
|
ctrl->sspdmacr = (cfg->dma_tx ? SPI_SSPDMACR_TXDMAE : 0) |
|
||
|
(cfg->dma_rx ? SPI_SSPDMACR_RXDMAE : 0);
|
||
|
ctrl->ssprxcr_tx = 0;
|
||
|
if (cfg->rx_frame_bits > 0) {
|
||
|
ctrl->sspcr0_rx = SET_BITFIELD(ctrl->sspcr0_tx, SPI_SSPCR0_DSS, cfg->rx_frame_bits - 1);
|
||
|
ctrl->ssprxcr_rx = SPI_SSPRXCR_EN | SPI_SSPRXCR_OEN_POLARITY | SPI_SSPRXCR_RXBITS(cfg->rx_bits - 1);
|
||
|
} else {
|
||
|
ctrl->sspcr0_rx = SET_BITFIELD(ctrl->sspcr0_tx, SPI_SSPCR0_DSS, cfg->rx_bits - 1);
|
||
|
ctrl->ssprxcr_rx = 0;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void NOINLINE POSSIBLY_UNUSED hal_spi_set_xfer_type_id(enum HAL_SPI_ID_T id, const struct HAL_SPI_CTRL_T *ctrl, enum HAL_SPI_XFER_TYPE_T type)
|
||
|
{
|
||
|
uint32_t sspcr0;
|
||
|
uint32_t ssprxcr;
|
||
|
|
||
|
if (type == HAL_SPI_XFER_TYPE_SEND) {
|
||
|
sspcr0 = ctrl->sspcr0_tx;
|
||
|
ssprxcr = ctrl->ssprxcr_tx;
|
||
|
} else {
|
||
|
sspcr0 = ctrl->sspcr0_rx;
|
||
|
ssprxcr = ctrl->ssprxcr_rx;
|
||
|
}
|
||
|
|
||
|
spi[id]->SSPCR0 = sspcr0;
|
||
|
spi[id]->SSPRXCR = ssprxcr;
|
||
|
}
|
||
|
|
||
|
static void NOINLINE hal_spi_enable_id(enum HAL_SPI_ID_T id, const struct HAL_SPI_CTRL_T *ctrl, enum HAL_SPI_XFER_TYPE_T type)
|
||
|
{
|
||
|
hal_spi_set_xfer_type_id(id, ctrl, type);
|
||
|
|
||
|
spi[id]->SSPCR1 = ctrl->sspcr1;
|
||
|
spi[id]->SSPCPSR = ctrl->sspcpsr;
|
||
|
spi[id]->SSPDMACR = ctrl->sspdmacr;
|
||
|
|
||
|
#ifdef SPI_ROM_ONLY
|
||
|
if (id == HAL_SPI_ID_INTERNAL) {
|
||
|
hal_cmu_ispi_set_freq(HAL_CMU_PERIPH_FREQ_26M);
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
} else if (id == HAL_SPI_ID_0) {
|
||
|
hal_cmu_spi_set_freq(HAL_CMU_PERIPH_FREQ_26M);
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
} else if (id == HAL_SPI_ID_SLCD) {
|
||
|
hal_cmu_slcd_set_freq(HAL_CMU_PERIPH_FREQ_26M);
|
||
|
#endif
|
||
|
}
|
||
|
#else // !SPI_ROM_ONLY
|
||
|
if (clk_sel[id] != ctrl->clk_sel) {
|
||
|
clk_sel[id] = ctrl->clk_sel;
|
||
|
if (ctrl->clk_sel == HAL_SPI_MOD_CLK_SEL_PLL) {
|
||
|
#ifdef PERIPH_PLL_FREQ
|
||
|
if (0) {
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
} else if (id == HAL_SPI_ID_0) {
|
||
|
hal_cmu_spi_set_div(2);
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
} else if (id == HAL_SPI_ID_SLCD) {
|
||
|
hal_cmu_slcd_set_div(2);
|
||
|
#endif
|
||
|
}
|
||
|
// ISPI cannot use PLL clock
|
||
|
#endif
|
||
|
} else {
|
||
|
enum HAL_CMU_PERIPH_FREQ_T periph_freq;
|
||
|
|
||
|
if (ctrl->clk_sel == HAL_SPI_MOD_CLK_SEL_OSC_X2) {
|
||
|
periph_freq = HAL_CMU_PERIPH_FREQ_52M;
|
||
|
} else {
|
||
|
periph_freq = HAL_CMU_PERIPH_FREQ_26M;
|
||
|
}
|
||
|
|
||
|
if (id == HAL_SPI_ID_INTERNAL) {
|
||
|
hal_cmu_ispi_set_freq(periph_freq);
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
} else if (id == HAL_SPI_ID_0) {
|
||
|
hal_cmu_spi_set_freq(periph_freq);
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
} else if (id == HAL_SPI_ID_SLCD) {
|
||
|
hal_cmu_slcd_set_freq(periph_freq);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif // !SPI_ROM_ONLY
|
||
|
}
|
||
|
|
||
|
static void hal_spi_disable_id(enum HAL_SPI_ID_T id)
|
||
|
{
|
||
|
spi[id]->SSPCR1 &= ~SPI_SSPCR1_SSE;
|
||
|
}
|
||
|
|
||
|
static void POSSIBLY_UNUSED hal_spi_get_ctrl_id(enum HAL_SPI_ID_T id, struct HAL_SPI_CTRL_T *ctrl)
|
||
|
{
|
||
|
ctrl->sspcr0_tx = spi[id]->SSPCR0;
|
||
|
ctrl->sspcr1 = spi[id]->SSPCR1;
|
||
|
ctrl->sspcpsr = spi[id]->SSPCPSR;
|
||
|
ctrl->sspdmacr = spi[id]->SSPDMACR;
|
||
|
ctrl->ssprxcr_tx = spi[id]->SSPRXCR;
|
||
|
}
|
||
|
|
||
|
static int NOINLINE hal_spi_open_id(enum HAL_SPI_ID_T id, const struct HAL_SPI_CFG_T *cfg, struct HAL_SPI_CTRL_T *ctrl)
|
||
|
{
|
||
|
int ret;
|
||
|
struct HAL_SPI_CTRL_T ctrl_regs;
|
||
|
bool cfg_clk = true;
|
||
|
|
||
|
//SPI_ASSERT(id < HAL_SPI_ID_QTY, invalid_id, id);
|
||
|
|
||
|
if (ctrl == NULL) {
|
||
|
ctrl = &ctrl_regs;
|
||
|
}
|
||
|
|
||
|
ret = hal_spi_init_ctrl(cfg, ctrl);
|
||
|
if (ret) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
#ifndef SPI_ROM_ONLY
|
||
|
if (!spi_init_done) {
|
||
|
spi_init_done = true;
|
||
|
for (int i = HAL_SPI_ID_INTERNAL; i < HAL_SPI_ID_QTY; i++) {
|
||
|
spi_txdma_chan[i] = HAL_DMA_CHAN_NONE;
|
||
|
spi_rxdma_chan[i] = HAL_DMA_CHAN_NONE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (spi_cs_map[id]) {
|
||
|
cfg_clk = false;
|
||
|
}
|
||
|
spi_cs_map[id] |= (1 << cfg->cs);
|
||
|
#endif
|
||
|
|
||
|
if (cfg_clk) {
|
||
|
hal_cmu_clock_enable(spi_mod[id].mod);
|
||
|
hal_cmu_clock_enable(spi_mod[id].apb);
|
||
|
hal_cmu_reset_clear(spi_mod[id].mod);
|
||
|
hal_cmu_reset_clear(spi_mod[id].apb);
|
||
|
}
|
||
|
|
||
|
hal_spi_enable_id(id, ctrl, HAL_SPI_XFER_TYPE_SEND);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int POSSIBLY_UNUSED hal_spi_close_id(enum HAL_SPI_ID_T id, uint32_t cs)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
bool cfg_clk = true;
|
||
|
|
||
|
#ifndef SPI_ROM_ONLY
|
||
|
if (spi_cs_map[id] & (1 << cs)) {
|
||
|
spi_cs_map[id] &= ~(1 << cs);
|
||
|
#if (CHIP_SPI_VER >= 2)
|
||
|
if (spi_cs_map[id]) {
|
||
|
cfg_clk = false;
|
||
|
}
|
||
|
#endif
|
||
|
} else {
|
||
|
ret = 1;
|
||
|
cfg_clk = false;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (cfg_clk) {
|
||
|
hal_spi_disable_id(id);
|
||
|
|
||
|
hal_cmu_reset_set(spi_mod[id].apb);
|
||
|
hal_cmu_reset_set(spi_mod[id].mod);
|
||
|
hal_cmu_clock_disable(spi_mod[id].apb);
|
||
|
hal_cmu_clock_disable(spi_mod[id].mod);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static void POSSIBLY_UNUSED hal_spi_set_cs_id(enum HAL_SPI_ID_T id, uint32_t cs)
|
||
|
{
|
||
|
spi[id]->SSPCR1 = SET_BITFIELD(spi[id]->SSPCR1, SPI_SLAVE_ID, cs);
|
||
|
}
|
||
|
|
||
|
static bool hal_spi_busy_id(enum HAL_SPI_ID_T id)
|
||
|
{
|
||
|
return ((spi[id]->SSPCR1 & SPI_SSPCR1_SSE) && (spi[id]->SSPSR & SPI_SSPSR_BSY));
|
||
|
}
|
||
|
|
||
|
static void hal_spi_enable_slave_output_id(enum HAL_SPI_ID_T id)
|
||
|
{
|
||
|
if (spi[id]->SSPCR1 & SPI_SSPCR1_MS) {
|
||
|
spi[id]->SSPCR1 &= ~SPI_SSPCR1_SOD;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void hal_spi_disable_slave_output_id(enum HAL_SPI_ID_T id)
|
||
|
{
|
||
|
if (spi[id]->SSPCR1 & SPI_SSPCR1_MS) {
|
||
|
spi[id]->SSPCR1 |= SPI_SSPCR1_SOD;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int hal_spi_send_id(enum HAL_SPI_ID_T id, const void *data, uint32_t len)
|
||
|
{
|
||
|
uint8_t cnt;
|
||
|
uint32_t sent, value;
|
||
|
int ret;
|
||
|
|
||
|
//SPI_ASSERT(id < HAL_SPI_ID_QTY, invalid_id, id);
|
||
|
SPI_ASSERT((spi[id]->SSPDMACR & SPI_SSPDMACR_TXDMAE) == 0, "TX-DMA configured on SPI %d", id);
|
||
|
|
||
|
cnt = get_frame_bytes(id);
|
||
|
|
||
|
if (len == 0 || (len & (cnt - 1)) != 0) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
sent = 0;
|
||
|
|
||
|
hal_spi_enable_slave_output_id(id);
|
||
|
|
||
|
while (sent < len) {
|
||
|
if ((spi[id]->SSPCR1 & SPI_SSPCR1_SSE) == 0) {
|
||
|
break;
|
||
|
}
|
||
|
if (spi[id]->SSPSR & SPI_SSPSR_TNF) {
|
||
|
value = 0;
|
||
|
copy_frame_from_bytes(&value, (uint8_t *)data + sent, cnt);
|
||
|
spi[id]->SSPDR = value;
|
||
|
sent += cnt;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (sent >= len) {
|
||
|
ret = 0;
|
||
|
} else {
|
||
|
ret = 1;
|
||
|
}
|
||
|
|
||
|
while (hal_spi_busy_id(id));
|
||
|
hal_spi_disable_slave_output_id(id);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static int hal_spi_recv_id(enum HAL_SPI_ID_T id, const void *cmd, void *data, uint32_t len)
|
||
|
{
|
||
|
uint8_t cnt;
|
||
|
uint32_t sent, recv, value;
|
||
|
int ret;
|
||
|
|
||
|
//SPI_ASSERT(id < HAL_SPI_ID_QTY, invalid_id, id);
|
||
|
SPI_ASSERT((spi[id]->SSPDMACR & (SPI_SSPDMACR_TXDMAE | SPI_SSPDMACR_RXDMAE)) == 0, "RX/TX-DMA configured on SPI %d", id);
|
||
|
|
||
|
cnt = get_frame_bytes(id);
|
||
|
|
||
|
if (len == 0 || (len & (cnt - 1)) != 0) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// Rx transaction should start from idle state
|
||
|
if (spi[id]->SSPSR & SPI_SSPSR_BSY) {
|
||
|
return -11;
|
||
|
}
|
||
|
|
||
|
sent = 0;
|
||
|
recv = 0;
|
||
|
|
||
|
// Flush the RX FIFO by reset or CPU read
|
||
|
while (spi[id]->SSPSR & SPI_SSPSR_RNE) {
|
||
|
spi[id]->SSPDR;
|
||
|
}
|
||
|
spi[id]->SSPICR = ~0UL;
|
||
|
|
||
|
hal_spi_enable_slave_output_id(id);
|
||
|
|
||
|
while (recv < len || sent < len) {
|
||
|
if ((spi[id]->SSPCR1 & SPI_SSPCR1_SSE) == 0) {
|
||
|
break;
|
||
|
}
|
||
|
if (sent < len && (spi[id]->SSPSR & SPI_SSPSR_TNF)) {
|
||
|
value = 0;
|
||
|
copy_frame_from_bytes(&value, (uint8_t *)cmd + sent, cnt);
|
||
|
spi[id]->SSPDR = value;
|
||
|
sent += cnt;
|
||
|
}
|
||
|
if (recv < len && (spi[id]->SSPSR & SPI_SSPSR_RNE)) {
|
||
|
value = spi[id]->SSPDR;
|
||
|
copy_bytes_from_frame((uint8_t *)data + recv, value, cnt);
|
||
|
recv += cnt;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (recv >= len && sent >= len) {
|
||
|
ret = 0;
|
||
|
} else {
|
||
|
ret = 1;
|
||
|
}
|
||
|
|
||
|
while (hal_spi_busy_id(id));
|
||
|
hal_spi_disable_slave_output_id(id);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
#ifdef SPI_ROM_ONLY
|
||
|
|
||
|
//------------------------------------------------------------
|
||
|
// ISPI ROM functions
|
||
|
//------------------------------------------------------------
|
||
|
|
||
|
int hal_ispi_rom_open(const struct HAL_SPI_CFG_T *cfg)
|
||
|
{
|
||
|
SPI_ASSERT(cfg->tx_bits == cfg->rx_bits && cfg->rx_frame_bits == 0, "ISPI_ROM: Bad bits cfg");
|
||
|
|
||
|
return hal_spi_open_id(HAL_SPI_ID_INTERNAL, cfg, NULL);
|
||
|
}
|
||
|
|
||
|
void hal_ispi_rom_activate_cs(uint32_t cs)
|
||
|
{
|
||
|
SPI_ASSERT(cs < HAL_SPI_CS_QTY, "ISPI_ROM: SPI cs bad: %d", cs);
|
||
|
|
||
|
hal_spi_set_cs_id(HAL_SPI_ID_INTERNAL, cs);
|
||
|
}
|
||
|
|
||
|
int hal_ispi_rom_busy(void)
|
||
|
{
|
||
|
return hal_spi_busy_id(HAL_SPI_ID_INTERNAL);
|
||
|
}
|
||
|
|
||
|
int hal_ispi_rom_send(const void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = hal_spi_send_id(HAL_SPI_ID_INTERNAL, data, len);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_ispi_rom_recv(const void *cmd, void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = hal_spi_recv_id(HAL_SPI_ID_INTERNAL, cmd, data, len);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
#ifdef CHIP_HAS_SPIPHY
|
||
|
//------------------------------------------------------------
|
||
|
// SPI PHY ROM functions
|
||
|
//------------------------------------------------------------
|
||
|
|
||
|
int hal_spiphy_rom_open(const struct HAL_SPI_CFG_T *cfg)
|
||
|
{
|
||
|
SPI_ASSERT(cfg->tx_bits == cfg->rx_bits && cfg->rx_frame_bits == 0, "SPIPHY_ROM: Bad bits cfg");
|
||
|
|
||
|
return hal_spi_open_id(HAL_SPI_ID_PHY, cfg, NULL);
|
||
|
}
|
||
|
|
||
|
int hal_spiphy_rom_busy(void)
|
||
|
{
|
||
|
return hal_spi_busy_id(HAL_SPI_ID_PHY);
|
||
|
}
|
||
|
|
||
|
int hal_spiphy_rom_send(const void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = hal_spi_send_id(HAL_SPI_ID_PHY, data, len);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_spiphy_rom_recv(const void *cmd, void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = hal_spi_recv_id(HAL_SPI_ID_PHY, cmd, data, len);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#else // !SPI_ROM_ONLY
|
||
|
|
||
|
static int hal_spi_activate_cs_id(enum HAL_SPI_ID_T id, uint32_t cs)
|
||
|
{
|
||
|
struct HAL_SPI_CTRL_T *ctrl = NULL;
|
||
|
|
||
|
SPI_ASSERT(cs < HAL_SPI_CS_QTY, "SPI cs bad: %d", cs);
|
||
|
SPI_ASSERT(spi_cs_map[id] & (1 << cs), "SPI cs not opened: %d", cs);
|
||
|
|
||
|
#if (CHIP_SPI_VER >= 2)
|
||
|
if (0) {
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
} else if (id == HAL_SPI_ID_0) {
|
||
|
spi0_cs = cs;
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
} else if (id == HAL_SPI_ID_SLCD) {
|
||
|
spilcd_cs = cs;
|
||
|
#endif
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (0) {
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
} else if (id == HAL_SPI_ID_0) {
|
||
|
ctrl = &spi0_ctrl[spi0_cs];
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
} else if (id == HAL_SPI_ID_SLCD) {
|
||
|
ctrl = &spilcd_ctrl[spilcd_cs];
|
||
|
#endif
|
||
|
}
|
||
|
if (ctrl) {
|
||
|
hal_spi_enable_id(id, ctrl, HAL_SPI_XFER_TYPE_SEND);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int POSSIBLY_UNUSED hal_spi_enable_and_send_id(enum HAL_SPI_ID_T id, const struct HAL_SPI_CTRL_T *ctrl, const void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
struct HAL_SPI_CTRL_T saved;
|
||
|
|
||
|
//SPI_ASSERT(id < HAL_SPI_ID_QTY, invalid_id, id);
|
||
|
|
||
|
if (set_bool_flag(&in_use[id])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
hal_spi_get_ctrl_id(id, &saved);
|
||
|
hal_spi_enable_id(id, ctrl, HAL_SPI_XFER_TYPE_SEND);
|
||
|
ret = hal_spi_send_id(id, data, len);
|
||
|
hal_spi_enable_id(id, &saved, HAL_SPI_XFER_TYPE_SEND);
|
||
|
|
||
|
clear_bool_flag(&in_use[id]);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static int POSSIBLY_UNUSED hal_spi_enable_and_recv_id(enum HAL_SPI_ID_T id, const struct HAL_SPI_CTRL_T *ctrl, const void *cmd, void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
struct HAL_SPI_CTRL_T saved;
|
||
|
|
||
|
if (set_bool_flag(&in_use[id])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
hal_spi_get_ctrl_id(id, &saved);
|
||
|
hal_spi_enable_id(id, ctrl, HAL_SPI_XFER_TYPE_RECV);
|
||
|
ret = hal_spi_recv_id(id, cmd, data, len);
|
||
|
hal_spi_enable_id(id, &saved, HAL_SPI_XFER_TYPE_SEND);
|
||
|
|
||
|
clear_bool_flag(&in_use[id]);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static void hal_spi_txdma_handler(uint8_t chan, uint32_t remains, uint32_t error, struct HAL_DMA_DESC_T *lli)
|
||
|
{
|
||
|
enum HAL_SPI_ID_T id;
|
||
|
uint32_t lock;
|
||
|
|
||
|
lock = int_lock();
|
||
|
for (id = HAL_SPI_ID_INTERNAL; id < HAL_SPI_ID_QTY; id++) {
|
||
|
if (spi_txdma_chan[id] == chan) {
|
||
|
spi_txdma_chan[id] = HAL_DMA_CHAN_NONE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
int_unlock(lock);
|
||
|
|
||
|
if (id >= HAL_SPI_ID_QTY) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
hal_gpdma_free_chan(chan);
|
||
|
|
||
|
clear_bool_flag(&in_use[id]);
|
||
|
|
||
|
if (spi_txdma_handler[id]) {
|
||
|
spi_txdma_handler[id](error);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int hal_spi_dma_send_id(enum HAL_SPI_ID_T id, const void *data, uint32_t len, HAL_SPI_DMA_HANDLER_T handler)
|
||
|
{
|
||
|
uint8_t cnt;
|
||
|
enum HAL_DMA_RET_T ret;
|
||
|
struct HAL_DMA_CH_CFG_T dma_cfg;
|
||
|
enum HAL_DMA_WDITH_T dma_width;
|
||
|
uint32_t lock;
|
||
|
enum HAL_DMA_PERIPH_T dst_periph;
|
||
|
|
||
|
//SPI_ASSERT(id < HAL_SPI_ID_QTY, invalid_id, id);
|
||
|
SPI_ASSERT((spi[id]->SSPDMACR & SPI_SSPDMACR_TXDMAE), "TX-DMA not configured on SPI %d", id);
|
||
|
|
||
|
spi_txdma_handler[id] = handler;
|
||
|
|
||
|
cnt = get_frame_bytes(id);
|
||
|
|
||
|
if ((len & (cnt - 1)) != 0) {
|
||
|
return -1;
|
||
|
}
|
||
|
if (((uint32_t)data & (cnt - 1)) != 0) {
|
||
|
return -2;
|
||
|
}
|
||
|
|
||
|
// Tx transaction should start from idle state for SPI mode 1 and 3 (SPH=1)
|
||
|
if ((spi[id]->SSPCR0 & SPI_SSPCR0_SPH) && (spi[id]->SSPSR & SPI_SSPSR_BSY)) {
|
||
|
return -11;
|
||
|
}
|
||
|
|
||
|
if (id == HAL_SPI_ID_INTERNAL) {
|
||
|
dst_periph = HAL_GPDMA_ISPI_TX;
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
} else if (id == HAL_SPI_ID_0) {
|
||
|
dst_periph = HAL_GPDMA_SPI_TX;
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
} else if (id == HAL_SPI_ID_SLCD) {
|
||
|
dst_periph = HAL_GPDMA_SPILCD_TX;
|
||
|
#endif
|
||
|
} else {
|
||
|
return -12;
|
||
|
}
|
||
|
|
||
|
lock = int_lock();
|
||
|
if (spi_txdma_chan[id] != HAL_DMA_CHAN_NONE) {
|
||
|
int_unlock(lock);
|
||
|
return -3;
|
||
|
}
|
||
|
spi_txdma_chan[id] = hal_gpdma_get_chan(dst_periph, HAL_DMA_HIGH_PRIO);
|
||
|
if (spi_txdma_chan[id] == HAL_DMA_CHAN_NONE) {
|
||
|
int_unlock(lock);
|
||
|
return -4;
|
||
|
}
|
||
|
int_unlock(lock);
|
||
|
|
||
|
if (cnt == 1) {
|
||
|
dma_width = HAL_DMA_WIDTH_BYTE;
|
||
|
} else if (cnt == 2) {
|
||
|
dma_width = HAL_DMA_WIDTH_HALFWORD;
|
||
|
} else {
|
||
|
dma_width = HAL_DMA_WIDTH_WORD;
|
||
|
}
|
||
|
|
||
|
memset(&dma_cfg, 0, sizeof(dma_cfg));
|
||
|
dma_cfg.ch = spi_txdma_chan[id];
|
||
|
dma_cfg.dst = 0; // useless
|
||
|
dma_cfg.dst_bsize = HAL_DMA_BSIZE_4;
|
||
|
dma_cfg.dst_periph = dst_periph;
|
||
|
dma_cfg.dst_width = dma_width;
|
||
|
dma_cfg.handler = handler ? hal_spi_txdma_handler : NULL;
|
||
|
dma_cfg.src = (uint32_t)data;
|
||
|
dma_cfg.src_bsize = HAL_DMA_BSIZE_16;
|
||
|
//dma_cfg.src_periph = HAL_GPDMA_PERIPH_QTY; // useless
|
||
|
dma_cfg.src_tsize = len / cnt;
|
||
|
dma_cfg.src_width = dma_width;
|
||
|
dma_cfg.try_burst = 0;
|
||
|
dma_cfg.type = HAL_DMA_FLOW_M2P_DMA;
|
||
|
|
||
|
hal_spi_enable_slave_output_id(id);
|
||
|
|
||
|
ret = hal_gpdma_start(&dma_cfg);
|
||
|
if (ret != HAL_DMA_OK) {
|
||
|
hal_spi_disable_slave_output_id(id);
|
||
|
return -5;
|
||
|
}
|
||
|
|
||
|
if (handler == NULL) {
|
||
|
while ((spi[id]->SSPCR1 & SPI_SSPCR1_SSE) && hal_gpdma_chan_busy(spi_txdma_chan[id]));
|
||
|
hal_gpdma_free_chan(spi_txdma_chan[id]);
|
||
|
spi_txdma_chan[id] = HAL_DMA_CHAN_NONE;
|
||
|
while (hal_spi_busy_id(id));
|
||
|
hal_spi_disable_slave_output_id(id);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void hal_spi_stop_dma_send_id(enum HAL_SPI_ID_T id)
|
||
|
{
|
||
|
uint32_t lock;
|
||
|
uint8_t tx_chan;
|
||
|
|
||
|
lock = int_lock();
|
||
|
tx_chan = spi_txdma_chan[id];
|
||
|
spi_txdma_chan[id] = HAL_DMA_CHAN_NONE;
|
||
|
int_unlock(lock);
|
||
|
|
||
|
if (tx_chan != HAL_DMA_CHAN_NONE) {
|
||
|
hal_gpdma_cancel(tx_chan);
|
||
|
hal_gpdma_free_chan(tx_chan);
|
||
|
}
|
||
|
|
||
|
clear_bool_flag(&in_use[id]);
|
||
|
}
|
||
|
|
||
|
static void hal_spi_rxdma_handler(uint8_t chan, uint32_t remains, uint32_t error, struct HAL_DMA_DESC_T *lli)
|
||
|
{
|
||
|
enum HAL_SPI_ID_T id;
|
||
|
uint32_t lock;
|
||
|
uint8_t tx_chan = HAL_DMA_CHAN_NONE;
|
||
|
struct HAL_SPI_CTRL_T *ctrl = NULL;
|
||
|
|
||
|
lock = int_lock();
|
||
|
for (id = HAL_SPI_ID_INTERNAL; id < HAL_SPI_ID_QTY; id++) {
|
||
|
if (spi_rxdma_chan[id] == chan) {
|
||
|
tx_chan = spi_txdma_chan[id];
|
||
|
spi_rxdma_chan[id] = HAL_DMA_CHAN_NONE;
|
||
|
spi_txdma_chan[id] = HAL_DMA_CHAN_NONE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
int_unlock(lock);
|
||
|
|
||
|
if (id >= HAL_SPI_ID_QTY) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
hal_gpdma_free_chan(chan);
|
||
|
hal_gpdma_cancel(tx_chan);
|
||
|
hal_gpdma_free_chan(tx_chan);
|
||
|
|
||
|
if (0) {
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
} else if (id == HAL_SPI_ID_0) {
|
||
|
ctrl = &spi0_ctrl[spi0_cs];
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
} else if (id == HAL_SPI_ID_SLCD) {
|
||
|
ctrl = &spilcd_ctrl[spilcd_cs];
|
||
|
#endif
|
||
|
}
|
||
|
if (ctrl) {
|
||
|
hal_spi_set_xfer_type_id(id, ctrl, HAL_SPI_XFER_TYPE_SEND);
|
||
|
}
|
||
|
clear_bool_flag(&in_use[id]);
|
||
|
|
||
|
if (spi_rxdma_handler[id]) {
|
||
|
spi_rxdma_handler[id](error);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int hal_spi_dma_recv_id(enum HAL_SPI_ID_T id, const void *cmd, void *data, uint32_t len, HAL_SPI_DMA_HANDLER_T handler)
|
||
|
{
|
||
|
uint8_t cnt;
|
||
|
enum HAL_DMA_RET_T ret;
|
||
|
struct HAL_DMA_CH_CFG_T dma_cfg;
|
||
|
enum HAL_DMA_WDITH_T dma_width;
|
||
|
uint32_t lock;
|
||
|
int result;
|
||
|
enum HAL_DMA_PERIPH_T dst_periph, src_periph;
|
||
|
struct HAL_SPI_CTRL_T *ctrl = NULL;
|
||
|
|
||
|
//SPI_ASSERT(id < HAL_SPI_ID_QTY, invalid_id, id);
|
||
|
SPI_ASSERT((spi[id]->SSPDMACR & (SPI_SSPDMACR_TXDMAE | SPI_SSPDMACR_RXDMAE)) ==
|
||
|
(SPI_SSPDMACR_TXDMAE | SPI_SSPDMACR_RXDMAE), "RX/TX-DMA not configured on SPI %d", id);
|
||
|
|
||
|
spi_rxdma_handler[id] = handler;
|
||
|
|
||
|
result = 0;
|
||
|
|
||
|
cnt = get_frame_bytes(id);
|
||
|
|
||
|
if ((len & (cnt - 1)) != 0) {
|
||
|
return -1;
|
||
|
}
|
||
|
if (((uint32_t)data & (cnt - 1)) != 0) {
|
||
|
return -2;
|
||
|
}
|
||
|
|
||
|
// Rx transaction should start from idle state
|
||
|
if (spi[id]->SSPSR & SPI_SSPSR_BSY) {
|
||
|
return -11;
|
||
|
}
|
||
|
|
||
|
if (id == HAL_SPI_ID_INTERNAL) {
|
||
|
src_periph = HAL_GPDMA_ISPI_RX;
|
||
|
dst_periph = HAL_GPDMA_ISPI_TX;
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
} else if (id == HAL_SPI_ID_0) {
|
||
|
src_periph = HAL_GPDMA_SPI_RX;
|
||
|
dst_periph = HAL_GPDMA_SPI_TX;
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
} else if (id == HAL_SPI_ID_SLCD) {
|
||
|
src_periph = HAL_GPDMA_SPILCD_RX;
|
||
|
dst_periph = HAL_GPDMA_SPILCD_TX;
|
||
|
#endif
|
||
|
} else {
|
||
|
return -12;
|
||
|
}
|
||
|
|
||
|
lock = int_lock();
|
||
|
if (spi_txdma_chan[id] != HAL_DMA_CHAN_NONE || spi_rxdma_chan[id] != HAL_DMA_CHAN_NONE) {
|
||
|
int_unlock(lock);
|
||
|
return -3;
|
||
|
}
|
||
|
spi_txdma_chan[id] = hal_gpdma_get_chan(dst_periph, HAL_DMA_HIGH_PRIO);
|
||
|
if (spi_txdma_chan[id] == HAL_DMA_CHAN_NONE) {
|
||
|
int_unlock(lock);
|
||
|
return -4;
|
||
|
}
|
||
|
spi_rxdma_chan[id] = hal_gpdma_get_chan(src_periph, HAL_DMA_HIGH_PRIO);
|
||
|
if (spi_rxdma_chan[id] == HAL_DMA_CHAN_NONE) {
|
||
|
hal_gpdma_free_chan(spi_txdma_chan[id]);
|
||
|
spi_txdma_chan[id] = HAL_DMA_CHAN_NONE;
|
||
|
int_unlock(lock);
|
||
|
return -5;
|
||
|
}
|
||
|
int_unlock(lock);
|
||
|
|
||
|
if (cnt == 1) {
|
||
|
dma_width = HAL_DMA_WIDTH_BYTE;
|
||
|
} else if (cnt == 2) {
|
||
|
dma_width = HAL_DMA_WIDTH_HALFWORD;
|
||
|
} else {
|
||
|
dma_width = HAL_DMA_WIDTH_WORD;
|
||
|
}
|
||
|
|
||
|
memset(&dma_cfg, 0, sizeof(dma_cfg));
|
||
|
dma_cfg.ch = spi_rxdma_chan[id];
|
||
|
dma_cfg.dst = (uint32_t)data;
|
||
|
dma_cfg.dst_bsize = HAL_DMA_BSIZE_16;
|
||
|
//dma_cfg.dst_periph = HAL_GPDMA_PERIPH_QTY; // useless
|
||
|
dma_cfg.dst_width = dma_width;
|
||
|
dma_cfg.handler = handler ? hal_spi_rxdma_handler : NULL;
|
||
|
dma_cfg.src = 0; // useless
|
||
|
dma_cfg.src_periph = src_periph;
|
||
|
dma_cfg.src_bsize = HAL_DMA_BSIZE_4;
|
||
|
dma_cfg.src_tsize = len / cnt;
|
||
|
dma_cfg.src_width = dma_width;
|
||
|
dma_cfg.try_burst = 0;
|
||
|
dma_cfg.type = HAL_DMA_FLOW_P2M_DMA;
|
||
|
|
||
|
// Flush the RX FIFO by reset or DMA read (CPU read is forbidden when DMA is enabled)
|
||
|
if (spi[id]->SSPSR & SPI_SSPSR_RNE) {
|
||
|
// Reset SPI MODULE might cause the increment of the FIFO pointer
|
||
|
hal_cmu_reset_pulse(spi_mod[id].mod);
|
||
|
// Reset SPI APB will reset the FIFO pointer
|
||
|
hal_cmu_reset_pulse(spi_mod[id].apb);
|
||
|
if (0) {
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
} else if (id == HAL_SPI_ID_0) {
|
||
|
ctrl = &spi0_ctrl[spi0_cs];
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
} else if (id == HAL_SPI_ID_SLCD) {
|
||
|
ctrl = &spilcd_ctrl[spilcd_cs];
|
||
|
#endif
|
||
|
}
|
||
|
if (ctrl) {
|
||
|
// hal_spi_set_xfer_type_id() is not enough, for all the registers have been reset by APB reset
|
||
|
hal_spi_enable_id(id, ctrl, HAL_SPI_XFER_TYPE_RECV);
|
||
|
}
|
||
|
}
|
||
|
spi[id]->SSPICR = ~0UL;
|
||
|
|
||
|
ret = hal_gpdma_start(&dma_cfg);
|
||
|
if (ret != HAL_DMA_OK) {
|
||
|
result = -8;
|
||
|
goto _exit;
|
||
|
}
|
||
|
|
||
|
dma_cfg.ch = spi_txdma_chan[id];
|
||
|
dma_cfg.dst = 0; // useless
|
||
|
dma_cfg.dst_bsize = HAL_DMA_BSIZE_4;
|
||
|
dma_cfg.dst_periph = dst_periph;
|
||
|
dma_cfg.dst_width = dma_width;
|
||
|
dma_cfg.handler = NULL;
|
||
|
dma_cfg.src = (uint32_t)cmd;
|
||
|
dma_cfg.src_bsize = HAL_DMA_BSIZE_16;
|
||
|
//dma_cfg.src_periph = HAL_GPDMA_PERIPH_QTY; // useless
|
||
|
dma_cfg.src_tsize = len / cnt;
|
||
|
dma_cfg.src_width = dma_width;
|
||
|
dma_cfg.try_burst = 0;
|
||
|
dma_cfg.type = HAL_DMA_FLOW_M2P_DMA;
|
||
|
|
||
|
hal_spi_enable_slave_output_id(id);
|
||
|
|
||
|
ret = hal_gpdma_start(&dma_cfg);
|
||
|
if (ret != HAL_DMA_OK) {
|
||
|
result = -9;
|
||
|
goto _exit;
|
||
|
}
|
||
|
|
||
|
if (handler == NULL) {
|
||
|
while ((spi[id]->SSPCR1 & SPI_SSPCR1_SSE) && hal_gpdma_chan_busy(spi_rxdma_chan[id]));
|
||
|
}
|
||
|
|
||
|
_exit:
|
||
|
if (result || handler == NULL) {
|
||
|
hal_gpdma_cancel(spi_txdma_chan[id]);
|
||
|
hal_gpdma_free_chan(spi_txdma_chan[id]);
|
||
|
spi_txdma_chan[id] = HAL_DMA_CHAN_NONE;
|
||
|
|
||
|
while (hal_spi_busy_id(id));
|
||
|
hal_spi_disable_slave_output_id(id);
|
||
|
|
||
|
hal_gpdma_cancel(spi_rxdma_chan[id]);
|
||
|
hal_gpdma_free_chan(spi_rxdma_chan[id]);
|
||
|
spi_rxdma_chan[id] = HAL_DMA_CHAN_NONE;
|
||
|
|
||
|
if (ctrl) {
|
||
|
hal_spi_set_xfer_type_id(id, ctrl, HAL_SPI_XFER_TYPE_SEND);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void hal_spi_stop_dma_recv_id(enum HAL_SPI_ID_T id)
|
||
|
{
|
||
|
uint32_t lock;
|
||
|
uint8_t rx_chan, tx_chan;
|
||
|
struct HAL_SPI_CTRL_T *ctrl = NULL;
|
||
|
|
||
|
lock = int_lock();
|
||
|
rx_chan = spi_rxdma_chan[id];
|
||
|
spi_rxdma_chan[id] = HAL_DMA_CHAN_NONE;
|
||
|
tx_chan = spi_txdma_chan[id];
|
||
|
spi_txdma_chan[id] = HAL_DMA_CHAN_NONE;
|
||
|
int_unlock(lock);
|
||
|
|
||
|
if (rx_chan == HAL_DMA_CHAN_NONE && tx_chan == HAL_DMA_CHAN_NONE) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (rx_chan != HAL_DMA_CHAN_NONE) {
|
||
|
hal_gpdma_cancel(rx_chan);
|
||
|
hal_gpdma_free_chan(rx_chan);
|
||
|
}
|
||
|
if (tx_chan != HAL_DMA_CHAN_NONE) {
|
||
|
hal_gpdma_cancel(tx_chan);
|
||
|
hal_gpdma_free_chan(tx_chan);
|
||
|
}
|
||
|
|
||
|
if (0) {
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
} else if (id == HAL_SPI_ID_0) {
|
||
|
ctrl = &spi0_ctrl[spi0_cs];
|
||
|
#endif
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
} else if (id == HAL_SPI_ID_SLCD) {
|
||
|
ctrl = &spilcd_ctrl[spilcd_cs];
|
||
|
#endif
|
||
|
}
|
||
|
if (ctrl) {
|
||
|
hal_spi_set_xfer_type_id(id, ctrl, HAL_SPI_XFER_TYPE_SEND);
|
||
|
}
|
||
|
clear_bool_flag(&in_use[id]);
|
||
|
}
|
||
|
|
||
|
//------------------------------------------------------------
|
||
|
// ISPI functions
|
||
|
//------------------------------------------------------------
|
||
|
|
||
|
int hal_ispi_open(const struct HAL_SPI_CFG_T *cfg)
|
||
|
{
|
||
|
SPI_ASSERT(cfg->tx_bits == cfg->rx_bits && cfg->rx_frame_bits == 0, "ISPI: Bad bits cfg");
|
||
|
|
||
|
return hal_spi_open_id(HAL_SPI_ID_INTERNAL, cfg, NULL);
|
||
|
}
|
||
|
|
||
|
int hal_ispi_close(uint32_t cs)
|
||
|
{
|
||
|
return hal_spi_close_id(HAL_SPI_ID_INTERNAL, cs);
|
||
|
}
|
||
|
|
||
|
void hal_ispi_activate_cs(uint32_t cs)
|
||
|
{
|
||
|
SPI_ASSERT(cs < HAL_SPI_CS_QTY, "ISPI: SPI cs bad: %d", cs);
|
||
|
|
||
|
hal_spi_set_cs_id(HAL_SPI_ID_INTERNAL, cs);
|
||
|
}
|
||
|
|
||
|
int hal_ispi_busy(void)
|
||
|
{
|
||
|
return hal_spi_busy_id(HAL_SPI_ID_INTERNAL);
|
||
|
}
|
||
|
|
||
|
int hal_ispi_send(const void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_INTERNAL])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
ret = hal_spi_send_id(HAL_SPI_ID_INTERNAL, data, len);
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_INTERNAL]);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_ispi_recv(const void *cmd, void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_INTERNAL])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
ret = hal_spi_recv_id(HAL_SPI_ID_INTERNAL, cmd, data, len);
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_INTERNAL]);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_ispi_dma_send(const void *data, uint32_t len, HAL_SPI_DMA_HANDLER_T handler)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_INTERNAL])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
ret = hal_spi_dma_send_id(HAL_SPI_ID_INTERNAL, data, len, handler);
|
||
|
|
||
|
if (ret || handler == NULL) {
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_INTERNAL]);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_ispi_dma_recv(const void *cmd, void *data, uint32_t len, HAL_SPI_DMA_HANDLER_T handler)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_INTERNAL])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
ret = hal_spi_dma_recv_id(HAL_SPI_ID_INTERNAL, cmd, data, len, handler);
|
||
|
|
||
|
if (ret || handler == NULL) {
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_INTERNAL]);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void hal_ispi_stop_dma_send(void)
|
||
|
{
|
||
|
hal_spi_stop_dma_send_id(HAL_SPI_ID_INTERNAL);
|
||
|
}
|
||
|
|
||
|
void hal_ispi_stop_dma_recv(void)
|
||
|
{
|
||
|
hal_spi_stop_dma_recv_id(HAL_SPI_ID_INTERNAL);
|
||
|
}
|
||
|
|
||
|
#ifdef CHIP_HAS_SPI
|
||
|
//------------------------------------------------------------
|
||
|
// SPI peripheral functions
|
||
|
//------------------------------------------------------------
|
||
|
|
||
|
int hal_spi_open(const struct HAL_SPI_CFG_T *cfg)
|
||
|
{
|
||
|
int ret;
|
||
|
uint32_t lock;
|
||
|
|
||
|
if (cfg->cs >= HAL_SPI_CS_QTY) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
lock = int_lock();
|
||
|
|
||
|
ret = hal_spi_open_id(HAL_SPI_ID_0, cfg, &spi0_ctrl[cfg->cs]);
|
||
|
|
||
|
#if (CHIP_SPI_VER >= 2)
|
||
|
if (ret == 0) {
|
||
|
spi0_cs = cfg->cs;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
int_unlock(lock);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_spi_close(uint32_t cs)
|
||
|
{
|
||
|
int ret;
|
||
|
uint32_t lock;
|
||
|
|
||
|
lock = int_lock();
|
||
|
|
||
|
ret = hal_spi_close_id(HAL_SPI_ID_0, cs);
|
||
|
|
||
|
#if (CHIP_SPI_VER >= 2)
|
||
|
if (ret == 0 && spi0_cs == cs) {
|
||
|
uint32_t lowest_cs;
|
||
|
|
||
|
lowest_cs = __CLZ(__RBIT(spi_cs_map[HAL_SPI_ID_0]));
|
||
|
if (lowest_cs < HAL_SPI_CS_QTY) {
|
||
|
hal_spi_activate_cs_id(HAL_SPI_ID_0, lowest_cs);
|
||
|
} else {
|
||
|
lowest_cs = HAL_SPI_CS_0;
|
||
|
}
|
||
|
spi0_cs = lowest_cs;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
int_unlock(lock);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_spi_activate_cs(uint32_t cs)
|
||
|
{
|
||
|
return hal_spi_activate_cs_id(HAL_SPI_ID_0, cs);
|
||
|
}
|
||
|
|
||
|
int hal_spi_busy(void)
|
||
|
{
|
||
|
return hal_spi_busy_id(HAL_SPI_ID_0);
|
||
|
}
|
||
|
|
||
|
int hal_spi_send(const void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_0])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
ret = hal_spi_send_id(HAL_SPI_ID_0, data, len);
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_0]);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_spi_recv(const void *cmd, void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_0])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
hal_spi_set_xfer_type_id(HAL_SPI_ID_0, &spi0_ctrl[spi0_cs], HAL_SPI_XFER_TYPE_RECV);
|
||
|
ret = hal_spi_recv_id(HAL_SPI_ID_0, cmd, data, len);
|
||
|
hal_spi_set_xfer_type_id(HAL_SPI_ID_0, &spi0_ctrl[spi0_cs], HAL_SPI_XFER_TYPE_SEND);
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_0]);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_spi_dma_send(const void *data, uint32_t len, HAL_SPI_DMA_HANDLER_T handler)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_0])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
ret = hal_spi_dma_send_id(HAL_SPI_ID_0, data, len, handler);
|
||
|
|
||
|
if (ret || handler == NULL) {
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_0]);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_spi_dma_recv(const void *cmd, void *data, uint32_t len, HAL_SPI_DMA_HANDLER_T handler)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_0])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
hal_spi_set_xfer_type_id(HAL_SPI_ID_0, &spi0_ctrl[spi0_cs], HAL_SPI_XFER_TYPE_RECV);
|
||
|
|
||
|
ret = hal_spi_dma_recv_id(HAL_SPI_ID_0, cmd, data, len, handler);
|
||
|
|
||
|
if (ret || handler == NULL) {
|
||
|
hal_spi_set_xfer_type_id(HAL_SPI_ID_0, &spi0_ctrl[spi0_cs], HAL_SPI_XFER_TYPE_SEND);
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_0]);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void hal_spi_stop_dma_send(void)
|
||
|
{
|
||
|
hal_spi_stop_dma_send_id(HAL_SPI_ID_0);
|
||
|
}
|
||
|
|
||
|
void hal_spi_stop_dma_recv(void)
|
||
|
{
|
||
|
hal_spi_stop_dma_recv_id(HAL_SPI_ID_0);
|
||
|
}
|
||
|
|
||
|
int hal_spi_enable_and_send(const struct HAL_SPI_CTRL_T *ctrl, const void *data, uint32_t len)
|
||
|
{
|
||
|
return hal_spi_enable_and_send_id(HAL_SPI_ID_0, ctrl, data, len);
|
||
|
}
|
||
|
|
||
|
int hal_spi_enable_and_recv(const struct HAL_SPI_CTRL_T *ctrl, const void *cmd, void *data, uint32_t len)
|
||
|
{
|
||
|
return hal_spi_enable_and_recv_id(HAL_SPI_ID_0, ctrl, cmd, data, len);
|
||
|
}
|
||
|
#endif // CHIP_HAS_SPI
|
||
|
|
||
|
#ifdef CHIP_HAS_SPILCD
|
||
|
//------------------------------------------------------------
|
||
|
// SPI LCD functions
|
||
|
//------------------------------------------------------------
|
||
|
|
||
|
int hal_spilcd_open(const struct HAL_SPI_CFG_T *cfg)
|
||
|
{
|
||
|
int ret;
|
||
|
uint32_t lock;
|
||
|
|
||
|
if (cfg->cs >= HAL_SPI_CS_QTY) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
lock = int_lock();
|
||
|
|
||
|
ret = hal_spi_open_id(HAL_SPI_ID_SLCD, cfg, &spilcd_ctrl[cfg->cs]);
|
||
|
|
||
|
#if (CHIP_SPI_VER >= 2)
|
||
|
if (ret == 0) {
|
||
|
spilcd_cs = cfg->cs;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
int_unlock(lock);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_spilcd_close(uint32_t cs)
|
||
|
{
|
||
|
int ret;
|
||
|
uint32_t lock;
|
||
|
|
||
|
lock = int_lock();
|
||
|
|
||
|
ret = hal_spi_close_id(HAL_SPI_ID_SLCD, cs);
|
||
|
|
||
|
#if (CHIP_SPI_VER >= 2)
|
||
|
if (ret == 0 && spilcd_cs == cs) {
|
||
|
uint32_t lowest_cs;
|
||
|
|
||
|
lowest_cs = __CLZ(__RBIT(spi_cs_map[HAL_SPI_ID_SLCD]));
|
||
|
if (lowest_cs < HAL_SPI_CS_QTY) {
|
||
|
hal_spi_activate_cs_id(HAL_SPI_ID_SLCD, lowest_cs);
|
||
|
} else {
|
||
|
lowest_cs = HAL_SPI_CS_0;
|
||
|
}
|
||
|
spilcd_cs = lowest_cs;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
int_unlock(lock);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_spilcd_activate_cs(uint32_t cs)
|
||
|
{
|
||
|
return hal_spi_activate_cs_id(HAL_SPI_ID_SLCD, cs);
|
||
|
}
|
||
|
|
||
|
int hal_spilcd_busy(void)
|
||
|
{
|
||
|
return hal_spi_busy_id(HAL_SPI_ID_SLCD);
|
||
|
}
|
||
|
|
||
|
int hal_spilcd_send(const void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_SLCD])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
ret = hal_spi_send_id(HAL_SPI_ID_SLCD, data, len);
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_SLCD]);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_spilcd_recv(const void *cmd, void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_SLCD])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
hal_spi_set_xfer_type_id(HAL_SPI_ID_SLCD, &spilcd_ctrl[spilcd_cs], HAL_SPI_XFER_TYPE_RECV);
|
||
|
ret = hal_spi_recv_id(HAL_SPI_ID_SLCD, cmd, data, len);
|
||
|
hal_spi_set_xfer_type_id(HAL_SPI_ID_SLCD, &spilcd_ctrl[spilcd_cs], HAL_SPI_XFER_TYPE_SEND);
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_SLCD]);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_spilcd_dma_send(const void *data, uint32_t len, HAL_SPI_DMA_HANDLER_T handler)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_SLCD])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
ret = hal_spi_dma_send_id(HAL_SPI_ID_SLCD, data, len, handler);
|
||
|
|
||
|
if (ret || handler == NULL) {
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_SLCD]);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_spilcd_dma_recv(const void *cmd, void *data, uint32_t len, HAL_SPI_DMA_HANDLER_T handler)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_SLCD])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
hal_spi_set_xfer_type_id(HAL_SPI_ID_SLCD, &spilcd_ctrl[spilcd_cs], HAL_SPI_XFER_TYPE_RECV);
|
||
|
|
||
|
ret = hal_spi_dma_recv_id(HAL_SPI_ID_SLCD, cmd, data, len, handler);
|
||
|
|
||
|
if (ret || handler == NULL) {
|
||
|
hal_spi_set_xfer_type_id(HAL_SPI_ID_SLCD, &spilcd_ctrl[spilcd_cs], HAL_SPI_XFER_TYPE_SEND);
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_SLCD]);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void hal_spilcd_stop_dma_send(void)
|
||
|
{
|
||
|
hal_spi_stop_dma_send_id(HAL_SPI_ID_SLCD);
|
||
|
}
|
||
|
|
||
|
void hal_spilcd_stop_dma_recv(void)
|
||
|
{
|
||
|
hal_spi_stop_dma_recv_id(HAL_SPI_ID_SLCD);
|
||
|
}
|
||
|
|
||
|
int hal_spilcd_set_data_mode(void)
|
||
|
{
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_SLCD])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
spi[HAL_SPI_ID_SLCD]->SSPCR1 |= SPI_LCD_DC_DATA;
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_SLCD]);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int hal_spilcd_set_cmd_mode(void)
|
||
|
{
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_SLCD])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
spi[HAL_SPI_ID_SLCD]->SSPCR1 &= ~SPI_LCD_DC_DATA;
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_SLCD]);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int hal_spilcd_enable_and_send(const struct HAL_SPI_CTRL_T *ctrl, const void *data, uint32_t len)
|
||
|
{
|
||
|
return hal_spi_enable_and_send_id(HAL_SPI_ID_SLCD, ctrl, data, len);
|
||
|
}
|
||
|
|
||
|
int hal_spilcd_enable_and_recv(const struct HAL_SPI_CTRL_T *ctrl, const void *cmd, void *data, uint32_t len)
|
||
|
{
|
||
|
return hal_spi_enable_and_recv_id(HAL_SPI_ID_SLCD, ctrl, cmd, data, len);
|
||
|
}
|
||
|
#endif // CHIP_HAS_SPILCD
|
||
|
|
||
|
#ifdef CHIP_HAS_SPIPHY
|
||
|
//------------------------------------------------------------
|
||
|
// SPI PHY functions
|
||
|
//------------------------------------------------------------
|
||
|
|
||
|
int hal_spiphy_open(const struct HAL_SPI_CFG_T *cfg)
|
||
|
{
|
||
|
SPI_ASSERT(cfg->tx_bits == cfg->rx_bits && cfg->rx_frame_bits == 0, "SPIPHY: Bad bits cfg");
|
||
|
|
||
|
return hal_spi_open_id(HAL_SPI_ID_PHY, cfg, NULL);
|
||
|
}
|
||
|
|
||
|
int hal_spiphy_close(uint32_t cs)
|
||
|
{
|
||
|
return hal_spi_close_id(HAL_SPI_ID_PHY, cs);
|
||
|
}
|
||
|
|
||
|
void hal_spiphy_activate_cs(uint32_t cs)
|
||
|
{
|
||
|
SPI_ASSERT(cs < HAL_SPI_CS_QTY, "SPIPHY: SPI cs bad: %d", cs);
|
||
|
|
||
|
hal_spi_set_cs_id(HAL_SPI_ID_PHY, cs);
|
||
|
}
|
||
|
|
||
|
int hal_spiphy_busy(void)
|
||
|
{
|
||
|
return hal_spi_busy_id(HAL_SPI_ID_PHY);
|
||
|
}
|
||
|
|
||
|
int hal_spiphy_send(const void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_PHY])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
ret = hal_spi_send_id(HAL_SPI_ID_PHY, data, len);
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_PHY]);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_spiphy_recv(const void *cmd, void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_PHY])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
ret = hal_spi_recv_id(HAL_SPI_ID_PHY, cmd, data, len);
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_PHY]);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
#endif // CHIP_HAS_SPIPHY
|
||
|
|
||
|
#ifdef CHIP_HAS_SPIDPD
|
||
|
//------------------------------------------------------------
|
||
|
// SPI DPD functions
|
||
|
//------------------------------------------------------------
|
||
|
|
||
|
int hal_spidpd_open(const struct HAL_SPI_CFG_T *cfg)
|
||
|
{
|
||
|
SPI_ASSERT(cfg->rx_frame_bits == 0, "SPIDPD: Bad bits cfg");
|
||
|
|
||
|
return hal_spi_open_id(HAL_SPI_ID_DPD, cfg, &spidpd_ctrl);
|
||
|
}
|
||
|
|
||
|
int hal_spidpd_close(uint32_t cs)
|
||
|
{
|
||
|
return hal_spi_close_id(HAL_SPI_ID_DPD, cs);
|
||
|
}
|
||
|
|
||
|
void hal_spidpd_activate_cs(uint32_t cs)
|
||
|
{
|
||
|
SPI_ASSERT(cs < HAL_SPI_CS_QTY, "SPIDPD: SPI cs bad: %d", cs);
|
||
|
|
||
|
hal_spi_set_cs_id(HAL_SPI_ID_DPD, cs);
|
||
|
}
|
||
|
|
||
|
int hal_spidpd_busy(void)
|
||
|
{
|
||
|
return hal_spi_busy_id(HAL_SPI_ID_DPD);
|
||
|
}
|
||
|
|
||
|
int hal_spidpd_send(const void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_DPD])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
ret = hal_spi_send_id(HAL_SPI_ID_DPD, data, len);
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_DPD]);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int hal_spidpd_recv(const void *cmd, void *data, uint32_t len)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
if (set_bool_flag(&in_use[HAL_SPI_ID_DPD])) {
|
||
|
return -31;
|
||
|
}
|
||
|
|
||
|
hal_spi_set_xfer_type_id(HAL_SPI_ID_DPD, &spidpd_ctrl, HAL_SPI_XFER_TYPE_RECV);
|
||
|
ret = hal_spi_recv_id(HAL_SPI_ID_DPD, cmd, data, len);
|
||
|
hal_spi_set_xfer_type_id(HAL_SPI_ID_DPD, &spidpd_ctrl, HAL_SPI_XFER_TYPE_SEND);
|
||
|
|
||
|
clear_bool_flag(&in_use[HAL_SPI_ID_DPD]);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
#endif // CHIP_HAS_SPIDPD
|
||
|
|
||
|
#endif // !SPI_ROM_ONLY
|
||
|
|