int32_t dw_spi_control()

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;
}