int32_t dw_iic_control()

in hw/mcu/arc/src/ext/sdk/device/designware/iic/dw_iic.c [1200:1407]


int32_t dw_iic_control (DEV_IIC *iic_obj, uint32_t ctrl_cmd, void *param)
{
	int32_t ercd = E_OK;
	DEV_IIC_INFO *iic_info_ptr = &(iic_obj->iic_info);

	/* START ERROR CHECK */
	VALID_CHK_IIC_INFO_OBJECT(iic_info_ptr);
	DW_IIC_CHECK_EXP(iic_info_ptr->opn_cnt > 0, E_CLSED);
	/* END OF ERROR CHECK */

	uint32_t val32; /** to receive unsigned int value */
	DEV_BUFFER *devbuf;

	DW_IIC_CTRL *iic_ctrl_ptr = (DW_IIC_CTRL *)(iic_info_ptr->iic_ctrl);
	DW_IIC_REG *iic_reg_ptr = (DW_IIC_REG *)(iic_ctrl_ptr->dw_iic_regs);

	/* check whether current device is disabled */
	if ((iic_info_ptr->status & DEV_ENABLED) == 0) {
		/** When device is disabled,
		 * only IIC_CMD_ENA_DEV, IIC_CMD_DIS_DEV, IIC_CMD_GET_STATUS, IIC_CMD_RESET
		 * are available, other commands will return E_SYS
		 */
		if ((ctrl_cmd != IIC_CMD_ENA_DEV) && \
			(ctrl_cmd != IIC_CMD_DIS_DEV) && \
			(ctrl_cmd != IIC_CMD_GET_STATUS) && \
			(ctrl_cmd != IIC_CMD_RESET) ) {
			return E_SYS;
		}
	}

	switch (ctrl_cmd) {
		/* Commmon commands for both master and slave mode */
		case IIC_CMD_GET_STATUS:
			DW_IIC_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
			*((int32_t *)param) = iic_info_ptr->status;
			break;
		case IIC_CMD_ENA_DEV:
			dw_iic_enable_device(iic_info_ptr);
			break;
		case IIC_CMD_DIS_DEV:
			dw_iic_disable_device(iic_info_ptr);
			break;
		case IIC_CMD_RESET:
			dw_iic_reset_device(iic_info_ptr);
			break;
		case IIC_CMD_FLUSH_TX:
			dw_iic_flush_tx(iic_reg_ptr);
			break;
		case IIC_CMD_FLUSH_RX:
			dw_iic_flush_rx(iic_reg_ptr);
			break;
		case IIC_CMD_SET_ADDR_MODE:
			val32 = (uint32_t)param;
			DW_IIC_CHECK_EXP((val32==IIC_7BIT_ADDRESS) || (val32==IIC_10BIT_ADDRESS), E_PAR);
			if (iic_info_ptr->mode == DEV_MASTER_MODE) {
				dw_iic_set_mstaddr_mode(iic_reg_ptr, val32);
			} else {
				dw_iic_set_slvaddr_mode(iic_reg_ptr, val32);
			}
			iic_info_ptr->addr_mode = val32;
			break;
		case IIC_CMD_GET_RXAVAIL:
			DW_IIC_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
			*((int32_t *)param) = dw_iic_get_rxavail(iic_ctrl_ptr);
			break;
		case IIC_CMD_GET_TXAVAIL:
			DW_IIC_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
			*((int32_t *)param) = dw_iic_get_txavail(iic_ctrl_ptr);
			break;
		case IIC_CMD_SET_TXCB:
			DW_IIC_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
			iic_info_ptr->iic_cbs.tx_cb = param;
			break;
		case IIC_CMD_SET_RXCB:
			DW_IIC_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
			iic_info_ptr->iic_cbs.rx_cb = param;
			break;
		case IIC_CMD_SET_ERRCB:
			DW_IIC_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
			iic_info_ptr->iic_cbs.err_cb = param;
			break;
		case IIC_CMD_ABORT_TX:
			dw_iic_abort_tx(iic_obj);
			if ((iic_info_ptr->mode == DEV_MASTER_MODE) \
				&& (iic_info_ptr->cur_state == IIC_IN_TX)) {
				iic_info_ptr->cur_state = IIC_FREE;
			}
			break;
		case IIC_CMD_ABORT_RX:
			dw_iic_abort_rx(iic_obj);
			if ((iic_info_ptr->mode == DEV_MASTER_MODE) \
				&& (iic_info_ptr->cur_state == IIC_IN_RX)) {
				iic_info_ptr->cur_state = IIC_FREE;
			}
			break;
		case IIC_CMD_SET_TXINT:
			if (iic_info_ptr->mode == DEV_MASTER_MODE) {
				DW_IIC_CHECK_EXP(iic_info_ptr->cur_state != IIC_IN_RX, E_CTX);
			}
			val32 = (uint32_t)param;
			if (val32 == 0) {
				dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_SND);
				iic_info_ptr->cur_state = IIC_FREE;
			} else {
				iic_info_ptr->cur_state = IIC_IN_TX;
				dw_iic_ena_cbr(iic_info_ptr, DW_IIC_RDY_SND);
			}
			break;
		case IIC_CMD_SET_RXINT:
			if (iic_info_ptr->mode == DEV_MASTER_MODE) {
				DW_IIC_CHECK_EXP(iic_info_ptr->cur_state != IIC_IN_TX, E_CTX);
			}
			val32 = (uint32_t)param;
			if (val32 == 0) {
				iic_info_ptr->cur_state = IIC_FREE;
				dw_iic_dis_cbr(iic_info_ptr, DW_IIC_RDY_RCV);
			} else {
				iic_info_ptr->cur_state = IIC_IN_RX;
				dw_iic_ena_cbr(iic_info_ptr, DW_IIC_RDY_RCV);
			}
			break;
		case IIC_CMD_SET_TXINT_BUF:
			if (iic_info_ptr->mode == DEV_MASTER_MODE) {
				DW_IIC_CHECK_EXP(iic_info_ptr->cur_state != IIC_IN_TX, E_CTX);
			}
			DW_IIC_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
			if (param != NULL) {
				devbuf = (DEV_BUFFER *)param;
				iic_info_ptr->tx_buf = *devbuf;
				iic_info_ptr->tx_buf.ofs = 0;
			} else {
				iic_info_ptr->tx_buf.buf = NULL;
				iic_info_ptr->tx_buf.len = 0;
				iic_info_ptr->tx_buf.ofs = 0;
			}
			break;
		case IIC_CMD_SET_RXINT_BUF:
			if (iic_info_ptr->mode == DEV_MASTER_MODE) {
				DW_IIC_CHECK_EXP(iic_info_ptr->cur_state != IIC_IN_RX, E_CTX);
			}
			DW_IIC_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
			if (param != NULL) {
				devbuf = (DEV_BUFFER *)param;
				iic_info_ptr->rx_buf = *devbuf;
				iic_info_ptr->rx_buf.ofs = 0;
				iic_ctrl_ptr->dw_iic_rxbuf.ofs = 0;
				iic_ctrl_ptr->dw_iic_rxbuf.len = devbuf->len;
			} else {
				iic_info_ptr->rx_buf.buf = NULL;
				iic_info_ptr->rx_buf.len = 0;
				iic_info_ptr->rx_buf.ofs = 0;
				iic_ctrl_ptr->dw_iic_rxbuf.ofs = 0;
				iic_ctrl_ptr->dw_iic_rxbuf.len = 0;
			}
			break;

		/* Master mode only commands */
		case IIC_CMD_MST_SET_SPEED_MODE:
			DW_IIC_CHECK_EXP(iic_info_ptr->mode == DEV_MASTER_MODE, E_NOSPT);
			val32 = (uint32_t)param;
			DW_IIC_CHECK_EXP((val32>=IIC_SPEED_STANDARD) && (val32<=IIC_SPEED_ULTRA), E_PAR);
			dw_iic_set_speedmode(iic_reg_ptr, val32);
			iic_info_ptr->speed_mode = val32;
			break;
		case IIC_CMD_MST_SET_TAR_ADDR:
			DW_IIC_CHECK_EXP(iic_info_ptr->mode == DEV_MASTER_MODE, E_NOSPT);
			if (iic_info_ptr->addr_mode == IIC_7BIT_ADDRESS) {
				val32 = ((uint32_t)param) & IIC_7BIT_ADDRESS_MASK;
			} else {
				val32 = ((uint32_t)param) & IIC_10BIT_ADDRESS_MASK;
			}
			if (val32 != iic_info_ptr->tar_addr) {
				dw_iic_set_taraddr(iic_reg_ptr, val32);
				iic_info_ptr->tar_addr = val32;
			}
			break;
		case IIC_CMD_MST_SET_NEXT_COND:
			DW_IIC_CHECK_EXP(iic_info_ptr->mode == DEV_MASTER_MODE, E_NOSPT);
			val32 = (uint32_t)param;
			DW_IIC_CHECK_EXP((val32==IIC_MODE_STOP) || (val32==IIC_MODE_RESTART), E_PAR);
			iic_info_ptr->next_cond = (uint32_t)param;
			break;

		/* Slave mode only commands */
		case IIC_CMD_SLV_SET_SLV_ADDR:
			DW_IIC_CHECK_EXP(iic_info_ptr->mode == DEV_SLAVE_MODE, E_NOSPT);
			if (iic_info_ptr->addr_mode == IIC_7BIT_ADDRESS) {
				val32 = ((uint32_t)param) & IIC_7BIT_ADDRESS_MASK;
			} else {
				val32 = ((uint32_t)param) & IIC_10BIT_ADDRESS_MASK;
			}
			dw_iic_set_slvaddr(iic_reg_ptr, val32);
			iic_info_ptr->slv_addr = val32;
			break;
		case IIC_CMD_SLV_GET_SLV_STATE:
			DW_IIC_CHECK_EXP(iic_info_ptr->mode == DEV_SLAVE_MODE, E_NOSPT);
			DW_IIC_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
			*((uint32_t *)param) = dw_iic_get_slv_state(iic_reg_ptr);
			break;

		default:
			ercd = E_NOSPT;
			break;
	}

error_exit:
	return ercd;
}