From 768f2f048b6d7172ebcc23b03b9e7a885f50aa82 Mon Sep 17 00:00:00 2001 From: shsu Date: Mon, 8 Jan 2024 16:35:35 +0800 Subject: [PATCH] 1. Modify the following interfaces to fix stack corrupted if user pass the parameter, rxbuf_size not correctly. I3C_ErrCode_Enum api_I3C_Master_Insert_Task_ENTDAA(__u16 *rxbuf_size, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF) I3C_ErrCode_Enum api_I3C_Master_Insert_Task_CCCr(__u8 CCC, __u8 HSize, __u16 txbuf_size, __u16 *rxbuf_size, __u8 *txbuf, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF) I3C_ErrCode_Enum I3C_Master_Insert_Task_ENTDAA(__u16 *rxbuf_size, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF) I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCr(__u8 CCC, __u8 HSize, __u16 txbuf_size, __u16 *rxbuf_size, __u8 *txbuf, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF) I3C_ErrCode_Enum I3C_Master_Insert_Task_EVENT(__u16 *rxbuf_size, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF) 2. Enable CHANDLED for slave interrupt 3. Add I3C_CTRL_EVENT_Enum definition 4. update sample code in tests/boards/npcm400f_evb --- drivers/i3c/i3c_npcm4xx.c | 443 +++++++++++------- drivers/i3c/npcm4xx/api_i3c.c | 4 +- drivers/i3c/npcm4xx/api_i3c.h | 4 +- drivers/i3c/npcm4xx/i3c_core.c | 62 ++- drivers/i3c/npcm4xx/i3c_core.h | 6 +- drivers/i3c/npcm4xx/i3c_drv.h | 7 + drivers/i3c/npcm4xx/i3c_master.c | 50 +- .../npcm400f_evb/boards/npcm400f_evb.conf | 8 +- tests/boards/npcm400f_evb/prj.conf | 2 +- tests/boards/npcm400f_evb/src/i3c.c | 27 +- tests/boards/npcm400f_evb/src/main.c | 5 +- 11 files changed, 400 insertions(+), 218 deletions(-) diff --git a/drivers/i3c/i3c_npcm4xx.c b/drivers/i3c/i3c_npcm4xx.c index 365095dddd5bb6..2f7a8f76320d62 100644 --- a/drivers/i3c/i3c_npcm4xx.c +++ b/drivers/i3c/i3c_npcm4xx.c @@ -255,6 +255,7 @@ const struct device *GetDevNodeFromPort(I3C_PORT_Enum port) case I3C6_IF: return device_get_binding(DT_LABEL(DT_NODELABEL(i3c5))); #endif + default: return NULL; } @@ -336,6 +337,7 @@ void I3C_Disable_Interface(I3C_PORT_Enum port) * in scatter gather mode * Rx always use basic mode */ + struct SCAT { struct dsct_reg SCAT_DSCT[16] __aligned(16); }; @@ -352,6 +354,71 @@ uint32_t PDMA_TxBuf_END[I3C_PORT_MAX] __aligned(4); #define PDMA_T struct pdma_reg #define PDMA ((PDMA_T *)PDMA_BASE_ADDR) + +static void i3c_setup_dma_channel(uint8_t hw_id, int dma_channel) +{ + uint32_t pdma_offset = 0; + uint32_t pdma_value = 0; + + if (dma_channel < 4) + pdma_value = PDMA->REQSEL0_3; + else if (dma_channel < 8) + pdma_value = PDMA->REQSEL4_7; + else if (dma_channel < 12) + pdma_value = PDMA->REQSEL8_11; + else if (dma_channel < 16) + pdma_value = PDMA->REQSEL12_15; + else + return; + + pdma_offset = dma_channel % 4; + pdma_value = pdma_value & ~(0xFF << (8 * pdma_offset)); + pdma_value = pdma_value | (hw_id << (8 * pdma_offset)); + + if (dma_channel < 4) + PDMA->REQSEL0_3 = pdma_value; + else if (dma_channel < 8) + PDMA->REQSEL4_7 = pdma_value; + else if (dma_channel < 12) + PDMA->REQSEL8_11 = pdma_value; + else if (dma_channel < 16) + PDMA->REQSEL12_15 = pdma_value; + else + return; +} + +static void i3c_setup_dma_configure(I3C_PORT_Enum port, int tx_dma_channel, int rx_dma_channel) +{ + switch (port) { + case I3C1_IF: + i3c_setup_dma_channel(PDMA_I3C1_TX, tx_dma_channel); + i3c_setup_dma_channel(PDMA_I3C1_RX, rx_dma_channel); + break; + case I3C2_IF: + i3c_setup_dma_channel(PDMA_I3C2_TX, tx_dma_channel); + i3c_setup_dma_channel(PDMA_I3C2_RX, rx_dma_channel); + break; + case I3C3_IF: + i3c_setup_dma_channel(PDMA_I3C3_TX, tx_dma_channel); + i3c_setup_dma_channel(PDMA_I3C3_RX, rx_dma_channel); + break; + case I3C4_IF: + i3c_setup_dma_channel(PDMA_I3C4_TX, tx_dma_channel); + i3c_setup_dma_channel(PDMA_I3C4_RX, rx_dma_channel); + break; + case I3C5_IF: + i3c_setup_dma_channel(PDMA_I3C5_TX, tx_dma_channel); + i3c_setup_dma_channel(PDMA_I3C5_RX, rx_dma_channel); + break; + case I3C6_IF: + i3c_setup_dma_channel(PDMA_I3C6_TX, tx_dma_channel); + i3c_setup_dma_channel(PDMA_I3C6_RX, rx_dma_channel); + break; + default: + break; + } +} + /*==========================================================================*/ #define I3C_GET_REG_MCONFIG(port) sys_read32(I3C_BASE_ADDR(port) + OFFSET_MCONFIG) #define I3C_SET_REG_MCONFIG(port, val) sys_write32(val, I3C_BASE_ADDR(port) + OFFSET_MCONFIG) @@ -500,70 +567,6 @@ void hal_I3C_Config_Internal_Device(I3C_PORT_Enum port, I3C_DEVICE_INFO_t *pDevi /* move to dtsi and i3c_npcm4xx_init() */ } -static void i3c_setup_dma_channel(uint8_t hw_id, int dma_channel) -{ - uint32_t pdma_offset = 0; - uint32_t pdma_value = 0; - - if (dma_channel < 4) - pdma_value = PDMA->REQSEL0_3; - else if (dma_channel < 8) - pdma_value = PDMA->REQSEL4_7; - else if (dma_channel < 12) - pdma_value = PDMA->REQSEL8_11; - else if (dma_channel < 16) - pdma_value = PDMA->REQSEL12_15; - else - return; - - pdma_offset = dma_channel % 4; - pdma_value = pdma_value & ~(0xFF << (8 * pdma_offset)); - pdma_value = pdma_value | (hw_id << (8 * pdma_offset)); - - if (dma_channel < 4) - PDMA->REQSEL0_3 = pdma_value; - else if (dma_channel < 8) - PDMA->REQSEL4_7 = pdma_value; - else if (dma_channel < 12) - PDMA->REQSEL8_11 = pdma_value; - else if (dma_channel < 16) - PDMA->REQSEL12_15 = pdma_value; - else - return; -} - -static void i3c_setup_dma_configure(I3C_PORT_Enum port, int tx_dma_channel, int rx_dma_channel) -{ - switch (port) { - case I3C1_IF: - i3c_setup_dma_channel(PDMA_I3C1_TX, tx_dma_channel); - i3c_setup_dma_channel(PDMA_I3C1_RX, rx_dma_channel); - break; - case I3C2_IF: - i3c_setup_dma_channel(PDMA_I3C2_TX, tx_dma_channel); - i3c_setup_dma_channel(PDMA_I3C2_RX, rx_dma_channel); - break; - case I3C3_IF: - i3c_setup_dma_channel(PDMA_I3C3_TX, tx_dma_channel); - i3c_setup_dma_channel(PDMA_I3C3_RX, rx_dma_channel); - break; - case I3C4_IF: - i3c_setup_dma_channel(PDMA_I3C4_TX, tx_dma_channel); - i3c_setup_dma_channel(PDMA_I3C4_RX, rx_dma_channel); - break; - case I3C5_IF: - i3c_setup_dma_channel(PDMA_I3C5_TX, tx_dma_channel); - i3c_setup_dma_channel(PDMA_I3C5_RX, rx_dma_channel); - break; - case I3C6_IF: - i3c_setup_dma_channel(PDMA_I3C6_TX, tx_dma_channel); - i3c_setup_dma_channel(PDMA_I3C6_RX, rx_dma_channel); - break; - default: - break; - } -} - /*--------------------------------------------------------------------------------------*/ /** * @brief Update I3C register settings for the specific internal device @@ -736,7 +739,7 @@ I3C_ErrCode_Enum hal_I3C_Config_Device(I3C_DEVICE_INFO_t *pDevice) I3C_INTCLR_DACHG_MASK | I3C_INTCLR_TXNOTFULL_MASK | I3C_INTCLR_RXPEND_MASK | I3C_INTCLR_STOP_MASK | I3C_INTCLR_MATCHED_MASK | I3C_INTCLR_START_MASK); - I3C_SET_REG_INTSET(port, /*I3C_INTSET_CHANDLED_MASK | */I3C_INTSET_DDRMATCHED_MASK | + I3C_SET_REG_INTSET(port, I3C_INTSET_CHANDLED_MASK | I3C_INTSET_DDRMATCHED_MASK | I3C_INTSET_ERRWARN_MASK | I3C_INTSET_CCC_MASK | I3C_INTSET_DACHG_MASK | I3C_INTSET_STOP_MASK | I3C_INTSET_START_MASK); @@ -1141,11 +1144,11 @@ uint8_t Get_PDMA_Channel(I3C_PORT_Enum port, I3C_TRANSFER_DIR_Enum direction) * 6: I3C1_RX, 7: I3C2_RX, 8: I3C3_RX, 9: I3C4_RX, 10: I3C5_RX, 11: I3C6_RX, */ + pDevice = api_I3C_Get_INODE(port); + if (port >= I3C_PORT_MAX) return 0xFF; - pDevice = api_I3C_Get_INODE(port); - if (direction == I3C_TRANSFER_DIR_WRITE) return pDevice->dma_tx_channel; else @@ -1819,6 +1822,8 @@ I3C_ErrCode_Enum hal_I3C_Slave_Query_TxLen(I3C_PORT_Enum port, uint16_t *txLen) ((pDevice->mode != I3C_DEVICE_MODE_SECONDARY_MASTER))) return I3C_ERR_PARAMETER_INVALID; + /* Slave TX data has send ? DMA will move response data to FIFO automatically */ + /* Response data still in Tx FIFO ? */ txDataLen = (I3C_GET_REG_DATACTRL(port) & I3C_DATACTRL_TXCOUNT_MASK) >> I3C_DATACTRL_TXCOUNT_SHIFT; @@ -2036,8 +2041,10 @@ static void i3c_npcm4xx_start_xfer(struct i3c_npcm4xx_obj *obj, struct i3c_npcm4 k_spin_unlock(&obj->lock, key); /* wait until current task complete */ - while (pBus->pCurrentTask) - k_usleep(0); + while (pBus->pCurrentTask) { + k_yield(); + /* k_usleep(0); */ + } return; } } @@ -2654,7 +2661,7 @@ int i3c_npcm4xx_master_send_ccc(const struct device *dev, struct i3c_ccc_cmd *cc __u16 TxLen = 0; __u8 TxBuf[I3C_PAYLOAD_SIZE_MAX] = { 0 }; - __u16 RxLen = 0; + __u16 RxLen; __u8 *RxBuf = NULL; if (ccc->id & I3C_CCC_DIRECT) { @@ -2765,21 +2772,21 @@ int i3c_npcm4xx_master_send_ccc(const struct device *dev, struct i3c_ccc_cmd *cc RxLen = 2; TxBuf[0] = ccc->addr; RxBuf = cmd.rx_buf; - I3C_Master_Insert_Task_CCCr(CCC, 1, TxLen, RxLen, TxBuf, RxBuf, Baudrate, + I3C_Master_Insert_Task_CCCr(CCC, 1, TxLen, &RxLen, TxBuf, RxBuf, Baudrate, Timeout, callback, PortId, Policy, bHIF); } else if (CCC == CCC_DIRECT_GETMRL) { TxLen = 1; RxLen = 3; TxBuf[0] = ccc->addr; RxBuf = cmd.rx_buf; - I3C_Master_Insert_Task_CCCr(CCC, 1, TxLen, RxLen, TxBuf, RxBuf, Baudrate, + I3C_Master_Insert_Task_CCCr(CCC, 1, TxLen, &RxLen, TxBuf, RxBuf, Baudrate, Timeout, callback, PortId, Policy, bHIF); } else if (CCC == CCC_DIRECT_GETPID) { TxLen = 1; RxLen = 6; TxBuf[0] = ccc->addr; RxBuf = cmd.rx_buf; - I3C_Master_Insert_Task_CCCr(CCC, 1, TxLen, RxLen, TxBuf, RxBuf, Baudrate, + I3C_Master_Insert_Task_CCCr(CCC, 1, TxLen, &RxLen, TxBuf, RxBuf, Baudrate, Timeout, callback, PortId, Policy, bHIF); } else if ((CCC == CCC_DIRECT_GETBCR) || (CCC == CCC_DIRECT_GETDCR) || (CCC == CCC_DIRECT_GETACCMST)) { @@ -2787,14 +2794,14 @@ int i3c_npcm4xx_master_send_ccc(const struct device *dev, struct i3c_ccc_cmd *cc RxLen = 1; TxBuf[0] = ccc->addr; RxBuf = cmd.rx_buf; - I3C_Master_Insert_Task_CCCr(CCC, 1, TxLen, RxLen, TxBuf, RxBuf, Baudrate, + I3C_Master_Insert_Task_CCCr(CCC, 1, TxLen, &RxLen, TxBuf, RxBuf, Baudrate, Timeout, callback, PortId, Policy, bHIF); } else if (CCC == CCC_DIRECT_GETSTATUS) { TxLen = 1; RxLen = 2; TxBuf[0] = ccc->addr; RxBuf = cmd.rx_buf; - I3C_Master_Insert_Task_CCCr(CCC, 1, TxLen, RxLen, TxBuf, RxBuf, Baudrate, + I3C_Master_Insert_Task_CCCr(CCC, 1, TxLen, &RxLen, TxBuf, RxBuf, Baudrate, Timeout, callback, PortId, Policy, bHIF); } else { return -2; @@ -2803,7 +2810,7 @@ int i3c_npcm4xx_master_send_ccc(const struct device *dev, struct i3c_ccc_cmd *cc if (CCC == CCC_BROADCAST_ENTDAA) { RxLen = (sizeof(cmd.rx_buf) >= 63) ? 63 : (sizeof(cmd.rx_buf) % 9) * 9; RxBuf = cmd.rx_buf; - I3C_Master_Insert_Task_ENTDAA(63, RxBuf, Baudrate, Timeout, callback, + I3C_Master_Insert_Task_ENTDAA(&RxLen, RxBuf, Baudrate, Timeout, callback, PortId, Policy, bHIF); } else { if ((CCC == CCC_BROADCAST_ENEC) || (CCC == CCC_BROADCAST_DISEC)) { @@ -2972,6 +2979,10 @@ int i3c_npcm4xx_master_priv_xfer(struct i3c_dev_desc *i3cdev, struct i3c_priv_xf Baudrate = (pSlaveDev->attr.b.runI3C) ? I3C_TRANSFER_SPEED_SDR_12p5MHZ : I3C_TRANSFER_SPEED_I2C_100KHZ; + /* Try to slow down for the fly line */ + /* Baudrate = (pSlaveDev->attr.b.runI3C) ? I3C_TRANSFER_SPEED_SDR_6MHZ : */ + /* I3C_TRANSFER_SPEED_I2C_100KHZ; */ + if (!bWnR) { if (xfers[i].rnw) { Protocol = (pSlaveDev->attr.b.runI3C) ? @@ -3000,15 +3011,18 @@ int i3c_npcm4xx_master_priv_xfer(struct i3c_dev_desc *i3cdev, struct i3c_priv_xf Baudrate, Timeout, callback, PortId, Policy, bHIF); if (pTaskInfo != NULL) { k_sem_init(&xfer.sem, 0, 1); - xfer.ret = -ETIMEDOUT; i3c_npcm4xx_start_xfer(obj, &xfer); /* wait done, xfer.ret will be changed in ISR */ - k_sem_take(&xfer.sem, I3C_NPCM4XX_XFER_TIMEOUT); + if (k_sem_take(&xfer.sem, I3C_NPCM4XX_XFER_TIMEOUT) != 0) { + xfer.ret = -ETIMEDOUT; + break; + } /* report actual read length */ - if (bWnR) + if (bWnR) { i++; + } } } @@ -3052,7 +3066,7 @@ int i3c_npcm4xx_master_send_entdaa(struct i3c_dev_desc *i3cdev) cmd.rx_length = 0; cmd.tx_length = 0; - api_I3C_Master_Insert_Task_ENTDAA(rxlen, RxBuf_expected, I3C_TRANSFER_SPEED_SDR_1MHZ, + api_I3C_Master_Insert_Task_ENTDAA(&rxlen, RxBuf_expected, I3C_TRANSFER_SPEED_SDR_1MHZ, TIMEOUT_TYPICAL, NULL, port, I3C_TASK_POLICY_APPEND_LAST, IS_HIF); k_sem_init(&xfer.sem, 0, 1); @@ -3065,7 +3079,6 @@ int i3c_npcm4xx_master_send_entdaa(struct i3c_dev_desc *i3cdev) if (k_sem_take(&xfer.sem, I3C_NPCM4XX_CCC_TIMEOUT) == 0) { if (xfer.ret == 0) { i3cdev->info.i2c_mode = 0; - /*i3cdev->info.dynamic_addr = i3cdev->info.assigned_dynamic_addr;*/ } } @@ -3079,11 +3092,23 @@ void I3C_Slave_Handle_DMA(__u32 Parm); uint32_t I3C_Slave_Register_Access(I3C_PORT_Enum port, uint16_t rx_cnt, uint8_t *pRx_buff, bool bHDR); -#define ENTER_MASTER_ISR() { /* GPIO_Set_Data(GPIOC, 4, GPIO_DATA_LOW); */ } -#define EXIT_MASTER_ISR() { /* GPIO_Set_Data(GPIOC, 4, GPIO_DATA_HIGH); */ } - -#define ENTER_SLAVE_ISR() { /* GPIO_Set_Data(GPIOC, 5, GPIO_DATA_LOW); */ } -#define EXIT_SLAVE_ISR() { /* GPIO_Set_Data(GPIOC, 5, GPIO_DATA_HIGH); */ } +#define ENTER_MASTER_ISR() { \ + /* GPIO_Set_Data(GPIOC, 4, GPIO_DATA_LOW); */ \ + /* GPIOC5 goes L */ \ + /* RegClrBit(M8(0x40081000 + (0x0C * 0x2000L)), MaskBit(5)); */ } +#define EXIT_MASTER_ISR() { \ + /* GPIO_Set_Data(GPIOC, 4, GPIO_DATA_HIGH); */ \ + /* GPIOC5 goes H */ \ + /* RegSetBit(M8(0x40081000 + (0x0C * 0x2000L)), MaskBit(5)); */ } + +#define ENTER_SLAVE_ISR() { \ + /* GPIO_Set_Data(GPIOC, 5, GPIO_DATA_LOW); */ \ + /* GPIOC4 goes L */ \ + /* RegClrBit(M8(0x40081000 + (0x0C * 0x2000L)), MaskBit(4)); */ } +#define EXIT_SLAVE_ISR() { \ + /* GPIO_Set_Data(GPIOC, 5, GPIO_DATA_HIGH); */ \ + /* GPIOC4 goes H */ \ + /* RegSetBit(M8(0x40081000 + (0x0C * 0x2000L)), MaskBit(4)); */ } /* MDMA */ #define I3C_MDMA_STOP_TX(p) {\ @@ -3117,8 +3142,10 @@ void I3C_Master_ISR(uint8_t I3C_IF) pBus = api_I3C_Get_Bus_From_Port(I3C_IF); mintmask = I3C_GET_REG_MINTMASKED(I3C_IF); - if (mintmask == 0) + if (mintmask == 0) { + EXIT_MASTER_ISR(); return; + } if (mintmask & I3C_MINTMASKED_ERRWARN_MASK) { merrwarn = I3C_GET_REG_MERRWARN(I3C_IF); @@ -3484,17 +3511,54 @@ void I3C_Slave_ISR(uint8_t I3C_IF) I3C_TRANSFER_TASK_t *pTask; I3C_TRANSFER_FRAME_t *pFrame; uint32_t intmasked; + uint32_t status; + uint32_t ctrl; uint8_t evdet; uint32_t errwarn; + bool bMATCHSS; ENTER_SLAVE_ISR(); - pDevice = api_I3C_Get_INODE(I3C_IF); + intmasked = I3C_GET_REG_INTMASKED(I3C_IF); if (intmasked == 0) { EXIT_SLAVE_ISR(); return; } + status = I3C_GET_REG_STATUS(I3C_IF); + bMATCHSS = (I3C_GET_REG_CONFIG(I3C_IF) & I3C_CONFIG_MATCHSS_MASK) ? TRUE : FALSE; + + pDevice = api_I3C_Get_INODE(I3C_IF); + + if (bMATCHSS && (intmasked & I3C_INTMASKED_EVENT_MASK)) { + evdet = (uint8_t)((status & I3C_STATUS_EVDET_MASK) >> I3C_STATUS_EVDET_SHIFT); + + I3C_SET_REG_STATUS(I3C_IF, I3C_STATUS_EVENT_MASK); + if (evdet == 0x03) { + /* Ack Hot-Join --> status = 0x341000 */ + pTask = pDevice->pTaskListHead; + if (pTask == NULL) { + EXIT_SLAVE_ISR(); + return; + } + + pTaskInfo = pTask->pTaskInfo; + if (pTaskInfo == NULL) { + EXIT_SLAVE_ISR(); + return; + } + + pTaskInfo->result = I3C_ERR_OK; + api_I3C_Slave_End_Request((uint32_t)pTask); + } + + intmasked &= ~I3C_INTMASKED_EVENT_MASK; + if (!intmasked) { + EXIT_SLAVE_ISR(); + return; + } + } + if (intmasked & I3C_INTMASKED_DACHG_MASK) { /* LOG_INF("dynamic address changed\n"); */ uint8_t addr; @@ -3503,78 +3567,117 @@ void I3C_Slave_ISR(uint8_t I3C_IF) obj = gObj[I3C_IF]; if (addr) { obj->sir_allowed_by_sw = 1; - LOG_WRN("dyn addr = %X", addr); + LOG_WRN("dyn addr = %X\n", addr); } else { obj->sir_allowed_by_sw = 0; - LOG_WRN("reset dyn addr"); + LOG_WRN("reset dyn addr\n"); } I3C_SET_REG_STATUS(I3C_IF, I3C_STATUS_DACHG_MASK); - if (intmasked == I3C_INTMASKED_DACHG_MASK) { + intmasked &= ~I3C_INTMASKED_DACHG_MASK; + if (!intmasked) { EXIT_SLAVE_ISR(); return; } } if (intmasked & I3C_INTMASKED_START_MASK) { - evdet = (uint8_t)((I3C_GET_REG_STATUS(I3C_IF) & I3C_STATUS_EVDET_MASK) >> - I3C_STATUS_EVDET_SHIFT); - - /* IBI_NACKED and follow DISEC with RESTART */ - if (evdet == 0x02) { - pTask = pDevice->pTaskListHead; - if (pTask != NULL) { - pTaskInfo = pTask->pTaskInfo; - pTaskInfo->result = I3C_ERR_NACK_SLVSTART; - api_I3C_Slave_End_Request((uint32_t) pTask); - } - - /* clear STOP */ - if (I3C_GET_REG_STATUS(I3C_IF) & I3C_STATUS_STOP_MASK) { - I3C_SET_REG_STATUS(I3C_IF, I3C_STATUS_START_MASK | I3C_STATUS_STOP_MASK); - } + I3C_SET_REG_STATUS(I3C_IF, I3C_STATUS_START_MASK); + intmasked &= ~I3C_INTMASKED_START_MASK; + if (!intmasked) { EXIT_SLAVE_ISR(); return; } - - /* - * for RESTART - * 1. We must terminate previous RX DMA / FIFO before master send "Index" / Data - * 2. We must init RX DMA to get "Index" and data - */ - if (intmasked & I3C_INTMASKED_STOP_MASK) { - /* do nothing */ - } else { - /* update tx buffer here, only when slave doesn't get STOP */ - /* I3C_Slave_Handle_DMA((uint32_t)pDevice); */ - } - - I3C_SET_REG_STATUS(I3C_IF, I3C_STATUS_START_MASK); } /* !!! Don't remove to leave ISR after slave wakeup */ if (intmasked & I3C_INTMASKED_MATCHED_MASK) { I3C_SET_REG_STATUS(I3C_IF, I3C_INTMASKED_MATCHED_MASK); + + intmasked &= ~I3C_INTMASKED_MATCHED_MASK; + if (!intmasked) { + EXIT_SLAVE_ISR(); + return; + } } if (intmasked & I3C_INTMASKED_CCC_MASK) { - /* Can't reset here, will validate CCC in I3C_Slave_Handle_DMA() */ - /* I3C_SET_REG_STATUS(I3C_IF, I3C_STATUS_CCC_MASK); */ + /* must handle vendor CCC here, STOP will not be triggerred when MATCHSS == 1 */ + I3C_Slave_Handle_DMA((uint32_t) pDevice); + + intmasked = I3C_GET_REG_INTMASKED(I3C_IF); + if (!intmasked) { + EXIT_SLAVE_ISR(); + return; + } } - if (intmasked & I3C_INTMASKED_DDRMATCHED_MASK) { -/* - tmp = I3C_Slave_Register_Access(I3C_IF, slvRxOffset[I3C_IF], - slvRxBuf[I3C_IF], TRUE); + if (bMATCHSS && (intmasked & I3C_INTMASKED_CHANDLED_MASK)) { + /* CCC Command, auto */ + I3C_SET_REG_STATUS(I3C_IF, I3C_STATUS_CHANDLED_MASK); - if (tmp == 0xFFFFFFFC) { - I3C_SET_REG_INTCLR(I3C_IF, I3C_INTCLR_DDRMATCHED_MASK); - } else { - I3C_SET_REG_STATUS(I3C_IF, I3C_STATUS_DDRMATCH_MASK); + /* must handle nack SLVSTART here if MATCHSS = 1 */ + /* If master send disec after SLVSTART, the slave task should be removed. + * If master doesn't send disec, HW will retry automatically. + * So, the task should not be removed + */ + + ctrl = I3C_GET_REG_CTRL(I3C_IF); + if (ctrl & I3C_CTRL_EVENT_MASK) { + evdet = (uint8_t)((status & + I3C_STATUS_EVDET_MASK) >> I3C_STATUS_EVDET_SHIFT); + + if (evdet == 0x02) { + /* IBI ?, NACK */ + /* Master Request ?, NACK */ + /* Hot-Join, NACK SLVSTART and follow DISEC with RESTART */ + pTask = pDevice->pTaskListHead; + + if (pTask == NULL) { + LOG_WRN("Invalid Task !\n"); + EXIT_SLAVE_ISR(); + return; + } + + pTaskInfo = pTask->pTaskInfo; + pTaskInfo->result = I3C_ERR_NACK_SLVSTART; + + if ((ctrl & I3C_CTRL_EVENT_MASK) == I3C_CTRL_EVENT_IBI) { + if (status & I3C_STATUS_IBIDIS_MASK) { + pTaskInfo->result = I3C_ERR_OK; + } + } else if ((ctrl & I3C_CTRL_EVENT_MASK) == I3C_CTRL_EVENT_MstReq) { + if (status & I3C_STATUS_MRDIS_MASK) { + pTaskInfo->result = I3C_ERR_OK; + } + } else if ((ctrl & I3C_CTRL_EVENT_MASK) == I3C_CTRL_EVENT_HotJoin) { + if (status & I3C_STATUS_HJDIS_MASK) { + pTaskInfo->result = I3C_ERR_OK; + } + } + + api_I3C_Slave_End_Request((uint32_t)pTask); + } + } + + intmasked &= ~I3C_INTMASKED_CHANDLED_MASK; + if (!intmasked) { + EXIT_SLAVE_ISR(); + return; + } + } + + if (bMATCHSS && (intmasked & I3C_INTMASKED_DDRMATCHED_MASK)) { + LOG_WRN("Not support DDR, yet\n"); + + I3C_SET_REG_STATUS(I3C_IF, I3C_STATUS_DDRMATCH_MASK); + + if (!intmasked) { + EXIT_SLAVE_ISR(); + return; } -*/ } if (intmasked & I3C_INTMASKED_RXPEND_MASK) { @@ -3584,23 +3687,36 @@ void I3C_Slave_ISR(uint8_t I3C_IF) errwarn = I3C_GET_REG_ERRWARN(I3C_IF); if (errwarn & I3C_ERRWARN_SPAR_MASK) { + /*LOG_WRN("\nSPAR\n");*/ I3C_SET_REG_ERRWARN(I3C_IF, I3C_ERRWARN_SPAR_MASK); + if (errwarn == I3C_ERRWARN_SPAR_MASK) { + EXIT_SLAVE_ISR(); + return; + } + + errwarn &= ~I3C_ERRWARN_SPAR_MASK; } if (errwarn & I3C_ERRWARN_URUNNACK_MASK) { I3C_SET_REG_ERRWARN(I3C_IF, I3C_ERRWARN_URUNNACK_MASK); if (errwarn == I3C_ERRWARN_URUNNACK_MASK) { + LOG_WRN("\nURUNNACK\n"); EXIT_SLAVE_ISR(); return; } + + errwarn &= ~I3C_ERRWARN_URUNNACK_MASK; } if (errwarn & I3C_ERRWARN_INVSTART_MASK) { I3C_SET_REG_ERRWARN(I3C_IF, I3C_ERRWARN_INVSTART_MASK); if (errwarn & I3C_ERRWARN_INVSTART_MASK) { + LOG_WRN("\nInvalid START\n"); EXIT_SLAVE_ISR(); return; } + + errwarn &= ~I3C_ERRWARN_INVSTART_MASK; } if (errwarn & I3C_ERRWARN_OWRITE_MASK) { @@ -3663,41 +3779,56 @@ void I3C_Slave_ISR(uint8_t I3C_IF) } else { } + /* IBI and Hot-Join only */ + /* Master Request handled in NOWMASTER */ if (I3C_GET_REG_STATUS(I3C_IF) & I3C_STATUS_EVENT_MASK) { I3C_SET_REG_STATUS(I3C_IF, I3C_STATUS_EVENT_MASK); + if (pTask->protocol == I3C_TRANSFER_PROTOCOL_MASTER_REQUEST) { + /* master request */ } else { + /* Ack IBI or Hot-Join */ if (pTaskInfo != NULL) { pTaskInfo->result = I3C_ERR_OK; - api_I3C_Slave_End_Request((uint32_t) pTask); + api_I3C_Slave_End_Request((uint32_t)pTask); } } } else if ((pTask != NULL) && ((I3C_GET_REG_STATUS(I3C_IF) & I3C_STATUS_EVDET_MASK) == I3C_STATUS_EVDET(2))) { -#if 0 + /* NACK SLVSTART */ if ((pFrame->flag & I3C_TRANSFER_RETRY_ENABLE) && (pFrame->retry_count >= 1)) { pFrame->retry_count--; - api_I3C_Slave_Start_Request((uint32_t) pTaskInfo); + api_I3C_Slave_Start_Request((uint32_t)pTaskInfo); } else { I3C_SET_REG_CTRL(I3C_IF, I3C_MCTRL_REQUEST_NONE); + pTaskInfo->result = I3C_ERR_NACK; - api_I3C_Slave_End_Request((uint32_t) pTask); + api_I3C_Slave_End_Request((uint32_t)pTask); } -#endif } - if (I3C_GET_REG_STATUS(I3C_IF) & I3C_STATUS_CHANDLED_MASK) + /* Force End RX DMA */ + + /* clear auto CCC */ + if (I3C_GET_REG_STATUS(I3C_IF) & I3C_STATUS_CHANDLED_MASK) { I3C_SET_REG_STATUS(I3C_IF, I3C_STATUS_CHANDLED_MASK); - if (I3C_GET_REG_STATUS(I3C_IF) & I3C_STATUS_MATCHED_MASK) + } + + /* clear Address Matched for SDR */ + if (I3C_GET_REG_STATUS(I3C_IF) & I3C_STATUS_MATCHED_MASK) { I3C_SET_REG_STATUS(I3C_IF, I3C_STATUS_MATCHED_MASK); + } + + /* clear Address Matched for HDR Write */ if (I3C_GET_REG_STATUS(I3C_IF) & I3C_STATUS_DDRMATCH_MASK) { I3C_SET_REG_STATUS(I3C_IF, I3C_STATUS_DDRMATCH_MASK); I3C_SET_REG_INTSET(I3C_IF, I3C_INTSET_DDRMATCHED_MASK); } - if (I3C_GET_REG_STATUS(I3C_IF) & (I3C_STATUS_START_MASK | I3C_STATUS_STOP_MASK)) + if (I3C_GET_REG_STATUS(I3C_IF) & (I3C_STATUS_START_MASK | I3C_STATUS_STOP_MASK)) { LOG_DBG("\r\nRE-ENTRY\r\n"); + } } EXIT_SLAVE_ISR(); @@ -3748,8 +3879,8 @@ void I3C_Slave_Handle_DMA(__u32 Parm) } else { /* PDMA Rx Task not finish */ slvRxOffset[port + (I3C_PORT_MAX * idx)] = slvRxLen[port] - - (((PDMA->DSCT[PDMA_OFFSET + pdma_ch].CTL & PDMA_DSCT_CTL_TXCNT_Msk) >> PDMA_DSCT_CTL_TXCNT_Pos) - + 1); + - (((PDMA->DSCT[PDMA_OFFSET + pdma_ch].CTL & PDMA_DSCT_CTL_TXCNT_Msk) + >> PDMA_DSCT_CTL_TXCNT_Pos) + 1); } /* Process the Rcvd Data */ @@ -3802,13 +3933,12 @@ void I3C_Slave_Handle_DMA(__u32 Parm) if (obj->config->priv_xfer_pec) { ret = pec_valid(dev, (uint8_t *)&slvRxBuf[port + (I3C_PORT_MAX * idx)], slvRxOffset[port + (I3C_PORT_MAX * idx)]); - } - if (ret) { LOG_WRN("PEC error\n"); bRet = FALSE; payload->size = 0; } + } memcpy(payload->buf, slvRxBuf[port + (I3C_PORT_MAX * idx)], payload->size); } @@ -3823,22 +3953,8 @@ void I3C_Slave_Handle_DMA(__u32 Parm) /* Slave TX data has send ? */ if ((pDevice->txLen != 0) && (pDevice->txOffset != 0)) { txDataLen = 0; - if (I3C_GET_REG_DMACTRL(port) & I3C_DMACTRL_DMATB_MASK) { - - pdma_ch = Get_PDMA_Channel(port, I3C_TRANSFER_DIR_WRITE); - - if (PDMA->TDSTS & MaskBit(PDMA_OFFSET + pdma_ch)) { - txDataLen = 0; - } else { - txDataLen = ((PDMA->DSCT[port].CTL & PDMA_DSCT_CTL_TXCNT_Msk) >> - PDMA_DSCT_CTL_TXCNT_Pos) + 1; - } - } - - /* Response data still in Tx FIFO */ - txDataLen += (I3C_GET_REG_DATACTRL(port) & I3C_DATACTRL_TXCOUNT_MASK) >> - I3C_DATACTRL_TXCOUNT_SHIFT; + hal_I3C_Slave_Query_TxLen(port, &txDataLen); if (txDataLen == 0) { /* call tx send complete hook */ api_I3C_Slave_Finish_Response(pDevice); @@ -4093,6 +4209,14 @@ static int i3c_init_work_queue(I3C_PORT_Enum port) return 0; } +static void sir_allowed_worker(struct k_work *work) +{ + struct i3c_npcm4xx_obj *obj = CONTAINER_OF(work, struct i3c_npcm4xx_obj, work); + + /* k_msleep(1000); */ + obj->sir_allowed_by_sw = 1; +} + static int i3c_npcm4xx_init(const struct device *dev) { struct i3c_npcm4xx_config *config = DEV_CFG(dev); @@ -4164,6 +4288,7 @@ static int i3c_npcm4xx_init(const struct device *dev) pDevice->capability.OFFLINE = FALSE; obj->sir_allowed_by_sw = 0; + k_work_init(&obj->work, sir_allowed_worker); /* for loopback test without ibi behavior only */ pDevice->pReg = I3C_REGs_PORT_SLAVE; diff --git a/drivers/i3c/npcm4xx/api_i3c.c b/drivers/i3c/npcm4xx/api_i3c.c index 49bba3b239a428..a895c9c77e9744 100644 --- a/drivers/i3c/npcm4xx/api_i3c.c +++ b/drivers/i3c/npcm4xx/api_i3c.c @@ -443,7 +443,7 @@ I3C_TASK_INFO_t *api_I3C_Slave_Create_Task(I3C_TRANSFER_PROTOCOL_Enum Protocol, callback, PortId, bHIF); } -I3C_ErrCode_Enum api_I3C_Master_Insert_Task_ENTDAA(__u16 rxbuf_size, __u8 *rxbuf, __u32 Baudrate, +I3C_ErrCode_Enum api_I3C_Master_Insert_Task_ENTDAA(__u16 *rxbuf_size, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF) { @@ -468,7 +468,7 @@ I3C_ErrCode_Enum api_I3C_Master_Insert_Task_CCCw(__u8 CCC, __u8 HSize, __u16 buf } I3C_ErrCode_Enum api_I3C_Master_Insert_Task_CCCr(__u8 CCC, __u8 HSize, __u16 txbuf_size, - __u16 rxbuf_size, __u8 *txbuf, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, + __u16 *rxbuf_size, __u8 *txbuf, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF) { return I3C_Master_Insert_Task_CCCr(CCC, HSize, txbuf_size, rxbuf_size, txbuf, rxbuf, diff --git a/drivers/i3c/npcm4xx/api_i3c.h b/drivers/i3c/npcm4xx/api_i3c.h index f8d688f0ef9a58..1223302b690d74 100644 --- a/drivers/i3c/npcm4xx/api_i3c.h +++ b/drivers/i3c/npcm4xx/api_i3c.h @@ -73,7 +73,7 @@ extern I3C_TASK_INFO_t *api_I3C_Slave_Create_Task(I3C_TRANSFER_PROTOCOL_Enum Pro __u16 *pWrCnt, __u16 *pRdCnt, __u8 *WrBuf, __u8 *RdBuf, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, _Bool bHIF); -extern I3C_ErrCode_Enum api_I3C_Master_Insert_Task_ENTDAA(__u16 rxbuf_size, __u8 *rxbuf, +extern I3C_ErrCode_Enum api_I3C_Master_Insert_Task_ENTDAA(__u16 *rxbuf_size, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF); extern I3C_ErrCode_Enum api_I3C_Master_Insert_Task_CCCb(__u8 CCC, __u16 buf_size, __u8 *buf, @@ -83,7 +83,7 @@ extern I3C_ErrCode_Enum api_I3C_Master_Insert_Task_CCCw(__u8 CCC, __u8 HSize, __ __u8 *buf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF); extern I3C_ErrCode_Enum api_I3C_Master_Insert_Task_CCCr(__u8 CCC, __u8 HSize, __u16 txbuf_size, - __u16 rxbuf_size, __u8 *txbuf, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, + __u16 *rxbuf_size, __u8 *txbuf, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF); extern I3C_ErrCode_Enum api_ValidateBuffer(I3C_TRANSFER_PROTOCOL_Enum Protocol, __u8 Address, diff --git a/drivers/i3c/npcm4xx/i3c_core.c b/drivers/i3c/npcm4xx/i3c_core.c index 2881657584d2aa..a25c4b17137d25 100644 --- a/drivers/i3c/npcm4xx/i3c_core.c +++ b/drivers/i3c/npcm4xx/i3c_core.c @@ -1085,6 +1085,7 @@ void I3C_CCCb_RSTDAA(I3C_BUS_INFO_t *pBus) void I3C_CCCb_ENTDAA(I3C_BUS_INFO_t *pBus) { I3C_DEVICE_INFO_t *pDevice; + uint16_t rxLen; if (pBus == NULL) { return; @@ -1094,8 +1095,9 @@ void I3C_CCCb_ENTDAA(I3C_BUS_INFO_t *pBus) return; } + rxLen = 63; pDevice = pBus->pCurrentMaster; - I3C_Master_Insert_Task_ENTDAA(63, NULL, I3C_TRANSFER_SPEED_I2C_1MHZ, TIMEOUT_TYPICAL, + I3C_Master_Insert_Task_ENTDAA(&rxLen, NULL, I3C_TRANSFER_SPEED_I2C_1MHZ, TIMEOUT_TYPICAL, I3C_Master_Callback, pDevice->port, I3C_TASK_POLICY_APPEND_LAST, NOT_HIF); } @@ -2930,7 +2932,7 @@ I3C_ErrCode_Enum InsertTaskNode(I3C_DEVICE_INFO_t *pDevice, * @return I3C_ERR_OK, if the task insert successfully */ /*------------------------------------------------------------------------------*/ -I3C_ErrCode_Enum I3C_Master_Insert_Task_ENTDAA(__u16 rxbuf_size, __u8 *rxbuf, +I3C_ErrCode_Enum I3C_Master_Insert_Task_ENTDAA(__u16 *rxbuf_size, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF) { @@ -2940,19 +2942,25 @@ I3C_ErrCode_Enum I3C_Master_Insert_Task_ENTDAA(__u16 rxbuf_size, __u8 *rxbuf, __u16 RxLen; I3C_ErrCode_Enum result; - if (rxbuf_size < 9) { + if (rxbuf_size == NULL) { return I3C_ERR_PARAMETER_INVALID; } - if ((bHIF == IS_HIF) && (rxbuf == NULL)) { + if (*rxbuf_size < 9) { + return I3C_ERR_PARAMETER_INVALID; + } + + if ((rxbuf_size == NULL) && (rxbuf == NULL)) { return I3C_ERR_PARAMETER_INVALID; } TxBuf[0] = CCC_BROADCAST_ENTDAA; TxLen = 1; - RxLen = (rxbuf_size / 9) * 9; + RxLen = (*rxbuf_size / 9) * 9; + *rxbuf_size = RxLen; + pNewTaskInfo = I3C_Master_Create_Task(I3C_TRANSFER_PROTOCOL_ENTDAA, 0, TxLen, - &TxLen, &RxLen, TxBuf, rxbuf, Baudrate, Timeout, I3C_Master_Callback, PortId, + &TxLen, rxbuf_size, TxBuf, rxbuf, Baudrate, Timeout, I3C_Master_Callback, PortId, Policy, bHIF); if (pNewTaskInfo == NULL) { @@ -3180,7 +3188,7 @@ I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCw(__u8 CCC, __u8 HSize, __u16 buf_siz */ /*------------------------------------------------------------------------------*/ I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCr(__u8 CCC, __u8 HSize, __u16 txbuf_size, - __u16 rxbuf_size, __u8 *txbuf, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, + __u16 *rxbuf_size, __u8 *txbuf, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF) { I3C_TASK_INFO_t *pNewTaskInfo; @@ -3192,6 +3200,14 @@ I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCr(__u8 CCC, __u8 HSize, __u16 txbuf_s __u8 fmt = 0; __u16 dev_count; + if (rxbuf_size == NULL) { + return I3C_ERR_PARAMETER_INVALID; + } + + if (rxbuf == NULL) { + return I3C_ERR_PARAMETER_INVALID; + } + if (HSize < 1) { return I3C_ERR_PARAMETER_INVALID; } @@ -3208,16 +3224,16 @@ I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCr(__u8 CCC, __u8 HSize, __u16 txbuf_s return I3C_ERR_PARAMETER_INVALID; } - if (rxbuf_size == 0) { + if (*rxbuf_size == 0) { return I3C_ERR_PARAMETER_INVALID; } - if (rxbuf_size > 64) { + if (*rxbuf_size > 64) { return I3C_ERR_PARAMETER_INVALID; } dev_count = txbuf_size - (HSize - 1); - if (dev_count > rxbuf_size) { + if (dev_count > *rxbuf_size) { return I3C_ERR_PARAMETER_INVALID; } @@ -3251,7 +3267,7 @@ I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCr(__u8 CCC, __u8 HSize, __u16 txbuf_s } else if (TxBuf[1] == 0x91) { fmt = 2; } else { - fmt = rxbuf_size / dev_count; + fmt = *rxbuf_size / dev_count; } } else if (CCC == CCC_DIRECT_GETMXDS) { if (HSize == 1) { @@ -3259,23 +3275,23 @@ I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCr(__u8 CCC, __u8 HSize, __u16 txbuf_s } else if (TxBuf[1] == 0x91) { fmt = 1; } else { - fmt = rxbuf_size / dev_count; + fmt = *rxbuf_size / dev_count; } } else if (CCC == CCC_DIRECT_GETCAPS) { if (HSize == 1) { fmt = 4; } else { - fmt = rxbuf_size / dev_count; + fmt = *rxbuf_size / dev_count; } } - if ((dev_count * fmt) < rxbuf_size) { + if ((dev_count * fmt) < *rxbuf_size) { return I3C_ERR_PARAMETER_INVALID; } - RxLen = rxbuf_size; + RxLen = *rxbuf_size; - pNewTaskInfo = I3C_Master_Create_Task(I3C_TRANSFER_PROTOCOL_CCCr, fmt, HSize, - &TxLen, &RxLen, TxBuf, rxbuf, Baudrate, Timeout, callback, PortId, Policy, bHIF); + pNewTaskInfo = I3C_Master_Create_Task(I3C_TRANSFER_PROTOCOL_CCCr, fmt, HSize, &TxLen, + rxbuf_size, TxBuf, rxbuf, Baudrate, Timeout, callback, PortId, Policy, bHIF); if (pNewTaskInfo == NULL) { return I3C_ERR_OUT_OF_MEMORY; @@ -3306,25 +3322,27 @@ I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCr(__u8 CCC, __u8 HSize, __u16 txbuf_s * @return I3C_ERR_OK, if the task insert successfully */ /*------------------------------------------------------------------------------*/ -I3C_ErrCode_Enum I3C_Master_Insert_Task_EVENT(__u16 rxbuf_size, __u8 *rxbuf, __u32 Baudrate, +I3C_ErrCode_Enum I3C_Master_Insert_Task_EVENT(__u16 *rxbuf_size, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF) { I3C_TASK_INFO_t *pNewTaskInfo; __u16 TxLen; - __u16 RxLen; I3C_ErrCode_Enum result; - if ((bHIF == IS_HIF) && (rxbuf == NULL)) { + if (rxbuf_size == NULL) { + return I3C_ERR_PARAMETER_INVALID; + } + + if ((*rxbuf_size == 0) && (rxbuf == NULL)) { return I3C_ERR_PARAMETER_INVALID; } TxLen = 0; /* ibi payload should not more than 255 byte specified in GETMRL if supported */ - RxLen = rxbuf_size; pNewTaskInfo = I3C_Master_Create_Task(I3C_TRANSFER_PROTOCOL_EVENT, I3C_BROADCAST_ADDR, 0, - &TxLen, &RxLen, NULL, rxbuf, Baudrate, Timeout, callback, PortId, Policy, bHIF); + &TxLen, rxbuf_size, NULL, rxbuf, Baudrate, Timeout, callback, PortId, Policy, bHIF); if (pNewTaskInfo == NULL) { return I3C_ERR_OUT_OF_MEMORY; diff --git a/drivers/i3c/npcm4xx/i3c_core.h b/drivers/i3c/npcm4xx/i3c_core.h index 53ec76f64d0cbf..7ccb0a3f69d1a0 100644 --- a/drivers/i3c/npcm4xx/i3c_core.h +++ b/drivers/i3c/npcm4xx/i3c_core.h @@ -128,7 +128,7 @@ extern I3C_ErrCode_Enum InsertTaskNode(I3C_DEVICE_INFO_t *pDevice, I3C_TRANSFER_TASK_t *pNewTask, __u8 bType); /* Sample to create master task and might be used in the driver */ -extern I3C_ErrCode_Enum I3C_Master_Insert_Task_ENTDAA(__u16 rxbuf_size, __u8 *rxbuf, +extern I3C_ErrCode_Enum I3C_Master_Insert_Task_ENTDAA(__u16 *rxbuf_size, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF); extern I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCb(__u8 CCC, __u16 buf_size, __u8 *buf, @@ -138,10 +138,10 @@ extern I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCw(__u8 CCC, __u8 HSize, __u16 buf_size, __u8 *buf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF); extern I3C_ErrCode_Enum I3C_Master_Insert_Task_CCCr(__u8 CCC, __u8 HSize, - __u16 txbuf_size, __u16 rxbuf_size, __u8 *txbuf, __u8 *rxbuf, __u32 Baudrate, + __u16 txbuf_size, __u16 *rxbuf_size, __u8 *txbuf, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF); -extern I3C_ErrCode_Enum I3C_Master_Insert_Task_EVENT(__u16 rxbuf_size, __u8 *rxbuf, +extern I3C_ErrCode_Enum I3C_Master_Insert_Task_EVENT(__u16 *rxbuf_size, __u8 *rxbuf, __u32 Baudrate, __u32 Timeout, ptrI3C_RetFunc callback, __u8 PortId, I3C_TASK_POLICY_Enum Policy, _Bool bHIF); diff --git a/drivers/i3c/npcm4xx/i3c_drv.h b/drivers/i3c/npcm4xx/i3c_drv.h index 29d57c0300a78f..5087483c3e85cc 100644 --- a/drivers/i3c/npcm4xx/i3c_drv.h +++ b/drivers/i3c/npcm4xx/i3c_drv.h @@ -1118,6 +1118,13 @@ enum I3C_CONFIG_SLVENA_Enum { #define I3C_CTRL_EVENT(x) (((uint32_t)(((uint32_t)(x)) \ << I3C_CTRL_EVENT_SHIFT)) & I3C_CTRL_EVENT_MASK) +enum I3C_CTRL_EVENT_Enum { + I3C_CTRL_EVENT_None = 0, + I3C_CTRL_EVENT_IBI = 1, + I3C_CTRL_EVENT_MstReq = 2, + I3C_CTRL_EVENT_HotJoin = 3, +}; + /* INTSET */ #define I3C_INTSET_EVENT_MASK (0x40000U) #define I3C_INTSET_EVENT_SHIFT (18U) diff --git a/drivers/i3c/npcm4xx/i3c_master.c b/drivers/i3c/npcm4xx/i3c_master.c index 53ec173f3c883c..cc4a8ee7227304 100644 --- a/drivers/i3c/npcm4xx/i3c_master.c +++ b/drivers/i3c/npcm4xx/i3c_master.c @@ -1223,12 +1223,17 @@ void I3C_Master_New_Request(__u32 Parm) I3C_TRANSFER_TASK_t *pTask; I3C_TASK_INFO_t *pTaskInfo; + __u16 rxLen; + if (Parm >= I3C_PORT_MAX) { return; } + rxLen = IBI_PAYLOAD_SIZE_MAX; + port = (__u8)Parm; - I3C_Master_Insert_Task_EVENT(IBI_PAYLOAD_SIZE_MAX, NULL, I3C_TRANSFER_SPEED_SDR_IBI, + /* must use NOT_HIF */ + I3C_Master_Insert_Task_EVENT(&rxLen, NULL, I3C_TRANSFER_SPEED_SDR_IBI, TIMEOUT_TYPICAL, I3C_Master_Callback, port, I3C_TASK_POLICY_INSERT_FIRST, NOT_HIF); pBus = Get_Bus_From_Port(port); @@ -1359,6 +1364,8 @@ void I3C_Master_IBIACK(__u32 Parm) uint8_t ibiAddress; I3C_DEVICE_INFO_SHORT_t *pSlvDev; +__u16 rxLen; + if (Parm == 0) { return; } @@ -1383,7 +1390,8 @@ void I3C_Master_IBIACK(__u32 Parm) /* Insert Event task and assume event task has running to * restore IBI Type and IBI address */ - I3C_Master_Insert_Task_EVENT(IBI_PAYLOAD_SIZE_MAX, NULL, +rxLen = IBI_PAYLOAD_SIZE_MAX; + I3C_Master_Insert_Task_EVENT(&rxLen, NULL, I3C_TRANSFER_SPEED_SDR_IBI, TIMEOUT_TYPICAL, I3C_Master_Callback, port, I3C_TASK_POLICY_INSERT_FIRST, NOT_HIF); @@ -1436,7 +1444,9 @@ void I3C_Master_Insert_GETACCMST_After_IbiAckMR(__u32 Parm) I3C_DEVICE_INFO_SHORT_t *pDev; I3C_TRANSFER_FRAME_t *pFrame; __u8 wrBuf[2]; - __u8 *rdBuf; + __u8 rdBuf[2]; /* addr + pec */ + __u16 rxLen; + I3C_ErrCode_Enum res; if (Parm == 0) { return; @@ -1454,7 +1464,6 @@ void I3C_Master_Insert_GETACCMST_After_IbiAckMR(__u32 Parm) } port = pTaskInfo->Port; - hal_I3C_Ack_IBI_Without_MDB(port); hal_I3C_Disable_Master_RX_DMA(port); @@ -1473,17 +1482,26 @@ void I3C_Master_Insert_GETACCMST_After_IbiAckMR(__u32 Parm) return; } - rdBuf = hal_I3C_MemAlloc(1); + rxLen = 1; + wrBuf[0] = ibiAddress; - I3C_Master_Insert_Task_CCCr(CCC_DIRECT_GETACCMST, 1, 1, 1, wrBuf, rdBuf, - I3C_TRANSFER_SPEED_SDR_IBI, TIMEOUT_TYPICAL, - I3C_Master_Callback, port, I3C_TASK_POLICY_INSERT_FIRST, IS_HIF); - pTask = pBus->pCurrentMaster->pTaskListHead; - pTaskInfo = pTask->pTaskInfo; - pFrame = &pTask->pFrameList[pTask->frame_idx]; - pFrame->flag |= I3C_TRANSFER_REPEAT_START; - I3C_Master_Start_Request((uint32_t) pTaskInfo); + /* don't change NOT_HIF to IS_HIF */ + /* We should malloc rdBuf and rxLen for IS_HIF if needed */ + res = I3C_Master_Insert_Task_CCCr(CCC_DIRECT_GETACCMST, 1, 1, &rxLen, wrBuf, + rdBuf, I3C_TRANSFER_SPEED_SDR_IBI, TIMEOUT_TYPICAL, + I3C_Master_Callback, port, I3C_TASK_POLICY_INSERT_FIRST, NOT_HIF); + + if (res == I3C_ERR_OK) { + pTask = pBus->pCurrentMaster->pTaskListHead; + pTaskInfo = pTask->pTaskInfo; + pFrame = &pTask->pFrameList[pTask->frame_idx]; + pFrame->flag |= I3C_TRANSFER_REPEAT_START; + I3C_Master_Start_Request((uint32_t) pTaskInfo); + } + + /* rdBuf[2] and rxLen might release here */ + /* return data should be saved in variables allocated in I3C_Master_Create_Task */ } /*------------------------------------------------------------------------------*/ @@ -1498,7 +1516,7 @@ void I3C_Master_Insert_ENTDAA_After_IbiAckHJ(__u32 Parm) I3C_TRANSFER_TASK_t *pTask; I3C_TASK_INFO_t *pTaskInfo; __u8 port; - + __u16 rxLen; if (Parm == 0) { return; @@ -1528,7 +1546,9 @@ void I3C_Master_Insert_ENTDAA_After_IbiAckHJ(__u32 Parm) * Can't use RESTART + ENTDAA, that will cause MERRWARN.INVREQ */ I3C_Master_Stop_Request((__u32)pTask); - I3C_Master_Insert_Task_ENTDAA(63, NULL, I3C_TRANSFER_SPEED_SDR_1MHZ, TIMEOUT_TYPICAL, + + rxLen = 63; + I3C_Master_Insert_Task_ENTDAA(&rxLen, NULL, I3C_TRANSFER_SPEED_SDR_1MHZ, TIMEOUT_TYPICAL, NULL, port, I3C_TASK_POLICY_INSERT_FIRST, NOT_HIF); } diff --git a/tests/boards/npcm400f_evb/boards/npcm400f_evb.conf b/tests/boards/npcm400f_evb/boards/npcm400f_evb.conf index 15ea997339cb70..31332cf80478e0 100644 --- a/tests/boards/npcm400f_evb/boards/npcm400f_evb.conf +++ b/tests/boards/npcm400f_evb/boards/npcm400f_evb.conf @@ -11,4 +11,10 @@ CONFIG_I3C_SLAVE=y CONFIG_I3C_SLAVE_MQUEUE=y #CONFIG_TIMESLICING=y -#CONFIG_TIMESLICE_SIZE=1 \ No newline at end of file +#CONFIG_TIMESLICE_SIZE=1 + + +#CONFIG_THREAD_ANALYZER=y +#CONFIG_THREAD_ANALYZER_USE_PRINTK=y +#CONFIG_THREAD_ANALYZER_AUTO=y +#CONFIG_THREAD_ANALYZER_AUTO_INTERVAL=5 \ No newline at end of file diff --git a/tests/boards/npcm400f_evb/prj.conf b/tests/boards/npcm400f_evb/prj.conf index f707aaf204378d..b85c64b523a765 100644 --- a/tests/boards/npcm400f_evb/prj.conf +++ b/tests/boards/npcm400f_evb/prj.conf @@ -24,7 +24,7 @@ CONFIG_HEAP_MEM_POOL_SIZE=65536 #CONFIG_STACK_SENTINEL=y CONFIG_LOG=y -CONFIG_THREAD_ANALYZER=y +#CONFIG_THREAD_ANALYZER=y # Following configuration declare for rand32 CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/boards/npcm400f_evb/src/i3c.c b/tests/boards/npcm400f_evb/src/i3c.c index 3410318f43284c..2866446d9ba57e 100644 --- a/tests/boards/npcm400f_evb/src/i3c.c +++ b/tests/boards/npcm400f_evb/src/i3c.c @@ -11,6 +11,10 @@ #include #include "ast_test.h" + +#include +#include + #define LOG_MODULE_NAME i3c_test #include @@ -25,7 +29,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); extern int i3c_slave_mqueue_read(const struct device *dev, uint8_t *dest, int budget); extern int i3c_slave_mqueue_write(const struct device *dev, uint8_t *src, int size); -#define TEST_I3C_SLAVE_THREAD_STACK_SIZE 1024 +#define TEST_I3C_SLAVE_THREAD_STACK_SIZE 2048 #define TEST_I3C_SLAVE_THREAD_PRIO CONFIG_ZTEST_THREAD_PRIORITY K_THREAD_STACK_DEFINE(test_i3c_slave_thread_stack_area, TEST_I3C_SLAVE_THREAD_STACK_SIZE); @@ -159,6 +163,13 @@ static void test_i3c_ci(int count) i3c_master_attach_device(dev_master, slave); + /* PinSelect(Pin_M3_GPIOC4) */ + /* PinSelect(Pin_L3_GPIOC5) */ + /* RegClrBit(M8(0x400C3000 + 0x62), BIT4 | BIT5); */ + /* RegSetBit(M8(0x40081000 + (0x0C * 0x2000L)), MaskBit(4) | MaskBit(5)); */ + /* RegClrBit(M8(0x40081000 + (0x0C * 0x2000L) + 0x06), MaskBit(4) | MaskBit(5)); */ + /* RegSetBit(M8(0x40081000 + (0x0C * 0x2000L) + 0x02), MaskBit(4) | MaskBit(5)); */ + /* try to enter i3c mode */ /* assign dynamic address with setdasa or entdaa, doesn't support setaasa in slave mode */ i3c_master_send_rstdaa(dev_master); @@ -188,17 +199,17 @@ static void test_i3c_ci(int count) mdb = DT_PROP(DT_NODELABEL(i3c1_smq), mandatory_data_byte); - /* create semaphore to synchronize master and slave between ibi */ - if (IS_MDB_PENDING_READ_NOTIFY(mdb)) { - k_sem_init(&ibi_complete, 0, 1); - } - for (i = 0; i < count; i++) { /* prepare request message */ prepare_test_data(test_data_tx_mst, TEST_PRIV_XFER_SIZE); /* test_data_tx_mst[0] = i; */ /* for debug only */ /* k_usleep(100); */ /* debug only */ + /* create semaphore to synchronize master and slave between ibi */ + if (IS_MDB_PENDING_READ_NOTIFY(mdb)) { + k_sem_init(&ibi_complete, 0, 1); + } + /* Requester send request message */ xfer[0].rnw = 0; xfer[0].len = TEST_PRIV_XFER_SIZE; @@ -217,9 +228,6 @@ static void test_i3c_ci(int count) /* master waits IBI from the slave */ k_sem_take(&ibi_complete, K_FOREVER); - /* init the flag for the next loop */ - k_sem_init(&ibi_complete, 0, 1); - /* check result */ ast_zassert_equal(mdb, test_data_rx_mst[0], "IBI MDB mismatch: %02x %02x\n", @@ -230,7 +238,6 @@ static void test_i3c_ci(int count) xfer[0].rnw = 1; xfer[0].len = TEST_IBI_PAYLOAD_SIZE; xfer[0].data.in = test_data_rx_mst; - k_yield(); ret = i3c_master_priv_xfer(slave, &xfer[0], 1); ast_zassert_mem_equal(test_data_tx_slv, test_data_rx_mst, TEST_IBI_PAYLOAD_SIZE, "data mismatch %d %X %X", i, test_data_tx_slv[0], test_data_rx_mst[0]); diff --git a/tests/boards/npcm400f_evb/src/main.c b/tests/boards/npcm400f_evb/src/main.c index 17bfb08b627b02..76b75b4d977a29 100644 --- a/tests/boards/npcm400f_evb/src/main.c +++ b/tests/boards/npcm400f_evb/src/main.c @@ -20,11 +20,11 @@ extern void test_i3c(void); #define TEST_MODULE_CNT 1 #define TEST_STACKSIZE 8192 -#define TEST_CI_TIMEOUT 40 +#define TEST_CI_TIMEOUT 60 #define TEST_SLT_TIMEOUT 20 #define TEST_FT_TIMEOUT 5 -#define TEST_CI_FUNC_COUNT 100 +#define TEST_CI_FUNC_COUNT 2048 #define TEST_SLT_FUNC_COUNT 1 #define TEST_FT_FUNC_COUNT 1 @@ -193,7 +193,6 @@ static void nuvoton_run_test_suite(const char *name, struct unit_test *suite, goto end; unit_test_remain = unit_test_count; - thread_analyzer_print(); nuvoton_run_test();