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