in hw/mcu/arc/src/ext/sdk/device/designware/spi/dw_spi.c [951:1182]
int32_t dw_spi_control (DEV_SPI *spi_obj, uint32_t ctrl_cmd, void *param)
{
int32_t ercd = E_OK;
DEV_SPI_INFO *spi_info_ptr = &(spi_obj->spi_info);
/* START ERROR CHECK */
VALID_CHK_SPI_INFO_OBJECT(spi_info_ptr);
DW_SPI_CHECK_EXP(spi_info_ptr->opn_cnt > 0, E_CLSED);
/* END OF ERROR CHECK */
uint32_t val32; /** to receive unsigned int value */
DEV_BUFFER *devbuf;
DW_SPI_CTRL *spi_ctrl_ptr = (DW_SPI_CTRL *)(spi_info_ptr->spi_ctrl);
DW_SPI_REG *spi_reg_ptr = (DW_SPI_REG *)(spi_ctrl_ptr->dw_spi_regs);
DEV_SPI_TRANSFER *spi_xfer = &(spi_info_ptr->xfer);
/* check whether current device is disabled */
if ((spi_info_ptr->status & DEV_ENABLED) == 0) {
/** When device is disabled,
* only SPI_CMD_ENA_DEV, SPI_CMD_DIS_DEV, SPI_CMD_GET_STATUS, SPI_CMD_RESET
* are available, other commands will return E_SYS
*/
if ((ctrl_cmd != SPI_CMD_ENA_DEV) && \
(ctrl_cmd != SPI_CMD_DIS_DEV) && \
(ctrl_cmd != SPI_CMD_GET_STATUS) && \
(ctrl_cmd != SPI_CMD_RESET) ) {
return E_SYS;
}
}
switch (ctrl_cmd) {
/* Commmon commands for both master and slave mode */
case SPI_CMD_GET_STATUS:
DW_SPI_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = spi_info_ptr->status;
break;
case SPI_CMD_SET_CLK_MODE:
DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX);
val32 = (uint32_t)param;
DW_SPI_CHECK_EXP((val32>=SPI_CPOL_0_CPHA_0) && (val32<=SPI_CPOL_1_CPHA_1), E_PAR);
if (dw_spi_set_clockmode(spi_reg_ptr, val32) == 0) {
spi_info_ptr->clk_mode = val32;
} else {
ercd = E_SYS;
}
break;
case SPI_CMD_ENA_DEV:
dw_spi_enable_device(spi_info_ptr);
break;
case SPI_CMD_DIS_DEV:
dw_spi_disable_device(spi_info_ptr);
break;
case SPI_CMD_RESET:
dw_spi_reset_device(spi_info_ptr);
break;
case SPI_CMD_FLUSH_TX:
DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX);
dw_spi_flush_tx(spi_reg_ptr);
break;
case SPI_CMD_FLUSH_RX:
DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX);
dw_spi_flush_rx(spi_reg_ptr);
break;
case SPI_CMD_SET_DFS:
DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX);
val32 = (uint32_t)param;
DW_SPI_CHECK_EXP(val32>0, E_PAR);
if (dw_spi_set_dfs(spi_reg_ptr, val32) == 0) {
spi_info_ptr->dfs = val32;
} else {
ercd = E_SYS;
}
break;
case SPI_CMD_SET_DUMMY_DATA:
val32 = (uint32_t)param;
spi_info_ptr->dummy = val32;
break;
case SPI_CMD_GET_RXAVAIL: /* Notice in bytes unit */
DW_SPI_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = dw_spi_get_rxavail(spi_ctrl_ptr) * dw_spi_nbytes(spi_info_ptr->dfs);
break;
case SPI_CMD_GET_TXAVAIL: /* Notice in bytes unit */
DW_SPI_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
*((int32_t *)param) = dw_spi_get_txavail(spi_ctrl_ptr) * dw_spi_nbytes(spi_info_ptr->dfs);
break;
case SPI_CMD_SET_TXCB:
DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
spi_info_ptr->spi_cbs.tx_cb = param;
break;
case SPI_CMD_SET_RXCB:
DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
spi_info_ptr->spi_cbs.rx_cb = param;
break;
case SPI_CMD_SET_XFERCB:
DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
spi_info_ptr->spi_cbs.xfer_cb = param;
break;
case SPI_CMD_SET_ERRCB:
DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
spi_info_ptr->spi_cbs.err_cb = param;
break;
case SPI_CMD_ABORT_TX:
ercd = dw_spi_abort_tx(spi_obj);
break;
case SPI_CMD_ABORT_RX:
ercd = dw_spi_abort_rx(spi_obj);
break;
case SPI_CMD_ABORT_XFER:
ercd = dw_spi_abort_xfer(spi_obj);
break;
case SPI_CMD_SET_TXINT:
val32 = (uint32_t)param;
if (val32 == 0) {
ercd = dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_SND);
} else {
ercd = dw_spi_ena_cbr(spi_info_ptr, DW_SPI_RDY_SND);
}
break;
case SPI_CMD_SET_RXINT:
val32 = (uint32_t)param;
if (val32 == 0) {
ercd = dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_RCV);
} else {
ercd = dw_spi_ena_cbr(spi_info_ptr, DW_SPI_RDY_RCV);
}
break;
case SPI_CMD_SET_TXINT_BUF:
DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX);
if (param != NULL) {
devbuf = (DEV_BUFFER *)param;
DEV_SPI_XFER_SET_TXBUF(spi_xfer, devbuf->buf, 0, devbuf->len);
DEV_SPI_XFER_SET_RXBUF(spi_xfer, NULL, devbuf->len, 0);
DEV_SPI_XFER_SET_NEXT(spi_xfer, NULL);
DW_SPI_CHECK_EXP(dw_spi_chk_xfer_aligned(spi_xfer, spi_info_ptr->dfs) == 0, E_PAR);
dw_spi_init_transfer(spi_ctrl_ptr, spi_xfer, spi_info_ptr->dfs);
} else {
DEV_SPI_XFER_SET_TXBUF(spi_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_RXBUF(spi_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(spi_xfer, NULL);
dw_spi_init_transfer(spi_ctrl_ptr, NULL, spi_info_ptr->dfs);
}
break;
case SPI_CMD_SET_RXINT_BUF:
DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX);
if (param != NULL) {
devbuf = (DEV_BUFFER *)param;
DEV_SPI_XFER_SET_TXBUF(spi_xfer, NULL, devbuf->len, 0);
DEV_SPI_XFER_SET_RXBUF(spi_xfer, devbuf->buf, 0, devbuf->len);
DEV_SPI_XFER_SET_NEXT(spi_xfer, NULL);
/* Check transfer align */
DW_SPI_CHECK_EXP(dw_spi_chk_xfer_aligned(spi_xfer, spi_info_ptr->dfs) == 0, E_PAR);
dw_spi_init_transfer(spi_ctrl_ptr, spi_xfer, spi_info_ptr->dfs);
} else {
DEV_SPI_XFER_SET_TXBUF(spi_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_RXBUF(spi_xfer, NULL, 0, 0);
DEV_SPI_XFER_SET_NEXT(spi_xfer, NULL);
dw_spi_init_transfer(spi_ctrl_ptr, NULL, spi_info_ptr->dfs);
}
break;
case SPI_CMD_TRANSFER_POLLING:
DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX);
if (param != NULL) {
/* Check transfer align */
DW_SPI_CHECK_EXP(dw_spi_chk_xfer_aligned((DEV_SPI_TRANSFER *)param, spi_info_ptr->dfs) == 0, E_PAR);
*spi_xfer = *((DEV_SPI_TRANSFER *)param);
dw_spi_init_transfer(spi_ctrl_ptr, spi_xfer, spi_info_ptr->dfs);
/* Transfer data by poll */
dw_spi_poll_transfer(spi_info_ptr);
} else {
ercd = E_PAR;
}
break;
case SPI_CMD_TRANSFER_INT:
DW_SPI_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
if (param != NULL) {
DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX);
/* Check transfer align */
DW_SPI_CHECK_EXP(dw_spi_chk_xfer_aligned((DEV_SPI_TRANSFER *)param, spi_info_ptr->dfs) == 0, E_PAR);
*spi_xfer = *((DEV_SPI_TRANSFER *)param);
dw_spi_init_transfer(spi_ctrl_ptr, spi_xfer, spi_info_ptr->dfs);
/* Transfer data by interrupt */
ercd = dw_spi_ena_cbr(spi_info_ptr, DW_SPI_RDY_XFER);
} else {
ercd = dw_spi_dis_cbr(spi_info_ptr, DW_SPI_RDY_XFER);
}
break;
/* Master mode only commands */
case SPI_CMD_MST_SET_FREQ:
DW_SPI_CHECK_EXP(spi_info_ptr->mode == DEV_MASTER_MODE, E_NOSPT);
DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX);
val32 = (uint32_t)param;
DW_SPI_CHECK_EXP(val32>0, E_PAR);
dw_spi_set_freq(spi_ctrl_ptr, val32);
spi_info_ptr->freq = val32;
break;
case SPI_CMD_MST_SEL_DEV:
DW_SPI_CHECK_EXP(spi_info_ptr->mode == DEV_MASTER_MODE, E_NOSPT);
DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX);
val32 = (uint32_t)param;
if (dw_spi_select_slave(spi_reg_ptr, val32) == 0) {
spi_info_ptr->slave = val32;
} else {
ercd = E_SYS;
}
break;
case SPI_CMD_MST_DSEL_DEV:
DW_SPI_CHECK_EXP(spi_info_ptr->mode == DEV_MASTER_MODE, E_NOSPT);
DW_SPI_CHECK_EXP((spi_info_ptr->status & DEV_IN_XFER) == 0, E_CTX);
val32 = (uint32_t)param;
if (dw_spi_deselect_slave(spi_reg_ptr, val32) == 0) {
spi_info_ptr->slave = SPI_SLAVE_NOT_SELECTED;
} else {
ercd = E_SYS;
}
break;
/* Slave mode only commands */
default:
ercd = E_NOSPT;
break;
}
error_exit:
return ercd;
}